#!/bin/bash
#
# SPDX-FileCopyrightText: 2018 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
#
# SPDX-License-Identifier: LGPL-2.1-only

TEST_DESC="Change working directory of process"

CURDIR=$(dirname "$0")/
TESTDIR=$CURDIR/../../../

DIR=$(readlink -f "$TESTDIR")

NUM_TESTS=36

source $TESTDIR/utils/utils.sh

#MUST set TESTDIR before calling those functions
plan_tests $NUM_TESTS

print_test_banner "$TEST_DESC"
function test_relayd()
{
	local relayd_bin_path="$DIR/../src/bin/lttng-relayd/$RELAYD_BIN"
	local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")
	local pid
	local cwd

	diag "Test lttng-relayd normal mode change working directory"
	start_lttng_relayd "--working-directory $working_dir"
	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"

	cwd=$(readlink "/proc/${pid}/cwd")
	test "$working_dir" = "$cwd"
	ok "${?}" "Working directory changed"

	stop_lttng_relayd
	rm -rf "$working_dir"
}

function test_relayd_daemon()
{
	local cwd
	local pid
	local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")

	diag "Test lttng-relayd daemon mode change working directory"

	start_lttng_relayd_opt 1 "-d" "--working-directory $working_dir"
	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p "${pid}" >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/${pid}/cwd")
	is "${cwd:-no working directory found}" "$working_dir" "Working directory changed"

	stop_lttng_relayd
	rm -rf "$working_dir"
}

function test_relayd_daemon_no_working_dir()
{
	local expected_working_dir="/"
	local cwd
	local pid

	diag "Test lttng-relayd daemon mode change working directory"

	start_lttng_relayd_opt 1 "-d"
	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p $pid >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/${pid}/cwd")
	is "${cwd:-no working directory found}" "$expected_working_dir" "Working directory is $expected_working_dir"

	stop_lttng_relayd
	rm -rf "$working_dir"
}

function test_relayd_background()
{
	local cwd
	local pid
	local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")

	diag "Test lttng-relayd background mode change working directory"

	start_lttng_relayd_opt 1 "-b" "--working-directory $working_dir"
	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p "${pid}" >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/${pid}/cwd")
	is "${cwd:-no working directory found}" "$working_dir" "Working directory changed"

	stop_lttng_relayd
	rm -rf "$working_dir"
}

function test_relayd_background_no_working_dir()
{
	local expected_working_dir="/"
	local cwd
	local pid

	diag "Test lttng-relayd background working directory"

	start_lttng_relayd_opt 1 "-b"
	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p "${pid}" >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/${pid}/cwd")
	is "${cwd:-no working directory found}" "$expected_working_dir" "Working directory is $expected_working_dir"

	stop_lttng_relayd
	rm -rf "$working_dir"
}

function test_relayd_debug_permission()
{
	local is_user

	diag "Test lttng-relayd change working directory on non writable directory"

	if [ "$(id -u)" == "0" ]; then
		is_user=0
	else
		is_user=1
	fi

	skip $is_user "Skipping permission debug output test; operation can't fail as root" 6 ||
	{
		local output_pattern='Working directory \".*\" is not writable'
		local cwd
		local pid
		local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")

		# Removing write access to working dir
		okx chmod -w "$working_dir"

		# Redirect the error output to a temporary file

		RELAYD_ERROR_OUTPUT_DEST=$(mktemp -t "tmp.${FUNCNAME[0]}_error_output.XXXXXX")
		start_lttng_relayd_opt 1 "-b" "-v --working-dir $working_dir"
		# When the relayd is successfully started, the PID will be appended
		# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
		# the working directory. If relayd fails to start, there will be either
		# no PID, or a different lttng-relayd PID without the same working
		# directory and the test will fail.
		pid="${LTTNG_RELAYD_PIDS[-1]}"
		ps -p "${pid}" > /dev/null
		ok $? "Found lttng-relayd"

		cwd=$(readlink "/proc/${pid}/cwd")
		is "${cwd:-no working directory found}" "$working_dir" "Working directory changed"

		grep -q "$output_pattern" "${RELAYD_ERROR_OUTPUT_DEST}"
		ok $? "Warning about missing write permission is present"

		stop_lttng_relayd
		rm "${RELAYD_ERROR_OUTPUT_DEST}"
		rm -rf "$working_dir" "${RELAYD_ERROR_OUTPUT_DEST}"
		unset RELAYD_ERROR_OUTPUT_DEST
	}
}

function test_relayd_failure()
{
	local output_pattern='Failed to change working directory to'
	local relayd_bin_path="$DIR/../src/bin/lttng-relayd/$RELAYD_BIN"
	local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")
	local output_dest=$(mktemp -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")

	local working_dir_imaginary
	local pid

	working_dir_imaginary="${working_dir}/imaginary_directory"

	diag "Test lttng-relayd normal mode change non-existing directory"

	RELAYD_ERROR_OUTPUT_DEST="${output_dest}" start_lttng_relayd_opt 0 -b "--working-directory $working_dir_imaginary"
	test $? -eq "1"
	ok $? "Expect failure to start lttng-relayd for non-existent working directory"

	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be no PID.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	if [ -z "$pid" ]; then
		pass "No lttng-relayd present"
	else
		fail "No lttng-relayd present"
		stop_lttng_relayd_notap
	fi

	grep -q "$output_pattern" "$output_dest"
	ok $? "Found error message: invalid directory"

	rm -rf "$working_dir" "${output_dest}"
}

function test_relayd_env()
{
	local cwd
	local pid
	local working_dir=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir.XXXXXX")")

	diag "Test lttng-relayd change working directory from env. variable"

	export LTTNG_RELAYD_WORKING_DIRECTORY=${working_dir}
	start_lttng_relayd_opt 1 "-b"

	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p "${pid}" >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/$pid/cwd")
	is "${cwd:-no working directory found}" "$working_dir" "Working directory changed"

	stop_lttng_relayd
	rm -rf "$working_dir"
	unset LTTNG_RELAYD_WORKING_DIRECTORY
}

function test_relayd_cmdline_overwrite_env()
{
	local cwd
	local pid
	local working_dir_env=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir_even.XXXXXX")")
	local working_dir_cmdline=$(realpath "$(mktemp -d -t "tmp.${FUNCNAME[0]}_working_dir_cmdline.XXXXXX")")

	diag "Test lttng-relayd change working directory command line overwrite env variable"

	export LTTNG_RELAYD_WORKING_DIRECTORY=${working_dir_env}
	start_lttng_relayd_opt 1 "-b" "--working-dir ${working_dir_cmdline}"

	# When the relayd is successfully started, the PID will be appended
	# to `LTTNG_RELAYD_PIDS`. Use the last (most recent) PID for checking
	# the working directory. If relayd fails to start, there will be either
	# no PID, or a different lttng-relayd PID without the same working
	# directory and the test will fail.
	pid="${LTTNG_RELAYD_PIDS[-1]}"
	ps -p "${pid}" >/dev/null
	ok $? "Found lttng-relayd"

	cwd=$(readlink "/proc/$pid/cwd")
	is "${cwd:-no working directory found}" "$working_dir_cmdline" "Working directory is the one from command line"

	stop_lttng_relayd
	rm -rf "$working_dir_env" "$working_dir_cmdline"
	unset LTTNG_RELAYD_WORKING_DIRECTORY
}

TESTS=(
	test_relayd
	test_relayd_daemon
	test_relayd_daemon_no_working_dir
	test_relayd_background
	test_relayd_background_no_working_dir
	test_relayd_debug_permission
	test_relayd_failure
	test_relayd_env
	test_relayd_cmdline_overwrite_env
)

for fct_test in "${TESTS[@]}";
do
	if ! ${fct_test}; then
		break;
	fi
done
