e9e6b2342d15927eb0a397223dc07ccde77168cf
[gnupg.git] / g10 / test.c
1 /* test.c - Infrastructure for unit tests.
2  * Copyright (C) 2015 g10 Code GmbH
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23
24 #include "gpg.h"
25
26 /* A unit test consists of one or more tests.  Tests can be broken
27    into groups and each group can consist of one or more tests.  */
28
29 /* The number of test groups.  */
30 static int test_groups;
31 /* The current test group.  */
32 static char *test_group;
33
34 /* Whether there was already a failure in the current test group.  */
35 static int current_test_group_failed;
36 /* The number of test groups with a failure.  */
37 static int test_groups_failed;
38
39 /* The total number of tests.  */
40 static int tests;
41 /* The total number of tests that failed.  */
42 static int tests_failed;
43
44 /* Flag to request verbose diagnostics.  This is set if the envvar
45    "verbose" exists and is not the empty string.  */
46 static int verbose;
47
48 #define TEST_GROUP(description)      \
49   do {                               \
50     test_group = (description);      \
51     test_groups ++;                  \
52     current_test_group_failed = 0;   \
53   } while (0)
54
55 #define STRINGIFY2(x) #x
56 #define STRINGIFY(x) STRINGIFY2(x)
57
58 /* Execute a test.  */
59 #define TEST(description, test, expected)       \
60   do {                                          \
61     int test_result;                            \
62     int expected_result;                        \
63                                                 \
64     tests ++;                                   \
65                                                 \
66     printf ("%d. Checking %s...",               \
67             tests, (description) ?: "");        \
68     fflush (stdout);                            \
69                                                 \
70     test_result = (test);                       \
71     expected_result = (expected);               \
72                                                 \
73     if (test_result == expected_result)         \
74       {                                         \
75         printf (" ok.\n");                      \
76       }                                         \
77     else                                        \
78       {                                         \
79         printf (" failed.\n");                  \
80         printf ("  %s == %s failed.\n",         \
81                 STRINGIFY(test),                \
82                 STRINGIFY(expected));           \
83         tests_failed ++;                        \
84         if (! current_test_group_failed)        \
85           {                                     \
86             current_test_group_failed = 1;      \
87             test_groups_failed ++;              \
88           }                                     \
89       }                                         \
90   } while (0)
91
92 /* Test that a condition evaluates to true.  */
93 #define TEST_P(description, test)               \
94   TEST(description, !!(test), 1)
95
96 /* Like CHECK, but if the test fails, abort the program.  */
97 #define ASSERT(description, test, expected)             \
98   do {                                                  \
99     int tests_failed_pre = tests_failed;                \
100     CHECK(description, test, expected);                 \
101     if (tests_failed_pre != tests_failed)               \
102       exit_tests (1);                                   \
103   } while (0)
104
105 /* Call this if something went wrong.  */
106 #define ABORT(message)                          \
107   do {                                          \
108     printf ("aborting...");                     \
109     if (message)                                \
110       printf (" %s\n", (message));              \
111                                                 \
112     exit_tests (1);                             \
113   } while (0)
114
115 /* You need to fill this function in.  */
116 static void do_test (int argc, char *argv[]);
117
118
119 /* Print stats and call the real exit.  If FORCE is set use
120    EXIT_FAILURE even if no test has failed.  */
121 static void
122 exit_tests (int force)
123 {
124   if (tests_failed == 0)
125     {
126       printf ("All %d tests passed.\n", tests);
127       exit (!!force);
128     }
129   else
130     {
131       printf ("%d of %d tests failed",
132               tests_failed, tests);
133       if (test_groups > 1)
134         printf (" (%d of %d groups)",
135                 test_groups_failed, test_groups);
136       printf ("\n");
137       exit (1);
138     }
139 }
140
141 int
142 main (int argc, char *argv[])
143 {
144   const char *s;
145
146   (void) test_group;
147
148   s = getenv ("verbose");
149   if (s && *s)
150     verbose = 1;
151
152   do_test (argc, argv);
153   exit_tests (0);
154
155   return !!tests_failed;
156 }