@@ -92,5 +92,38 @@ int cmd__example_tap(int argc, const char **argv)
test_res = TEST(t_empty(), "test with no checks");
TEST(check_int(test_res, ==, 0), "test with no checks returns 0");
+ if (TEST_RUN("TEST_RUN passing test"))
+ check_int(1, ==, 1);
+ if (TEST_RUN("TEST_RUN failing test"))
+ check_int(1, ==, 2);
+ if (TEST_RUN("TEST_RUN passing TEST_TODO()"))
+ TEST_TODO(check(0));
+ if (TEST_RUN("TEST_RUN failing TEST_TODO()"))
+ TEST_TODO(check(1));
+ if (TEST_RUN("TEST_RUN test_skip()")) {
+ check(0);
+ test_skip("missing prerequisite");
+ check(1);
+ }
+ if (TEST_RUN("TEST_RUN test_skip() inside TEST_TODO()"))
+ TEST_TODO((test_skip("missing prerequisite"), 1));
+ if (TEST_RUN("TEST_RUN TEST_TODO() after failing check")) {
+ check(0);
+ TEST_TODO(check(0));
+ }
+ if (TEST_RUN("TEST_RUN failing check after TEST_TODO()")) {
+ check(1);
+ TEST_TODO(check(0));
+ check(0);
+ }
+ if (TEST_RUN("TEST_RUN messages from failing string and char comparison")) {
+ check_str("\thello\\", "there\"\n");
+ check_str("NULL", NULL);
+ check_char('a', ==, '\n');
+ check_char('\\', ==, '\'');
+ }
+ if (TEST_RUN("TEST_RUN test with no checks"))
+ ; /* nothing */
+
return test_done();
}
@@ -40,4 +40,37 @@ not ok 17 - messages from failing string and char comparison
# BUG: test has no checks at t/helper/test-example-tap.c:92
not ok 18 - test with no checks
ok 19 - test with no checks returns 0
-1..19
+ok 20 - TEST_RUN passing test
+# check "1 == 2" failed at t/helper/test-example-tap.c:98
+# left: 1
+# right: 2
+not ok 21 - TEST_RUN failing test
+not ok 22 - TEST_RUN passing TEST_TODO() # TODO
+# todo check 'check(1)' succeeded at t/helper/test-example-tap.c:102
+not ok 23 - TEST_RUN failing TEST_TODO()
+# check "0" failed at t/helper/test-example-tap.c:104
+# skipping test - missing prerequisite
+# skipping check '1' at t/helper/test-example-tap.c:106
+ok 24 - TEST_RUN test_skip() # SKIP
+# skipping test - missing prerequisite
+ok 25 - TEST_RUN test_skip() inside TEST_TODO() # SKIP
+# check "0" failed at t/helper/test-example-tap.c:111
+not ok 26 - TEST_RUN TEST_TODO() after failing check
+# check "0" failed at t/helper/test-example-tap.c:117
+not ok 27 - TEST_RUN failing check after TEST_TODO()
+# check "!strcmp("\thello\\", "there\"\n")" failed at t/helper/test-example-tap.c:120
+# left: "\011hello\\"
+# right: "there\"\012"
+# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:121
+# left: "NULL"
+# right: NULL
+# check "'a' == '\n'" failed at t/helper/test-example-tap.c:122
+# left: 'a'
+# right: '\012'
+# check "'\\' == '\''" failed at t/helper/test-example-tap.c:123
+# left: '\\'
+# right: '\''
+not ok 28 - TEST_RUN messages from failing string and char comparison
+# BUG: test has no checks at t/helper/test-example-tap.c:125
+not ok 29 - TEST_RUN test with no checks
+1..29
@@ -16,6 +16,8 @@ static struct {
unsigned running :1;
unsigned skip_all :1;
unsigned todo :1;
+ char *desc;
+ char *location;
} ctx = {
.lazy_plan = 1,
.result = RESULT_NONE,
@@ -123,9 +125,45 @@ void test_plan(int count)
ctx.lazy_plan = 0;
}
-int test_done(void)
+static void test__run_maybe_end(void)
{
+ if (ctx.running) {
+ assert(ctx.location);
+ assert(ctx.desc);
+ test__run_end(0, ctx.location, "%s", ctx.desc);
+ FREE_AND_NULL(ctx.location);
+ FREE_AND_NULL(ctx.desc);
+ }
assert(!ctx.running);
+ assert(!ctx.location);
+ assert(!ctx.desc);
+}
+
+int test__run(const char *location, const char *format, ...)
+{
+ va_list ap;
+ char *desc;
+
+ test__run_maybe_end();
+
+ va_start(ap, format);
+ desc = xstrvfmt(format, ap);
+ va_end(ap);
+
+ if (test__run_begin()) {
+ test__run_end(1, location, "%s", desc);
+ free(desc);
+ return 0;
+ } else {
+ ctx.location = xstrdup(location);
+ ctx.desc = desc;
+ return 1;
+ }
+}
+
+int test_done(void)
+{
+ test__run_maybe_end();
if (ctx.lazy_plan)
test_plan(ctx.count);
@@ -169,7 +207,7 @@ void test_skip_all(const char *format, ...)
int test__run_begin(void)
{
- assert(!ctx.running);
+ test__run_maybe_end();
ctx.count++;
ctx.result = RESULT_NONE;
@@ -21,6 +21,13 @@
*/
void test_plan(int count);
+/*
+ * Start a test, returns 1 if the test was actually started or 0 if it
+ * was skipped. The test ends when the next test starts or test_done()
+ * is called.
+ */
+#define TEST_RUN(...) test__run(TEST_LOCATION(), __VA_ARGS__)
+
/*
* test_done() must be called at the end of main(). It will print the
* plan if plan() was not called at the beginning of the test program
@@ -156,6 +163,7 @@ extern union test__tmp test__tmp[2];
int test__run_begin(void);
__attribute__((format (printf, 3, 4)))
int test__run_end(int, const char *, const char *, ...);
+int test__run(const char *location, const char *format, ...);
void test__todo_begin(void);
int test__todo_end(const char *, const char *, int);
The macro TEST only allows defining a test that consists of a single expression. Add the new macro, TEST_RUN, which provides a way to define unit tests that are made up of one or more statements. A test started with it implicitly ends when the next test is started or test_done() is called. TEST_RUN allows defining self-contained tests en bloc, a bit like test_expect_success does for regular tests. Unlike TEST it does not require defining wrapper functions for test statements. No public method is provided for ending a test explicitly, yet; let's see if we'll ever need one. Signed-off-by: René Scharfe <l.s.r@web.de> --- t/helper/test-example-tap.c | 33 +++++++++++++++++++++++++++++ t/t0080/expect | 35 ++++++++++++++++++++++++++++++- t/unit-tests/test-lib.c | 42 +++++++++++++++++++++++++++++++++++-- t/unit-tests/test-lib.h | 8 +++++++ 4 files changed, 115 insertions(+), 3 deletions(-) -- 2.45.2