diff options
| author | Garrett D'Amore <garrett@damore.org> | 2016-12-17 20:52:30 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2016-12-17 20:52:30 -0800 |
| commit | 01b53ac4ce84aae2b2a1dcb1a68f748fd16f0ede (patch) | |
| tree | ad5ecac7f88c367ff2414b3f145d44e907ac63f5 /tests/test.h | |
| parent | 293a8e2c4f7a13fe81c043a91a9e7e3fd5ba4093 (diff) | |
| download | nng-01b53ac4ce84aae2b2a1dcb1a68f748fd16f0ede.tar.gz nng-01b53ac4ce84aae2b2a1dcb1a68f748fd16f0ede.tar.bz2 nng-01b53ac4ce84aae2b2a1dcb1a68f748fd16f0ede.zip | |
Test framework is dev-complete. More functionality may be added later.
Also, the current code is not Win32 safe.
Diffstat (limited to 'tests/test.h')
| -rw-r--r-- | tests/test.h | 143 |
1 files changed, 79 insertions, 64 deletions
diff --git a/tests/test.h b/tests/test.h index c712cb3f..0ddf428f 100644 --- a/tests/test.h +++ b/tests/test.h @@ -80,85 +80,88 @@ typedef struct test_ctx { void *T_data; } test_ctx_t; -extern test_ctx_t *T_C; +#define T_C test_get_context() /* These functions are not for use by tests -- they are used internally. */ -extern int test_ctx_init(test_ctx_t *, test_ctx_t *, const char *); -extern int test_ctx_loop(test_ctx_t *, int); -extern void test_ctx_fini(test_ctx_t *, int *); -extern void test_assert_pass(test_ctx_t *, const char *, const char *, int); -extern void test_assert_skip(test_ctx_t *, const char *, const char *, int); -extern void test_assert_fail(test_ctx_t *, const char *, const char *, int); -extern void test_assert_fatal(test_ctx_t *, const char *, const char *, int); +extern int test_i_start(test_ctx_t *, test_ctx_t *, const char *); +extern int test_i_loop(test_ctx_t *, int); +extern void test_i_finish(test_ctx_t *, int *); +extern int test_i_main(int, char **); + +extern void test_i_assert_pass(const char *, const char *, int); +extern void test_i_assert_skip(const char *, const char *, int); +extern void test_i_assert_fail(const char *, const char *, int); +extern void test_i_assert_fatal(const char *, const char *, int); +extern void test_i_skip(const char *, int, const char *); +extern void test_i_fail(const char *, int, const char *); +extern void test_i_fatal(const char *, int, const char *); /* - * test_ctx_do is a helper function not to be called directly by user - * code. It has to be here exposed, in order for setjmp() to work. Do - * not call it directly, instead use one of the other macros. + * test_i_run is a helper function not to be called directly by user + * code. It has to be here exposed, in order for setjmp() to work. + * and for the code block to be inlined. */ -#define test_ctx_do(T_xparent, T_xname, T_xcode, T_rvp) \ +#define test_i_run(T_xparent, T_xname, T_code, T_rvp) \ do { \ static test_ctx_t T_ctx; \ - int T_jumped; \ - if (test_ctx_init(&T_ctx, T_xparent, T_xname) != 0) { \ + int T_unwind; \ + if (test_i_start(&T_ctx, T_xparent, T_xname) != 0) { \ break; \ } \ - T_jumped = setjmp(T_ctx.T_jmp); \ - if (test_ctx_loop(&T_ctx, T_jumped) != 0) { \ + T_unwind = setjmp(T_ctx.T_jmp); \ + if (test_i_loop(&T_ctx, T_unwind) != 0) { \ break; \ } \ do { \ - T_xcode \ + T_code \ } while (0); \ - test_ctx_fini(&T_ctx, T_rvp); \ + test_i_finish(&T_ctx, T_rvp); \ } while (0) /* - * test_ctx_convey creates a "convey" using a custom parent context. - * The idea is that this new context creates a new "root" context, - * which can be useful for running tests in separate threads, or for - * passing context around explicitly. It should rarely be needed. - */ -#define test_ctx_convey(T_xparent, T_xname, T_xcode) \ - test_ctx_do(T_xparent, T_xname, T_xcode, NULL) - -/* * test_main is used to wrap the top-level of your test suite, and is * used in lieu of a normal main() function. */ -#define test_main(name, code) \ +#define test_main(T_name, T_code) \ int test_main_impl(void) { \ - static test_ctx_t ctx; \ - int rv; \ - test_ctx_do(NULL, name, code, &rv); \ - return (rv); \ + int T_rv; \ + test_i_run(NULL, T_name, T_code, &T_rv); \ + return (T_rv); \ +} \ +int main(int argc, char **argv) { \ + return (test_i_main(argc, argv)); \ } /* - * test_ctx_assert and test_ctx_so allow you to run assertions against - * an explicit context. You shouldn't need these. + * test_block declares an enclosing test block. The block is inlined, + * and a new context is created. The purpose is to create a new block + * in a thread, or other function, instead of using main(). Note that + * tests that run concurrently may lead to confused output. A suitable + * parent context can be obtained with test_get_context(). If NULL is + * supplied instead, then a new root context is created. + */ +#define test_block(T_parent, T_name, T_code) \ + test_i_run(T_parent, T_name, T_code, NULL) + +/* + * test_assert and test_so allow you to run assertions. */ -#define test_ctx_assert(T_xctx, T_cond) \ +#define test_assert(T_cond) \ if (!(T_cond)) { \ - test_assert_fatal(T_xctx, #T_cond, __FILE__, __LINE__); \ + test_i_assert_fatal(#T_cond, __FILE__, __LINE__); \ } else { \ - test_assert_pass(T_xctx, #T_cond, __FILE__, __LINE__); \ + test_i_assert_pass(#T_cond, __FILE__, __LINE__); \ } -#define test_ctx_so(T_xctx, T_cond) \ +#define test_so(T_cond) \ if (!(T_cond)) { \ - test_assert_fail(T_xctx, #T_cond, __FILE__, __LINE__); \ + test_i_assert_fail(#T_cond, __FILE__, __LINE__); \ } else { \ - test_assert_pass(T_xctx, #T_cond, __FILE__, __LINE__); \ + test_i_assert_pass(#T_cond, __FILE__, __LINE__); \ } /* - * test_ctx_skip can be used to skip further processing in the context. - */ -extern void test_ctx_skip(test_ctx_t *); - -/* * These are convenience versions that use the "global" context. * Note that normally convey() will create its own contexts. These * are the macros you should use. @@ -169,41 +172,53 @@ extern void test_ctx_skip(test_ctx_t *); * the body. The <code> is its scope, and may be called repeatedly * within the body of a loop. */ -#define test_convey(T_xn, T_xc) test_ctx_convey(T_C, T_xn, T_xc) - -/* - * test_assert is just like assert(3), but applies to the context. - * Failures in these are treated as "fatal" failures; and get higher - * alerting than other other kinds of failures. The entire test run - * all the way to the root context is aborted. (Other root contexts - * can run, however.) - */ -#define test_assert(T_cond) test_ctx_assert(T_C, T_cond) - -/* - * test_so() is like test_assert, but failures here only abort the current - * test. - */ -#define test_so(T_cond) test_ctx_so(T_C, T_cond) +#define test_convey(T_name, T_code) test_i_run(T_C, T_name, T_code, NULL) /* * test_skip() just stops processing of the rest of the current context, * and records that processing was skipped. */ -#define test_skip() test_ctx_skip(T_C) +#define test_skip(reason) test_i_skip(__FILE__, __LINE__, reason) +#define test_fail(reason) test_i_fail(__FILE__, __LINE__, reason) +#define test_fatal(reason) test_i_fatal(__FILE__, __LINE__, reason) /* * test_skip_assert() is used to skip processing of a single assertion. * Further processing in the same context continues. */ -#define test_skip_assert(T_cnd) test_assert_skip(T_C, T_cnd) +#define test_skip_assert(T_cnd) test_i_assert_skip(T_cnd) /* * test_skip_convey() is used to skip a convey context. This is intended * to permit changing "test_convey", to "test_skip_convey". This is logged, * and the current convey context continues processing. */ -#define test_skip_convey(X_n, X_c) /* TBD */ +#define test_skip_convey(T_name, T_code) \ + test_convey(T_name, test_skip()) +/* + * test_get_context obtains the current context. It uses thread local + * storage in the event that threading is in use, allowing concurrent threads + * to "sort" of work. + */ +extern test_ctx_t *test_get_context(void); + +/* + * test_init sets up initial things required for testing. If you don't + * use test_main(), then you need to call this somewhere early in your + * main routine. If it returns non-zero, then you can't use the framework. + */ +extern int test_init(void); + +/* + * test_set_verbose sets verbose mode. You shouldn't set this normally, + * as the main() wrapper looks at argv, and does if -v is supplied. + */ +extern void test_set_verbose(void); + +/* + * test_debugf() is like printf, but it goes to a test-specific debug log. + */ +extern void test_debugf(const char *, ...); #endif /* TEST_TEST_H */ |
