Browse code

Upgrade greatest to version 3.1

John Hawthorn authored on 08/10/2017 04:34:47
Showing 1 changed files

... ...
@@ -1,5 +1,5 @@
1 1
 /*
2
- * Copyright (c) 2011-2016 Scott Vokes <vokes.s@gmail.com>
2
+ * Copyright (c) 2011-2017 Scott Vokes <vokes.s@gmail.com>
3 3
  *
4 4
  * Permission to use, copy, modify, and/or distribute this software for any
5 5
  * purpose with or without fee is hereby granted, provided that the above
... ...
@@ -17,14 +17,14 @@
17 17
 #ifndef GREATEST_H
18 18
 #define GREATEST_H
19 19
 
20
-#ifdef __cplusplus
20
+#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS)
21 21
 extern "C" {
22 22
 #endif
23 23
 
24
-/* 1.2.2 */
24
+/* 1.3.1 */
25 25
 #define GREATEST_VERSION_MAJOR 1
26
-#define GREATEST_VERSION_MINOR 2
27
-#define GREATEST_VERSION_PATCH 2
26
+#define GREATEST_VERSION_MINOR 3
27
+#define GREATEST_VERSION_PATCH 1
28 28
 
29 29
 /* A unit testing system for C, contained in 1 file.
30 30
  * It doesn't use dynamic allocation or depend on anything
... ...
@@ -122,6 +122,12 @@ int main(int argc, char **argv) {
122 122
 #define GREATEST_USE_LONGJMP 1
123 123
 #endif
124 124
 
125
+/* Make it possible to replace fprintf with another
126
+ * function with the same interface. */
127
+#ifndef GREATEST_FPRINTF
128
+#define GREATEST_FPRINTF fprintf
129
+#endif
130
+
125 131
 #if GREATEST_USE_LONGJMP
126 132
 #include <setjmp.h>
127 133
 #endif
... ...
@@ -141,6 +147,7 @@ int main(int argc, char **argv) {
141 147
 #define GREATEST_FLOAT_FMT "%g"
142 148
 #endif
143 149
 
150
+
144 151
 /*********
145 152
  * Types *
146 153
  *********/
... ...
@@ -162,12 +169,12 @@ typedef struct greatest_suite_info {
162 169
 } greatest_suite_info;
163 170
 
164 171
 /* Type for a suite function. */
165
-typedef void (greatest_suite_cb)(void);
172
+typedef void greatest_suite_cb(void);
166 173
 
167 174
 /* Types for setup/teardown callbacks. If non-NULL, these will be run
168 175
  * and passed the pointer to their additional data. */
169
-typedef void (greatest_setup_cb)(void *udata);
170
-typedef void (greatest_teardown_cb)(void *udata);
176
+typedef void greatest_setup_cb(void *udata);
177
+typedef void greatest_teardown_cb(void *udata);
171 178
 
172 179
 /* Type for an equality comparison between two pointers of the same type.
173 180
  * Should return non-0 if equal, otherwise 0.
... ...
@@ -201,6 +208,20 @@ typedef enum {
201 208
     GREATEST_FLAG_LIST_ONLY = 0x02
202 209
 } greatest_flag_t;
203 210
 
211
+/* Internal state for a PRNG, used to shuffle test order. */
212
+struct greatest_prng {
213
+    unsigned char random_order; /* use random ordering? */
214
+    unsigned char initialized;  /* is random ordering initialized? */
215
+    unsigned char pad_0[2];
216
+    unsigned long state;        /* PRNG state */
217
+    unsigned long count;        /* how many tests, this pass */
218
+    unsigned long count_ceil;   /* total number of tests */
219
+    unsigned long count_run;    /* total tests run */
220
+    unsigned long mod;          /* power-of-2 ceiling of count_ceil */
221
+    unsigned long a;            /* LCG multiplier */
222
+    unsigned long c;            /* LCG increment */
223
+};
224
+
204 225
 /* Struct containing all test runner state. */
205 226
 typedef struct greatest_run_info {
206 227
     unsigned char flags;
... ...
@@ -237,6 +258,9 @@ typedef struct greatest_run_info {
237 258
     /* only run a specific suite or test */
238 259
     const char *suite_filter;
239 260
     const char *test_filter;
261
+    const char *test_exclude;
262
+
263
+    struct greatest_prng prng[2]; /* 0: suites, 1: tests */
240 264
 
241 265
 #if GREATEST_USE_TIME
242 266
     /* overall timers */
... ...
@@ -273,18 +297,25 @@ typedef const char *greatest_enum_str_fun(int value);
273 297
 void greatest_do_pass(const char *name);
274 298
 void greatest_do_fail(const char *name);
275 299
 void greatest_do_skip(const char *name);
276
-int greatest_pre_test(const char *name);
277
-void greatest_post_test(const char *name, int res);
300
+int greatest_suite_pre(const char *suite_name);
301
+void greatest_suite_post(void);
302
+int greatest_test_pre(const char *name);
303
+void greatest_test_post(const char *name, int res);
278 304
 void greatest_usage(const char *name);
279 305
 int greatest_do_assert_equal_t(const void *exp, const void *got,
280
-    greatest_type_info *type_info, void *udata);
306
+greatest_type_info *type_info, void *udata);
307
+void greatest_prng_init_first_pass(int id);
308
+int greatest_prng_init_second_pass(int id, unsigned long seed);
309
+void greatest_prng_step(int id);
281 310
 
282 311
 /* These are part of the public greatest API. */
283 312
 void GREATEST_SET_SETUP_CB(greatest_setup_cb *cb, void *udata);
284 313
 void GREATEST_SET_TEARDOWN_CB(greatest_teardown_cb *cb, void *udata);
285 314
 int greatest_all_passed(void);
286
-void greatest_set_test_filter(const char *name);
287
-void greatest_set_suite_filter(const char *name);
315
+void greatest_set_suite_filter(const char *filter);
316
+void greatest_set_test_filter(const char *filter);
317
+void greatest_set_test_exclude(const char *filter);
318
+void greatest_stop_at_first_fail(void);
288 319
 void greatest_get_report(struct greatest_report_t *report);
289 320
 unsigned int greatest_get_verbosity(void);
290 321
 void greatest_set_verbosity(unsigned int verbosity);
... ...
@@ -329,14 +360,12 @@ typedef enum greatest_test_res {
329 360
 /* Run a test in the current suite. */
330 361
 #define GREATEST_RUN_TEST(TEST)                                         \
331 362
     do {                                                                \
332
-        if (greatest_pre_test(#TEST) == 1) {                            \
363
+        if (greatest_test_pre(#TEST) == 1) {                            \
333 364
             enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \
334 365
             if (res == GREATEST_TEST_RES_PASS) {                        \
335 366
                 res = TEST();                                           \
336 367
             }                                                           \
337
-            greatest_post_test(#TEST, res);                             \
338
-        } else if (GREATEST_LIST_ONLY()) {                              \
339
-            fprintf(GREATEST_STDOUT, "  %s\n", #TEST);                  \
368
+            greatest_test_post(#TEST, res);                             \
340 369
         }                                                               \
341 370
     } while (0)
342 371
 
... ...
@@ -347,22 +376,24 @@ typedef enum greatest_test_res {
347 376
  * which can be a pointer to a struct with multiple arguments. */
348 377
 #define GREATEST_RUN_TEST1(TEST, ENV)                                   \
349 378
     do {                                                                \
350
-        if (greatest_pre_test(#TEST) == 1) {                            \
351
-            int res = TEST(ENV);                                        \
352
-            greatest_post_test(#TEST, res);                             \
353
-        } else if (GREATEST_LIST_ONLY()) {                              \
354
-            fprintf(GREATEST_STDOUT, "  %s\n", #TEST);                  \
379
+        if (greatest_test_pre(#TEST) == 1) {                            \
380
+            enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \
381
+            if (res == GREATEST_TEST_RES_PASS) {                        \
382
+                res = TEST(ENV);                                        \
383
+            }                                                           \
384
+            greatest_test_post(#TEST, res);                             \
355 385
         }                                                               \
356 386
     } while (0)
357 387
 
358 388
 #ifdef GREATEST_VA_ARGS
359 389
 #define GREATEST_RUN_TESTp(TEST, ...)                                   \
360 390
     do {                                                                \
361
-        if (greatest_pre_test(#TEST) == 1) {                            \
362
-            int res = TEST(__VA_ARGS__);                                \
363
-            greatest_post_test(#TEST, res);                             \
364
-        } else if (GREATEST_LIST_ONLY()) {                              \
365
-            fprintf(GREATEST_STDOUT, "  %s\n", #TEST);                  \
391
+        if (greatest_test_pre(#TEST) == 1) {                            \
392
+            enum greatest_test_res res = GREATEST_SAVE_CONTEXT();       \
393
+            if (res == GREATEST_TEST_RES_PASS) {                        \
394
+                res = TEST(__VA_ARGS__);                                \
395
+            }                                                           \
396
+            greatest_test_post(#TEST, res);                             \
366 397
         }                                                               \
367 398
     } while (0)
368 399
 #endif
... ...
@@ -375,7 +406,8 @@ typedef enum greatest_test_res {
375 406
 #define GREATEST_FIRST_FAIL()                                           \
376 407
     (greatest_info.flags & GREATEST_FLAG_FIRST_FAIL)
377 408
 #define GREATEST_FAILURE_ABORT()                                        \
378
-    (greatest_info.suite.failed > 0 && GREATEST_FIRST_FAIL())
409
+    (GREATEST_FIRST_FAIL() &&                                           \
410
+        (greatest_info.suite.failed > 0 || greatest_info.failed > 0))
379 411
 
380 412
 /* Message-less forms of tests defined below. */
381 413
 #define GREATEST_PASS() GREATEST_PASSm(NULL)
... ...
@@ -442,11 +474,11 @@ typedef enum greatest_test_res {
442 474
     do {                                                                \
443 475
         greatest_info.assertions++;                                     \
444 476
         if ((EXP) != (GOT)) {                                           \
445
-            fprintf(GREATEST_STDOUT, "\nExpected: ");                   \
446
-            fprintf(GREATEST_STDOUT, FMT, EXP);                         \
447
-            fprintf(GREATEST_STDOUT, "\n     Got: ");                   \
448
-            fprintf(GREATEST_STDOUT, FMT, GOT);                         \
449
-            fprintf(GREATEST_STDOUT, "\n");                             \
477
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: ");          \
478
+            GREATEST_FPRINTF(GREATEST_STDOUT, FMT, EXP);                \
479
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n     Got: ");          \
480
+            GREATEST_FPRINTF(GREATEST_STDOUT, FMT, GOT);                \
481
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                    \
450 482
             GREATEST_FAILm(MSG);                                        \
451 483
         }                                                               \
452 484
     } while (0)
... ...
@@ -458,9 +490,9 @@ typedef enum greatest_test_res {
458 490
         int greatest_GOT = (int)(GOT);                                  \
459 491
         greatest_enum_str_fun *greatest_ENUM_STR = ENUM_STR;            \
460 492
         if (greatest_EXP != greatest_GOT) {                             \
461
-            fprintf(GREATEST_STDOUT, "\nExpected: %s",                  \
493
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: %s",         \
462 494
                 greatest_ENUM_STR(greatest_EXP));                       \
463
-            fprintf(GREATEST_STDOUT, "\n     Got: %s\n",                \
495
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n     Got: %s\n",       \
464 496
                 greatest_ENUM_STR(greatest_GOT));                       \
465 497
             GREATEST_FAILm(MSG);                                        \
466 498
         }                                                               \
... ...
@@ -477,7 +509,7 @@ typedef enum greatest_test_res {
477 509
                 greatest_EXP - greatest_GOT > greatest_TOL) ||          \
478 510
             (greatest_EXP < greatest_GOT &&                             \
479 511
                 greatest_GOT - greatest_EXP > greatest_TOL)) {          \
480
-            fprintf(GREATEST_STDOUT,                                    \
512
+            GREATEST_FPRINTF(GREATEST_STDOUT,                           \
481 513
                 "\nExpected: " GREATEST_FLOAT_FMT                       \
482 514
                 " +/- " GREATEST_FLOAT_FMT                              \
483 515
                 "\n     Got: " GREATEST_FLOAT_FMT                       \
... ...
@@ -578,13 +610,13 @@ typedef enum greatest_test_res {
578 610
 #define GREATEST_SET_TIME(NAME)                                         \
579 611
     NAME = clock();                                                     \
580 612
     if (NAME == (clock_t) -1) {                                         \
581
-        fprintf(GREATEST_STDOUT,                                        \
613
+        GREATEST_FPRINTF(GREATEST_STDOUT,                               \
582 614
             "clock error: %s\n", #NAME);                                \
583 615
         exit(EXIT_FAILURE);                                             \
584 616
     }
585 617
 
586 618
 #define GREATEST_CLOCK_DIFF(C1, C2)                                     \
587
-    fprintf(GREATEST_STDOUT, " (%lu ticks, %.3f sec)",                  \
619
+    GREATEST_FPRINTF(GREATEST_STDOUT, " (%lu ticks, %.3f sec)",         \
588 620
         (long unsigned int) (C2) - (long unsigned int)(C1),             \
589 621
         (double)((C2) - (C1)) / (1.0 * (double)CLOCKS_PER_SEC))
590 622
 #else
... ...
@@ -594,8 +626,8 @@ typedef enum greatest_test_res {
594 626
 
595 627
 #if GREATEST_USE_LONGJMP
596 628
 #define GREATEST_SAVE_CONTEXT()                                         \
597
-        /* setjmp returns 0 (GREATEST_TEST_RES_PASS) on first call */   \
598
-        /* so the test runs, then RES_FAIL from FAIL_WITH_LONGJMP. */   \
629
+        /* setjmp returns 0 (GREATEST_TEST_RES_PASS) on first call *    \
630
+         * so the test runs, then RES_FAIL from FAIL_WITH_LONGJMP. */   \
599 631
         ((enum greatest_test_res)(setjmp(greatest_info.jump_dest)))
600 632
 #else
601 633
 #define GREATEST_SAVE_CONTEXT()                                         \
... ...
@@ -603,14 +635,46 @@ typedef enum greatest_test_res {
603 635
     GREATEST_TEST_RES_PASS
604 636
 #endif
605 637
 
638
+/* Run every suite / test function run within BODY in pseudo-random
639
+ * order, seeded by SEED. (The top 3 bits of the seed are ignored.)
640
+ *
641
+ * This should be called like:
642
+ *     GREATEST_SHUFFLE_TESTS(seed, {
643
+ *         GREATEST_RUN_TEST(some_test);
644
+ *         GREATEST_RUN_TEST(some_other_test);
645
+ *         GREATEST_RUN_TEST(yet_another_test);
646
+ *     });
647
+ *
648
+ * Note that the body of the second argument will be evaluated
649
+ * multiple times. */
650
+#define GREATEST_SHUFFLE_SUITES(SD, BODY) GREATEST_SHUFFLE(0, SD, BODY)
651
+#define GREATEST_SHUFFLE_TESTS(SD, BODY) GREATEST_SHUFFLE(1, SD, BODY)
652
+#define GREATEST_SHUFFLE(ID, SD, BODY)                                  \
653
+    do {                                                                \
654
+        struct greatest_prng *prng = &greatest_info.prng[ID];           \
655
+        greatest_prng_init_first_pass(ID);                              \
656
+        do {                                                            \
657
+            prng->count = 0;                                            \
658
+            if (prng->initialized) { greatest_prng_step(ID); }          \
659
+            BODY;                                                       \
660
+            if (!prng->initialized) {                                   \
661
+                if (!greatest_prng_init_second_pass(ID, SD)) { break; } \
662
+            } else if (prng->count_run == prng->count_ceil) {           \
663
+                break;                                                  \
664
+            }                                                           \
665
+        } while (!GREATEST_FAILURE_ABORT());                            \
666
+        prng->count_run = prng->random_order = prng->initialized = 0;   \
667
+    } while(0)
668
+
606 669
 /* Include several function definitions in the main test file. */
607 670
 #define GREATEST_MAIN_DEFS()                                            \
608 671
                                                                         \
609 672
 /* Is FILTER a subset of NAME? */                                       \
610
-static int greatest_name_match(const char *name,                        \
611
-    const char *filter) {                                               \
673
+static int greatest_name_match(const char *name, const char *filter,    \
674
+        int res_if_none) {                                              \
612 675
     size_t offset = 0;                                                  \
613
-    size_t filter_len = strlen(filter);                                 \
676
+    size_t filter_len = filter ? strlen(filter) : 0;                    \
677
+    if (filter_len == 0) { return res_if_none; } /* no filter */        \
614 678
     while (name[offset] != '\0') {                                      \
615 679
         if (name[offset] == filter[0]) {                                \
616 680
             if (0 == strncmp(&name[offset], filter, filter_len)) {      \
... ...
@@ -623,22 +687,34 @@ static int greatest_name_match(const char *name,                        \
623 687
     return 0;                                                           \
624 688
 }                                                                       \
625 689
                                                                         \
626
-int greatest_pre_test(const char *name) {                               \
627
-    if (!GREATEST_LIST_ONLY()                                           \
628
-        && (!GREATEST_FIRST_FAIL() || greatest_info.suite.failed == 0)  \
629
-        && (greatest_info.test_filter == NULL ||                        \
630
-            greatest_name_match(name, greatest_info.test_filter))) {    \
631
-        GREATEST_SET_TIME(greatest_info.suite.pre_test);                \
632
-        if (greatest_info.setup) {                                      \
633
-            greatest_info.setup(greatest_info.setup_udata);             \
690
+/* Before running a test, check the name filtering and                  \
691
+ * test shuffling state, if applicable, and then call setup hooks. */   \
692
+int greatest_test_pre(const char *name) {                               \
693
+    struct greatest_run_info *g = &greatest_info;                       \
694
+    int match = greatest_name_match(name, g->test_filter, 1) &&         \
695
+      !greatest_name_match(name, g->test_exclude, 0);                   \
696
+    if (GREATEST_LIST_ONLY()) { /* just listing test names */           \
697
+        if (match) { fprintf(GREATEST_STDOUT, "  %s\n", name); }        \
698
+        return 0;                                                       \
699
+    }                                                                   \
700
+    if (match && (!GREATEST_FIRST_FAIL() || g->suite.failed == 0)) {    \
701
+            struct greatest_prng *p = &g->prng[1];                      \
702
+        if (p->random_order) {                                          \
703
+            p->count++;                                                 \
704
+            if (!p->initialized || ((p->count - 1) != p->state)) {      \
705
+                return 0;       /* don't run this test yet */           \
706
+            }                                                           \
634 707
         }                                                               \
708
+        GREATEST_SET_TIME(g->suite.pre_test);                           \
709
+        if (g->setup) { g->setup(g->setup_udata); }                     \
710
+        p->count_run++;                                                 \
635 711
         return 1;               /* test should be run */                \
636 712
     } else {                                                            \
637 713
         return 0;               /* skipped */                           \
638 714
     }                                                                   \
639 715
 }                                                                       \
640 716
                                                                         \
641
-void greatest_post_test(const char *name, int res) {                    \
717
+void greatest_test_post(const char *name, int res) {                    \
642 718
     GREATEST_SET_TIME(greatest_info.suite.post_test);                   \
643 719
     if (greatest_info.teardown) {                                       \
644 720
         void *udata = greatest_info.teardown_udata;                     \
... ...
@@ -657,9 +733,9 @@ void greatest_post_test(const char *name, int res) {                    \
657 733
     if (GREATEST_IS_VERBOSE()) {                                        \
658 734
         GREATEST_CLOCK_DIFF(greatest_info.suite.pre_test,               \
659 735
             greatest_info.suite.post_test);                             \
660
-        fprintf(GREATEST_STDOUT, "\n");                                 \
736
+        GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                        \
661 737
     } else if (greatest_info.col % greatest_info.width == 0) {          \
662
-        fprintf(GREATEST_STDOUT, "\n");                                 \
738
+        GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                        \
663 739
         greatest_info.col = 0;                                          \
664 740
     }                                                                   \
665 741
     fflush(GREATEST_STDOUT);                                            \
... ...
@@ -667,7 +743,7 @@ void greatest_post_test(const char *name, int res) {                    \
667 743
                                                                         \
668 744
 static void report_suite(void) {                                        \
669 745
     if (greatest_info.suite.tests_run > 0) {                            \
670
-        fprintf(GREATEST_STDOUT,                                        \
746
+        GREATEST_FPRINTF(GREATEST_STDOUT,                               \
671 747
             "\n%u test%s - %u passed, %u failed, %u skipped",           \
672 748
             greatest_info.suite.tests_run,                              \
673 749
             greatest_info.suite.tests_run == 1 ? "" : "s",              \
... ...
@@ -676,7 +752,7 @@ static void report_suite(void) {                                        \
676 752
             greatest_info.suite.skipped);                               \
677 753
         GREATEST_CLOCK_DIFF(greatest_info.suite.pre_suite,              \
678 754
             greatest_info.suite.post_suite);                            \
679
-        fprintf(GREATEST_STDOUT, "\n");                                 \
755
+        GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                        \
680 756
     }                                                                   \
681 757
 }                                                                       \
682 758
                                                                         \
... ...
@@ -693,46 +769,63 @@ static void update_counts_and_reset_suite(void) {                       \
693 769
     greatest_info.col = 0;                                              \
694 770
 }                                                                       \
695 771
                                                                         \
696
-static void greatest_run_suite(greatest_suite_cb *suite_cb,             \
697
-                               const char *suite_name) {                \
698
-    if (greatest_info.suite_filter &&                                   \
699
-        !greatest_name_match(suite_name, greatest_info.suite_filter)) { \
700
-        return;                                                         \
772
+int greatest_suite_pre(const char *suite_name) {                        \
773
+    struct greatest_prng *p = &greatest_info.prng[0];                   \
774
+    if (!greatest_name_match(suite_name, greatest_info.suite_filter, 1) \
775
+        || (GREATEST_FIRST_FAIL() && greatest_info.failed > 0)) {       \
776
+        return 0;                                                       \
701 777
     }                                                                   \
778
+    if (p->random_order) {                                              \
779
+        p->count++;                                                     \
780
+        if (!p->initialized || ((p->count - 1) != p->state)) {          \
781
+            return 0; /* don't run this suite yet */                    \
782
+        }                                                               \
783
+    }                                                                   \
784
+    p->count_run++;                                                     \
702 785
     update_counts_and_reset_suite();                                    \
703
-    if (GREATEST_FIRST_FAIL() && greatest_info.failed > 0) { return; }  \
704
-    fprintf(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name);            \
786
+    GREATEST_FPRINTF(GREATEST_STDOUT, "\n* Suite %s:\n", suite_name);   \
705 787
     GREATEST_SET_TIME(greatest_info.suite.pre_suite);                   \
706
-    suite_cb();                                                         \
788
+    return 1;                                                           \
789
+}                                                                       \
790
+                                                                        \
791
+void greatest_suite_post(void) {                                        \
707 792
     GREATEST_SET_TIME(greatest_info.suite.post_suite);                  \
708 793
     report_suite();                                                     \
709 794
 }                                                                       \
710 795
                                                                         \
796
+static void greatest_run_suite(greatest_suite_cb *suite_cb,             \
797
+                               const char *suite_name) {                \
798
+    if (greatest_suite_pre(suite_name)) {                               \
799
+        suite_cb();                                                     \
800
+        greatest_suite_post();                                          \
801
+    }                                                                   \
802
+}                                                                       \
803
+                                                                        \
711 804
 void greatest_do_pass(const char *name) {                               \
712 805
     if (GREATEST_IS_VERBOSE()) {                                        \
713
-        fprintf(GREATEST_STDOUT, "PASS %s: %s",                         \
806
+        GREATEST_FPRINTF(GREATEST_STDOUT, "PASS %s: %s",                \
714 807
             name, greatest_info.msg ? greatest_info.msg : "");          \
715 808
     } else {                                                            \
716
-        fprintf(GREATEST_STDOUT, ".");                                  \
809
+        GREATEST_FPRINTF(GREATEST_STDOUT, ".");                         \
717 810
     }                                                                   \
718 811
     greatest_info.suite.passed++;                                       \
719 812
 }                                                                       \
720 813
                                                                         \
721 814
 void greatest_do_fail(const char *name) {                               \
722 815
     if (GREATEST_IS_VERBOSE()) {                                        \
723
-        fprintf(GREATEST_STDOUT,                                        \
816
+        GREATEST_FPRINTF(GREATEST_STDOUT,                               \
724 817
             "FAIL %s: %s (%s:%u)",                                      \
725 818
             name, greatest_info.msg ? greatest_info.msg : "",           \
726 819
             greatest_info.fail_file, greatest_info.fail_line);          \
727 820
     } else {                                                            \
728
-        fprintf(GREATEST_STDOUT, "F");                                  \
821
+        GREATEST_FPRINTF(GREATEST_STDOUT, "F");                         \
729 822
         greatest_info.col++;                                            \
730 823
         /* add linebreak if in line of '.'s */                          \
731 824
         if (greatest_info.col != 0) {                                   \
732
-            fprintf(GREATEST_STDOUT, "\n");                             \
825
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                    \
733 826
             greatest_info.col = 0;                                      \
734 827
         }                                                               \
735
-        fprintf(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n",               \
828
+        GREATEST_FPRINTF(GREATEST_STDOUT, "FAIL %s: %s (%s:%u)\n",      \
736 829
             name,                                                       \
737 830
             greatest_info.msg ? greatest_info.msg : "",                 \
738 831
             greatest_info.fail_file, greatest_info.fail_line);          \
... ...
@@ -742,12 +835,12 @@ void greatest_do_fail(const char *name) {                               \
742 835
                                                                         \
743 836
 void greatest_do_skip(const char *name) {                               \
744 837
     if (GREATEST_IS_VERBOSE()) {                                        \
745
-        fprintf(GREATEST_STDOUT, "SKIP %s: %s",                         \
838
+        GREATEST_FPRINTF(GREATEST_STDOUT, "SKIP %s: %s",                \
746 839
             name,                                                       \
747 840
             greatest_info.msg ?                                         \
748 841
             greatest_info.msg : "" );                                   \
749 842
     } else {                                                            \
750
-        fprintf(GREATEST_STDOUT, "s");                                  \
843
+        GREATEST_FPRINTF(GREATEST_STDOUT, "s");                         \
751 844
     }                                                                   \
752 845
     greatest_info.suite.skipped++;                                      \
753 846
 }                                                                       \
... ...
@@ -761,13 +854,13 @@ int greatest_do_assert_equal_t(const void *exp, const void *got,        \
761 854
     eq = type_info->equal(exp, got, udata);                             \
762 855
     if (!eq) {                                                          \
763 856
         if (type_info->print != NULL) {                                 \
764
-            fprintf(GREATEST_STDOUT, "\nExpected: ");                   \
857
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\nExpected: ");          \
765 858
             (void)type_info->print(exp, udata);                         \
766
-            fprintf(GREATEST_STDOUT, "\n     Got: ");                   \
859
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n     Got: ");          \
767 860
             (void)type_info->print(got, udata);                         \
768
-            fprintf(GREATEST_STDOUT, "\n");                             \
861
+            GREATEST_FPRINTF(GREATEST_STDOUT, "\n");                    \
769 862
         } else {                                                        \
770
-            fprintf(GREATEST_STDOUT,                                    \
863
+            GREATEST_FPRINTF(GREATEST_STDOUT,                           \
771 864
                 "GREATEST_ASSERT_EQUAL_T failure at %s:%u\n",           \
772 865
                 greatest_info.fail_file,                                \
773 866
                 greatest_info.fail_line);                               \
... ...
@@ -777,63 +870,73 @@ int greatest_do_assert_equal_t(const void *exp, const void *got,        \
777 870
 }                                                                       \
778 871
                                                                         \
779 872
 void greatest_usage(const char *name) {                                 \
780
-    fprintf(GREATEST_STDOUT,                                            \
781
-        "Usage: %s [-hlfv] [-s SUITE] [-t TEST]\n"                      \
873
+    GREATEST_FPRINTF(GREATEST_STDOUT,                                   \
874
+        "Usage: %s [--help] [-hlfv] [-s SUITE] [-t TEST]\n"             \
782 875
         "  -h, --help  print this Help\n"                               \
783
-        "  -l          List suites and their tests, then exit\n"        \
876
+        "  -l          List suites and tests, then exit (dry run)\n"    \
784 877
         "  -f          Stop runner after first failure\n"               \
785 878
         "  -v          Verbose output\n"                                \
786 879
         "  -s SUITE    only run suites containing string SUITE\n"       \
787
-        "  -t TEST     only run tests containing string TEST\n",        \
880
+        "  -t TEST     only run tests containing string TEST\n"         \
881
+        "  -x EXCLUDE  exclude tests containing string EXCLUDE\n",      \
788 882
         name);                                                          \
789 883
 }                                                                       \
790 884
                                                                         \
791
-static void greatest_parse_args(int argc, char **argv) {                \
885
+static void greatest_parse_options(int argc, char **argv) {             \
792 886
     int i = 0;                                                          \
793 887
     for (i = 1; i < argc; i++) {                                        \
794
-        if (0 == strncmp("-t", argv[i], 2)) {                           \
795
-            if (argc <= i + 1) {                                        \
796
-                greatest_usage(argv[0]);                                \
797
-                exit(EXIT_FAILURE);                                     \
888
+        if (argv[i][0] == '-') {                                        \
889
+            char f = argv[i][1];                                        \
890
+            if ((f == 's' || f == 't' || f == 'x') && argc <= i + 1) {  \
891
+                greatest_usage(argv[0]); exit(EXIT_FAILURE);            \
798 892
             }                                                           \
799
-            greatest_info.test_filter = argv[i+1];                      \
800
-            i++;                                                        \
801
-        } else if (0 == strncmp("-s", argv[i], 2)) {                    \
802
-            if (argc <= i + 1) {                                        \
893
+            switch (f) {                                                \
894
+            case 's': /* suite name filter */                           \
895
+                greatest_set_suite_filter(argv[i + 1]); i++; break;     \
896
+            case 't': /* test name filter */                            \
897
+                greatest_set_test_filter(argv[i + 1]); i++; break;      \
898
+            case 'x': /* test name exclusion */                         \
899
+                greatest_set_test_exclude(argv[i + 1]); i++; break;     \
900
+            case 'f': /* first fail flag */                             \
901
+                greatest_stop_at_first_fail(); break;                   \
902
+            case 'l': /* list only (dry run) */                         \
903
+                greatest_info.flags |= GREATEST_FLAG_LIST_ONLY; break;  \
904
+            case 'v': /* first fail flag */                             \
905
+                greatest_info.verbosity++; break;                       \
906
+            case 'h': /* help */                                        \
907
+                greatest_usage(argv[0]); exit(EXIT_SUCCESS);            \
908
+            case '-':                                                   \
909
+                if (0 == strncmp("--help", argv[i], 6)) {               \
910
+                    greatest_usage(argv[0]); exit(EXIT_SUCCESS);        \
911
+                } else if (0 == strncmp("--", argv[i], 2)) {            \
912
+                    return; /* ignore following arguments */            \
913
+                }  /* fall through */                                   \
914
+            default:                                                    \
915
+                GREATEST_FPRINTF(GREATEST_STDOUT,                       \
916
+                    "Unknown argument '%s'\n", argv[i]);                \
803 917
                 greatest_usage(argv[0]);                                \
804 918
                 exit(EXIT_FAILURE);                                     \
805 919
             }                                                           \
806
-            greatest_info.suite_filter = argv[i+1];                     \
807
-            i++;                                                        \
808
-        } else if (0 == strncmp("-f", argv[i], 2)) {                    \
809
-            greatest_info.flags |= GREATEST_FLAG_FIRST_FAIL;            \
810
-        } else if (0 == strncmp("-v", argv[i], 2)) {                    \
811
-            greatest_info.verbosity++;                                  \
812
-        } else if (0 == strncmp("-l", argv[i], 2)) {                    \
813
-            greatest_info.flags |= GREATEST_FLAG_LIST_ONLY;             \
814
-        } else if (0 == strncmp("-h", argv[i], 2) ||                    \
815
-                   0 == strncmp("--help", argv[i], 6)) {                \
816
-            greatest_usage(argv[0]);                                    \
817
-            exit(EXIT_SUCCESS);                                         \
818
-        } else if (0 == strncmp("--", argv[i], 2)) {                    \
819
-            break;                                                      \
820
-        } else {                                                        \
821
-            fprintf(GREATEST_STDOUT,                                    \
822
-                "Unknown argument '%s'\n", argv[i]);                    \
823
-            greatest_usage(argv[0]);                                    \
824
-            exit(EXIT_FAILURE);                                         \
825 920
         }                                                               \
826 921
     }                                                                   \
827 922
 }                                                                       \
828 923
                                                                         \
829 924
 int greatest_all_passed(void) { return (greatest_info.failed == 0); }   \
830 925
                                                                         \
831
-void greatest_set_test_filter(const char *name) {                       \
832
-    greatest_info.test_filter = name;                                   \
926
+void greatest_set_test_filter(const char *filter) {                     \
927
+    greatest_info.test_filter = filter;                                 \
833 928
 }                                                                       \
834 929
                                                                         \
835
-void greatest_set_suite_filter(const char *name) {                      \
836
-    greatest_info.suite_filter = name;                                  \
930
+void greatest_set_test_exclude(const char *filter) {                    \
931
+    greatest_info.test_exclude = filter;                                \
932
+}                                                                       \
933
+                                                                        \
934
+void greatest_set_suite_filter(const char *filter) {                    \
935
+    greatest_info.suite_filter = filter;                                \
936
+}                                                                       \
937
+                                                                        \
938
+void greatest_stop_at_first_fail(void) {                                \
939
+    greatest_info.flags |= GREATEST_FLAG_FIRST_FAIL;                    \
837 940
 }                                                                       \
838 941
                                                                         \
839 942
 void greatest_get_report(struct greatest_report_t *report) {            \
... ...
@@ -878,7 +981,7 @@ static int greatest_string_equal_cb(const void *exp, const void *got,   \
878 981
                                                                         \
879 982
 static int greatest_string_printf_cb(const void *t, void *udata) {      \
880 983
     (void)udata; /* note: does not check \0 termination. */             \
881
-    return fprintf(GREATEST_STDOUT, "%s", (const char *)t);             \
984
+    return GREATEST_FPRINTF(GREATEST_STDOUT, "%s", (const char *)t);    \
882 985
 }                                                                       \
883 986
                                                                         \
884 987
 greatest_type_info greatest_type_info_string = {                        \
... ...
@@ -892,6 +995,7 @@ static int greatest_memory_equal_cb(const void *exp, const void *got,   \
892 995
     return (0 == memcmp(exp, got, env->size));                          \
893 996
 }                                                                       \
894 997
                                                                         \
998
+/* Hexdump raw memory, with differences highlighted */                  \
895 999
 static int greatest_memory_printf_cb(const void *t, void *udata) {      \
896 1000
     greatest_memory_cmp_env *env = (greatest_memory_cmp_env *)udata;    \
897 1001
     const unsigned char *buf = (const unsigned char *)t;                \
... ...
@@ -906,24 +1010,64 @@ static int greatest_memory_printf_cb(const void *t, void *udata) {      \
906 1010
         for (line_i = i; line_i < i + line_len; line_i++) {             \
907 1011
             if (env->exp[line_i] != env->got[line_i]) diff_mark = 'X';  \
908 1012
         }                                                               \
909
-        len += fprintf(out, "\n%04x %c ", (unsigned int)i, diff_mark);  \
1013
+        len += GREATEST_FPRINTF(out, "\n%04x %c ",                      \
1014
+            (unsigned int)i, diff_mark);                                \
910 1015
         for (line_i = i; line_i < i + line_len; line_i++) {             \
911 1016
             int m = env->exp[line_i] == env->got[line_i]; /* match? */  \
912
-            len += fprintf(out, "%02x%c", buf[line_i], m ? ' ' : '<');  \
1017
+            len += GREATEST_FPRINTF(out, "%02x%c",                      \
1018
+                buf[line_i], m ? ' ' : '<');                            \
913 1019
         }                                                               \
914 1020
         for (line_i = 0; line_i < 16 - line_len; line_i++) {            \
915
-            len += fprintf(out, "   ");                                 \
1021
+            len += GREATEST_FPRINTF(out, "   ");                        \
916 1022
         }                                                               \
917
-        fprintf(out, " ");                                              \
1023
+        GREATEST_FPRINTF(out, " ");                                     \
918 1024
         for (line_i = i; line_i < i + line_len; line_i++) {             \
919 1025
             unsigned char c = buf[line_i];                              \
920
-            len += fprintf(out, "%c", isprint(c) ? c : '.');            \
1026
+            len += GREATEST_FPRINTF(out, "%c", isprint(c) ? c : '.');   \
921 1027
         }                                                               \
922 1028
     }                                                                   \
923
-    len += fprintf(out, "\n");                                          \
1029
+    len += GREATEST_FPRINTF(out, "\n");                                 \
924 1030
     return len;                                                         \
925 1031
 }                                                                       \
926 1032
                                                                         \
1033
+void greatest_prng_init_first_pass(int id) {                            \
1034
+    greatest_info.prng[id].random_order = 1;                            \
1035
+    greatest_info.prng[id].count_run = 0;                               \
1036
+}                                                                       \
1037
+                                                                        \
1038
+int greatest_prng_init_second_pass(int id, unsigned long seed) {        \
1039
+    static unsigned long primes[] = { 11, 101, 1009, 10007,             \
1040
+        100003, 1000003, 10000019, 100000007, 1000000007,               \
1041
+        1538461, 1865471, 17471, 2147483647 /* 2**32 - 1 */, };         \
1042
+    struct greatest_prng *prng = &greatest_info.prng[id];               \
1043
+    if (prng->count == 0) { return 0; }                                 \
1044
+    prng->mod = 1;                                                      \
1045
+    prng->count_ceil = prng->count;                                     \
1046
+    while (prng->mod < prng->count) { prng->mod <<= 1; }                \
1047
+    prng->state = seed & 0x1fffffff;    /* only use lower 29 bits... */ \
1048
+    prng->a = (4LU * prng->state) + 1;  /* to avoid overflow */         \
1049
+    prng->c = primes[(seed * 16451) % sizeof(primes)/sizeof(primes[0])];\
1050
+    prng->initialized = 1;                                              \
1051
+    return 1;                                                           \
1052
+}                                                                       \
1053
+                                                                        \
1054
+/* Step the pseudorandom number generator until its state reaches       \
1055
+ * another test ID between 0 and the test count.                        \
1056
+ * This use a linear congruential pseudorandom number generator,        \
1057
+ * with the power-of-two ceiling of the test count as the modulus, the  \
1058
+ * masked seed as the multiplier, and a prime as the increment. For     \
1059
+ * each generated value < the test count, run the corresponding test.   \
1060
+ * This will visit all IDs 0 <= X < mod once before repeating,          \
1061
+ * with a starting position chosen based on the initial seed.           \
1062
+ * For details, see: Knuth, The Art of Computer Programming             \
1063
+ * Volume. 2, section 3.2.1. */                                         \
1064
+void greatest_prng_step(int id) {                                       \
1065
+    struct greatest_prng *p = &greatest_info.prng[id];                  \
1066
+    do {                                                                \
1067
+        p->state = ((p->a * p->state) + p->c) & (p->mod - 1);           \
1068
+    } while (p->state >= p->count_ceil);                                \
1069
+}                                                                       \
1070
+                                                                        \
927 1071
 greatest_type_info greatest_type_info_memory = {                        \
928 1072
     greatest_memory_equal_cb,                                           \
929 1073
     greatest_memory_printf_cb,                                          \
... ...
@@ -936,7 +1080,10 @@ greatest_run_info greatest_info
936 1080
     do {                                                                \
937 1081
         /* Suppress unused function warning if features aren't used */  \
938 1082
         (void)greatest_run_suite;                                       \
939
-        (void)greatest_parse_args;                                      \
1083
+        (void)greatest_parse_options;                                   \
1084
+        (void)greatest_prng_step;                                       \
1085
+        (void)greatest_prng_init_first_pass;                            \
1086
+        (void)greatest_prng_init_second_pass;                           \
940 1087
                                                                         \
941 1088
         memset(&greatest_info, 0, sizeof(greatest_info));               \
942 1089
         greatest_info.width = GREATEST_DEFAULT_WIDTH;                   \
... ...
@@ -947,7 +1094,7 @@ greatest_run_info greatest_info
947 1094
 #define GREATEST_MAIN_BEGIN()                                           \
948 1095
     do {                                                                \
949 1096
         GREATEST_INIT();                                                \
950
-        greatest_parse_args(argc, argv);                                \
1097
+        greatest_parse_options(argc, argv);                             \
951 1098
     } while (0)
952 1099
 
953 1100
 /* Report passes, failures, skipped tests, the number of
... ...
@@ -957,16 +1104,16 @@ greatest_run_info greatest_info
957 1104
         if (!GREATEST_LIST_ONLY()) {                                    \
958 1105
             update_counts_and_reset_suite();                            \
959 1106
             GREATEST_SET_TIME(greatest_info.end);                       \
960
-            fprintf(GREATEST_STDOUT,                                    \
1107
+            GREATEST_FPRINTF(GREATEST_STDOUT,                           \
961 1108
                 "\nTotal: %u test%s",                                   \
962 1109
                 greatest_info.tests_run,                                \
963 1110
                 greatest_info.tests_run == 1 ? "" : "s");               \
964 1111
             GREATEST_CLOCK_DIFF(greatest_info.begin,                    \
965 1112
                 greatest_info.end);                                     \
966
-            fprintf(GREATEST_STDOUT, ", %u assertion%s\n",              \
1113
+            GREATEST_FPRINTF(GREATEST_STDOUT, ", %u assertion%s\n",     \
967 1114
                 greatest_info.assertions,                               \
968 1115
                 greatest_info.assertions == 1 ? "" : "s");              \
969
-            fprintf(GREATEST_STDOUT,                                    \
1116
+            GREATEST_FPRINTF(GREATEST_STDOUT,                           \
970 1117
                 "Pass: %u, fail: %u, skip: %u.\n",                      \
971 1118
                 greatest_info.passed,                                   \
972 1119
                 greatest_info.failed, greatest_info.skipped);           \
... ...
@@ -1019,6 +1166,8 @@ greatest_run_info greatest_info
1019 1166
 #define SET_SETUP      GREATEST_SET_SETUP_CB
1020 1167
 #define SET_TEARDOWN   GREATEST_SET_TEARDOWN_CB
1021 1168
 #define CHECK_CALL     GREATEST_CHECK_CALL
1169
+#define SHUFFLE_TESTS  GREATEST_SHUFFLE_TESTS
1170
+#define SHUFFLE_SUITES GREATEST_SHUFFLE_SUITES
1022 1171
 
1023 1172
 #ifdef GREATEST_VA_ARGS
1024 1173
 #define RUN_TESTp      GREATEST_RUN_TESTp
... ...
@@ -1033,7 +1182,7 @@ greatest_run_info greatest_info
1033 1182
 
1034 1183
 #endif /* USE_ABBREVS */
1035 1184
 
1036
-#ifdef __cplusplus
1185
+#if defined(__cplusplus) && !defined(GREATEST_NO_EXTERN_CPLUSPLUS)
1037 1186
 }
1038 1187
 #endif
1039 1188