chiark / gitweb /
gnupg2 (2.1.18-6) unstable; urgency=medium
[gnupg2.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 <https://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         if (verbose) printf (" ok.\n");         \
78       }                                         \
79     else                                        \
80       {                                         \
81         if (!verbose)                           \
82           printf ("%d. Checking %s...",         \
83                   tests, (description) ?: "");  \
84         printf (" failed.\n");                  \
85         printf ("  %s == %s failed.\n",         \
86                 STRINGIFY(test),                \
87                 STRINGIFY(expected));           \
88         tests_failed ++;                        \
89         if (! current_test_group_failed)        \
90           {                                     \
91             current_test_group_failed = 1;      \
92             test_groups_failed ++;              \
93           }                                     \
94       }                                         \
95   } while (0)
96
97 /* Test that a condition evaluates to true.  */
98 #define TEST_P(description, test)               \
99   TEST(description, !!(test), 1)
100
101 /* Like CHECK, but if the test fails, abort the program.  */
102 #define ASSERT(description, test, expected)             \
103   do {                                                  \
104     int tests_failed_pre = tests_failed;                \
105     CHECK(description, test, expected);                 \
106     if (tests_failed_pre != tests_failed)               \
107       exit_tests (1);                                   \
108   } while (0)
109
110 /* Call this if something went wrong.  */
111 #define ABORT(message)                          \
112   do {                                          \
113     printf ("aborting...");                     \
114     if (message)                                \
115       printf (" %s\n", (message));              \
116                                                 \
117     exit_tests (1);                             \
118   } while (0)
119
120 /* You need to fill this function in.  */
121 static void do_test (int argc, char *argv[]);
122
123
124 /* Print stats and call the real exit.  If FORCE is set use
125    EXIT_FAILURE even if no test has failed.  */
126 static void
127 exit_tests (int force)
128 {
129   if (tests_failed == 0)
130     {
131       if (verbose)
132         printf ("All %d tests passed.\n", tests);
133       exit (!!force);
134     }
135   else
136     {
137       printf ("%d of %d tests failed",
138               tests_failed, tests);
139       if (test_groups > 1)
140         printf (" (%d of %d groups)",
141                 test_groups_failed, test_groups);
142       printf ("\n");
143       exit (1);
144     }
145 }
146
147
148 /* Prepend FNAME with the srcdir environment variable's value and
149    return a malloced filename.  Caller must release the returned
150    string using test_free.  */
151 char *
152 prepend_srcdir (const char *fname)
153 {
154   static const char *srcdir;
155   char *result;
156
157   if (!srcdir && !(srcdir = getenv ("srcdir")))
158     srcdir = ".";
159
160   result = malloc (strlen (srcdir) + 1 + strlen (fname) + 1);
161   strcpy (result, srcdir);
162   strcat (result, "/");
163   strcat (result, fname);
164   return result;
165 }
166
167
168 void
169 test_free (void *a)
170 {
171   if (a)
172     free (a);
173 }
174
175
176 int
177 main (int argc, char *argv[])
178 {
179   const char *s;
180
181   (void) test_group;
182
183   s = getenv ("verbose");
184   if (s && *s)
185     verbose = 1;
186
187   do_test (argc, argv);
188   exit_tests (0);
189
190   return !!tests_failed;
191 }