gpg: Refactor the printing of binary notations.
[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 #include <string.h>
24
25 #include "gpg.h"
26
27 /* A unit test consists of one or more tests.  Tests can be broken
28    into groups and each group can consist of one or more tests.  */
29
30 /* The number of test groups.  */
31 static int test_groups;
32 /* The current test group.  */
33 static char *test_group;
34
35 /* Whether there was already a failure in the current test group.  */
36 static int current_test_group_failed;
37 /* The number of test groups with a failure.  */
38 static int test_groups_failed;
39
40 /* The total number of tests.  */
41 static int tests;
42 /* The total number of tests that failed.  */
43 static int tests_failed;
44
45 /* Flag to request verbose diagnostics.  This is set if the envvar
46    "verbose" exists and is not the empty string.  */
47 static int verbose;
48
49 #define TEST_GROUP(description)      \
50   do {                               \
51     test_group = (description);      \
52     test_groups ++;                  \
53     current_test_group_failed = 0;   \
54   } while (0)
55
56 #define STRINGIFY2(x) #x
57 #define STRINGIFY(x) STRINGIFY2(x)
58
59 /* Execute a test.  */
60 #define TEST(description, test, expected)       \
61   do {                                          \
62     int test_result;                            \
63     int expected_result;                        \
64                                                 \
65     tests ++;                                   \
66     if (verbose)                                \
67       {                                         \
68          printf ("%d. Checking %s...",          \
69                 tests, (description) ?: "");    \
70          fflush (stdout);                       \
71       }                                         \
72     test_result = (test);                       \
73     expected_result = (expected);               \
74                                                 \
75     if (test_result == expected_result)         \
76       {                                         \
77         printf (" ok.\n");                      \
78       }                                         \
79     else                                        \
80       {                                         \
81         printf (" failed.\n");                  \
82         printf ("  %s == %s failed.\n",         \
83                 STRINGIFY(test),                \
84                 STRINGIFY(expected));           \
85         tests_failed ++;                        \
86         if (! current_test_group_failed)        \
87           {                                     \
88             current_test_group_failed = 1;      \
89             test_groups_failed ++;              \
90           }                                     \
91       }                                         \
92   } while (0)
93
94 /* Test that a condition evaluates to true.  */
95 #define TEST_P(description, test)               \
96   TEST(description, !!(test), 1)
97
98 /* Like CHECK, but if the test fails, abort the program.  */
99 #define ASSERT(description, test, expected)             \
100   do {                                                  \
101     int tests_failed_pre = tests_failed;                \
102     CHECK(description, test, expected);                 \
103     if (tests_failed_pre != tests_failed)               \
104       exit_tests (1);                                   \
105   } while (0)
106
107 /* Call this if something went wrong.  */
108 #define ABORT(message)                          \
109   do {                                          \
110     printf ("aborting...");                     \
111     if (message)                                \
112       printf (" %s\n", (message));              \
113                                                 \
114     exit_tests (1);                             \
115   } while (0)
116
117 /* You need to fill this function in.  */
118 static void do_test (int argc, char *argv[]);
119
120
121 /* Print stats and call the real exit.  If FORCE is set use
122    EXIT_FAILURE even if no test has failed.  */
123 static void
124 exit_tests (int force)
125 {
126   if (tests_failed == 0)
127     {
128       printf ("All %d tests passed.\n", tests);
129       exit (!!force);
130     }
131   else
132     {
133       printf ("%d of %d tests failed",
134               tests_failed, tests);
135       if (test_groups > 1)
136         printf (" (%d of %d groups)",
137                 test_groups_failed, test_groups);
138       printf ("\n");
139       exit (1);
140     }
141 }
142
143
144 /* Prepend FNAME with the srcdir environment variable's value and
145    return a malloced filename.  Caller must release the returned
146    string using test_free.  */
147 char *
148 prepend_srcdir (const char *fname)
149 {
150   static const char *srcdir;
151   char *result;
152
153   if (!srcdir && !(srcdir = getenv ("srcdir")))
154     srcdir = ".";
155
156   result = malloc (strlen (srcdir) + 1 + strlen (fname) + 1);
157   strcpy (result, srcdir);
158   strcat (result, "/");
159   strcat (result, fname);
160   return result;
161 }
162
163
164 void
165 test_free (void *a)
166 {
167   if (a)
168     free (a);
169 }
170
171
172 int
173 main (int argc, char *argv[])
174 {
175   const char *s;
176
177   (void) test_group;
178
179   s = getenv ("verbose");
180   if (s && *s)
181     verbose = 1;
182
183   do_test (argc, argv);
184   exit_tests (0);
185
186   return !!tests_failed;
187 }