commit - 5bc4ca7fa3c49d5b57406f3872f169737984cc87
commit + be897a7b9bdff1a8faae3850d96d39a03ef75bb0
blob - 4387b4bc96d75f771e7e6cc1220532f315c101e7
blob + ed698719d8f3a01b6f046d3b6e78dd389d8b1db2
--- exercise.1
+++ exercise.1
-.Dd May 25, 2025
+.Dd July 23, 2025
.Dt EXERCISE 1
.Os
.
double quotes.
.
.Sh SEE ALSO
-.Xr sh 1
+.Xr sh 1 ,
+.Xr test.h 3
.
.Sh AUTHORS
.An Sven M. Hallberg Aq Mt pesco@khjk.org
blob - dc4a939317c2e7a83d535985ded67c49838312b6
blob + b1f35683ba3b436400f30fe3c12a5280615f9b80
--- lang/c/test.h
+++ lang/c/test.h
-/* test.h - terribly simple tests in plain C
+/*
+ * test.h - terribly simple tests in plain C
* pesco 2020, 2024, 2025
* ISC license
- *
- * SYNOPSIS
- * #include "test.h"
- *
- * static int status;
- *
- * TEST(function, ...);
- * RUNT(function, ...);
- *
- * 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
- * families of tests.
- *
- * TEST() is meant to be called from main() and inspects argc/argv. The
- * command line should consist (only) of string prefixes that select the
- * corresponding tests. An empty command line selects all tests. Any
- * selected tests are passed to RUNT(). The RUNT() macro executes a test
- * 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; 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 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 (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.
- *
- * V Verbose. Print any tests that are skipped and enable
- * informational output from rem().
- *
- * K Keep going after a failed test instead of exiting.
- *
- * X Exit with a call to abort(3) as soon as fail() is called.
- *
- * EXAMPLES
- * The following shows a test program:
- *
- * #include "test.h"
- *
- * void foo(void)
- * {
- * expect(1 == 1);
- * }
- *
- * void bar(unsigned int mask)
- * {
- * expect(0x01 & mask != 0);
- * expect(0x10 & mask != 0);
- * }
- *
- * int main(int argc, char **argv)
- * {
- * TEST(foo);
- * TEST(bar, 0x0f);
- * TEST(bar, 0xff);
- *
- * return status;
- * }
- *
- * To run only the 'bar' family of tests:
- *
- * $ ./test bar
- * bar(0xff) OK
- * test.c:11: condition failed: (0x10 & mask) != 0
- * bar(0x0f) FAIL
- *
- * Running 'foo' and 'bar(0xff)':
- *
- * $ ./test foo bar\(0xf
- * foo() OK
- * bar(0xff) OK
- *
- * A list or count of tests matching a given selection can be produced by
- * issuing a dry run:
- *
- * $ D=1 ./test
- * foo()
- * bar(0xff)
- * bar(0x0f)
- *
- * $ D=1 ./test bar | wc -l
- * 2
*/
#ifndef TEST_H
blob - /dev/null
blob + d3d345769acbfc6d5784598262b8b669269bbd7f (mode 644)
--- /dev/null
+++ test.h.3
+.Dd July 23, 2025
+.Dt TEST.H 3
+.Os
+.
+.Sh NAME
+.Nm test.h
+.Nd terribly simple tests in plain C
+.
+.Sh SYNOPSIS
+.In test.h
+.Vt static int status;
+.Fn TEST function ...
+.Fn RUNT function ...
+.Fn expect expression
+.Fn fail fmt ...
+.Fn rem fmt ...
+.
+.Sh DESCRIPTION
+The
+.Fn TEST
+macro calls the given function as a test.
+Any additional arguments are be passed through to
+.Ar function ,
+allowing parameterized families of tests.
+.Pp
+.Fn TEST
+is meant to be called from
+.Fn main
+and inspects
+.Va argc
+and
+.Va argv .
+The command line should consist (only) of string prefixes
+that select the corresponding tests.
+An empty command line selects all tests.
+Each selected test is passed to the
+.Fn RUNT
+macro.
+.Pp
+.Fn RUNT
+unconditionally executes the given test
+and prints its result to standard output.
+It does not depend on
+.Va argc
+and
+.Va argv
+being in scope.
+.Pp
+Test functions may be defined with any return type;
+their return value is ignored.
+To signal failure of a test, the
+.Fn fail
+macro should be called with an appropriate error message, using
+.Xr printf 3 Ns
+-style arguments.
+Diagnostics relating to the failure may be printed to
+.Va stderr .
+.Pp
+The
+.Fn expect
+macro tests a boolean condition.
+It calls
+.Fn fail
+if the given expression evaluates to false.
+The user should define custom variants of
+.Fn expect
+as suitable.
+.Pp
+The
+.Fn rem
+macro can be used to produce miscellaneous messages;
+it is ignored unless
+.Ev V
+is set.
+Messages should consist of a single line,
+without a trailing newline,
+and will be printed to
+.\"Va stdout
+standard output
+prefixed by a TAB character to maintain a simple TSV format.
+No other output should be made to
+.Va stdout .
+.Pp
+By default, calling
+.Fn fail
+does not immediately abort the running test.
+Checks that are a strict precondition for the continuation of
+the test should use
+.Xr assert 3
+\(em
+.Pa test.h
+includes
+.In assert.h for convenience.
+After a failed test returns,
+.Fn RUNT
+normally calls
+.Xr exit 3 ,
+forgoing any remaining tests.
+See the
+.Ev K
+and
+.Ev X
+environment variables for changing the default behavior.
+.Pp
+The global variable
+.Va status
+is set to 1 upon test failure and should be
+used to return the correct value from main (when
+.Ev K
+is set).
+.
+.Sh ENVIRONMENT
+The following variables serve as flags.
+They enable the stated behavior whenever set, regardless of value.
+.Bl -tag -width 3n
+.It Ev D
+Dry run.
+Print tests without executing them.
+.It Ev V
+Verbose.
+Print any tests that are skipped and enable informational output from
+.Fn rem .
+.It Ev K
+Keep going after a failed test instead of exiting.
+.It Ev X
+Exit with a call to
+.Xr abort 3
+as soon as
+.Fn fail
+is called.
+.El
+.
+.Sh EXAMPLES
+The following shows a test program consisting of two test functions,
+one parameterized over an
+.Vt unsigned int ,
+for a total of three test cases.
+.Bd -literal -offset Ds
+#include "test.h"
+
+void
+foo(void)
+{
+ expect(1 == 1);
+}
+
+void
+bar(unsigned int mask)
+{
+ expect(0x01 & mask != 0);
+ expect(0x10 & mask != 0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ TEST(foo);
+ TEST(bar, 0x0f);
+ TEST(bar, 0xff);
+
+ return status;
+}
+.Ed
+.Pp
+To run only the
+.Sq bar
+family of tests:
+.Bd -literal -offset Ds
+$ ./test bar
+bar(0xff) OK
+test.c:11: condition failed: (0x10 & mask) != 0
+bar(0x0f) FAIL
+.Ed
+.Pp
+Running
+.Sq foo
+and
+.Sq bar(0xff) :
+.Bd -literal -offset Ds
+$ ./test foo bar\\(0xf
+foo() OK
+bar(0xff) OK
+.Ed
+.Pp
+A list or count of tests matching a given selection can be produced by
+issuing a dry run:
+.Bd -literal -offset Ds
+$ D=1 ./test
+foo()
+bar(0xff)
+bar(0x0f)
+
+$ D=1 ./test bar | wc -l
+2
+.Ed
+.
+.Sh SEE ALSO
+.Xr abort 3 ,
+.Xr assert 3 ,
+.Xr printf 3
+.
+.Sh AUTHORS
+.An Sven M. Hallberg Aq Mt pesco@khjk.org