From 434e195ce9eee5b54d0698ff62bd44b0bd2facd5 Mon Sep 17 00:00:00 2001 From: Gal Szkolnik Date: Mon, 8 Jul 2024 22:58:07 -0400 Subject: [PATCH] Automated testing script (#215) --- .github/workflows/test.yml | 5 +- test/test-jlmkr | 192 +++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 3 deletions(-) create mode 100755 test/test-jlmkr diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d339374..127ac8f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -87,6 +87,5 @@ jobs: env: PYTHONUNBUFFERED: 1 run: | - sudo chown 0:0 jlmkr.py test/test.sh - sudo chmod +x jlmkr.py test/test.sh - sudo ./test/test.sh + sudo chown 0:0 jlmkr.py ./test/test-jlmkr + sudo bash ./test/test-jlmkr diff --git a/test/test-jlmkr b/test/test-jlmkr new file mode 100755 index 0000000..bc87295 --- /dev/null +++ b/test/test-jlmkr @@ -0,0 +1,192 @@ +#! /usr/bin/env bash + +# Example invokation +# sudo SCALE_POOL_ROOT=$SCALE_POOL_ROOT $SCALE_POOL_ROOT/jailmaker/test/test-jlmkr docker + +set -e + +#### Global variables + +if [[ -z "$JLMKR_PATH" && -n "$SCALE_POOL_ROOT" ]]; then + SCALE_POOL_ROOT=${SCALE_POOL_ROOT:?must be exported before you can run test suite} + JLMKR_PATH=${SCALE_POOL_ROOT}/jailmaker +elif [[ -z "$JLMKR_PATH" ]]; then + JLMKR_PATH=${PWD:-.} +fi +if [[ ! -r "$JLMKR_PATH/jlmkr.py" ]]; then + >&2 printf "%s\n" \ + "couldn't find jlmkr.py. Are you running from the jailmaker directory?" \ + "If not, setup either JLMKR_PATH or SCALE_POOL_ROOT" \ + "" + + >&2 printf "\tPWD: %s\n\tJLMKR_PATH: %s\n\tSCALE_POOL_ROOT: %s\n" \ + "$PWD" "$JLMKR_PATH" "$SCALE_POOL_ROOT" + + >&2 printf "\n" + exit 2 +fi +JAIL_TYPE="${1}" +if [ -n "${JAIL_TYPE}" ]; then + if [ -r "${JAIL_TYPE}" ]; then + JAIL_CONFIG="$JAIL_TYPE" + JAIL_TYPE= + # Can't perform full test with config path + FULL_TEST=0 + else + JAIL_CONFIG="$JLMKR_PATH/templates/$JAIL_TYPE/config" + # Full test is an option when using JAIL_TYPE + FULL_TEST=${FULL_TEST:-0} + fi + if [ ! -r "${JAIL_CONFIG}" ]; then + >&2 printf "Must supply a valid jail type or config path\n" + exit 2 + fi +fi + +# shellcheck disable=SC2034 # JAIL is used inside perform_test_suite +JAIL="${2:-${JAIL_TYPE:-default}-test}" + +# STOP=0 - (default) perform all tests, in non-blocking mode +# STOP=l - only list and images, nothing else +# STOP=i - interactive test, includ console-blocking waiting for input tests (edit and shell) +STOP=${STOP:-0} + +REPORT=(create edit exec images list log remove restart shell start status stop) + +WAIT_FOR_JAIL=${WAIT_FOR_JAIL:-4s} + +#### Functions +jlmkr () { + /usr/bin/env python3 "$JLMKR_PATH/jlmkr.py" "${@:---help}" +} + +iterate () { + # shellcheck disable=SC2206 # $1 will pass multiple values, we want splitting here + local SET=($1) DO=("${@:2}") + local x j _x x_STATUS + + for j in "${SET[@]}"; do + for _x in "${DO[@]}"; do + x="${_x//\(Jv)/JLMKR_"$j"}" + # echo "$x" >&2 + ${NO_EVAL:+:} eval "echo \$JLMKR_${j} \"$x\"" + x_STATUS=✅ + ${NO_EVAL:+:} eval "JLMKR_$j=$x_STATUS" + ${NO_EVAL:+:} eval "JLMKR_${j}_x=\"${x//\"/\'}\"" + + if [[ -n "$DELAY" ]]; then + printf "Waiting %s seconds before test...\n" "${DELAY}" + sleep "${DELAY}" + fi + + set +e + eval "$x" || x_STATUS=$? + set -e + if [[ "$x_STATUS" != "✅" ]]; then + ${NO_EVAL:+:} eval "JLMKR_${j}_x=\"($x_STATUS) ${x//\"/\'}\"" + ${NO_EVAL:+:} eval "JLMKR_$j=❌" + STOP=E:$x_STATUS + return + fi + done + done +} + +perform_test_suite() { + # shellcheck disable=SC2016 # function relies heavily on single quotes preventing expansion + + if [[ "$STOP" =~ ^(0|l|i)$ ]]; then + # Initialize REPORT with empty checkboxes - NO_EVAL=1 is important here, otherwise Status will be evaluated + NO_EVAL=1 iterate "${REPORT[*]}" '(Jv)="🔳"' + + TESTS=(list images) + iterate "${TESTS[*]}" 'jlmkr $j' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(create) \ + && iterate "${TESTS[*]}" 'jlmkr $j ${JAIL_CONFIG:+--config} $JAIL_CONFIG $JAIL' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(start) \ + && iterate "${TESTS[*]}" 'jlmkr $j $JAIL' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(restart) \ + && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL' + + # If this is an interactive test, edit and shell will wait for input + [[ "$STOP" == "i" ]] && TESTS=(edit shell) \ + && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL' + + # This is the non-interactive test for edit + [[ "$STOP" == "0" ]] && TESTS=(edit) \ + && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'EDITOR=cat jlmkr $j $JAIL' + + # This is the non-interactive test for shell + [[ "$STOP" == "0" ]] && TESTS=(shell) \ + && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL /bin/sh -c "echo shell called successful"' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(exec) \ + && DELAY=$WAIT_FOR_JAIL iterate "${TESTS[*]}" 'jlmkr $j $JAIL /bin/sh -c "echo exec called successful"' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(status) \ + && iterate "${TESTS[*]}" 'jlmkr $j $JAIL --no-pager' + + [[ "$STOP" =~ ^(0|i)$ ]] && TESTS=(log) \ + && iterate "${TESTS[*]}" 'jlmkr $j $JAIL -n 10' + + [[ "$STOP" =~ ^(0|l|i)$ ]] || >&2 printf "Had an Error. Cleanup up and stopping.\n" + + # Always perform these cleanup steps, even if something failed + [[ "$STOP" != l ]] \ + && TESTS=(stop) \ + && iterate "${TESTS[*]}" 'jlmkr $j $JAIL' \ + + [[ "$STOP" != l ]] \ + && TESTS=(remove) \ + && iterate "${TESTS[*]}" 'jlmkr $j $JAIL <<<"$JAIL" ' + + fi + printf '\n\nReport for:\n\tCWD: %s\t\tJAIL_CONFIG: %s\n\n' "$(pwd)" "${JAIL_CONFIG}" + + # shellcheck disable=SC2016 + NO_EVAL=1 iterate "${REPORT[*]}" 'echo "$(Jv) ${(Jv)_x:-$j}"' +} + +#### Execution starts here + +perform_test_suite + +if [[ "$STOP" =~ ^(0|i)$ ]]; then + [[ "$FULL_TEST" == 1 ]] || STOP="Single Test" +fi + +if [[ "$STOP" =~ ^(0|i)$ ]]; then + pushd "$JLMKR_PATH" > /dev/null || STOP=pushd + STOP=0 # The following test suite should only be run non-interactivley + + JAIL_CONFIG="./templates/$JAIL_TYPE/config" + perform_test_suite + + JAIL_CONFIG="templates/$JAIL_TYPE/config" + perform_test_suite + + JAIL_CONFIG="$JLMKR_PATH/$JAIL_CONFIG" + perform_test_suite + + cd ~ + perform_test_suite + + TMP_JAIL_CFG=$(mktemp) \ + && cp "$JAIL_CONFIG" "$TMP_JAIL_CFG" \ + && JAIL_CONFIG="${TMP_JAIL_CFG}" perform_test_suite \ + && rm "$TMP_JAIL_CFG" \ + || STOP=E:temp_file + + popd > /dev/null || STOP=popd +fi + +if [[ "$STOP" = 0 ]]; then + printf "All tests completed\n" +else + printf "Stopped: %s\n" "$STOP" + [[ "$STOP" = "Single Test" ]] || exit 1 +fi +