|
|
906690 |
#!/bin/bash
|
|
|
906690 |
#
|
|
|
906690 |
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
906690 |
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
906690 |
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
906690 |
#
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Copyright (c) 2014, Joyent, Inc.
|
|
|
906690 |
#
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# catest: a simple testing tool and framework. See usage below for details.
|
|
|
906690 |
#
|
|
|
906690 |
|
|
|
906690 |
shopt -s xpg_echo
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Global configuration
|
|
|
906690 |
#
|
|
|
906690 |
cat_arg0=$(basename $0) # canonical name of "catest"
|
|
|
906690 |
cat_outbase="catest.$$" # output directory name
|
|
|
906690 |
cat_tstdir="test" # test directory
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Options and arguments
|
|
|
906690 |
#
|
|
|
906690 |
cat_tests="" # list of tests (absolute paths)
|
|
|
906690 |
opt_a=false # run all tests
|
|
|
906690 |
opt_c=false # colorize test results
|
|
|
906690 |
opt_k=false # keep output of successful tests
|
|
|
906690 |
opt_o="/var/tmp" # parent directory for output directory
|
|
|
906690 |
opt_t= # TAP format output file
|
|
|
906690 |
opt_S=false # Non-strict mode for js tests
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Current state
|
|
|
906690 |
#
|
|
|
906690 |
cat_outdir= # absolute path to output directory
|
|
|
906690 |
cat_tapfile= # absolute path of TAP output file
|
|
|
906690 |
cat_ntests= # total number of tests
|
|
|
906690 |
cat_nfailed=0 # number of failed tests run
|
|
|
906690 |
cat_npassed=0 # number of successful tests run
|
|
|
906690 |
cat_nrun=0 # total number of tests run
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Allow environment-specific customizations.
|
|
|
906690 |
#
|
|
|
906690 |
[[ -f $(dirname $0)/catest_init.sh ]] && . $(dirname $0)/catest_init.sh
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# fail MSG: emits the given error message to stderr and exits non-zero.
|
|
|
906690 |
#
|
|
|
906690 |
function fail
|
|
|
906690 |
{
|
|
|
906690 |
echo "$cat_arg0: $@" >&2
|
|
|
906690 |
|
|
|
906690 |
[[ -n $cat_tapfile ]] && echo "Bail out! $@" >> $cat_tapfile
|
|
|
906690 |
|
|
|
906690 |
exit 1
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# usage [MSG]: emits the given message, if any, and a usage message, then exits.
|
|
|
906690 |
#
|
|
|
906690 |
function usage
|
|
|
906690 |
{
|
|
|
906690 |
[[ $# -ne 0 ]] && echo "$cat_arg0: $@\n" >&2
|
|
|
906690 |
|
|
|
906690 |
cat <<USAGE >&2
|
|
|
906690 |
Usage: $cat_arg0 [-k] [-c] [-o dir] [-t file] test1 ...
|
|
|
906690 |
$cat_arg0 [-k] [-c] [-o dir] [-t file] -a
|
|
|
906690 |
|
|
|
906690 |
In the first form, runs specified tests. In the second form, runs all tests
|
|
|
906690 |
found under "$cat_tstdir" of the form "tst*.<ext>" for supported extensions.
|
|
|
906690 |
|
|
|
906690 |
TESTS
|
|
|
906690 |
|
|
|
906690 |
Tests are just files to be executed by some interpreter. In most cases, a
|
|
|
906690 |
test succeeds if it exits successfully and fails otherwise. You can also
|
|
|
906690 |
specify the expected stdout of the test in a file with the same name as the
|
|
|
906690 |
test plus a ".out" suffix, in which case the test will also fail if the
|
|
|
906690 |
actual output does not match the expected output.
|
|
|
906690 |
|
|
|
906690 |
Supported interpreter extensions are "sh" (bash) and "js" (node).
|
|
|
906690 |
|
|
|
906690 |
This framework does not provide per-test setup/teardown facilities, but
|
|
|
906690 |
test files can do whatever they want, including making use of common
|
|
|
906690 |
libraries for setup and teardown.
|
|
|
906690 |
|
|
|
906690 |
TEST OUTPUT
|
|
|
906690 |
|
|
|
906690 |
Summary output is printed to stdout. TAP output can be emitted with "-t".
|
|
|
906690 |
|
|
|
906690 |
Per-test output is placed in a new temporary directory inside the directory
|
|
|
906690 |
specified by the -o option, or /var/tmp if -o is not specified.
|
|
|
906690 |
|
|
|
906690 |
Within the output directory will be a directory for each failed test which
|
|
|
906690 |
includes a README describing why the test failed (e.g., exited non-zero), a
|
|
|
906690 |
copy of the test file itself, the actual stdout and stderr of the test, and
|
|
|
906690 |
the expected stdout of the test (if specified).
|
|
|
906690 |
|
|
|
906690 |
If -k is specified, the output directory will also include a directory for
|
|
|
906690 |
each test that passed including the stdout and stderr from the test.
|
|
|
906690 |
|
|
|
906690 |
The following options may be specified:
|
|
|
906690 |
|
|
|
906690 |
-a Runs all tests under $cat_tstdir
|
|
|
906690 |
(ignores other non-option arguments)
|
|
|
906690 |
-c Color code test result messages
|
|
|
906690 |
-h Output this message
|
|
|
906690 |
-k Keep output from all tests, not just failures
|
|
|
906690 |
-o directory Specifies the output directory for tests
|
|
|
906690 |
(default: /var/tmp)
|
|
|
906690 |
-S Turn off strict mode for tests
|
|
|
906690 |
-t file Emit summary output in TAP format
|
|
|
906690 |
|
|
|
906690 |
USAGE
|
|
|
906690 |
|
|
|
906690 |
exit 2
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# abspath FILE: emits a canonical, absolute path to the given file or directory.
|
|
|
906690 |
#
|
|
|
906690 |
function abspath
|
|
|
906690 |
{
|
|
|
906690 |
local dir=$(dirname $1) base=$(basename $1)
|
|
|
906690 |
|
|
|
906690 |
if [[ $base = ".." ]]; then
|
|
|
906690 |
cd "$dir"/.. > /dev/null || fail "abspath '$1': failed to chdir"
|
|
|
906690 |
pwd
|
|
|
906690 |
cd - > /dev/null || fail "abspath '$1': failed to chdir back"
|
|
|
906690 |
else
|
|
|
906690 |
cd "$dir" || fail "abspath '$1': failed to chdir"
|
|
|
906690 |
echo "$(pwd)/$base"
|
|
|
906690 |
cd - > /dev/null || fail "abspath '$1': failed to chdir back"
|
|
|
906690 |
fi
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# cleanup_test TESTDIR "success" | "failure": cleans up the output directory
|
|
|
906690 |
# for this test
|
|
|
906690 |
#
|
|
|
906690 |
function cleanup_test
|
|
|
906690 |
{
|
|
|
906690 |
local test_odir="$1" result=$2
|
|
|
906690 |
local newdir
|
|
|
906690 |
|
|
|
906690 |
if [[ $result = "success" ]]; then
|
|
|
906690 |
newdir="$(dirname $test_odir)/success.$cat_npassed"
|
|
|
906690 |
else
|
|
|
906690 |
newdir="$(dirname $test_odir)/failure.$cat_nfailed"
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
mv "$test_odir" "$newdir"
|
|
|
906690 |
echo $newdir
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# emit_failure TEST ODIR REASON: indicate that a test has failed
|
|
|
906690 |
#
|
|
|
906690 |
function emit_failure
|
|
|
906690 |
{
|
|
|
906690 |
local test_label=$1 odir=$2 reason=$3
|
|
|
906690 |
|
|
|
906690 |
if [[ $cat_tapfile ]]; then
|
|
|
906690 |
echo "not ok $(($cat_nrun+1)) $test_label" >> $cat_tapfile
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
echo "${TRED}FAILED.${TCLEAR}"
|
|
|
906690 |
echo "$test_path failed: $reason" > "$odir/README"
|
|
|
906690 |
|
|
|
906690 |
[[ -n "$odir" ]] && echo ">>> failure details in $odir\n"
|
|
|
906690 |
((cat_nfailed++))
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# emit_pass TEST: indicate that a test has passed
|
|
|
906690 |
#
|
|
|
906690 |
function emit_pass
|
|
|
906690 |
{
|
|
|
906690 |
local test_label=$1
|
|
|
906690 |
|
|
|
906690 |
if [[ $cat_tapfile ]]; then
|
|
|
906690 |
echo "ok $((cat_nrun+1)) $test_label" >> $cat_tapfile
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
echo "${TGREEN}success.${TCLEAR}"
|
|
|
906690 |
((cat_npassed++))
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Executes a single test
|
|
|
906690 |
#
|
|
|
906690 |
# Per-test actions:
|
|
|
906690 |
# - Make a directory for that test
|
|
|
906690 |
# - cd into that directory and exec the test
|
|
|
906690 |
# - Redirect standard output and standard error to files
|
|
|
906690 |
# - Tests return 0 to indicate success, non-zero to indicate failure
|
|
|
906690 |
#
|
|
|
906690 |
function execute_test
|
|
|
906690 |
{
|
|
|
906690 |
[[ $# -eq 1 ]] || fail "Missing test to execute"
|
|
|
906690 |
local test_path=$1
|
|
|
906690 |
local test_name=$(basename $1)
|
|
|
906690 |
local test_dir=$(dirname $1)
|
|
|
906690 |
local test_label=$(echo $test_path | sed -e s#^$SRC/##)
|
|
|
906690 |
local test_odir="$cat_outdir/test.$cat_nrun"
|
|
|
906690 |
local ext=${test_name##*.}
|
|
|
906690 |
local faildir
|
|
|
906690 |
local EXEC
|
|
|
906690 |
|
|
|
906690 |
echo "Executing test $test_label ... \c "
|
|
|
906690 |
mkdir "$test_odir" >/dev/null || fail "failed to create test directory"
|
|
|
906690 |
cp "$test_path" "$test_odir"
|
|
|
906690 |
|
|
|
906690 |
case "$ext" in
|
|
|
906690 |
"sh") EXEC=bash ;;
|
|
|
906690 |
"js") EXEC=node ;;
|
|
|
906690 |
*) faildir=$(cleanup_test "$test_odir" "failure")
|
|
|
906690 |
emit_failure "$test_label" "$faildir" "unknown file extension"
|
|
|
906690 |
return 0
|
|
|
906690 |
;;
|
|
|
906690 |
esac
|
|
|
906690 |
|
|
|
906690 |
pushd "$test_dir" >/dev/null
|
|
|
906690 |
if [[ $opt_S ]]; then
|
|
|
906690 |
$EXEC $test_name -S >$test_odir/$$.out 2>$test_odir/$$.err
|
|
|
906690 |
else
|
|
|
906690 |
$EXEC $test_name >$test_odir/$$.out 2>$test_odir/$$.err
|
|
|
906690 |
fi
|
|
|
906690 |
execres=$?
|
|
|
906690 |
popd > /dev/null
|
|
|
906690 |
|
|
|
906690 |
if [[ $execres != 0 ]]; then
|
|
|
906690 |
faildir=$(cleanup_test "$test_odir" "failure")
|
|
|
906690 |
emit_failure "$test_label" "$faildir" "test returned $execres"
|
|
|
906690 |
return 0
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
if [[ -f $test_path.out ]] && \
|
|
|
906690 |
! diff $test_path.out $test_odir/$$.out > /dev/null ; then
|
|
|
906690 |
cp $test_path.out $test_odir/$test_name.out
|
|
|
906690 |
faildir=$(cleanup_test "$test_odir" "failure")
|
|
|
906690 |
emit_failure "$test_label" "$faildir" "stdout mismatch"
|
|
|
906690 |
return 0
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
cleanup_test "$test_odir" "success" > /dev/null
|
|
|
906690 |
emit_pass "$test_label"
|
|
|
906690 |
}
|
|
|
906690 |
|
|
|
906690 |
while getopts ":o:t:ackSh?" c $@; do
|
|
|
906690 |
case "$c" in
|
|
|
906690 |
a|c|k|S) eval opt_$c=true ;;
|
|
|
906690 |
o|t) eval opt_$c="$OPTARG" ;;
|
|
|
906690 |
h) usage ;;
|
|
|
906690 |
:) usage "option requires an argument -- $OPTARG" ;;
|
|
|
906690 |
*) usage "invalid option: $OPTARG" ;;
|
|
|
906690 |
esac
|
|
|
906690 |
done
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# If configured to use terminal colors, record the escape sequences here.
|
|
|
906690 |
#
|
|
|
906690 |
if [[ $opt_c == "true" && -t 1 ]]; then
|
|
|
906690 |
TGREEN="$(tput setaf 2)"
|
|
|
906690 |
TRED="$(tput setaf 1)"
|
|
|
906690 |
TCLEAR="$(tput sgr0)"
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
shift $((OPTIND-1))
|
|
|
906690 |
[[ $# -eq 0 && $opt_a == "false" ]] && \
|
|
|
906690 |
usage "must specify \"-a\" or list of tests"
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Initialize paths and other environment variables.
|
|
|
906690 |
#
|
|
|
906690 |
export SRC=$(abspath $(dirname $0)/../..)
|
|
|
906690 |
export PATH=$SRC/deps/ctf2json:$PATH
|
|
|
906690 |
[[ -n $HOST ]] || export HOST=$(hostname)
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# We create and set CATMPDIR as a place for the tests to store temporary files.
|
|
|
906690 |
#
|
|
|
906690 |
export CATMPDIR="/var/tmp/catest.$$_tmpfiles"
|
|
|
906690 |
|
|
|
906690 |
if [[ $opt_a = "true" ]]; then
|
|
|
906690 |
cat_tests=$(find $SRC/$cat_tstdir \
|
|
|
906690 |
-name 'tst*.js' -o -name 'tst*.sh') || \
|
|
|
906690 |
fail "failed to locate tests in $SRC/$cat_tstdir"
|
|
|
906690 |
cat_tests=$(sort <<< "$cat_tests")
|
|
|
906690 |
else
|
|
|
906690 |
for t in $@; do
|
|
|
906690 |
[[ -f $t ]] || fail "cannot find test $t"
|
|
|
906690 |
cat_tests="$cat_tests $(abspath $t)"
|
|
|
906690 |
done
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
mkdir -p "$opt_o/$cat_outbase"
|
|
|
906690 |
cat_outdir=$(abspath $opt_o/$cat_outbase)
|
|
|
906690 |
|
|
|
906690 |
mkdir -p $CATMPDIR || fail "failed to create $CATMPDIR"
|
|
|
906690 |
|
|
|
906690 |
cat_ntests=$(echo $cat_tests | wc -w)
|
|
|
906690 |
printf "Configuration:\n"
|
|
|
906690 |
printf " SRC: $SRC\n"
|
|
|
906690 |
printf " Output directory: $cat_outdir\n"
|
|
|
906690 |
printf " Temp directory: $CATMPDIR\n"
|
|
|
906690 |
if [[ -n "$opt_t" ]]; then
|
|
|
906690 |
cat_tapfile=$(abspath $opt_t)
|
|
|
906690 |
printf " TAP output: $cat_tapfile\n"
|
|
|
906690 |
fi
|
|
|
906690 |
printf " Keep successful test output: $opt_k\n"
|
|
|
906690 |
printf " Found %d test(s) to run\n\n" $cat_ntests
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Validate parameters and finish setup.
|
|
|
906690 |
#
|
|
|
906690 |
[[ $cat_ntests -gt 0 ]] || fail "no tests found"
|
|
|
906690 |
|
|
|
906690 |
if [[ -n "$cat_tapfile" ]]; then
|
|
|
906690 |
echo "1..$(($cat_ntests))" > $cat_tapfile || \
|
|
|
906690 |
fail "failed to emit TAP output"
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Allow for environment-specific customizations. These are optionally loaded
|
|
|
906690 |
# by the catest_init.sh file sourced earlier.
|
|
|
906690 |
#
|
|
|
906690 |
if type catest_init > /dev/null 2>&1 && ! catest_init; then
|
|
|
906690 |
fail "catest_init failed"
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
#
|
|
|
906690 |
# Start the test run.
|
|
|
906690 |
#
|
|
|
906690 |
printf "===================================================\n\n"
|
|
|
906690 |
|
|
|
906690 |
for t in $cat_tests; do
|
|
|
906690 |
execute_test $t
|
|
|
906690 |
((cat_nrun++))
|
|
|
906690 |
done
|
|
|
906690 |
|
|
|
906690 |
printf "\n===================================================\n\n"
|
|
|
906690 |
printf "Results:\n"
|
|
|
906690 |
printf "\tTests passed:\t%2d/%2d\n" $cat_npassed $cat_nrun
|
|
|
906690 |
printf "\tTests failed:\t%2d/%2d\n" $cat_nfailed $cat_nrun
|
|
|
906690 |
printf "\n===================================================\n"
|
|
|
906690 |
|
|
|
906690 |
if [[ $opt_k == "false" ]]; then
|
|
|
906690 |
echo "Cleaning up output from successful tests ... \c "
|
|
|
906690 |
rm -rf $cat_outdir/success.*
|
|
|
906690 |
rm -rf $CATMPDIR
|
|
|
906690 |
echo "done."
|
|
|
906690 |
fi
|
|
|
906690 |
|
|
|
906690 |
exit $cat_nfailed
|