]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Upgrade to the latest version of tinytest.
authorNick Mathewson <nickm@torproject.org>
Thu, 6 Mar 2014 23:06:08 +0000 (18:06 -0500)
committerNick Mathewson <nickm@torproject.org>
Thu, 6 Mar 2014 23:06:08 +0000 (18:06 -0500)
This brings us to tinytest commit 709a36ba63ff16d8.

The only big change tor-side is that we don't need our own test_mem_op
operation any longer.

changes/tinytest_upgrade [new file with mode: 0644]
src/ext/tinytest.c
src/ext/tinytest.h
src/ext/tinytest_demo.c
src/ext/tinytest_macros.h
src/test/test.h

diff --git a/changes/tinytest_upgrade b/changes/tinytest_upgrade
new file mode 100644 (file)
index 0000000..ccac402
--- /dev/null
@@ -0,0 +1,2 @@
+  o Testing:
+    - Update to the latest version of tinytest
index 4d9afacce417a49e07c0848b1e220511c1bbcfe1..3a8e331055015365f72c861157becfc6ae5ceb47 100644 (file)
@@ -31,6 +31,8 @@
 #include <string.h>
 #include <assert.h>
 
+#ifndef NO_FORKING
+
 #ifdef _WIN32
 #include <windows.h>
 #else
 #include <unistd.h>
 #endif
 
+#if defined(__APPLE__) && defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__)
+#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 && \
+    __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1070)
+/* Workaround for a stupid bug in OSX 10.6 */
+#define FORK_BREAKS_GCOV
+#include <vproc.h>
+#endif
+#endif
+
+#endif /* !NO_FORKING */
+
 #ifndef __GNUC__
 #define __attribute__(x)
 #endif
@@ -58,6 +71,8 @@ static int opt_nofork = 0; /**< Suppress calls to fork() for debugging. */
 static int opt_verbosity = 1; /**< -==quiet,0==terse,1==normal,2==verbose */
 const char *verbosity_flag = "";
 
+const struct testlist_alias_t *cfg_aliases=NULL;
+
 enum outcome { SKIP=2, OK=1, FAIL=0 };
 static enum outcome cur_test_outcome = 0;
 const char *cur_test_prefix = NULL; /**< prefix of the current test group */
@@ -71,6 +86,7 @@ static char commandname[MAX_PATH+1];
 
 static void usage(struct testgroup_t *groups, int list_groups)
   __attribute__((noreturn));
+static int process_test_option(struct testgroup_t *groups, const char *test);
 
 static enum outcome
 testcase_run_bare_(const struct testcase_t *testcase)
@@ -99,6 +115,8 @@ testcase_run_bare_(const struct testcase_t *testcase)
 
 #define MAGIC_EXITCODE 42
 
+#ifndef NO_FORKING
+
 static enum outcome
 testcase_run_forked_(const struct testgroup_t *group,
                     const struct testcase_t *testcase)
@@ -160,6 +178,9 @@ testcase_run_forked_(const struct testgroup_t *group,
        if (opt_verbosity>0)
                printf("[forking] ");
        pid = fork();
+#ifdef FORK_BREAKS_GCOV
+       vproc_transaction_begin(0);
+#endif
        if (!pid) {
                /* child. */
                int test_r, write_r;
@@ -196,16 +217,19 @@ testcase_run_forked_(const struct testgroup_t *group,
 #endif
 }
 
+#endif /* !NO_FORKING */
+
 int
 testcase_run_one(const struct testgroup_t *group,
                 const struct testcase_t *testcase)
 {
        enum outcome outcome;
 
-       if (testcase->flags & TT_SKIP) {
+       if (testcase->flags & (TT_SKIP|TT_OFF_BY_DEFAULT)) {
                if (opt_verbosity>0)
-                       printf("%s%s: SKIPPED\n",
-                           group->prefix, testcase->name);
+                       printf("%s%s: %s\n",
+                          group->prefix, testcase->name,
+                          (testcase->flags & TT_SKIP) ? "SKIPPED" : "DISABLED");
                ++n_skipped;
                return SKIP;
        }
@@ -218,9 +242,13 @@ testcase_run_one(const struct testgroup_t *group,
                cur_test_name = testcase->name;
        }
 
+#ifndef NO_FORKING
        if ((testcase->flags & TT_FORK) && !(opt_forked||opt_nofork)) {
                outcome = testcase_run_forked_(group, testcase);
        } else {
+#else
+       {
+#endif
                outcome = testcase_run_bare_(testcase);
        }
 
@@ -247,7 +275,7 @@ testcase_run_one(const struct testgroup_t *group,
 }
 
 int
-tinytest_set_flag_(struct testgroup_t *groups, const char *arg, unsigned long flag)
+tinytest_set_flag_(struct testgroup_t *groups, const char *arg, int set, unsigned long flag)
 {
        int i, j;
        size_t length = LONGEST_TEST_NAME;
@@ -257,12 +285,23 @@ tinytest_set_flag_(struct testgroup_t *groups, const char *arg, unsigned long fl
                length = strstr(arg,"..")-arg;
        for (i=0; groups[i].prefix; ++i) {
                for (j=0; groups[i].cases[j].name; ++j) {
+                       struct testcase_t *testcase = &groups[i].cases[j];
                        snprintf(fullname, sizeof(fullname), "%s%s",
-                                groups[i].prefix, groups[i].cases[j].name);
-                       if (!flag) /* Hack! */
-                               printf("    %s\n", fullname);
+                                groups[i].prefix, testcase->name);
+                       if (!flag) { /* Hack! */
+                               printf("    %s", fullname);
+                               if (testcase->flags & TT_OFF_BY_DEFAULT)
+                                       puts("   (Off by default)");
+                               else if (testcase->flags & TT_SKIP)
+                                       puts("  (DISABLED)");
+                               else
+                                       puts("");
+                       }
                        if (!strncmp(fullname, arg, length)) {
-                               groups[i].cases[j].flags |= flag;
+                               if (set)
+                                       testcase->flags |= flag;
+                               else
+                                       testcase->flags &= ~flag;
                                ++found;
                        }
                }
@@ -275,15 +314,69 @@ usage(struct testgroup_t *groups, int list_groups)
 {
        puts("Options are: [--verbose|--quiet|--terse] [--no-fork]");
        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("  To skip a test, prefix its name with a colon.");
+       puts("  To enable a disabled test, prefix its name with a plus.");
        puts("  Use --list-tests for a list of tests.");
        if (list_groups) {
                puts("Known tests are:");
-               tinytest_set_flag_(groups, "..", 0);
+               tinytest_set_flag_(groups, "..", 1, 0);
        }
        exit(0);
 }
 
+static int
+process_test_alias(struct testgroup_t *groups, const char *test)
+{
+       int i, j, n, r;
+       for (i=0; cfg_aliases && cfg_aliases[i].name; ++i) {
+               if (!strcmp(cfg_aliases[i].name, test)) {
+                       n = 0;
+                       for (j = 0; cfg_aliases[i].tests[j]; ++j) {
+                               r = process_test_option(groups, cfg_aliases[i].tests[j]);
+                               if (r<0)
+                                       return -1;
+                               n += r;
+                       }
+                       return n;
+               }
+       }
+       printf("No such test alias as @%s!",test);
+       return -1;
+}
+
+static int
+process_test_option(struct testgroup_t *groups, const char *test)
+{
+       int flag = TT_ENABLED_;
+       int n = 0;
+       if (test[0] == '@') {
+               return process_test_alias(groups, test + 1);
+       } else if (test[0] == ':') {
+               ++test;
+               flag = TT_SKIP;
+       } else if (test[0] == '+') {
+               ++test;
+               ++n;
+               if (!tinytest_set_flag_(groups, test, 0, TT_OFF_BY_DEFAULT)) {
+                       printf("No such test as %s!\n", test);
+                       return -1;
+               }
+       } else {
+               ++n;
+       }
+       if (!tinytest_set_flag_(groups, test, 1, flag)) {
+               printf("No such test as %s!\n", test);
+               return -1;
+       }
+       return n;
+}
+
+void
+tinytest_set_aliases(const struct testlist_alias_t *aliases)
+{
+       cfg_aliases = aliases;
+}
+
 int
 tinytest_main(int c, const char **v, struct testgroup_t *groups)
 {
@@ -321,24 +414,18 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
                                return -1;
                        }
                } else {
-                       const char *test = v[i];
-                       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]);
+                       int r = process_test_option(groups, v[i]);
+                       if (r<0)
                                return -1;
-                       }
+                       n += r;
                }
        }
        if (!n)
-               tinytest_set_flag_(groups, "..", TT_ENABLED_);
+               tinytest_set_flag_(groups, "..", 1, TT_ENABLED_);
 
+#ifdef _IONBF
        setvbuf(stdout, NULL, _IONBF, 0);
+#endif
 
        ++in_tinytest_main;
        for (i=0; groups[i].prefix; ++i)
@@ -385,3 +472,22 @@ tinytest_set_test_skipped_(void)
                cur_test_outcome = SKIP;
 }
 
+char *
+tinytest_format_hex_(const void *val_, unsigned long len)
+{
+       const unsigned char *val = val_;
+       char *result, *cp;
+       size_t i;
+
+       if (!val)
+               return strdup("null");
+       if (!(result = malloc(len*2+1)))
+               return strdup("<allocation failure>");
+       cp = result;
+       for (i=0;i<len;++i) {
+               *cp++ = "0123456789ABCDEF"[val[i] >> 4];
+               *cp++ = "0123456789ABCDEF"[val[i] & 0x0f];
+       }
+       *cp = 0;
+       return result;
+}
index bcac9f079cb5c28438e0e2bef56600524a871df3..ed07b26bc006bd6f3c00ced89c0ba90198203466 100644 (file)
 #define TT_SKIP  (1<<1)
 /** Internal runtime flag for a test we've decided to run. */
 #define TT_ENABLED_  (1<<2)
+/** Flag for a test that's off by default. */
+#define TT_OFF_BY_DEFAULT  (1<<3)
 /** If you add your own flags, make them start at this point. */
-#define TT_FIRST_USER_FLAG (1<<3)
+#define TT_FIRST_USER_FLAG (1<<4)
 
 typedef void (*testcase_fn)(void *);
 
@@ -64,6 +66,12 @@ struct testgroup_t {
 };
 #define END_OF_GROUPS { NULL, NULL}
 
+struct testlist_alias_t {
+       const char *name;
+       const char **tests;
+};
+#define END_OF_ALIASES { NULL, NULL }
+
 /** Implementation: called from a test to indicate failure, before logging. */
 void tinytest_set_test_failed_(void);
 /** Implementation: called from a test to indicate that we're skipping. */
@@ -72,14 +80,19 @@ void tinytest_set_test_skipped_(void);
 int tinytest_get_verbosity_(void);
 /** Implementation: Set a flag on tests matching a name; returns number
  * of tests that matched. */
-int tinytest_set_flag_(struct testgroup_t *, const char *, unsigned long);
+int tinytest_set_flag_(struct testgroup_t *, const char *, int set, unsigned long);
+/** Implementation: Put a chunk of memory into hex. */
+char *tinytest_format_hex_(const void *, unsigned long);
 
 /** Set all tests in 'groups' matching the name 'named' to be skipped. */
 #define tinytest_skip(groups, named) \
-       tinytest_set_flag_(groups, named, TT_SKIP)
+       tinytest_set_flag_(groups, named, 1, TT_SKIP)
 
 /** Run a single testcase in a single group. */
 int testcase_run_one(const struct testgroup_t *,const struct testcase_t *);
+
+void tinytest_set_aliases(const struct testlist_alias_t *aliases);
+
 /** Run a set of testcases from an END_OF_GROUPS-terminated array of groups,
     as selected from the command line. */
 int tinytest_main(int argc, const char **argv, struct testgroup_t *groups);
index be95ce4c1db57285d03ea8f707d092cb1f4e0f72..bdd0e600897b91e448ba3e2517d5bd5799cabe50 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <time.h>
+#ifndef _WIN32
+#include <unistd.h>
+#endif
 
 /* ============================================================ */
 
@@ -148,6 +152,9 @@ test_memcpy(void *ptr)
        memcpy(db->buffer2, db->buffer1, sizeof(db->buffer1));
        tt_str_op(db->buffer1, ==, db->buffer2);
 
+        /* This one works if there's an internal NUL. */
+        tt_mem_op(db->buffer1, <, db->buffer2, sizeof(db->buffer1));
+
        /* Now we've allocated memory that's referenced by a local variable.
           The end block of the function will clean it up. */
        mem = strdup("Hello world.");
@@ -162,6 +169,27 @@ test_memcpy(void *ptr)
                free(mem);
 }
 
+void
+test_timeout(void *ptr)
+{
+       time_t t1, t2;
+       (void)ptr;
+       t1 = time(NULL);
+#ifdef _WIN32
+       Sleep(5000);
+#else
+       sleep(5);
+#endif
+       t2 = time(NULL);
+
+       tt_int_op(t2-t1, >=, 4);
+
+       tt_int_op(t2-t1, <=, 6);
+
+ end:
+       ;
+}
+
 /* ============================================================ */
 
 /* Now we need to make sure that our tests get invoked.          First, you take
@@ -178,6 +206,10 @@ struct testcase_t demo_tests[] = {
           its environment. */
        { "memcpy", test_memcpy, TT_FORK, &data_buffer_setup },
 
+       /* This flag is off-by-default, since it takes a while to run.  You
+        * can enable it manually by passing +demo/timeout at the command line.*/
+       { "timeout", test_timeout, TT_OFF_BY_DEFAULT },
+
        /* The array has to end with END_OF_TESTCASES. */
        END_OF_TESTCASES
 };
@@ -192,6 +224,18 @@ struct testgroup_t groups[] = {
        END_OF_GROUPS
 };
 
+/* We can also define test aliases. These can be used for types of tests that
+ * cut across groups. */
+const char *alltests[] = { "+..", NULL };
+const char *slowtests[] = { "+demo/timeout", NULL };
+struct testlist_alias_t aliases[] = {
+
+       { "ALL", alltests },
+       { "SLOW", slowtests },
+
+       END_OF_ALIASES
+};
+
 
 int
 main(int c, const char **v)
@@ -211,5 +255,6 @@ main(int c, const char **v)
           "tinytest-demo" and "tinytest-demo .." mean the same thing.
 
        */
+       tinytest_set_aliases(aliases);
        return tinytest_main(c, v, groups);
 }
index 5bb8f8ec6929a57e7d788d2101803543630bc7db..db2dfcbe6bc31ac5679e8173f6ef20f00dc52f09 100644 (file)
            (val1_ && val2_ && strcmp(val1_,val2_) op 0),"<%s>",        \
            TT_EXIT_TEST_FUNCTION)
 
+#define tt_mem_op(expr1, op, expr2, len)                                \
+  tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2,            \
+                         const char *,                                 \
+                         (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), \
+                         char *, "%s",                                 \
+                         { print_ = tinytest_format_hex_(value_, (len)); }, \
+                         { if (print_) free(print_); },                \
+                         TT_EXIT_TEST_FUNCTION                         \
+                          );
+
 #define tt_want_int_op(a,op,b)                                         \
        tt_assert_test_type(a,b,#a" "#op" "#b,long,(val1_ op val2_),"%ld",(void)0)
 
index b902c6e47880a543b07ca972292e2bab1765b16f..ba82f52add20f4a32ca5b4a7ee2858e11f986f22 100644 (file)
 #define test_strneq(expr1, expr2) tt_str_op((expr1), !=, (expr2))
 
 #define test_mem_op(expr1, op, expr2, len)                              \
-  tt_assert_test_fmt_type(expr1,expr2,#expr1" "#op" "#expr2,            \
-                          const char *,                                 \
-                          (val1_ && val2_ && memcmp(val1_, val2_, len) op 0), \
-                          char *, "%s",                                 \
-                          { size_t printlen = (len)*2+1;                \
-                            if (value_) {                               \
-                              print_ = tor_malloc(printlen);            \
-                              base16_encode(print_, printlen, value_,   \
-                                            (len));                     \
-                            } else {                                    \
-                              print_ = tor_strdup("null");              \
-                            }                                           \
-                          },                                            \
-                          { tor_free(print_); },                        \
-                          TT_EXIT_TEST_FUNCTION                         \
-                          );
+  tt_mem_op((expr1), op, (expr2), (len))
 
 #define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len)
 #define test_memneq(expr1, expr2, len) test_mem_op((expr1), !=, (expr2), len)