Bump to the latest version of tinytest

This lets us do without libevent-specific code in tinytest.c, and
lets us add a feature to skip individual tests from the command
line.
This commit is contained in:
Nick Mathewson 2010-09-09 16:13:09 -04:00
parent a5ce9ad4af
commit f0bd83ea88
5 changed files with 74 additions and 28 deletions

View File

@ -1,13 +1,13 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include AM_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/compat -I$(top_srcdir)/include -I../include -DTINYTEST_LOCAL
EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c test.sh EXTRA_DIST = regress.rpc regress.gen.h regress.gen.c test.sh
noinst_PROGRAMS = test-init test-eof test-weof test-time regress \ noinst_PROGRAMS = test-init test-eof test-weof test-time regress \
bench bench_cascade bench_http bench_httpclient test-ratelim \ bench bench_cascade bench_http bench_httpclient test-ratelim \
test-changelist test-changelist
noinst_HEADERS = tinytest.h tinytest_macros.h regress.h noinst_HEADERS = tinytest.h tinytest_macros.h regress.h tinytest_local.h
TESTS = $(top_srcdir)/test/test.sh TESTS = $(top_srcdir)/test/test.sh

View File

@ -29,7 +29,6 @@
#include <assert.h> #include <assert.h>
#ifdef WIN32 #ifdef WIN32
#include <winsock2.h>
#include <windows.h> #include <windows.h>
#else #else
#include <sys/types.h> #include <sys/types.h>
@ -37,8 +36,13 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <event2/util.h> #ifndef __GNUC__
#define __attribute__(x)
#endif
#ifdef TINYTEST_LOCAL
#include "tinytest_local.h"
#endif
#include "tinytest.h" #include "tinytest.h"
#include "tinytest_macros.h" #include "tinytest_macros.h"
@ -57,7 +61,7 @@ const char *verbosity_flag = "";
enum outcome { SKIP=2, OK=1, FAIL=0 }; enum outcome { SKIP=2, OK=1, FAIL=0 };
static enum outcome cur_test_outcome = 0; static enum outcome cur_test_outcome = 0;
const char *cur_test_prefix = NULL; /**< prefix of the current test group */ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */ /** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL; const char *cur_test_name = NULL;
#ifdef WIN32 #ifdef WIN32
@ -65,6 +69,9 @@ const char *cur_test_name = NULL;
static const char *commandname = NULL; static const char *commandname = NULL;
#endif #endif
static void usage(struct testgroup_t *groups, int list_groups)
__attribute__((noreturn));
static enum outcome static enum outcome
_testcase_run_bare(const struct testcase_t *testcase) _testcase_run_bare(const struct testcase_t *testcase)
{ {
@ -119,7 +126,7 @@ _testcase_run_forked(const struct testgroup_t *group,
if (opt_verbosity>0) if (opt_verbosity>0)
printf("[forking] "); printf("[forking] ");
evutil_snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s", snprintf(buffer, sizeof(buffer), "%s --RUNNING-FORKED %s %s%s",
commandname, verbosity_flag, group->prefix, testcase->name); commandname, verbosity_flag, group->prefix, testcase->name);
memset(&si, 0, sizeof(si)); memset(&si, 0, sizeof(si));
@ -161,7 +168,7 @@ _testcase_run_forked(const struct testgroup_t *group,
test_r = _testcase_run_bare(testcase); test_r = _testcase_run_bare(testcase);
assert(0<=(int)test_r && (int)test_r<=2); assert(0<=(int)test_r && (int)test_r<=2);
b[0] = "NYS"[test_r]; b[0] = "NYS"[test_r];
write_r = write(outcome_pipe[1], b, 1); write_r = (int)write(outcome_pipe[1], b, 1);
if (write_r != 1) { if (write_r != 1) {
perror("write outcome to pipe"); perror("write outcome to pipe");
exit(1); exit(1);
@ -174,7 +181,7 @@ _testcase_run_forked(const struct testgroup_t *group,
/* Close this now, so that if the other side closes it, /* Close this now, so that if the other side closes it,
* our read fails. */ * our read fails. */
close(outcome_pipe[1]); close(outcome_pipe[1]);
r = read(outcome_pipe[0], b, 1); r = (int)read(outcome_pipe[0], b, 1);
if (r == 0) { if (r == 0) {
printf("[Lost connection!] "); printf("[Lost connection!] ");
return 0; return 0;
@ -213,7 +220,7 @@ testcase_run_one(const struct testgroup_t *group,
if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) { if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
outcome = _testcase_run_forked(group, testcase); outcome = _testcase_run_forked(group, testcase);
} else { } else {
outcome = _testcase_run_bare(testcase); outcome = _testcase_run_bare(testcase);
} }
if (outcome == OK) { if (outcome == OK) {
@ -241,14 +248,14 @@ int
_tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag) _tinytest_set_flag(struct testgroup_t *groups, const char *arg, unsigned long flag)
{ {
int i, j; int i, j;
int length = LONGEST_TEST_NAME; size_t length = LONGEST_TEST_NAME;
char fullname[LONGEST_TEST_NAME]; char fullname[LONGEST_TEST_NAME];
int found=0; int found=0;
if (strstr(arg, "..")) if (strstr(arg, ".."))
length = strstr(arg,"..")-arg; length = strstr(arg,"..")-arg;
for (i=0; groups[i].prefix; ++i) { for (i=0; groups[i].prefix; ++i) {
for (j=0; groups[i].cases[j].name; ++j) { for (j=0; groups[i].cases[j].name; ++j) {
evutil_snprintf(fullname, sizeof(fullname), "%s%s", snprintf(fullname, sizeof(fullname), "%s%s",
groups[i].prefix, groups[i].cases[j].name); groups[i].prefix, groups[i].cases[j].name);
if (!flag) /* Hack! */ if (!flag) /* Hack! */
printf(" %s\n", fullname); printf(" %s\n", fullname);
@ -266,6 +273,7 @@ usage(struct testgroup_t *groups, int list_groups)
{ {
puts("Options are: [--verbose|--quiet|--terse] [--no-fork]"); puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
puts(" Specify tests by name, or using a prefix ending with '..'"); puts(" Specify tests by name, or using a prefix ending with '..'");
puts(" To skip a test, list give its name prefixed with a colon.");
puts(" Use --list-tests for a list of tests."); puts(" Use --list-tests for a list of tests.");
if (list_groups) { if (list_groups) {
puts("Known tests are:"); puts("Known tests are:");
@ -306,8 +314,15 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
return -1; return -1;
} }
} else { } else {
++n; const char *test = v[i];
if (!_tinytest_set_flag(groups, v[i], _TT_ENABLED)) { int flag = _TT_ENABLED;
if (test[0] == ':') {
++test;
flag = TT_SKIP;
} else {
++n;
}
if (!_tinytest_set_flag(groups, test, flag)) {
printf("No such test as %s!\n", v[i]); printf("No such test as %s!\n", v[i]);
return -1; return -1;
} }

View File

@ -53,7 +53,7 @@ test_strcmp(void *data)
} }
/* Pretty often, calling tt_abort_msg to indicate failure is more /* Pretty often, calling tt_abort_msg to indicate failure is more
heavy-weight than you want. Instead, just say: */ heavy-weight than you want. Instead, just say: */
tt_assert(strcmp("testcase", "testcase") == 0); tt_assert(strcmp("testcase", "testcase") == 0);
/* Occasionally, you don't want to stop the current testcase just /* Occasionally, you don't want to stop the current testcase just
@ -86,12 +86,12 @@ test_strcmp(void *data)
/* Now let's mess with setup and teardown functions! These are handy if /* Now let's mess with setup and teardown functions! These are handy if
you have a bunch of tests that all need a similar environment, and you you have a bunch of tests that all need a similar environment, and you
wnat to reconstruct that environment freshly for each one. */ want to reconstruct that environment freshly for each one. */
/* First you declare a type to hold the environment info, and functions to /* First you declare a type to hold the environment info, and functions to
set it up and tear it down. */ set it up and tear it down. */
struct data_buffer { struct data_buffer {
/* We're just going to have couple of character buffer. Using /* We're just going to have couple of character buffer. Using
setup/teardown functions is probably overkill for this case. setup/teardown functions is probably overkill for this case.
You could also do file descriptors, complicated handles, temporary You could also do file descriptors, complicated handles, temporary
@ -164,7 +164,7 @@ test_memcpy(void *ptr)
/* ============================================================ */ /* ============================================================ */
/* Now we need to make sure that our tests get invoked. First, you take /* Now we need to make sure that our tests get invoked. First, you take
a bunch of related tests and put them into an array of struct testcase_t. a bunch of related tests and put them into an array of struct testcase_t.
*/ */
@ -183,7 +183,7 @@ struct testcase_t demo_tests[] = {
}; };
/* Next, we make an array of testgroups. This is mandatory. Unlike more /* Next, we make an array of testgroups. This is mandatory. Unlike more
heavy-duty testing frameworks, groups can't next. */ heavy-duty testing frameworks, groups can't nest. */
struct testgroup_t groups[] = { struct testgroup_t groups[] = {
/* Every group has a 'prefix', and an array of tests. That's it. */ /* Every group has a 'prefix', and an array of tests. That's it. */
@ -196,8 +196,8 @@ struct testgroup_t groups[] = {
int int
main(int c, const char **v) main(int c, const char **v)
{ {
/* Finally, just call tinytest_main(). It lets you specify verbose /* Finally, just call tinytest_main(). It lets you specify verbose
or quiet output with --verbose and --quiet. You can list or quiet output with --verbose and --quiet. You can list
specific tests: specific tests:
tinytest-demo demo/memcpy tinytest-demo demo/memcpy

9
test/tinytest_local.h Normal file
View File

@ -0,0 +1,9 @@
#ifdef WIN32
#include <winsock2.h>
#endif
#include <event2/util.h>
#include "util-internal.h"
#define snprintf evutil_snprintf

View File

@ -45,7 +45,7 @@
TT_STMT_END TT_STMT_END
#endif #endif
/* Announce a failure. Args are parenthesized printf args. */ /* Announce a failure. Args are parenthesized printf args. */
#define TT_GRIPE(args) TT_DECLARE("FAIL", args) #define TT_GRIPE(args) TT_DECLARE("FAIL", args)
/* Announce a non-failure if we're verbose. */ /* Announce a non-failure if we're verbose. */
@ -110,19 +110,40 @@
/* Assert b, and stop the test if b fails. */ /* Assert b, and stop the test if b fails. */
#define tt_assert(b) tt_assert_msg((b), "assert("#b")") #define tt_assert(b) tt_assert_msg((b), "assert("#b")")
#define tt_assert_test_type(a,b,str_test,type,test,fmt) \ #define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
setup_block,cleanup_block) \
TT_STMT_BEGIN \ TT_STMT_BEGIN \
type _val1 = (type)(a); \ type _val1 = (type)(a); \
type _val2 = (type)(b); \ type _val2 = (type)(b); \
if (!(test)) { \ int _tt_status = (test); \
TT_DIE(("assert(%s): "fmt" vs "fmt, \ if (!_tt_status || _tinytest_get_verbosity()>1) { \
str_test, _val1, _val2)); \ printf_type _print; \
} else { \ printf_type _print1; \
TT_BLATHER(("assert(%s): "fmt" vs "fmt, \ printf_type _print2; \
str_test, _val1, _val2)); \ type _value = _val1; \
setup_block; \
_print1 = _print; \
_value = _val2; \
setup_block; \
_print2 = _print; \
TT_DECLARE(_tt_status?" OK":"FAIL", \
("assert(%s): "printf_fmt" vs "printf_fmt, \
str_test, _print1, _print2)); \
_print = _print1; \
cleanup_block; \
_print = _print2; \
cleanup_block; \
if (!_tt_status) { \
_tinytest_set_test_failed(); \
TT_EXIT_TEST_FUNCTION; \
} \
} \ } \
TT_STMT_END TT_STMT_END
#define tt_assert_test_type(a,b,str_test,type,test,fmt) \
tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \
{_print=_value;},{})
/* Helper: assert that a op b, when cast to type. Format the values with /* Helper: assert that a op b, when cast to type. Format the values with
* printf format fmt on failure. */ * printf format fmt on failure. */
#define tt_assert_op_type(a,op,b,type,fmt) \ #define tt_assert_op_type(a,op,b,type,fmt) \
@ -134,6 +155,7 @@
#define tt_uint_op(a,op,b) \ #define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
(_val1 op _val2),"%lu") (_val1 op _val2),"%lu")
#define tt_ptr_op(a,op,b) \ #define tt_ptr_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
(_val1 op _val2),"%p") (_val1 op _val2),"%p")