#!/bin/sh -eu

# Process inputs
DD_DOMAIN="${1:-}"
tc="${2:-}"
duration="${3:-60}"
USE_SELENIUM="${USE_SELENIUM:-YES}"
SCRIPT_PATH="$(realpath "${0}")"
SCRIPT_NAME="$(basename "${0}")"

JMETER_DEFAULT="./apache-jmeter-5.5/bin/jmeter"

full_tests() {
	# Runtime: 7 tests * 5 mins / test = 35 mins
	# Cool-off periods: 30s * 6 = 3 mins
	# Total: 38 mins
	cooloff="30"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 10 	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 20 	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 30 	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 60 	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 100	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 300	300
	sleep "${cooloff}"
	"${SCRIPT_PATH}" "${DD_DOMAIN}" 600	300
}

help_users_file() {
	cat <<-EOF
	The format of the users.csv file must be:
	USERNAME1,PASSWORD1
	USERNAME2,PASSWORD2
	...

	Take care not to have any spaces between fields.
	EOF
}

help_jmeter() {
	cat <<-EOF
	Note this scripts depends on JMeter with some plugins enabled.
	You can set the JMETER environment variable to its binary path.
	If this variable is unset, ${JMETER_DEFAULT}
	will be used, from this script's location.
	See:
		https://jmeter.apache.org/download_jmeter.cgi
		https://jmeter-plugins.org/install/Install/
	EOF
}

help() {
	cat <<-EOF
	Examples:
		./${SCRIPT_NAME} DD_DOMAIN THREAD_COUNT [DURATION]
		or:
		./${SCRIPT_NAME} --full-tests DD_DOMAIN

	EOF

	help_jmeter

	cat <<-EOF

	When using --full-tests, a pre-selected combination of
	THREAD_COUNT and DURATION will be used against DD_DOMAIN.

	Where DD_DOMAIN is the base domain, e.g. if your DD instance's
	Nextcloud can be accessed at nextcloud.example.org, the parameter
	should be "example.org".

	THREAD_COUNT refers to the amount of users that will be simulated.

	DURATION is the total test time time in seconds. Defaults to 60.

	Note that you MUST have a users.csv file in the current directory.

	By default this script runs tests with selenium and documents the
	session as would be perceived by a user.
	You can disable this behaviour by setting the environment variable
	USE_SELENIUM=NO.
	EOF
	help_users_file
}

if [ "${DD_DOMAIN:-}" = "--full-tests" ]; then
	shift  # Consume operation argument
	# Re-set global variable
	DD_DOMAIN="${1:-}"
	# Execute full suite
	full_tests
	# And exit
	exit 0
elif [ "${1:-}" = "--help" ]; then
	help
	exit 0
elif [ -z "${DD_DOMAIN:-}" ] || [ -z "${tc:-}" ]; then
	help >> /dev/stderr
	exit 1
fi

USERS_FILE="$(pwd)/users.csv"
DOCS_FILE="$(pwd)/docs.csv"

# Change current path
cd "$(dirname "${SCRIPT_PATH}")"
out_dir="$(pwd)/results/${DD_DOMAIN}_${tc}_${duration}"

if [ -f "${USERS_FILE}" ]; then
	cat "${USERS_FILE}" > dd-stress-test.users.csv
else
	printf "ERROR: missing file\t%s\n\n" "${USERS_FILE}" >> /dev/stderr
	help_users_file >> /dev/stderr
	exit 2
fi

if [ -f "${DOCS_FILE}" ]; then
	cat "${DOCS_FILE}" > dd-stress-test.docs.csv
else
	cat > dd-stress-test.docs.csv <<-EOF
	/,Readme.md
	/,template.docx
	/,template_1.docx
	EOF
fi


JMETER="${JMETER:-${JMETER_DEFAULT}}"
# Ensure JMeter is available / bootstrap it
if [ ! -f "${JMETER}" ]; then
	echo "INFO: Could not find JMeter, attempting to download it" >> /dev/stderr
	curl -L 'https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.5.tgz' | tar -xz
	JMETER="${JMETER_DEFAULT}"
fi
if [ ! -f "${JMETER}" ]; then
	printf "ERROR: missing JMeter\t%s\n\n" "${JMETER}" >> /dev/stderr
fi
# Ensure JMeter plugins are available / bootstrap them
JMETER_PLUGINS="$(dirname "${JMETER}")/../lib/ext/jmeter-plugins-manager-1.8.jar"
if [ ! -f "${JMETER_PLUGINS}" ]; then
	echo "INFO: Could not find JMeter plugins, attempting to download them" >> /dev/stderr
	curl -L 'https://jmeter-plugins.org/get/' > "${JMETER_PLUGINS}"
fi
if [ ! -f "${JMETER_PLUGINS}" ]; then
	printf "ERROR: missing JMeter plugins\t%s\n\n" "${JMETER_PLUGINS}" >> /dev/stderr
fi
if [ ! -f "${JMETER}" ] || [ ! -f "${JMETER_PLUGINS}" ]; then
	help_jmeter >> /dev/stderr
	exit 3
fi

# Clean up out dir
rm -rf "${out_dir}"
mkdir -p "${out_dir}"

# Adapt template
sed -E \
	-e "s%([^>]*)>(.*)<\!-- TC.*$%\\1>${tc}</stringProp> <\!-- TC -->%" \
	-e "s%([^>]*)>(.*)<\!-- DURATION.*$%\\1>${duration}</stringProp> <\!-- DURATION -->%" \
	-e "s/DD_DOMAIN/${DD_DOMAIN}/g" \
	dd-stress-test.tpl.jmx > dd-stress-test.jmx

# Call Selenium test process in parallel
if [ "${USE_SELENIUM}" = "YES" ]; then
	printf "\n\nRunning parallel Selenium-based tests:\t%s\tover %s seconds\n\n" "${DD_DOMAIN}" "${duration}"
	python3 dd-tests-selenium.py test --duration "${duration}" --out-dir "${out_dir}/selenium" "${DD_DOMAIN}" 2>&1 > "${out_dir}/selenium.log" &
fi

# Execute test
printf "\n\nAbout to test:\t%s\twith %s 'users' over %s seconds\n\n" \
	"${DD_DOMAIN}" "${tc}" "${duration}"
env HEAP="-Xms2g -Xmx2g -XX:MaxMetaspaceSize=2g" "${JMETER}" -n -t dd-stress-test.jmx -l "${out_dir}/results" -e -o "${out_dir}/html"
mv jmeter.log "${out_dir}/log"

# Notify results
printf "\n\nYou can find the results at:\t%s\n\n" "${out_dir}"