Commit Diff


commit - 82c5d7ffa2717e040bee77e99df37f811f76eded
commit + 9e8613cdd656dae8a2147f346896043ce7bca20f
blob - /dev/null
blob + ec54dce8f6246aadc8840288e1f4fe2f1a597361 (mode 755)
--- /dev/null
+++ tests/helpers/assert-c
@@ -0,0 +1,45 @@
+#!/bin/sh
+#
+# compile and run a C program given on stdin, pass the given input, and
+# compare output and exit code to expected results. further arguments are
+# passed as arguments to the executable.
+
+if [ $# -lt 4 ]
+then
+	echo "usage: exit assert-c stdin stdout stderr [arg ...]" >&2
+	exit 127
+fi
+
+tst=${tst:-/tmp/assert-c.$$}
+src=$tst.c
+inp=$tst.inp
+out=$tst.out
+err=$tst.err
+expout=$tst.expout
+experr=$tst.experr
+expexit=$1
+
+trap "rm -f $tst $src $inp $out $err $expout $experr" EXIT
+
+cat >$src || exit 127
+echo -n "$2" >$inp
+echo -n "$3" >$expout || exit 127
+echo -n "$4" >$experr || exit 127
+shift 4
+
+${CC:-cc} -o $tst $CFLAGS $LDFLAGS $src $LIBS >&2 || exit 127
+# NB: in the case of a compile error we can't tell why it occurred.
+#     the code under test might not expose an expected API.
+#     or the test could be faulty, the compiler missing, or some other issue.
+
+pass=true
+<$inp >$out 2>$err $tst "$@"
+exit=$?
+diff -u $expout $out >&2 || pass=false
+diff -u $experr $err >&2 || pass=false
+if [ "$exit" -ne "$expexit" ]
+then
+	echo "exit code $exit - expected $expexit" >&2
+	pass=false
+fi
+$pass
blob - /dev/null
blob + b194ce3a4cbd59d332488cb21836f7abd272606b (mode 755)
--- /dev/null
+++ tests/helpers/assert-c-abort
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# similar to assert-c but for to exits due to abort(3), including assert(3).
+# requires the exit code to be (any value) greater than or equal to 128.
+# requires (only) a prefix of stderr to match the given expectation.
+
+if [ $# -lt 3 ]
+then
+	echo "usage: assert-c-abort stdin stdout stderr [arg ...]" >&2
+	exit 127
+fi
+
+tst=${tst:-/tmp/assert-c.$$}
+src=$tst.c
+inp=$tst.inp
+out=$tst.out
+err=$tst.err
+expout=$tst.expout
+experr=$tst.experr
+errpre=$tst.errpre
+core=$(basename "$tst").core
+
+trap "rm -f $tst $src $inp $out $err $expout $experr $errpre $core" EXIT
+
+cat >$src || exit 127
+echo -n "$1" >$inp
+echo -n "$2" >$expout || exit 127
+echo -n "$3" >$experr || exit 127
+shift 3
+
+${CC:-cc} -o $tst $CFLAGS $LDFLAGS $src $LIBS >&2 || exit 127
+# NB: in the case of a compile error we can't tell why it occurred.
+#     the code under test might not expose an expected API.
+#     or the test could be faulty, the compiler missing, or some other issue.
+
+nerr=$(wc -l <$experr)
+[ $? -eq 0 ] || exit 127
+nerr=$(echo $nerr)			# strips whitespace
+
+pass=true
+<$inp >$out 2>$err $tst "$@"
+exit=$?
+head -n $nerr $err >$errpre || exit 127
+diff -u $expout $out >&2 || pass=false
+diff -u $experr $errpre >&2 || pass=false
+if [ "$exit" -lt 128 ]
+then
+	echo "exit code $exit - expected 128 or greater" >&2
+	pass=false
+fi
+$pass
blob - /dev/null
blob + e357e755fde21db1d3fdefe8daa426d1109757c9 (mode 755)
--- /dev/null
+++ tests/lang/c/RUNT-argcv.t
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"foo called\nbar called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	void
+	runtests(void)
+	{
+		/* argc, argv not needed */
+		RUNT(foo);
+		RUNT(bar);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		runtests();
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 58bff5ea7a6d512ffd048b2920b4eca2c71f94b5 (mode 755)
--- /dev/null
+++ tests/lang/c/RUNT-args.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo(0x01)\tOK\nbar(\"x y z\")\tOK\n" \
+	"foo(1) called\nbar(\"x y z\") called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(int i)
+	{
+		fprintf(stderr, "foo(%d) called\n", i);
+	}
+
+	void
+	bar(const char *s)
+	{
+		fprintf(stderr, "bar(\"%s\") called\n", s);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		RUNT(foo, 0x01);
+		RUNT(bar, "x y z");
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 7d9884a039ea032514ba31232c306b7d7d563653 (mode 755)
--- /dev/null
+++ tests/lang/c/RUNT-dryrun.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+export D=1
+exec ./assert-c 0 \
+	"" \
+	"foo()\nbar()\n" \
+	"" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		RUNT(foo);
+		RUNT(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + d970873a45d9d23aacd58a1a66be094a60f21c83 (mode 755)
--- /dev/null
+++ tests/lang/c/RUNT.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"foo called\nbar called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		RUNT(foo);
+		RUNT(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 45f6e7c571ed29a759209fc16c59532c62793cb4 (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-args.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo(0x01)\tOK\nbar(\"x y z\")\tOK\n" \
+	"foo(1) called\nbar(\"x y z\") called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(int i)
+	{
+		fprintf(stderr, "foo(%d) called\n", i);
+	}
+
+	void
+	bar(const char *s)
+	{
+		fprintf(stderr, "bar(\"%s\") called\n", s);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo, 0x01);
+		TEST(bar, "x y z");
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 11481d6b28d81268043e638f9e94c1abce9a2514 (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-dryrun.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+export D=1
+exec ./assert-c 0 \
+	"" \
+	"foo()\nbar()\n" \
+	"" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 03de7bd387b8fcc262304d6c1365caee21384e2b (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-select.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\n" \
+	"foo called\n" \
+	fo \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + e0d67b096ffb78d29056ddf35fa025624ea4ef0d (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-stdin.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"xxxxxxxx\n" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"foo called\nbar called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 0b3fd763f04c730593d1414e2814da5face5e036 (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-type.t
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"foo called\nbar called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	int
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+		return 23;
+	}
+
+	const char *
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+		return "hallo";
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 3e218cea7fc6c5d087c507b878114e11e439678b (mode 755)
--- /dev/null
+++ tests/lang/c/TEST-verbose.t
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+export V=1
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tskipped\n" \
+	"foo called\n" \
+	fo \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 0653cd8bf21dde49f881b2427d9199224dea06dc (mode 755)
--- /dev/null
+++ tests/lang/c/TEST.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"foo called\nbar called\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fputs("foo called\n", stderr);
+	}
+
+	void
+	bar(void)
+	{
+		fputs("bar called\n", stderr);
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 73a4d13e5fd005108bd97ac8064d23c3d9e4bf4c (mode 755)
--- /dev/null
+++ tests/lang/c/expect-abort.t
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/$(basename "$0").$$
+export CFLAGS=-I../../lang/c
+export X=1
+exec ./assert-c-abort \
+	"" \
+	"" \
+	"$tst.c:7: condition failed: 2 == 3\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		expect(2 == 3);			/* aborts with X set */
+		fputs("foo running\n", stderr);	/* should not print */
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail and abort */
+		TEST(bar);	/* will not execute */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 19144d3739a05efa84e9de14c155923838db56b2 (mode 755)
--- /dev/null
+++ tests/lang/c/expect-false.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+exec ./assert-c 1 \
+	"" \
+	"foo()\tFAIL\n" \
+	"$tst.c:7: condition failed: 2 == 3\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		expect(2 == 3);
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail */
+		TEST(bar);	/* will not execute without K set */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 755833d5d4a854fa699a33f6e045488f751fc6c8 (mode 755)
--- /dev/null
+++ tests/lang/c/expect-noabort.t
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+exec ./assert-c 1 \
+	"" \
+	"foo()\tFAIL\n" \
+	"$tst.c:7: condition failed: 2 == 3\n$tst.c:9: condition failed: 0\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		expect(2 == 3);		/* will print an error */
+		expect(3 == 3);
+		expect(0);		/* will print an error */
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail */
+		TEST(bar);	/* will not execute without K set */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 875b6868d0a2d61a534b8fcfecf33a9e4d275222 (mode 755)
--- /dev/null
+++ tests/lang/c/expect-true.t
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+exec ./assert-c 0 \
+	"" \
+	"foo()\tOK\nbar()\tOK\n" \
+	"" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		expect(2 == 2);
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);
+		TEST(bar);
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 4f7ae2be169da60e8c3f4fbf9acff7ab190e1b7d (mode 755)
--- /dev/null
+++ tests/lang/c/fail-abort.t
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/$(basename "$0").$$
+export CFLAGS=-I../../lang/c
+export X=1
+exec ./assert-c-abort \
+	"" \
+	"" \
+	"$tst.c:7: foo failed\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fail("foo failed");		/* aborts with X set */
+		fputs("foo running\n", stderr);	/* should not print */
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail and abort */
+		TEST(bar);	/* will not execute */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 8b8a650c57ea1d7c6ba6e9615c3d0ee99a18d024 (mode 755)
--- /dev/null
+++ tests/lang/c/fail-fmt.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+exec ./assert-c 1 \
+	"" \
+	"foo(23)\tFAIL\n" \
+	"$tst.c:7: foo(23) failed\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(int i)
+	{
+		fail("foo(%d) failed", i);
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo, 23);	/* expected to fail */
+		TEST(bar);	/* will not execute without K set */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + 354f0380a47f2d49b04acf91b6fdd39cb163aa7b (mode 755)
--- /dev/null
+++ tests/lang/c/fail-keepgoing.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+export K=1
+exec ./assert-c 0 \
+	"" \
+	"foo()\tFAIL\nbar()\tOK\n" \
+	"$tst.c:7: foo failed\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fail("foo failed");
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail */
+		TEST(bar);	/* will still execute with K set */
+		return 0;	/* with K, we will exit 0! */
+	}
+EOF
blob - /dev/null
blob + 73f938d42271af687fd144b80740691fd9dea0b5 (mode 755)
--- /dev/null
+++ tests/lang/c/fail-noabort.t
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+exec ./assert-c 1 \
+	"" \
+	"foo()\tFAIL\n" \
+	"$tst.c:7: foo failed\nfoo running\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fail("foo failed");		/* does not abort */
+		fputs("foo running\n", stderr);	/* this should still print */
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail */
+		TEST(bar);	/* will not execute without K set */
+		return 0;
+	}
+EOF
blob - /dev/null
blob + bffaa1fb384fb56ece9a72f01bd1eb1519469744 (mode 755)
--- /dev/null
+++ tests/lang/c/fail.t
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+unset D V K X
+export tst=/tmp/fail.t.$$
+export CFLAGS=-I../../lang/c
+exec ./assert-c 1 \
+	"" \
+	"foo()\tFAIL\n" \
+	"$tst.c:7: foo failed\n" \
+<<-EOF
+	#include <stdio.h>
+	#include "test.h"
+
+	void
+	foo(void)
+	{
+		fail("foo failed");
+	}
+
+	void
+	bar(void)
+	{
+	}
+
+	int
+	main(int argc, char *argv[])
+	{
+		TEST(foo);	/* expected to fail */
+		TEST(bar);	/* will not execute without K set */
+		return 0;
+	}
+EOF