]>
Commit | Line | Data |
---|---|---|
ce019275 | 1 | /* Copyright (C) 2007-2010 Open Information Security Foundation |
c43319c3 | 2 | * |
ce019275 WM |
3 | * You can copy, redistribute or modify this Program under the terms of |
4 | * the GNU General Public License version 2 as published by the Free | |
5 | * Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
10 | * GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the GNU General Public License | |
13 | * version 2 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
15 | * 02110-1301, USA. | |
c43319c3 BS |
16 | */ |
17 | ||
ce019275 WM |
18 | /** |
19 | * \file | |
20 | * | |
21 | * \author Victor Julien <victor@inliniac.net> | |
22 | * \author Breno Silva <breno.silva@gmail.com> | |
23 | * | |
24 | * Unit test framework | |
25 | */ | |
c43319c3 | 26 | |
13cf2f82 JI |
27 | /** |
28 | * \defgroup Testing Testing | |
29 | * | |
30 | * \brief Unit testing support functions. | |
31 | * | |
32 | * @{ | |
33 | */ | |
34 | ||
ecf86f9c | 35 | #include "suricata-common.h" |
229f7281 | 36 | #include "runmodes.h" |
bab4b623 | 37 | #include "util-unittest.h" |
41752064 | 38 | #include "util-debug.h" |
5c3bbb8d | 39 | #include "util-time.h" |
b254719f | 40 | #include "conf.h" |
bab4b623 | 41 | |
0bff0de5 VJ |
42 | #include "stream-tcp.h" |
43 | #include "stream-tcp-reassemble.h" | |
44 | ||
1df33046 VJ |
45 | #ifdef UNITTESTS |
46 | ||
3633c48e PA |
47 | static pcre2_code *parse_regex; |
48 | static pcre2_match_data *parse_regex_match; | |
c43319c3 | 49 | |
83974139 | 50 | static UtTest *ut_list; |
bab4b623 | 51 | |
13cf2f82 JI |
52 | int unittests_fatal = 0; |
53 | ||
c43319c3 BS |
54 | /** |
55 | * \brief Allocate UtTest list member | |
56 | * | |
57 | * \retval ut Pointer to UtTest | |
58 | */ | |
59 | ||
8f1d7503 KS |
60 | static UtTest *UtAllocTest(void) |
61 | { | |
25a3a5c6 | 62 | UtTest *ut = SCMalloc(sizeof(UtTest)); |
e176be6f | 63 | if (unlikely(ut == NULL)) |
bab4b623 | 64 | return NULL; |
bab4b623 VJ |
65 | |
66 | memset(ut, 0, sizeof(UtTest)); | |
67 | ||
68 | return ut; | |
69 | } | |
70 | ||
c43319c3 BS |
71 | /** |
72 | * \brief Append test in UtTest list | |
73 | * | |
74 | * \param list Pointer to the start of the IP packet | |
75 | * \param test Pointer to unit test | |
76 | * | |
77 | * \retval 0 Function always returns zero | |
78 | */ | |
79 | ||
8f1d7503 KS |
80 | static int UtAppendTest(UtTest **list, UtTest *test) |
81 | { | |
bab4b623 VJ |
82 | if (*list == NULL) { |
83 | *list = test; | |
84 | } else { | |
85 | UtTest *tmp = *list; | |
86 | ||
87 | while (tmp->next != NULL) { | |
41752064 | 88 | tmp = tmp->next; |
bab4b623 VJ |
89 | } |
90 | tmp->next = test; | |
91 | } | |
92 | ||
93 | return 0; | |
94 | } | |
95 | ||
c43319c3 BS |
96 | /** |
97 | * \brief Register unit test | |
98 | * | |
99 | * \param name Unit test name | |
100 | * \param TestFn Unit test function | |
c43319c3 BS |
101 | */ |
102 | ||
ab1200fb | 103 | void UtRegisterTest(const char *name, int(*TestFn)(void)) |
8f1d7503 | 104 | { |
bab4b623 VJ |
105 | UtTest *ut = UtAllocTest(); |
106 | if (ut == NULL) | |
107 | return; | |
108 | ||
109 | ut->name = name; | |
689bbfdc | 110 | ut->TestFn = TestFn; |
bab4b623 VJ |
111 | ut->next = NULL; |
112 | ||
113 | /* append */ | |
114 | UtAppendTest(&ut_list, ut); | |
115 | } | |
116 | ||
c43319c3 BS |
117 | /** |
118 | * \brief Compile a regex to run a specific unit test | |
119 | * | |
120 | * \param regex_arg The regular expression | |
121 | * | |
122 | * \retval 1 Regex compiled | |
123 | * \retval -1 Regex error | |
124 | */ | |
ab1200fb | 125 | static int UtRegex (const char *regex_arg) |
8f1d7503 | 126 | { |
3633c48e PA |
127 | int en; |
128 | PCRE2_SIZE eo; | |
129 | int opts = PCRE2_CASELESS; | |
c43319c3 BS |
130 | |
131 | if(regex_arg == NULL) | |
132 | return -1; | |
133 | ||
3633c48e PA |
134 | parse_regex = |
135 | pcre2_compile((PCRE2_SPTR8)regex_arg, PCRE2_ZERO_TERMINATED, opts, &en, &eo, NULL); | |
c43319c3 BS |
136 | if(parse_regex == NULL) |
137 | { | |
3633c48e PA |
138 | PCRE2_UCHAR errbuffer[256]; |
139 | pcre2_get_error_message(en, errbuffer, sizeof(errbuffer)); | |
140 | SCLogError(SC_ERR_PCRE_COMPILE, | |
141 | "pcre2 compile of \"%s\" failed at " | |
142 | "offset %d: %s", | |
143 | regex_arg, (int)eo, errbuffer); | |
c43319c3 BS |
144 | goto error; |
145 | } | |
3633c48e | 146 | parse_regex_match = pcre2_match_data_create_from_pattern(parse_regex, NULL); |
c43319c3 BS |
147 | |
148 | return 1; | |
149 | ||
150 | error: | |
151 | return -1; | |
152 | } | |
153 | ||
097a77e9 JI |
154 | /** \brief List all registered unit tests. |
155 | * | |
156 | * \param regex_arg Regular expression to limit listed tests. | |
157 | */ | |
ab1200fb | 158 | void UtListTests(const char *regex_arg) |
8f1d7503 | 159 | { |
097a77e9 JI |
160 | UtTest *ut; |
161 | int ret = 0, rcomp = 0; | |
097a77e9 JI |
162 | |
163 | rcomp = UtRegex(regex_arg); | |
164 | ||
165 | for (ut = ut_list; ut != NULL; ut = ut->next) { | |
166 | if (rcomp == 1) { | |
3633c48e PA |
167 | ret = pcre2_match(parse_regex, (PCRE2_SPTR8)ut->name, strlen(ut->name), 0, 0, |
168 | parse_regex_match, NULL); | |
097a77e9 JI |
169 | if (ret >= 1) { |
170 | printf("%s\n", ut->name); | |
171 | } | |
172 | } | |
173 | else { | |
174 | printf("%s\n", ut->name); | |
175 | } | |
176 | } | |
3633c48e PA |
177 | pcre2_code_free(parse_regex); |
178 | pcre2_match_data_free(parse_regex_match); | |
097a77e9 JI |
179 | } |
180 | ||
85abc3ef | 181 | /** \brief Run all registered unittests. |
c43319c3 BS |
182 | * |
183 | * \param regex_arg The regular expression | |
85abc3ef VJ |
184 | * |
185 | * \retval 0 all successful | |
186 | * \retval result number of tests that failed | |
187 | */ | |
c43319c3 | 188 | |
ab1200fb | 189 | uint32_t UtRunTests(const char *regex_arg) |
8f1d7503 | 190 | { |
bab4b623 | 191 | UtTest *ut; |
41752064 | 192 | uint32_t good = 0, bad = 0, matchcnt = 0; |
c43319c3 | 193 | int ret = 0, rcomp = 0; |
c43319c3 | 194 | |
0bff0de5 VJ |
195 | StreamTcpInitMemuse(); |
196 | StreamTcpReassembleInitMemuse(); | |
197 | ||
c43319c3 | 198 | rcomp = UtRegex(regex_arg); |
bab4b623 | 199 | |
41752064 WM |
200 | if(rcomp == 1){ |
201 | for (ut = ut_list; ut != NULL; ut = ut->next) { | |
3633c48e PA |
202 | ret = pcre2_match(parse_regex, (PCRE2_SPTR8)ut->name, strlen(ut->name), 0, 0, |
203 | parse_regex_match, NULL); | |
c43319c3 | 204 | if( ret >= 1 ) { |
8f8de0e5 | 205 | printf("Test %-60.60s : ", ut->name); |
41752064 | 206 | matchcnt++; |
c43319c3 | 207 | fflush(stdout); /* flush so in case of a segv we see the testname */ |
5c3bbb8d VJ |
208 | |
209 | /* reset the time */ | |
210 | TimeModeSetOffline(); | |
211 | TimeSetToCurrentTime(); | |
212 | ||
c43319c3 | 213 | ret = ut->TestFn(); |
0bff0de5 VJ |
214 | |
215 | if (StreamTcpMemuseCounter() != 0) { | |
216 | printf("STREAM MEMORY IN USE %"PRIu64"\n", StreamTcpMemuseCounter()); | |
217 | ret = 0; | |
218 | } | |
e0aa7c1d VJ |
219 | if (FlowGetMemuse() != 0) { |
220 | printf("FLOW MEMORY IN USE %"PRIu64"\n", FlowGetMemuse()); | |
221 | ret = 0; | |
222 | } | |
0bff0de5 VJ |
223 | |
224 | if (StreamTcpReassembleMemuseGlobalCounter() != 0) { | |
225 | printf("STREAM REASSEMBLY MEMORY IN USE %"PRIu64"\n", StreamTcpReassembleMemuseGlobalCounter()); | |
226 | ret = 0; | |
227 | } | |
228 | ||
796dd522 | 229 | printf("%s\n", ret ? "pass" : "FAILED"); |
0bff0de5 | 230 | |
796dd522 | 231 | if (!ret) { |
13cf2f82 | 232 | if (unittests_fatal == 1) { |
b254719f GIG |
233 | fprintf(stderr, "ERROR: unittest failed.\n"); |
234 | exit(EXIT_FAILURE); | |
235 | } | |
c43319c3 BS |
236 | bad++; |
237 | } else { | |
238 | good++; | |
239 | } | |
240 | } | |
241 | } | |
41752064 WM |
242 | if(matchcnt > 0){ |
243 | printf("==== TEST RESULTS ====\n"); | |
244 | printf("PASSED: %" PRIu32 "\n", good); | |
245 | printf("FAILED: %" PRIu32 "\n", bad); | |
246 | printf("======================\n"); | |
247 | } else { | |
248 | SCLogInfo("UtRunTests: regex provided regex_arg: %s did not match any tests",regex_arg); | |
a798f84b | 249 | } |
41752064 WM |
250 | } else { |
251 | SCLogInfo("UtRunTests: pcre compilation failed"); | |
bab4b623 | 252 | } |
3633c48e PA |
253 | pcre2_code_free(parse_regex); |
254 | pcre2_match_data_free(parse_regex_match); | |
85abc3ef | 255 | return bad; |
bab4b623 | 256 | } |
c43319c3 BS |
257 | /** |
258 | * \brief Initialize unit test list | |
259 | */ | |
260 | ||
8f1d7503 KS |
261 | void UtInitialize(void) |
262 | { | |
bab4b623 VJ |
263 | ut_list = NULL; |
264 | } | |
265 | ||
c43319c3 BS |
266 | /** |
267 | * \brief Cleanup unit test list | |
268 | */ | |
269 | ||
8f1d7503 KS |
270 | void UtCleanup(void) |
271 | { | |
bab4b623 VJ |
272 | |
273 | UtTest *tmp = ut_list, *otmp; | |
274 | ||
275 | while (tmp != NULL) { | |
276 | otmp = tmp->next; | |
25a3a5c6 | 277 | SCFree(tmp); |
bab4b623 VJ |
278 | tmp = otmp; |
279 | } | |
280 | ||
281 | ut_list = NULL; | |
282 | } | |
283 | ||
229f7281 AS |
284 | void UtRunModeRegister(void) |
285 | { | |
286 | RunModeRegisterNewRunMode(RUNMODE_UNITTEST, | |
287 | "unittest", | |
288 | "Unittest mode", | |
289 | NULL); | |
290 | ||
291 | return; | |
292 | } | |
293 | ||
1df33046 VJ |
294 | /* |
295 | * unittests for the unittests code | |
296 | */ | |
c43319c3 BS |
297 | |
298 | /** \brief True test | |
299 | * | |
300 | * \retval 1 True | |
301 | * \retval 0 False | |
302 | */ | |
ab1200fb | 303 | static int UtSelftestTrue(void) |
8f1d7503 | 304 | { |
bab4b623 VJ |
305 | if (1)return 1; |
306 | else return 0; | |
307 | } | |
c43319c3 BS |
308 | |
309 | /** \brief False test | |
310 | * | |
311 | * \retval 1 False | |
312 | * \retval 0 True | |
313 | */ | |
ab1200fb | 314 | static int UtSelftestFalse(void) |
8f1d7503 | 315 | { |
52983bf3 JI |
316 | if (0)return 0; |
317 | else return 1; | |
bab4b623 | 318 | } |
13cf2f82 | 319 | |
c43319c3 BS |
320 | /** \brief Run self tests |
321 | * | |
322 | * \param regex_arg The regular expression | |
323 | * | |
324 | * \retval 0 all successful | |
325 | */ | |
326 | ||
ab1200fb | 327 | int UtRunSelftest (const char *regex_arg) |
8f1d7503 | 328 | { |
bab4b623 VJ |
329 | printf("* Running Unittesting subsystem selftests...\n"); |
330 | ||
331 | UtInitialize(); | |
332 | ||
796dd522 JI |
333 | UtRegisterTest("true", UtSelftestTrue); |
334 | UtRegisterTest("false", UtSelftestFalse); | |
bab4b623 | 335 | |
c43319c3 | 336 | int ret = UtRunTests(regex_arg); |
bab4b623 VJ |
337 | if (ret == 0) |
338 | printf("* Done running Unittesting subsystem selftests...\n"); | |
339 | else | |
340 | printf("* ERROR running Unittesting subsystem selftests failed...\n"); | |
341 | ||
342 | UtCleanup(); | |
343 | return 0; | |
344 | } | |
ab1200fb | 345 | #endif /* UNITTESTS */ |
13cf2f82 JI |
346 | |
347 | /** | |
348 | * @} | |
349 | */ |