digitaldemocratic/stress-tests/dd-test.sh

181 lines
4.9 KiB
Bash
Executable File

#!/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-test-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}"