1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 * Support routines for Unit Tests.
21 */
22
23 /*
24 * This is an example how to use unittests in your code:
25
26 int main()
27 {
28 int rc;
29
30 prolog("app_test");
31
32 ( ... your test application goes here ...)
33
34 rc = report();
35 epilog();
36 return rc;
37 }
38
39 * and a C++ approach for any C++ geeks:
40
41 int main()
42 {
43 Unittests tests("app_test");
44
45 ( ... your test application goes here ...)
46
47 return report();
48 }
49
50 */
51
52 #include <stdio.h>
53 #include "bacula.h"
54 #include "unittests.h"
55
56 static int err=0;
57 static int nb=0;
58 static bool lmgrinit = false;
59 static bool quiet = false;
60 static bool print_var = false;
61
Unittests(const char * name,bool lmgr,bool motd)62 Unittests::Unittests(const char *name, bool lmgr/*=false*/, bool motd/*=true*/)
63 {
64 if (getenv("UNITTEST_PRINT_VAR")) {
65 print_var = true;
66 }
67 prolog(name, lmgr, motd);
68 };
69
configure_test(uint64_t options)70 void configure_test(uint64_t options)
71 {
72 if (options & TEST_QUIET) {
73 quiet = true;
74 }
75 if (options & TEST_PRINT_LOCAL) {
76 print_var = true;
77 }
78 }
79
80 /* Get the total number of tests */
unittest_get_nb_tests()81 int unittest_get_nb_tests()
82 {
83 return nb;
84 }
85
86 /* Get the total number of tests in error */
unittest_get_nb_errors()87 int unittest_get_nb_errors()
88 {
89 return err;
90 }
91
92 /*
93 * Test success if value is not zero.
94 */
_ok(const char * file,int l,const char * op,int value,const char * label)95 bool _ok(const char *file, int l, const char *op, int value, const char *label)
96 {
97 nb++;
98 if (!value) {
99 err++;
100 if (err < 1000) {
101 Pmsg4(-1, "ERR %.80s %s:%i on %s\n", label, file, l, op);
102 } else if (err == 1000) {
103 Pmsg0(-1, "ERR Too much errors\n");
104 }
105 if (print_var) {
106 gdb_print_local(1);
107 }
108 } else if (!quiet) {
109 Pmsg1(-1, "OK %.80s\n", label);
110 }
111 return value;
112 }
113
114 /*
115 * Test success if value is zero.
116 */
_nok(const char * file,int l,const char * op,int value,const char * label)117 bool _nok(const char *file, int l, const char *op, int value, const char *label)
118 {
119 nb++;
120 if (value) {
121 err++;
122 if (err < 1000) {
123 Pmsg4(-1, "ERR %.80s %s:%i on !%s\n", label, file, l, op);
124 } else if (err == 1000) {
125 Pmsg0(-1, "ERR Too much errors\n");
126 }
127 if (print_var) {
128 gdb_print_local(1);
129 }
130 } else if (!quiet) {
131 Pmsg1(-1, "OK %.80s\n", label);
132 }
133 return !value;
134 }
135
136 /*
137 * Test success if value is different
138 */
_is(const char * file,int l,const char * op,const char * str,const char * str2,const char * label)139 bool _is(const char *file, int l, const char *op, const char *str, const char *str2, const char *label)
140 {
141 nb++;
142 bool value = (strcmp(str, str2) == 0);
143 if (!value) {
144 err++;
145 if (err < 1000) {
146 Pmsg6(-1, "ERR %.80s %s:%i on %s %s == %s\n", label, file, l, op, str, str2);
147 } else if (err == 1000) {
148 Pmsg0(-1, "ERR Too much errors\n");
149 }
150 if (print_var) {
151 gdb_print_local(1);
152 }
153 } else if (!quiet) {
154 Pmsg1(-1, "OK %.80s\n", label);
155 }
156 return value;
157 }
158
159 /*
160 * Test success if value is different
161 */
_is(const char * file,int l,const char * op,int64_t v,int64_t v2,const char * label)162 bool _is(const char *file, int l, const char *op, int64_t v, int64_t v2, const char *label)
163 {
164 nb++;
165 bool value = (v == v2);
166 if (!value) {
167 err++;
168 if (err < 1000) {
169 Pmsg6(-1, "ERR %.80s %s:%i on %s %lld == %lld\n", label, file, l, op, v, v2);
170 } else if (err == 1000) {
171 Pmsg0(-1, "ERR Too much errors\n");
172 }
173 if (print_var) {
174 gdb_print_local(1);
175 }
176 } else if (!quiet) {
177 Pmsg1(-1, "OK %.80s\n", label);
178 }
179 return value;
180 }
181
182 /*
183 * Test success if value is different
184 */
_isnt(const char * file,int l,const char * op,const char * str,const char * str2,const char * label)185 bool _isnt(const char *file, int l, const char *op, const char *str, const char *str2, const char *label)
186 {
187 nb++;
188 bool value = (strcmp(str, str2) != 0);
189 if (!value) {
190 err++;
191 if (err < 1000) {
192 Pmsg6(-1, "ERR %.80s %s:%i on %s %s == %s\n", label, file, l, op, str, str2);
193 } else if (err == 1000) {
194 Pmsg0(-1, "ERR Too much errors\n");
195 }
196 if (print_var) {
197 gdb_print_local(1);
198 }
199 } else if (!quiet) {
200 Pmsg1(-1, "OK %.80s\n", label);
201 }
202 return value;
203 }
204
205 /*
206 * Test success if value is different
207 */
_isnt(const char * file,int l,const char * op,int64_t v,int64_t v2,const char * label)208 bool _isnt(const char *file, int l, const char *op, int64_t v, int64_t v2, const char *label)
209 {
210 nb++;
211 bool value = (v != v2);
212 if (!value) {
213 err++;
214 if (err < 1000) {
215 Pmsg6(-1, "ERR %.80s %s:%i on %s == %lld\n", label, file, l, op, v, v2);
216 } else if (err == 1000) {
217 Pmsg0(-1, "ERR Too much errors\n");
218 }
219 if (print_var) {
220 gdb_print_local(1);
221 }
222 } else if (!quiet) {
223 Pmsg1(-1, "OK %.80s\n", label);
224 }
225 return value;
226 }
227
228 /*
229 * Short report of successful/all tests.
230 */
report()231 int report()
232 {
233 Pmsg0(-1, "==== Report ====\n");
234 Pmsg2(-1, "Result %i/%i OK\n", nb - err, nb);
235 return err > 0;
236 }
237
terminate(int sig)238 void terminate(int sig) {};
239
240 /*
241 * Initializes the application env, including lockmanager.
242 */
prolog(const char * name,bool lmgr,bool motd)243 void prolog(const char *name, bool lmgr, bool motd)
244 {
245 if (motd) {
246 Pmsg1(-1, "==== Starting %s ... ====\n", name);
247 }
248 my_name_is(0, NULL, name);
249 init_signals(terminate);
250
251 #ifdef HAVE_WIN32
252 InitWinAPIWrapper();
253 WSA_Init();
254 #endif
255
256 init_stack_dump();
257
258 if (lmgr){
259 lmgr_init_thread(); /* initialize the lockmanager stack */
260 lmgrinit = true;
261 }
262 };
263
264 /*
265 * Finish the application, shows report about memory leakage and terminates the lockmanager.
266 */
epilog()267 void epilog()
268 {
269 Pmsg0(-1, "\n");
270 stop_watchdog();
271 if (lmgrinit) {
272 lmgr_cleanup_main();
273 }
274 close_memory_pool();
275 sm_dump(false);
276 Pmsg0(-1, "==== Finish ====\n");
277 };
278