#!/bin/bash

#   BAREOS® - Backup Archiving REcovery Open Sourced
#
#   Copyright (C) 2025-2026 Bareos GmbH & Co. KG
#
#   This program is Free Software; you can redistribute it and/or
#   modify it under the terms of version three of the GNU Affero General Public
#   License as published by the Free Software Foundation and included
#   in the file LICENSE.
#
#   This program is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
#   Affero General Public License for more details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
#   02110-1301, USA.

# This testrunner performs a restore after the volume containing
# the jobid is ejected
# We are checking that these messages do not pop up:
# - Error: stored/block.cc:1004 Read error on fd=8
# - Warning: stored/acquire.cc:317 Read acquire:
# and that these messages do pop up:
# - No slot defined in catalog (slot=0)
# - Cartridge change or "update slots" may be required.
# - Please mount read Volume "XXXX" for:

set -e
set -o pipefail
set -u

TestName="$(basename "$(pwd)")"
export TestName
export BCONSOLE_TIMEOUT=120

#shellcheck source=../../environment.in
. ./environment
#shellcheck source=test-config.in
. ./test-config

#shellcheck source=../../scripts/functions
. "${BAREOS_SCRIPTS_DIR}"/functions

start_test

on_error()
{
  local lc="${BASH_COMMAND}"
  echo "Error occurred in testrunner script [${lc}]"
  export estat=1
  exit 1
}
trap 'on_error' ERR

# Be sure all devices are released before running
release_all_devices

jobid_to_restore=$(head -n 1 "${tmp}/list_of_jobids")

#determine volume to eject
volume_to_eject=$(bin/bconsole <<< ".api 2
list volumes jobid=${jobid_to_restore}
" | awk -F " " '/^.*"volumename":/ {gsub("\"","",$2);gsub(" ","",$2);gsub(",","",$2);print $2}'
)

echo "Emulate export volume ${volume_to_eject} with db update"
cat <<END_OF_DATA >"${tmp}/bconcmds"
@$out ${runner_tmp}/update_volume_to_slot_0.out
.api 2
.sql query="update media set slot=0,inchanger=0 where volumename='${volume_to_eject}';"
wait
list volume=${volume_to_eject}
quit
END_OF_DATA

run_bconsole

# Add check ejected volume has slot=0
if ! awk -F " " '/^.*"slot":/ {gsub("\"","",$2);gsub(" ","",$2);gsub(",","",$2);print $2}'\
     "${runner_tmp}/update_volume_to_slot_0.out"; then
	echo "Volume ${volume_to_eject} has still a slot number (${slot})" >&2
	exit 1
fi


if ! awk -F " " '/^.*"inchanger":/ {gsub("\"","",$2);gsub(" ","",$2);gsub(",","",$2);print $2}'\
    "${runner_tmp}/update_volume_to_slot_0.out"; then
	echo "Volume ${volume_to_eject} has still inchanger set (${inchanger})" >&2
	exit 1
fi

echo "Set debug on the Tape-Storage daemon"
tracefile="$(bin/bconsole <<< "setdebug level=200 trace=1 storage=Tape-0"\
 | awk -F"tracefile=" '/^3000/ {print $2}')"
: >"${tracefile}" # clear tracefile

echo "Run restore"
rm -f "${runner_tmp}/restore_non_present_volume.out"
cat <<END_OF_DATA >"${tmp}/bconcmds"
@$out ${runner_tmp}/restore_non_present_volume.out
restore jobid=${jobid_to_restore} where=${tmp}/bareos_restores_novolume
mark *
done
yes
messages
quit
END_OF_DATA

echo "bconsole timeout ${BCONSOLE_TIMEOUT}"
run_bconsole

# echo "export joblog for last restore"
last_jobid=$(awk -F"=" '/Job queued. JobId=/ {print $2}' "${runner_tmp}/restore_non_present_volume.out")


# To finish the test we have to unvault the ejected volume
# but not before getting the mount request
is_mount_requested=0
max_runs=120
while [ ${is_mount_requested} -eq 0 ]; do
	sleep 0.5
	echo "check mount request message"
	if [ $(bin/bconsole <<< ".status dir running" | grep -c "is waiting for a mount request") -eq 1 ]; then
		echo "check mount request found"
		bin/bconsole <<< "list joblog jobid=${last_jobid}" > "${runner_tmp}/jobid-${last_jobid}.log"
		drive_to_mount=$(awk '/ 3301 Issuing autochanger/ {gsub("\"","",$11);print "drive="$11}' "${runner_tmp}/jobid-${last_jobid}.log")
		is_mount_requested=1
	fi
	# Safety exit in case somehting unexpected happens
	max_runs=$((max_runs - 1))
	if [ ${max_runs} -le 0 ]; then
		echo "Timeout waiting for mount request" >&2
		exit 1
	fi
done

echo "Run update slots and mount volume ${volume_to_eject} into storage=Tape-0 and ${drive_to_mount}"
cat <<END_OF_DATA >"${tmp}/bconcmds"
@$out ${runner_tmp}/restore_non_present_volume.out
update slots storage=Tape-0 yes
mount storage=Tape-0 ${drive_to_mount} volume=${volume_to_eject}
wait
messages
quit
END_OF_DATA

run_bconsole

# Regenerate joblog after job completed
bin/bconsole <<< "list joblog jobid=${last_jobid}" > "${runner_tmp}/jobid-${last_jobid}.log"

# What we want to found in the log
expect_grep "No slot defined in catalog (slot=0)" \
	"${runner_tmp}/jobid-${last_jobid}.log" \
	"no 'no slot defined' found in log"

expect_grep "Cartridge change or \"update slots\" may be required." \
	"${runner_tmp}/jobid-${last_jobid}.log" \
	"no cartridge change message found in log"

expect_grep "Please mount read Volume \"${volume_to_eject}\" for:" \
	"${runner_tmp}/jobid-${last_jobid}.log" \
	"no 'please mount volume' message found in log"

if [ ${estat} -ne 0 ]; then
  exit ${estat}
fi

# What we absolutely not want to see in the log
expect_not_grep "Error: stored/block.cc:i.* Read error on fd" \
	"${runner_tmp}/jobid-${last_jobid}.log" \
	"stored/block.cc errors found in log"

expect_not_grep "Warning: stored/acquire.cc:.* Read acquire:" \
	"${runner_tmp}/jobid-${last_jobid}.log" \
	"stored/acquire.cc errors found in log"

if [ ${estat} -ne 0 ]; then
  exit ${estat}
fi

end_test
exit 0
