From 87379d7e50a51c9dad25ce6b12b22a6db3fea19b Mon Sep 17 00:00:00 2001 From: Andrei Stepanov Date: Apr 25 2019 16:57:52 +0000 Subject: Script for run tests in Basic role. Tested with: - hosts: localhost roles: - role: standard-test-basic tags: - classic tests: - test one: dir: "tdir for test 1" run: XXXXXXXXX="1 2 3 4 " env - test 2: dir: tdir two run: true; false - test 3 three: dir: dir3 run: echo -e "hello world\nnewline"; exit 111 Signed-off-by: Andrei Stepanov --- diff --git a/roles/standard-test-basic/files/run-basic-test b/roles/standard-test-basic/files/run-basic-test new file mode 100755 index 0000000..5bc42bc --- /dev/null +++ b/roles/standard-test-basic/files/run-basic-test @@ -0,0 +1,142 @@ +#!/bin/bash -efu + +# Called from standard-test-basic role to run basic tests +# This script is copied to test-environment. + +debug() { + if [ -n "$DEBUG" ]; then + echo "$*" >&2 + fi +} + +msg_usage() { + cat << EOF + +Run basic test. + +Usage: +$PROG + +Options: +-h, --help display this help and exit +-v, --verbose turn on debug +-w, --workdir test environment work dir. Directory for test execution. +-a, --artifactsdir test environment dir to store artifacts +-t, --testname name of the test +-c, --cmd shell command to run the test +EOF +} + +# Entry + +PROG="${PROG:-${0##*/}}" +DEBUG="${DEBUG:-}" +STR_CMD="${STR_CMD:-}" +STR_DEBUG="${STR_DEBUG:-}" +STR_VERBOSE="${STR_VERBOSE:-}" +STR_WORKDIR="${STR_WORKDIR:-}" +STR_TEST_NAME="${STR_TEST_NAME:-}" +STR_ARTIFACTS_DIR="${STR_ARTIFACTS_DIR:-/tmp}" + +# http://wiki.bash-hackers.org/howto/getopts_tutorial +opt=$(getopt -n "$0" --options "hvt:w:a:c:" --longoptions "help,verbose,cmd:,testname:,workdir:,artifactsdir:" -- "$@") +eval set -- "$opt" +while [[ $# -gt 0 ]]; do + case "$1" in + -t|--testname) + STR_TEST_NAME="$2" + shift 2 + ;; + -c|--cmd) + STR_CMD="$2" + shift 2 + ;; + -w|--workdir) + STR_WORKDIR="$2" + shift 2 + ;; + -a|--artifactsdir) + STR_ARTIFACTS_DIR="$2" + shift 2 + ;; + -v|--verbose) + DEBUG="-v" + shift + ;; + -h|--help) + msg_usage + exit 0 + ;; + --) + shift + ;; + *) + msg_usage + exit 1 + esac +done + +# Entry + +if [ -z "$STR_TEST_NAME" ] || [ -z "$STR_WORKDIR" ] || [ -z "$STR_CMD" ]; then + echo "Use: $PROG -h for help." + exit 0 +fi + +mkdir -p "$STR_WORKDIR" +mkdir -p "$STR_ARTIFACTS_DIR" +STR_WORKDIR="$(realpath "$STR_WORKDIR")" +STR_ARTIFACTS_DIR="$(realpath "$STR_ARTIFACTS_DIR")" +debug "Test: $STR_TEST_NAME" +debug "Command: $STR_CMD" +debug "Work dir: $STR_WORKDIR" +debug "Artifacts dir: $STR_ARTIFACTS_DIR" + +# Up to this point any fail is considered as ci-sytem fail. Exit code != 0. +# Starting from this point and bellow any fail is considered as a test fail. Exit code == 0. + +clean_exit() { + rc=$?; + trap - SIGINT SIGTERM SIGABRT EXIT # clear the trap + echo "Run test '$STR_TEST_NAME': done. Test's exit code: $rc" + # Exit code == 0, no matter of the test result. + # Close tee pipes + for pid in $(ps -o pid --no-headers --ppid $$); do + if [ -n "$(ps -p $pid -o pid=)" ]; then + kill -s HUP $pid + fi + done + # Return non-zero when test command not found + if [[ $rc -eq 127 ]]; then + echo "$STR_TEST_NAME (problem with test execution)" >&2 + fi + local status="FAIL" + if [[ $rc -eq 0 ]]; then + status="PASS" + fi + local run_journal="$STR_ARTIFACTS_DIR/test.log" + echo "${status} $STR_TEST_NAME" >> "$run_journal" + if [ -e "$logfile_stdout" ]; then + local new_logfile_stdout="$(dirname "$logfile_stdout")/${status}_str_$(basename "$logfile_stdout")" + mv -f "$logfile_stdout" "$new_logfile_stdout" + fi + exit 0 +} +trap clean_exit SIGINT SIGTERM SIGABRT EXIT + +export PATH="$PATH:$STR_WORKDIR" +mkdir -p "$STR_ARTIFACTS_DIR" +logfile_stdout="$STR_ARTIFACTS_DIR/$(echo "$STR_TEST_NAME" | sed -e 's/\//-/g').log" +logfile_stderr="$STR_ARTIFACTS_DIR/$(echo "$STR_TEST_NAME" | sed -e 's/\//-/g')-err.log" +logfile_stdout="$(realpath "$logfile_stdout")" +logfile_stderr="$(realpath "$logfile_stderr")" +exec 3>&1 4>&2 1> >(tee -a "$logfile_stdout" >&3) 2> >(tee -a "$logfile_stderr" >&4) +cd "$STR_WORKDIR" +# Purpose to spawn new bash is to ignore -efu setting for current shell +# Test command: run-basic-test -w wodir -c 'false; echo 123; echo 333 >&2; touch "123 123"; exit 43' -t my_test -a logs -v +if [ -f "$STR_CMD" ]; then + chmod 0775 "$STR_CMD" +fi +bash -c "$STR_CMD" +# Explicit return code +exit $? diff --git a/roles/standard-test-basic/tasks/main.yml b/roles/standard-test-basic/tasks/main.yml index d51e295..692b6f1 100644 --- a/roles/standard-test-basic/tasks/main.yml +++ b/roles/standard-test-basic/tasks/main.yml @@ -2,48 +2,12 @@ - block: - name: Execute tests - shell: | - if [[ -z ${TEST} ]]; then - echo "FAIL: Test case name is not set" >> {{ remote_artifacts }}/test.log - exit - fi - if [[ -z ${TEST_DIR} ]]; then - echo "FAIL: Test directory for $TEST not found" >> {{ remote_artifacts }}/test.log - exit - fi - if [[ -z ${TEST_CMD} ]]; then - echo "FAIL: Does not know how to run $TEST" >> {{ remote_artifacts }}/test.log - exit - fi - log_file_name=$(echo $TEST | sed -e 's/\//-/g').log - logfile={{ remote_artifacts }}/str_${log_file_name} - exec 2>>$logfile 1>>$logfile - cd $TEST_DIR - #if command is a file make it executable - cmd="$(echo $TEST_CMD | awk '{print $1;}')" - if [ -f "$cmd" ]; then - chmod 0775 "$cmd" - fi - status="FAIL" - #execute the test - eval $TEST_CMD - if [ $? -eq 0 ]; then - status="PASS" - fi - echo "${status} $TEST" >> {{ remote_artifacts }}/test.log - # Add test status as prefix to test case log - mv ${logfile} {{ remote_artifacts }}/${status}_str_${log_file_name} - environment: - #Allow to use tests as a simple string which means the test is expected - #to be in a directory with same name and test script `runtest.sh` - #It is also possible to define the test as dictionary, in that case it is possible - #to change test directory and test command line parameters while test name is item key - TEST: - "{{ item if item.keys is not defined else (item.keys()|list)[0] }}" - TEST_DIR: - "{{ tenv_workdir }}/{{ item if item.keys is not defined else item[(item.keys()|list)[0]]['dir']|default((item.keys()|list)[0]) }}" - TEST_CMD: - "{{'./runtest.sh' if item.keys is not defined else item[(item.keys()|list)[0]]['run']|default('./runtest.sh')}}" + script: + run-basic-test -v + --workdir {{ tenv_workdir | regex_escape() }}/{{ item if item.keys is not defined else item[(item.keys()|list)[0]]['dir']|default((item.keys()|list)[0]) | regex_escape() }} + --artifactsdir {{ remote_artifacts | regex_escape() }} + --test {{ item if item.keys is not defined else (item.keys()|list)[0] | regex_escape() }} + --cmd {{ './runtest.sh' if item.keys is not defined else item[(item.keys()|list)[0]]['run']|default('./runtest.sh') | regex_escape() }} with_items: - "{{ tests }}"