#!/bin/bash set -u #============================================================================== # Declarations and Environment Setup #------------------------------------------------------------------------------ declare ThisScript=${0##*/} declare Version="1.1.1" declare Log= declare Verbosity=3 declare HxDepots= declare ResetDir= declare SDPBranch=${SDP_BRANCH:-Unset} declare HelixInstallerTestDir= declare TmpFile= declare H1="\\n==============================================================================" declare H2="\\n------------------------------------------------------------------------------" declare -i ErrorCount=0 declare -i TestID=0 declare -i SilentMode=0 declare -i OverallExitCode=0 declare -i Debug=0 # The OS environment variable should be set in the Docker configuration. export OS="${OS:-UnsetOS}" TmpFile="$(mktemp)" #============================================================================== # Local Functions function msg () { echo -e "$*"; } function vmsg () { [[ "$Verbosity" -ge 4 ]] && msg "$*"; } function vvmsg () { [[ "$Verbosity" -ge 5 ]] && msg "$*"; } function dbg () { [[ "$Debug" -eq 1 ]] && msg "$*"; } function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; } function bail () { errmsg "BAILING: ${1:-Unknown Error}"; exit "${2:-255}"; } function run () { dbg "CALL run (${1:-}, ${2:-})" local cmdAndArgs="${1:-echo}" local desc="${2:-}" [[ -n "$desc" ]] && msg "$desc" msg "Running: $cmdAndArgs" $cmdAndArgs return $? } #------------------------------------------------------------------------------ # Function: usage (required function) # # Input: # $1 - style, either -h (for short form) or -man (for man-page like format). # The default is -h. # # $2 - error message (optional). Specify this if usage() is called due to # user error, in which case the given message displayed first, followed by the # standard usage message (short or long depending on $1). If displaying an # errror, usually $1 should be -h so that the longer usage message doesn't # obsure the error message. # # Sample Usage: # usage # usage -h # usage -man # usage -h "Incorrect command line usage." #------------------------------------------------------------------------------ function usage { dbg "CALL usage (${1:-}, ${2:-})" declare style="${1:--h}" declare errorMessage="${2:-Unset}" if [[ "$errorMessage" != "Unset" ]]; then errmsg "Bad Usage:\\n\\n$errorMessage\\n\\n" fi msg "USAGE for $ThisScript v$Version: $ThisScript [-v<n>] [-d|-D] or $ThisScript [-h|-man|-V] " if [[ $style == -man ]]; then msg " DESCRIPTION: This is the test suite for the Helix Installer. OPTIONS: -v<n> Set verbosity 1-5 (-v1 = quiet, -v5 = highest). Levels 1 and 2 are reserved for future use. See EXAMPLES below for more detail on -v3, -v4, and -v5. -L <log> Specify the path to a log file to enable logging. Or, specify '-L off' to disable logging using a default log file name: /tmp/$ThisScript.v$Version.<datestamp>.log NOTE: This script is self-logging if logging is enabled. That is, output displayed on the screen is simultaneously captured in the log file. Do not run this script with redirection operators like '> log' or '2>&1', and do not use 'tee.' -si Operate silently. All output (stdout and stderr) is redirected to the log only; no output appears on the terminal. This cannot be used with '-L off'. -D Set extreme debugging verbosity. HELP OPTIONS: -h Display short help message -man Display man-style help message -V Dispay version. EXIT CODE: If all tests are executed and all pass, the exit code is 0. If all tests are executed and some fail, the exit code is 1. If '-h' or '-man' (usage messages) are used, the exit code is 1. If there is a usage error to this script or something goes horribly wrong with testing, the exit code is 255. EXAMPLES: Example 1: Test Summary Normally, run with no arguments (equivalent to -v3): $ThisScript This verbosity level is mainly intended to get a quick summary of which tests pass or fail, but without detail as to why they failed. Example 2: A Bit More For a bit more pedantic output: $ThisScript -v4 This verbosity level shows the test summary, plus a bit more detail about output we're expecting in each test. At this level, command output is suppressed except in cases where expected output for a test is defined but not contained in the output. Example 3: Full Details For a lot more pedantic output: $ThisScript -v5 This verbosity level shows the test summary, plus a bit more detail about output we're expecting in each test, plus the full output of all commands, regardless of whether they passed or failed the tests. " | less fi if [[ "$errorMessage" != "Unset" ]]; then exit 255 else exit 1 fi } #------------------------------------------------------------------------------ # Function run_test_cmd (cmd, desc, expectedExitCode, expectedInOutput) # $1 - command to execute, required # $2 - description of test # $3 - expected exit code, default 0 # $4 - snippet of text to 'grep -q -E' for in output to pass. # The '-E' allows regex pattern greps, e.g. for "(this|that)" # # Test passes if command executes and returns expected exit code. # If $4 is defined, output must contain the expected string for test # to pass. Tests that don't meet pass criteria fail. # # Reads global $TmpFile # Increments global variable $TestID # May increment global variable $ErrorCount (if the test fails). #------------------------------------------------------------------------------ function run_test_cmd () { dbg "CALL run_test_cmd (${1:-}, ${2:-}, ${3:-}, ${4:-})" local testCmd="${1:-Unset}" local desc="${2:-}" local -i expectedExitCode="${3:-0}" local expectedInOutput="${4:-}" local -i exitCode=0 [[ "$testCmd" == Unset ]] && bail "TEST ERROR: No test specified." TestID+=1 msg "${H2}\\nTEST $TestID: $desc. Running:\\n$testCmd" $testCmd > "$TmpFile" 2>&1 exitCode="$?" cat "$TmpFile" if [[ "$Verbosity" -ge 5 ]]; then msg "BEGIN OUTPUT" cat "$TmpFile" msg "END OUTPUT" fi if [[ "$exitCode" -ne "$expectedExitCode" ]]; then errmsg "Exit code was $exitCode, but expected to be $expectedExitCode." msg "FAILED TEST $TestID" return 1 else vmsg "Exit code was $expectedExitCode, as expected." fi if [[ -n "$expectedInOutput" ]]; then # This 'grep' should never generate stderr, so we do NOT redirect stderr # here, just in case something goes insanely wrong with the testing # mechanism itself. The exit code determines the success/failure of # the test. if grep -q -E "$expectedInOutput" "$TmpFile"; then vmsg "Expected output detected: $expectedInOutput" else # Display output that did not contain expected output, which # causes the test to fail, at Verbosity level 4. Usuall # output is displayed only at Level 5, but we display it at 4 # for failed tests. (For verbosity Level 5, the output is # already displayed, so we don't show it again). if [[ "$Verbosity" -eq 4 ]]; then msg "BEGIN OUTPUT" cat "$TmpFile" msg "END OUTPUT" fi errmsg "MISSING expected output: $expectedInOutput" msg "FAILED TEST $TestID" return 1 fi else vmsg "No expected output defined for test $TestID. Skipping output grep check." fi msg "PASSED TEST $TestID" return 0 } #------------------------------------------------------------------------------ # Function run_test_su_cmd (cmd, user, desc, expectedExitCode, expectedInOutput) # $1 - command to execute, required # $2 - operating system user to run as # $3 - description of test # $4 - expected exit code, default 0 # $5 - snippet of text to 'grep -q -E' for in output to pass. # The '-E' allows regex pattern greps, e.g. for "(this|that)" # # Test passes if command executes and returns expected exit code. # If $5 is defined, output must contain the expected string for test # to pass. Tests that don't meet pass criteria fail. # # Reads global $TmpFile # Increments global variable $TestID # May increment global variable $ErrorCount (if the test fails). #------------------------------------------------------------------------------ function run_test_su_cmd () { dbg "CALL run_test_su_cmd (${1:-}, ${2:-}, ${3:-}, ${4:-}, ${5:-})" local testCmd="${1:-Unset}" local user="${2:-Unset}" local desc="${3:-}" local -i expectedExitCode="${4:-0}" local expectedInOutput="${5:-}" local -i exitCode=0 [[ "$testCmd" == Unset ]] && bail "TEST ERROR: No test specified." [[ "$user" == Unset ]] && bail "TEST ERROR: No user specified." TestID+=1 msg "${H2}\\nTEST $TestID: $desc. Running:\\n$testCmd" su - "$user" -c "$testCmd" > "$TmpFile" 2>&1 exitCode="$?" cat "$TmpFile" if [[ "$Verbosity" -ge 5 ]]; then msg "BEGIN OUTPUT" cat "$TmpFile" msg "END OUTPUT" fi if [[ "$exitCode" -ne "$expectedExitCode" ]]; then errmsg "Exit code was $exitCode, but expected to be $expectedExitCode." msg "FAILED TEST $TestID" return 1 else vmsg "Exit code was $expectedExitCode, as expected." fi if [[ -n "$expectedInOutput" ]]; then # This 'grep' should never generate stderr, so we do NOT redirect stderr # here, just in case something goes insanely wrong with the testing # mechanism itself. The exit code determines the success/failure of # the test. if grep -q -E "$expectedInOutput" "$TmpFile"; then vmsg "Expected output detected: $expectedInOutput" else # Display output that did not contain expected output, which # causes the test to fail, at Verbosity level 4. Usuall # output is displayed only at Level 5, but we display it at 4 # for failed tests. (For verbosity Level 5, the output is # already displayed, so we don't show it again). if [[ "$Verbosity" -eq 4 ]]; then msg "BEGIN OUTPUT" cat "$TmpFile" msg "END OUTPUT" fi errmsg "MISSING expected output: $expectedInOutput" msg "FAILED TEST $TestID" return 1 fi else vmsg "No expected output defined for test $TestID. Skipping output grep check." fi msg "PASSED TEST $TestID" return 0 } #------------------------------------------------------------------------------ # Function terminate, run on termination. #------------------------------------------------------------------------------ function terminate () { trap - EXIT SIGINT SIGTERM [[ -r "$TmpFile" ]] && /bin/rm -f "$TmpFile" [[ "$Log" == "off" ]] || msg "\\nLog is: $Log${H2}" } #============================================================================== # Command Line Parsing declare -i shiftArgs=0 set +u while [[ $# -gt 0 ]]; do case $1 in (-h) usage -h;; (-man) usage -man;; (-V) msg "$ThisScript v$Version"; exit 1;; (-v1) Verbosity=1;; (-v2) Verbosity=2;; (-v3) Verbosity=3;; (-v4) Verbosity=4;; (-v5) Verbosity=5;; (-L) Log="$2"; shiftArgs=1;; (-si) SilentMode=1;; (-d) Debug=1;; # Debug (-D) Debug=1; set -x;; # Debug; use 'set -x' mode. (*) usage -h "Unknown arg ($1).";; esac # Shift (modify $#) the appropriate number of times. shift; while [[ $shiftArgs -gt 0 ]]; do [[ $# -eq 0 ]] && usage -h "Incorrect number of arguments." shiftArgs=$shiftArgs-1 shift done done set -u [[ "${Log:-Unset}" == "off" && "$SilentMode" -eq 1 ]] &&\ bail "Usage Error: The '-L off' and '-si' options are mutually exclusive." [[ "${Log:-Unset}" == "Unset" ]] && \ Log="/tmp/${ThisScript%.sh}.v$Version.$(date +'%Y%m%d-%H%M%S').log" #============================================================================== # Main Program #------------------------------------------------------------------------------ trap terminate EXIT SIGINT SIGTERM if [[ "$Log" != off ]]; then touch "$Log" || bail "Couldn't touch log file [$Log]." # Redirect stdout and stderr to a log file. if [[ "$SilentMode" -eq 0 ]]; then exec > >(tee "$Log") exec 2>&1 else exec > "${Log}" exec 2>&1 fi msg "Logging to: $Log" fi msg "${H1}\\nStarted ${0##*/} v$Version as $(whoami)@${HOSTNAME%%.*} at $(date)." msg "$H1\\nTest Prep - Part 1." # The SDP_BRANCH variable is passed in via the Docker environment, and can be set # locally on the VM for manual testing. if [[ "$SDPBranch" != Unset ]]; then msg "\\nInfo: SDP $SDPBranch selected for testing." else SDPBranch="dev" msg "\\nWarning: No SDP branch selected for testing. Using $SDPBranch branch." fi HxDepots="hxdepots" ResetDir="/$HxDepots/reset" HelixInstallerSrcDir="/hi/src" HelixInstallerTestDir="/hi/test" run "mkdir /$HxDepots" || bail "Failed to mkdir /$HxDepots" run "rsync -a $HelixInstallerSrcDir/ $ResetDir" || bail "Failed to rsync to: $ResetDir" cd "$ResetDir" || "Could not cd to: $ResetDir" msg "Operating in: $PWD" run "scp $HelixInstallerTestDir/settings.fgs.cfg $ResetDir/." || \ bail "Failed to copy cfg file to: $ResetDir" msg "$H1\\nStarting Version check test." run_test_cmd './reset_sdp.sh -h' 'Version' 1 'reset_sdp.sh v' run_test_cmd './reset_sdp.sh -man' 'Manual Page' 1 'DESCRIPTION:' msg "$H1\\nNormal Flow Tests - fgs.\\n" run_test_cmd "./reset_sdp.sh -b $SDPBranch -c settings.fgs.cfg -fast -no_ssl -no_sd -no_cron -no_ppr -no_tweaks -M" \ 'Basic usage test for instance fgs' 0 'SUCCESS' run_test_cmd 'id -u cooldude' 'Checking that OS user cooldude got created.' 0 run_test_cmd '/p4/common/bin/p4master_run fgs p4 set -q P4USER' \ 'Confirming P4USER is superman.' 0 'superman' # run_test_su_cmd 'crontab -l' 'cooldude' 'Checking crontab of OSUSER cooldude.' 0 \ # 'P4AdminList' msg "$H1\\nTest Prep - Part 2." msg "Operating in: $PWD" run_test_cmd "./reset_sdp.sh -X -R -c settings.fgs.cfg" \ 'Test of Extreme Cleanup with -X and -R flags' 0 'Extreme Cleanup complete' msg "$H1\\nTest Prep - Part 3." HxDepots="bigdisk" ResetDir="/$HxDepots/reset" run "mkdir /$HxDepots" || bail "Failed to mkdir /$HxDepots" run "rsync -a $HelixInstallerSrcDir/ $ResetDir" || bail "Failed to rsync to: $ResetDir" cd "$ResetDir" || "Could not cd to: $ResetDir" msg "Operating in: $PWD" run "scp $HelixInstallerTestDir/settings.fgs2.cfg $ResetDir/." || \ bail "Failed to copy cfg file to: $ResetDir" msg "$H1\\nNormal Flow Tests - fgs2.\\n" run_test_cmd "./reset_sdp.sh -b $SDPBranch -c settings.fgs2.cfg -fast -no_ssl -no_sd -no_cron -no_ppr -no_tweaks" \ 'Basic usage test for instance fgs2' 0 'SUCCESS' run_test_cmd 'id -u cooldude' 'Checking that OS user cooldude got created.' 0 run_test_cmd 'id -g -n cooldude' 'Checking that OS user cooldude is in group heroes.' 0 heroes run_test_cmd '/p4/common/bin/p4master_run fgs2 p4 set -q P4USER' \ 'Confirming P4USER is superman.' 0 'superman' if [[ "$ErrorCount" -eq 0 ]]; then msg "$H1\\nSummary: Executed $TestID tests, ALL PASSED." else msg "$H1\\nSummary: Executed $TestID tests, $ErrorCount FAILED, $((TestID-ErrorCount)) passed." OverallExitCode=1 fi msg "\\nTest suite executed in $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\n" exit "$OverallExitCode"
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#12 | 30410 | C. Thomas Tyler | Added '-f' option to simplfy re-running tests in interactive environent. | ||
#11 | 28582 | C. Thomas Tyler |
reset_sdp.sh v4.9.0: Added '-no_sudo' option. Added '-no_firewall' option. Fixed minor issue where 'systemctl' commands try to execute when systemctl isn't avail. Added test coverage in test_hi.sh. |
||
#10 | 28123 | C. Thomas Tyler |
Configured test to avoid using systemd (which doesn't work in Docker containerized environments). |
||
#9 | 27852 | C. Thomas Tyler | Changed 'scp' to 'cp' so test suite runs on minimalist distros. | ||
#8 | 27419 | C. Thomas Tyler |
Added '-v' option to run verify_sdp.sh with various options. Added test and doc for same. The options to verify_sdp.sh are dependent on options to reset_sdp.sh. Enabled configure_sample_depot_for_sdp.sh to work with non-default mount points. |
||
#7 | 27390 | C. Thomas Tyler |
Added check_log_test() to check log for text from executed command. Added test for limited sudo. Added test for renaming of reset_sdp.sh script. |
||
#6 | 27388 | C. Thomas Tyler |
test_hi.sh v1.3.0: * Improved log handling so test logs remain available for add'l grep checks. * Improved in-code docs. |
||
#5 | 27306 | C. Thomas Tyler |
Adjusted to skip 'crontab' tests on centos6 due to complexity setting up crontab on the Docker image for platform, possibly due to it being EOL already. |
||
#4 | 27304 | C. Thomas Tyler | Test suite robustness improvements, added cront tests back in. | ||
#3 | 27299 | C. Thomas Tyler | Added '-H <hostname>' and '-T <timezone>' options and cfg settings. | ||
#2 | 27289 | C. Thomas Tyler |
Added more tests to test suite. These work with '-o centos7'. |
||
#1 | 27284 | C. Thomas Tyler |
Added Docker test suite to displace Vagrant. Initial version passes with options: hits.sh -o centos7 |