From 60b2f52baff831fa306b19b022ec2feec6e3adaa Mon Sep 17 00:00:00 2001 From: Christian Dietrich Date: Sun, 28 Sep 2014 16:49:03 +0200 Subject: [PATCH] Testsuite as single files --- avr.testsuite.tex | 90 ------------------ tests/FOOTER | 1 + tests/HEADER | 17 ++++ tests/complex-memory.c | 22 +++++ tests/empty-main.c | 10 ++ tests/fibonacci-rec.c | 20 ++++ tests/sum-rec.c | 23 +++++ tests/test-suite | 206 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 299 insertions(+), 90 deletions(-) create mode 100644 tests/FOOTER create mode 100644 tests/HEADER create mode 100644 tests/complex-memory.c create mode 100644 tests/empty-main.c create mode 100644 tests/fibonacci-rec.c create mode 100644 tests/sum-rec.c create mode 100755 tests/test-suite diff --git a/avr.testsuite.tex b/avr.testsuite.tex index 3851a47..85410e2 100644 --- a/avr.testsuite.tex +++ b/avr.testsuite.tex @@ -388,70 +388,6 @@ } \preto\avr@test{\avr@test@ROR} -\begin{filecontents*}{empty-main.c} -int main() { - asm volatile ("break"); -} -\end{filecontents*} - -\def\avr@test@emptymain{% - \avr@test@setup{Empty Main Function}% - \avrloadc{empty-main.c} - \avr@instr@stepn{50} -} -\preto\avr@test{\avr@test@emptymain} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{filecontents*}{sum-rec.c} -#include - -char sum(char n) { - if (n <= 1) { - return n; - } - return n + sum(n-1); -} - -int main() { - UDR = sum(4); - asm volatile ("break"); -} -\end{filecontents*} - -\def\avr@test@sumRec{% - \avr@test@setup{Summing Recursive}% - \avrloadc{sum-rec.c} - \avr@instr@stepn{1000} - \avr@test@REG{r24}{00001010} -} - -\preto\avr@test{\avr@test@sumRec} - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -\begin{filecontents*}{fibonacci-rec.c} -#include - -char fib(char n) { - if (n <= 1) { - return 1; - } - return fib(n-1) + fib(n-2); -} - -int main() { - UDR = fib(5); - asm volatile ("break"); -} -\end{filecontents*} - -\def\avr@test@fibRec{% - \avr@test@setup{Fibonacci Recursive}% - \avrloadc{fibonacci-rec.c} - \avr@instr@stepn{1000} - \avr@test@REG{r24}{00001000} -} -\preto\avr@test{\avr@test@fibRec} - \def\avr@test@LDX{% \avr@test@setup{LDX}% @@ -501,32 +437,6 @@ int main() { } \preto\avr@test{\avr@test@STZ} -\begin{filecontents*}{complex-memory.c} -#include - -volatile char foo[30]; - -int main() { - foo[0] = 23; - foo[1] = 42; - foo[2] = foo[0] + foo[1]; - - asm volatile ("break"); -} -\end{filecontents*} - -\def\avr@test@complexMemory{% - \avr@test@setup{Complex Memory Operations}% - \avrloadc{complex-memory.c} - \avr@instr@stepn{1000} - - \avr@test@MEM{96}{00010111} % 23 - \avr@test@MEM{97}{00101010} % 42 - \avr@test@MEM{98}{01000001} % 65 -} -\preto\avr@test{\avr@test@complexMemory} - - %%% Local Variables: %%% mode: latex %%% TeX-master: "avr.tex" diff --git a/tests/FOOTER b/tests/FOOTER new file mode 100644 index 0000000..815ab68 --- /dev/null +++ b/tests/FOOTER @@ -0,0 +1 @@ +\end{document} \ No newline at end of file diff --git a/tests/HEADER b/tests/HEADER new file mode 100644 index 0000000..a8582db --- /dev/null +++ b/tests/HEADER @@ -0,0 +1,17 @@ +\documentclass{article} +\usepackage{etoolbox} +\usepackage{tabularx} + +\makeatletter +\errorcontextlines=23 + +\input{../avr.numbers} +\input{../avr.binary} +\input{../avr.bitops} +\input{../avr.memory} +\input{../avr.instr} +\input{../avr.io} +\input{../avr.testsuite} + +\begin{document} +\makeatletter diff --git a/tests/complex-memory.c b/tests/complex-memory.c new file mode 100644 index 0000000..a05bfdf --- /dev/null +++ b/tests/complex-memory.c @@ -0,0 +1,22 @@ +#include + +volatile char foo[30]; + +int main() { + foo[0] = 23; + foo[1] = 42; + foo[2] = foo[0] + foo[1]; + + asm volatile ("break"); +} + +/* + check-name: Complex Memory Operations + check-start: + \avr@instr@stepn{1000} + + \avr@test@MEM{96}{00010111} % 23 + \avr@test@MEM{97}{00101010} % 42 + \avr@test@MEM{98}{01000001} % 65 + check-end: +*/ diff --git a/tests/empty-main.c b/tests/empty-main.c new file mode 100644 index 0000000..fa0d0dc --- /dev/null +++ b/tests/empty-main.c @@ -0,0 +1,10 @@ +int main() { + asm volatile ("break"); +} + +/** + check-name: Run simple main Function + check-start: +\avr@instr@stepn{5000} + check-end: +**/ diff --git a/tests/fibonacci-rec.c b/tests/fibonacci-rec.c new file mode 100644 index 0000000..a3f2f6e --- /dev/null +++ b/tests/fibonacci-rec.c @@ -0,0 +1,20 @@ +#include + +char fib(char n) { + if (n <= 1) { + return 1; + } + return fib(n-1) + fib(n-2); +} + +int main() { + UDR = fib(5); + asm volatile ("break"); +} +/* + check-name: Fibonacci (Recursive) + check-start: + \avr@instr@stepn{1000} + \avr@test@REG{r24}{00001000} + check-end: +*/ diff --git a/tests/sum-rec.c b/tests/sum-rec.c new file mode 100644 index 0000000..0fa00fc --- /dev/null +++ b/tests/sum-rec.c @@ -0,0 +1,23 @@ +#include + +char sum(char n) { + if (n <= 1) { + return n; + } + return n + sum(n-1); +} + +int main() { + UDR = sum(4); + asm volatile ("break"); +} + +/* + check-name: Complex Memory Operations + check-start: + + \avr@instr@stepn{1000} + \avr@test@REG{r24}{00001010} + + check-end: +*/ diff --git a/tests/test-suite b/tests/test-suite new file mode 100755 index 0000000..ab2e80f --- /dev/null +++ b/tests/test-suite @@ -0,0 +1,206 @@ +#!/bin/bash + +#set -x + +default_path=".." +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 +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)" + + cp HEADER "$file".tex + echo "\avrloadc{$file}" >> "$file".tex + + awk '/check-start/,/check-end/ {print}' $file \ + | egrep -v 'check-(start|end)' >> "$file".tex + cat FOOTER >> "$file".tex + + + # grab the actual output & exit value + pdflatex -halt-on-error -shell-escape "$file".tex 1> $file.output 2> $file.error + actual_exit_value=$? + rm -f "$file.tex" *.log *.aux *.pdf + + if [ "$actual_exit_value" -ne 0 ]; then + error " Actual exit value does not match the expected one." + error " expected 0, got $actual_exit_value" + tail -n 10 $file.output | sed 's/^/ /' + 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 +} + +pwait() { + # This functions blocks until less than $1 subprocesses are running + jobs="$1" + [ -z "$jobs" ] && jobs=5 + + while [ $(jobs -r | wc -l) -gt "$jobs" ]; do + sleep 0.5 + done +} + +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 +} + +## +# 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 + if test `expr $ko_tests - $known_ko_tests` -gt 0; then + for f in *.error.diff *.output.diff; do + if test -s "$f"; then + echo "Contents of $f:" + cat "$f" + echo "===" + fi + done + exit 1 + fi + ;; + 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 +