| #!/bin/sh |
| |
| #set -x |
| |
| default_path=".." |
| default_cmd="sparse \$file" |
| tests_list=`find . -name '*.c' | sed -e 's#^\./\(.*\)#\1#' | sort` |
| prog_name=`basename $0` |
| |
| # counts: |
| # - tests that have not been converted to test-suite format |
| # - tests that passed |
| # - tests that failed |
| # - tests that failed but are known to fail |
| unhandled_tests=0 |
| ok_tests=0 |
| ko_tests=0 |
| known_ko_tests=0 |
| |
| # defaults to not verbose |
| [ -z "$V" ] && V=0 |
| |
| ## |
| # get_value(key, file) - gets the value of a (key, value) pair in file. |
| # |
| # returns 0 on success, 1 if the file does not have the key |
| get_value() |
| { |
| last_result=`grep $1: $2 | sed -e "s/^.*$1:\(.*\)$/\1/"` |
| [ -z "$last_result" ] && return 1 |
| return 0 |
| } |
| |
| ## |
| # get_tag(key, file) - does file has the tag key in it ? |
| # |
| # returns 0 if present, 1 otherwise |
| get_tag() |
| { |
| last_result=`grep $1 $2` |
| return $? |
| } |
| |
| ## |
| # verbose(string) - prints string if we are in verbose mode |
| verbose() |
| { |
| [ "$V" -eq "1" ] && echo " $1" |
| return 0 |
| } |
| |
| ## |
| # error(string[, die]) - prints an error and exits with value die if given |
| error() |
| { |
| echo "error: $1" |
| [ -n "$2" ] && exit $2 |
| return 0 |
| } |
| |
| do_usage() |
| { |
| echo "$prog_name - a tiny automatic testing script" |
| echo "Usage: $prog_name [command] [command arguments]" |
| echo |
| echo "commands:" |
| echo " none runs the whole test suite" |
| echo " single file runs the test in 'file'" |
| echo " format file [name [cmd]] helps writing a new test case using cmd" |
| echo |
| echo " help prints usage" |
| } |
| |
| ## |
| # do_test(file) - tries to validate a test case |
| # |
| # it "parses" file, looking for check-* tags and tries to validate |
| # the test against an expected result |
| # returns: |
| # - 0 if the test passed, |
| # - 1 if it failed, |
| # - 2 if it is not a "test-suite" test. |
| do_test() |
| { |
| test_failed=0 |
| file="$1" |
| |
| # can this test be handled by test-suite ? |
| # (it has to have a check-name key in it) |
| get_value "check-name" $file |
| if [ "$?" -eq 1 ]; then |
| echo "warning: test '$file' unhandled" |
| unhandled_tests=`expr $unhandled_tests + 1` |
| return 2 |
| fi |
| test_name=$last_result |
| |
| echo " TEST $test_name ($file)" |
| |
| # does the test provide a specific command ? |
| cmd=`eval echo $default_path/$default_cmd` |
| get_value "check-command" $file |
| if [ "$?" -eq "0" ]; then |
| last_result=`echo $last_result | sed -e 's/^ *//'` |
| cmd=`eval echo $default_path/$last_result` |
| fi |
| verbose "Using command : $cmd" |
| |
| # grab the expected exit value |
| get_value "check-exit-value" $file |
| if [ "$?" -eq "0" ]; then |
| expected_exit_value=`echo $last_result | tr -d ' '` |
| else |
| expected_exit_value=0 |
| fi |
| verbose "Expecting exit value: $expected_exit_value" |
| |
| # grab the expected output |
| sed -n '/check-output-start/,/check-output-end/p' $file \ |
| | grep -v check-output > "$file".output.expected |
| sed -n '/check-error-start/,/check-error-end/p' $file \ |
| | grep -v check-error > "$file".error.expected |
| |
| # grab the actual output & exit value |
| $cmd 1> $file.output.got 2> $file.error.got |
| actual_exit_value=$? |
| |
| for stream in output error; do |
| diff -u "$file".$stream.expected "$file".$stream.got > "$file".$stream.diff |
| if [ "$?" -ne "0" ]; then |
| error "actual $stream text does not match expected $stream text." |
| error "see $file.$stream.* for further investigation." |
| cat "$file".$stream.diff |
| test_failed=1 |
| fi |
| done |
| |
| if [ "$actual_exit_value" -ne "$expected_exit_value" ]; then |
| error "Actual exit value does not match the expected one." |
| error "expected $expected_exit_value, got $actual_exit_value." |
| test_failed=1 |
| fi |
| |
| if [ "$test_failed" -eq "1" ]; then |
| ko_tests=`expr $ko_tests + 1` |
| get_tag "check-known-to-fail" $file |
| if [ "$?" -eq "0" ]; then |
| echo "info: test '$file' is known to fail" |
| known_ko_tests=`expr $known_ko_tests + 1` |
| fi |
| return 1 |
| else |
| ok_tests=`expr $ok_tests + 1` |
| return 0 |
| fi |
| } |
| |
| do_test_suite() |
| { |
| for i in $tests_list; do |
| do_test "$i" |
| done |
| |
| # prints some numbers |
| tests_nr=`expr $ok_tests + $ko_tests` |
| echo -n "Out of $tests_nr tests, $ok_tests passed, $ko_tests failed" |
| echo " ($known_ko_tests of them are known to fail)" |
| if [ "$unhandled_tests" -ne "0" ]; then |
| echo "$unhandled_tests tests could not be handled by $prog_name" |
| fi |
| } |
| |
| ## |
| # do_format(file[, name[, cmd]]) - helps a test writer to format test-suite tags |
| do_format() |
| { |
| if [ -z "$2" ]; then |
| fname="$1" |
| fcmd=$default_cmd |
| elif [ -z "$3" ]; then |
| fname="$2" |
| fcmd=$default_cmd |
| else |
| fname="$2" |
| fcmd="$3" |
| fi |
| file="$1" |
| cmd=`eval echo $default_path/$fcmd` |
| $cmd 1> $file.output.got 2> $file.error.got |
| fexit_value=$? |
| cat <<_EOF |
| /* |
| * check-name: $fname |
| _EOF |
| if [ "$fcmd" != "$default_cmd" ]; then |
| echo " * check-command: $fcmd" |
| fi |
| if [ "$fexit_value" -ne "0" ]; then |
| echo " * check-exit-value: $fexit_value" |
| fi |
| for stream in output error; do |
| if [ -s "$file.$stream.got" ]; then |
| echo " *" |
| echo " * check-$stream-start" |
| cat "$file.$stream.got" |
| echo " * check-$stream-end" |
| fi |
| done |
| echo " */" |
| return 0 |
| } |
| |
| ## |
| # arg_file(filename) - checks if filename exists |
| arg_file() |
| { |
| [ -z "$1" ] && { |
| do_usage |
| exit 1 |
| } |
| [ -e "$1" ] || { |
| error "Can't open file $1" |
| exit 1 |
| } |
| return 0 |
| } |
| |
| case "$1" in |
| '') |
| do_test_suite |
| ;; |
| single) |
| arg_file "$2" |
| do_test "$2" |
| case "$?" in |
| 0) echo "$2 passed !";; |
| 1) echo "$2 failed !";; |
| 2) echo "$2 can't be handled by $prog_name";; |
| esac |
| ;; |
| format) |
| arg_file "$2" |
| do_format "$2" "$3" "$4" |
| ;; |
| help | *) |
| do_usage |
| exit 1 |
| ;; |
| esac |
| |
| exit 0 |
| |