1 /* test.c - Infrastructure for unit tests.
2 * Copyright (C) 2015 g10 Code GmbH
4 * This file is part of GnuPG.
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.
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.
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/>.
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. */
30 /* The number of test groups. */
31 static int test_groups;
32 /* The current test group. */
33 static char *test_group;
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;
40 /* The total number of tests. */
42 /* The total number of tests that failed. */
43 static int tests_failed;
45 /* Flag to request verbose diagnostics. This is set if the envvar
46 "verbose" exists and is not the empty string. */
49 #define TEST_GROUP(description) \
51 test_group = (description); \
53 current_test_group_failed = 0; \
56 #define STRINGIFY2(x) #x
57 #define STRINGIFY(x) STRINGIFY2(x)
60 #define TEST(description, test, expected) \
63 int expected_result; \
68 printf ("%d. Checking %s...", \
69 tests, (description) ?: ""); \
72 test_result = (test); \
73 expected_result = (expected); \
75 if (test_result == expected_result) \
77 if (verbose) printf (" ok.\n"); \
82 printf ("%d. Checking %s...", \
83 tests, (description) ?: ""); \
84 printf (" failed.\n"); \
85 printf (" %s == %s failed.\n", \
87 STRINGIFY(expected)); \
89 if (! current_test_group_failed) \
91 current_test_group_failed = 1; \
92 test_groups_failed ++; \
97 /* Test that a condition evaluates to true. */
98 #define TEST_P(description, test) \
99 TEST(description, !!(test), 1)
101 /* Like CHECK, but if the test fails, abort the program. */
102 #define ASSERT(description, test, expected) \
104 int tests_failed_pre = tests_failed; \
105 CHECK(description, test, expected); \
106 if (tests_failed_pre != tests_failed) \
110 /* Call this if something went wrong. */
111 #define ABORT(message) \
113 printf ("aborting..."); \
115 printf (" %s\n", (message)); \
120 /* You need to fill this function in. */
121 static void do_test (int argc, char *argv[]);
124 /* Print stats and call the real exit. If FORCE is set use
125 EXIT_FAILURE even if no test has failed. */
127 exit_tests (int force)
129 if (tests_failed == 0)
132 printf ("All %d tests passed.\n", tests);
137 printf ("%d of %d tests failed",
138 tests_failed, tests);
140 printf (" (%d of %d groups)",
141 test_groups_failed, test_groups);
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. */
152 prepend_srcdir (const char *fname)
154 static const char *srcdir;
157 if (!srcdir && !(srcdir = getenv ("srcdir")))
160 result = malloc (strlen (srcdir) + 1 + strlen (fname) + 1);
161 strcpy (result, srcdir);
162 strcat (result, "/");
163 strcat (result, fname);
177 main (int argc, char *argv[])
183 s = getenv ("verbose");
187 do_test (argc, argv);
190 return !!tests_failed;