commit - a6b35f66241ad24fdd4e12e934bbfc5c7e7e985e
commit + 5bc4ca7fa3c49d5b57406f3872f169737984cc87
blob - 3285332f16238af772bb564dc58f816e6afd7374
blob + dc4a939317c2e7a83d535985ded67c49838312b6
--- lang/c/test.h
+++ lang/c/test.h
* TEST(function, ...);
* RUNT(function, ...);
*
- * fail(fmt, ...);
- *
+ * assert(expression);
* expect(expression);
*
+ * fail(fmt, ...);
+ * rem(fmt, ...);
+ *
+ *
* DESCRIPTION
* The TEST() macro calls the given function as a unit test. Any
* additional arguments will be passed to function, allowing parameterized
* unconditionally and prints the test result to standard output. It does
* not depend on argc and argv being in scope.
*
- * Test functions may be defined with any return type, but the return
- * value is ignored. To signal failure of a test, the fail() macro should
- * be called with an appropriate error message, using printf(3)-style
- * arguments. Any other diagnostics should be printed to stderr as usual.
+ * Test functions may be defined with any return type; their return value
+ * is ignored. To signal failure of a test, the fail() macro should be
+ * called with an appropriate error message, using printf(3)-style
+ * arguments. Diagnostics relating to the failure may be printed to stderr.
*
* The expect() macro tests a boolean condition. It calls fail() if the
* given expression evaluates to false. The user should define custom
* variants of expect() as suitable.
*
- * The fail() macro does not abort the current test unless the X
- * environment variable is set (see below). Checks that always form a
- * precondition for the continuation of the test should use assert(3).
- * Meanwhile, RUNT() calls exit(3) after a failed test returns; see also
- * the K environment variable.
+ * The rem() macro can be used to produce miscellaneous messages; it is
+ * ignored unless V is set. Messages should consist of a single line,
+ * without a trailing newline, and will be printed to stdout prefixed by
+ * a TAB character to maintain a simple TSV format. No other output should
+ * be made to stdout.
*
+ * By default, the fail() macro does not immediately abort the running
+ * test. Checks that are a strict precondition for the continuation of
+ * the test should use assert(3); test.h includes assert.h for
+ * convenience. After a failed test returns, RUNT() normally calls
+ * exit(3), forgoing any remaining tests. See the K and X environment
+ * variables for changing the default behavior.
+ *
* The global variable status is set to 1 upon test failure and should be
- * used to return the correct value from main.
+ * used to return the correct value from main (when K is set).
*
* ENVIRONMENT
* The following variables serve as flags. They enable the stated behavior
* whenever set, regardless of value.
*
- * D Dry run; print tests without executing them.
+ * D Dry run. Print tests without executing them.
*
- * V Print tests that are skipped.
+ * V Verbose. Print any tests that are skipped and enable
+ * informational output from rem().
*
- * K Do not exit after a failed test.
+ * K Keep going after a failed test instead of exiting.
*
- * X Call abort(3) immediately when fail() is called.
+ * X Exit with a call to abort(3) as soon as fail() is called.
*
* EXAMPLES
* The following shows a test program:
failed_ = 1; \
} while (0)
+#define rem(...) do { \
+ if (getenv("V") == NULL) /* V = verbose */ \
+ break; \
+ printf("\t"); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+} while (0)
+
#endif /* TEST_H */
blob - /dev/null
blob + a7f07d8ab51c6619f6ff3f948535293cc4a6a919 (mode 755)
--- /dev/null
+++ tests/lang/c/rem.t
+#!/bin/sh
+
+set -e
+
+unset D V K X
+export CFLAGS=-I../../lang/c
+
+# rem() ignored when not V
+./assert-c 0 \
+ "" \
+ "foo()\tOK\nbar()\tOK\n" \
+ "main\n" \
+<<-EOF
+ #include <stdio.h>
+ #include "test.h"
+
+ void
+ foo(void)
+ {
+ rem("foo called");
+ }
+
+ void
+ bar(void)
+ {
+ rem("bar called");
+ }
+
+ int
+ main(int argc, char *argv[])
+ {
+ fputs("main\n", stderr);
+ TEST(foo);
+ TEST(bar);
+ return 0;
+ }
+EOF
+
+# rem() prints when V set
+V=1 \
+./assert-c 0 \
+ "" \
+ "\tfoo called\nfoo()\tOK\n\tbar called\nbar()\tOK\n" \
+ "main\n" \
+<<-EOF
+ #include <stdio.h>
+ #include "test.h"
+
+ void
+ foo(void)
+ {
+ rem("foo called");
+ }
+
+ void
+ bar(void)
+ {
+ rem("bar called");
+ }
+
+ int
+ main(int argc, char *argv[])
+ {
+ fputs("main\n", stderr);
+ TEST(foo);
+ TEST(bar);
+ return 0;
+ }
+EOF