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