#!/bin/bash set -u function msg () { echo -e "$*"; } function vmsg () { [[ "$Verbosity" -ge 4 ]] && msg "$*"; } function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; } function bail () { errmsg "${1:-Unknown Error}"; exit "${2:-255}"; } #------------------------------------------------------------------------------ # 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 { 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] or $ThisScript [-h|-man|-V] " if [[ $style == -man ]]; then msg " DESCRIPTION: This is the test suite for the Directory Structure Image (DSI) utility. 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 on' to enable logging using a default log file name: /tmp/$ThisScript.v$Version.<datestamp>.log By default, logging is disabled. 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, expectedExitCode, expectedInOutput) # $1 - command to execute, required # $2 - expected exit code, default 0 # $3 - snippet of text to 'grep -q -E' for in output to pass. # The '-E' allows regex pattern greps, e.g. for "(this|that)" # # Tests passes if command executes and returns expected exit code. # If $3 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 () { declare testCmd="${1:-Unset}" declare -i expectedExitCode="${2:-0}" declare expectedInOutput="${3:-}" declare -i exitCode=0 [[ "$testCmd" == Unset ]] && bail "TEST ERROR: No test specified." TestID+=1 msg "${H2}\\nTEST $TestID, running: $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 terminate, run on termination. #------------------------------------------------------------------------------ function terminate () { trap - EXIT SIGINT SIGTERM [[ "${Log}" != off ]] && msg "\\nLog is: $Log\\n${H1}" [[ -r "$TmpFile" ]] && /bin/rm -f "$TmpFile" exit "$OverallExitCode" } #------------------------------------------------------------------------------ # Declarations and Environment Setup #------------------------------------------------------------------------------ declare ThisScript=${0##*/} declare ThisUser= declare ThisHost= declare Version="1.2.0" declare Log="off" declare CfgFile="test_dsi.cfg" declare Verbosity=3 declare TmpFile= declare H1="==============================================================================\\n" declare H2="------------------------------------------------------------------------------\\n" declare -i ErrorCount=0 declare -i TestID=0 declare -i SilentMode=0 declare -i OverallExitCode=0 TmpFile="$(mktemp)" #------------------------------------------------------------------------------ # 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;; (-c) CfgFile="$2"; shiftArgs=1;; (-L) Log="$2"; shiftArgs=1;; (-si) SilentMode=1;; (-D) 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" == "off" && "$SilentMode" -eq 1 ]] &&\ bail "Usage Error: The '-L off' and '-si' options are mutually exclusive." [[ "$Log" == "on" ]] && Log="/tmp/$ThisScript.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 fi [[ "${Log}" != off ]] && msg "${H1}Log is: $Log" ThisUser=$(whoami) ThisHost=${HOSTNAME%%.*} msg "Started ${0##*/} v$Version as $ThisUser@$ThisHost at $(date)." if source "$CfgFile"; then msg "\\nLoaded test configuration file: $CfgFile" else bail "Failed to load test configuration file: $CfgFile" fi # Include ../src in PATH. export PATH="${PWD%/*}/src:$PATH" unset DSI_STORAGE DSI_TAG msg "Test Prep" /bin/rm -rf ${TestBaseDir}/storage/s* msg "$H1\\nStarting Version check test." run_test_cmd 'dsi -V' 1 'dsi v' msg "$H1\\nBad Usage Tests, with DSI_STORAGE and DSI_TAG unset.\\n" run_test_cmd 'dsi t' 1 'No storage dir defined.' run_test_cmd 'dsi c' 1 'For Create mode, specify .* or set DSI_TAG' run_test_cmd 'dsi c fgs' 1 'No storage dir defined' run_test_cmd 'dsi rm fgs' 1 'For Remove mode specify' run_test_cmd 'dsi rm fgs -s /tmp' 1 'For Remove mode specify ' run_test_cmd 'dsi rm -s /tmp' 1 'For Remove mode specify' run_test_cmd 'dsi rm' 1 'For Remove mode specify' run_test_cmd 'dsi rmall' 1 'For RemoveAll mode specify' run_test_cmd 'dsi rmall fgs@2' 1 'For Remove All mode specify only' run_test_cmd 'dsi l' 1 'For List mode, specify .* or set DSI_TAG.' run_test_cmd 'dsi d' 1 'For Diff mode, specify .* or set DSI_TAG.' msg "$H1\\nNormal Flow Tests with DSI_STORAGE and DSI_TAG unset.\\n" run_test_cmd 'dsi i' 0 'Package Root:' run_test_cmd 'dsi c fgs' 1 'No storage dir defined' run_test_cmd "dsi c fgs -i -s ${TestBaseDir}/storage/s1" 0 'Creating image for DSI tag fgs' export DSI_STORAGE="${TestBaseDir}/storage/s1" msg "Test Note: DSI_STORAGE now set to $DSI_STORAGE" run_test_cmd 'dsi c fgs' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi l fgs' 0 'Listing images for fgs' run_test_cmd 'dsi d fgs' 0 'Diffing image against fgs@LATEST' run_test_cmd 'dsi c fgs' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi c fgs' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi l fgs' 0 'Listing images for fgs' run_test_cmd 'dsi d fgs@2a' 1 'Value for revision .* must be LATEST or a positive integer' run_test_cmd 'dsi d fgs@2' 0 'Diffing image against fgs@2' run_test_cmd 'dsi rm fgs@LATEST' 0 'Removing image fgs@LATEST' run_test_cmd 'dsi l fgs' 0 'Listing images for fgs' run_test_cmd 'dsi rmall fgs' 0 'Removing all images for fgs' export DSI_TAG="fgs" msg "$H1\\nNormal Flow Tests with:\\n\\tDSI_STORAGE=$DSI_STORAGE\\n\\tDSI_TAG=$DSI_TAG\\n" run_test_cmd 'dsi l' 0 'Listing images for fgs' run_test_cmd 'dsi c' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi l' 0 'Listing images for fgs' run_test_cmd 'dsi d' 0 'Diffing image against fgs@LATEST' run_test_cmd 'dsi c' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi c' 0 'Creating image for DSI tag fgs' run_test_cmd 'dsi l' 0 'Listing images for fgs' run_test_cmd 'dsi d fgs@2' 0 'Diffing image against fgs@2' run_test_cmd 'dsi rm fgs@LATEST' 0 'Removing image fgs@LATEST' run_test_cmd 'dsi rm fgs@LATEST' 0 'Removing image fgs@LATEST' run_test_cmd 'dsi l' 0 'Listing images for fgs' run_test_cmd 'dsi rmall fgs' 0 'Removing all images for fgs' 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 | |
---|---|---|---|---|---|
#6 | 28093 | C. Thomas Tyler | Added stub functions. | ||
#5 | 27868 | C. Thomas Tyler |
Enhanced test suite to use a config file so tests can be easily run in a wide range of environments. |
||
#4 | 26937 | C. Thomas Tyler | Added packge format file, other work in progess. | ||
#3 | 26936 | C. Thomas Tyler |
Added 'Info' and 'Tags' modes, and tests for each. Enahnced fast usage message showing details of each mode. Enhanced command line processing and commmad line verification. |
||
#2 | 26752 | C. Thomas Tyler |
Adjustements to pass shellcheck. Test suite output is now more verbose. |
||
#1 | 26750 | C. Thomas Tyler |
Populate -f -o ... //dsi/dev/.... |
||
//guest/tom_tyler/sw/main/dsi/test/test_dsi.sh | |||||
#4 | 24918 | C. Thomas Tyler |
Converted mode and tag/rev arguments to not require flags, to simplfy usage. Adjusted tests accordingly. |
||
#3 | 24894 | Perforce maintenance |
Added DSI_TAG and DSI_DIR vers. Added verify_rev_format() and a test for it. Added more tests, including test for new verify_rev_format() function. |
||
#2 | 24892 | Perforce maintenance | Added test for bad usage with no args. | ||
#1 | 24887 | Perforce maintenance | Added test suite. |