GCC Code Coverage Report


Directory: src/gate/
File: src/gate/tests.c
Date: 2026-10-19 17:06:30
Exec Total Coverage
Lines: 245 294 83.3%
Functions: 26 30 86.7%
Branches: 64 116 55.2%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright (c) 2018-2026, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28
29 #include "gate/tests.h"
30 #include "gate/streams.h"
31 #include "gate/strings.h"
32 #include "gate/console.h"
33 #include "gate/arrays.h"
34 #include "gate/files.h"
35 #include "gate/environments.h"
36
37 typedef struct gate_test_session_class
38 {
39 gate_stream_t* stream;
40 gate_test_report_t reports[256];
41 unsigned reports_used;
42 gate_bool_t save_checks;
43 gate_linkedlist_t checks;
44 } gate_test_session_t;
45
46 typedef struct gate_test_history_class
47 {
48 char const* test_name;
49 char message[128];
50 gate_bool_t failed;
51 char const* origin;
52 unsigned line;
53
54 } gate_test_history_t;
55
56 static gate_test_session_t test_session = GATE_INIT_EMPTY;
57
58
59 290 static gate_test_report_t* gate_test_register(char const* unit_name)
60 {
61 290 gate_test_report_t* ptr = NULL;
62 290 gate_size_t unit_name_len = gate_str_length(unit_name);
63 290 gate_size_t const max_reports = sizeof(test_session.reports) / sizeof(test_session.reports[0]);
64
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
290 if (test_session.reports_used < max_reports)
65 {
66 290 ptr = &test_session.reports[test_session.reports_used];
67 290 ++test_session.reports_used;
68 290 gate_mem_clear(ptr, sizeof(gate_test_report_t));
69 290 gate_str_print_text(ptr->name, sizeof(ptr->name), unit_name, unit_name_len);
70 290 ptr->test_counter = 0;
71 290 ptr->error_counter = 0;
72 }
73 else
74 {
75 ✗ ptr = &test_session.reports[max_reports - 1];
76 }
77 290 return ptr;
78 }
79
80 496416 static gate_test_report_t* gate_test_current_unit()
81 {
82
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 496416 times.
496416 if (test_session.reports_used == 0)
83 {
84 ✗ return gate_test_register("unnamed_unit_test");
85 }
86 496416 return &test_session.reports[test_session.reports_used - 1];
87 }
88
89 312 static gate_stream_t* gate_test_current_stream()
90 {
91 312 return test_session.stream;
92 }
93
94 290 static void gate_test_print_source(gate_stream_t* stream, char const* filepath, unsigned codeline)
95 {
96
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
290 if (filepath)
97 {
98 290 gate_stream_print(stream,
99 GATE_PRINT_CSTR, filepath,
100 GATE_PRINT_CSTR, "(",
101 GATE_PRINT_UI32, (gate_uint32_t)codeline,
102 GATE_PRINT_CSTR, "): ",
103 GATE_PRINT_END
104 );
105 }
106 290 }
107
108 static gate_bool_t volatile global_trace_on;
109 static gate_bool_t volatile global_history_on;
110
111 ✗ void gate_test_trace_enable(gate_bool_t on)
112 {
113 ✗ global_trace_on = on;
114 ✗ }
115
116 22 void gate_test_history_enable(gate_bool_t on)
117 {
118 22 global_history_on = on;
119 22 }
120
121 290 static void gate_test_print_message(char const* msg_type, char const* message, char const* filepath, unsigned codeline)
122 {
123 290 gate_stream_t* stream = gate_test_current_stream();
124
125 290 gate_test_print_source(stream, filepath, codeline);
126 290 gate_stream_print(stream,
127 GATE_PRINT_CSTR, msg_type,
128 GATE_PRINT_CSTR, message,
129 GATE_PRINT_NEWLINE,
130 GATE_PRINT_END);
131 290 }
132
133 33 void gate_test_init(gate_stream_t* stream)
134 {
135 33 gate_mem_clear(&test_session, sizeof(test_session));
136 33 test_session.reports_used = 0;
137
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (stream == NULL)
138 {
139 33 gate_console_t* con = gate_console();
140
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 if (con)
141 {
142 33 test_session.stream = (gate_stream_t*)con;
143 }
144 else
145 {
146 ✗ test_session.stream = gate_nullstream();
147 }
148 }
149 else
150 {
151 ✗ test_session.stream = stream;
152 }
153
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 11 times.
33 if (global_history_on)
154 {
155 22 gate_linkedlist_create(&test_session.checks, sizeof(gate_test_history_t), NULL, NULL);
156 22 test_session.save_checks = true;
157 }
158 33 }
159
160 22 void gate_test_uninit()
161 {
162
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (test_session.save_checks)
163 {
164 22 gate_linkedlist_destroy(&test_session.checks);
165 }
166 22 gate_mem_clear(&test_session, sizeof(test_session));
167 22 }
168
169 248353 static void add_test_history_entry(gate_bool_t failed, char const* message, char const* filepath, unsigned codeline)
170 {
171 248353 gate_test_report_t* ptr = gate_test_current_unit();
172 248353 gate_test_history_t entry = GATE_INIT_EMPTY;
173 248353 entry.test_name = ptr->name;
174 248353 gate_str_print_text(entry.message, sizeof(entry.message), message, gate_str_length(message));
175 248353 entry.failed = failed;
176 248353 entry.origin = filepath;
177 248353 entry.line = codeline;
178 248353 gate_linkedlist_add(&test_session.checks, &entry);
179 248353 }
180
181 290 void gate_test_unit_begin(char const* unit_name, char const* filepath, unsigned codeline)
182 {
183 290 gate_test_register(unit_name);
184 290 gate_test_print_message("TEST-BEGIN: ", unit_name, filepath, codeline);
185
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
290 if (test_session.save_checks)
186 {
187 290 add_test_history_entry(false, unit_name, filepath, codeline);
188 }
189 290 }
190
191
192 248233 void gate_test_trace_message(char const* message, char const* filepath, unsigned codeline)
193 {
194
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248233 times.
248233 if (global_trace_on)
195 {
196 ✗ gate_test_print_message("TRACE: ", message, filepath, codeline);
197 }
198 248233 }
199
200 27 void gate_test_trace_value(gate_int64_t value, char const* filepath, unsigned codeline)
201 {
202 27 char buffer[128] = GATE_INIT_EMPTY;
203 27 gate_str_print_int64(buffer, sizeof(buffer), value);
204 27 gate_test_trace_message(buffer, filepath, codeline);
205 27 }
206
207 248063 void gate_test_success_message(char const* message, char const* filepath, unsigned codeline)
208 {
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248063 times.
248063 if (global_trace_on)
210 {
211 ✗ gate_test_print_message("SUCCESS: ", message, filepath, codeline);
212 }
213
1/2
✓ Branch 0 taken 248063 times.
✗ Branch 1 not taken.
248063 if (test_session.save_checks)
214 {
215 248063 add_test_history_entry(false, message, filepath, codeline);
216 }
217 248063 }
218
219 ✗ void gate_test_error_message(char const* message, char const* filepath, unsigned codeline)
220 {
221 ✗ gate_test_print_message("ERROR: ", message, filepath, codeline);
222 ✗ if (test_session.save_checks)
223 {
224 ✗ add_test_history_entry(true, message, filepath, codeline);
225 }
226 ✗ }
227
228
229 248063 void gate_test_count_test()
230 {
231 248063 gate_test_report_t* ptr = gate_test_current_unit();
232
1/2
✓ Branch 0 taken 248063 times.
✗ Branch 1 not taken.
248063 if (ptr)
233 {
234 248063 ++ptr->test_counter;
235 }
236 248063 }
237
238 ✗ void gate_test_count_error()
239 {
240 ✗ gate_test_report_t* ptr = gate_test_current_unit();
241 ✗ if (ptr)
242 {
243 ✗ ++ptr->error_counter;
244 }
245 ✗ }
246
247 ✗ unsigned gate_test_get_reports(gate_test_report_t* target_report_array, unsigned max_reports)
248 {
249 ✗ unsigned count = (max_reports < test_session.reports_used) ? max_reports : test_session.reports_used;
250 ✗ gate_mem_copy(target_report_array, &test_session.reports[0], count * sizeof(gate_test_report_t));
251 ✗ return count;
252 }
253
254 22 static void print_history_intro(gate_stream_t* stream, char const* test_name,
255 unsigned tests_count, unsigned skipped, unsigned errors, unsigned failures, float duration)
256 {
257 22 gate_stream_println_cstr(stream, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
258 22 gate_stream_print_cstr(stream, "<testsuite name=\""); gate_stream_print_cstr(stream, test_name);
259 22 gate_stream_print_cstr(stream, "\" tests=\""); gate_stream_print_uint(stream, tests_count);
260 22 gate_stream_print_cstr(stream, "\" skipped=\""); gate_stream_print_uint(stream, skipped);
261 22 gate_stream_print_cstr(stream, "\" errors=\""); gate_stream_print_uint(stream, errors);
262 22 gate_stream_print_cstr(stream, "\" failures=\""); gate_stream_print_uint(stream, failures);
263 22 gate_stream_print_cstr(stream, "\" time=\""); gate_stream_print_real(stream, duration, 0, 6, 0);
264 22 gate_stream_println_cstr(stream, "\">");
265 22 }
266
267 22 static void print_history_outro(gate_stream_t* stream)
268 {
269 22 gate_stream_println_cstr(stream, "</testsuite>");
270 22 }
271
272 290 static void print_history_testcase(gate_stream_t* stream,
273 char const* test_name, char const* case_name, unsigned assertions_count, float duration,
274 char const* file_path, unsigned line,
275 gate_strbuilder_t* success_lines, gate_strbuilder_t* failure_lines)
276 {
277 290 gate_stream_print(stream,
278 GATE_PRINT_CSTR, "<testcase name=\"",
279 GATE_PRINT_CSTR, case_name,
280 GATE_PRINT_CSTR, "\" classname=\"",
281 GATE_PRINT_CSTR, test_name,
282 GATE_PRINT_CSTR, "\" assertions=\"",
283 GATE_PRINT_UI32, (gate_uint32_t)assertions_count,
284 GATE_PRINT_CSTR, "\" time=\"",
285 GATE_PRINT_R64, duration,
286 GATE_PRINT_CSTR, "\" file=\"",
287 GATE_PRINT_CSTR, file_path,
288 GATE_PRINT_CSTR, "\" line=\"",
289 GATE_PRINT_UI32, (gate_uint32_t)line,
290 GATE_PRINT_CSTR, "\">",
291 GATE_PRINT_NEWLINE,
292 GATE_PRINT_END);
293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 290 times.
290 if (gate_strbuilder_length(failure_lines) > 0)
294 {
295 ✗ gate_stream_print(stream,
296 GATE_PRINT_CSTR, "<failure message=\"failure\" type=\"assertion error\"><![CDATA[FAILURE:",
297 GATE_PRINT_NEWLINE,
298 ✗ GATE_PRINT_CSTR, (gate_strbuilder_length(failure_lines) > 0)
299 ✗ ? gate_strbuilder_ptr(failure_lines, 0) : "",
300 GATE_PRINT_CSTR, "]]></failure>",
301 GATE_PRINT_NEWLINE,
302 GATE_PRINT_END);
303 }
304
1/2
✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
290 if (gate_strbuilder_length(success_lines) > 0)
305 {
306
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
580 gate_stream_print(stream,
307 GATE_PRINT_CSTR, "<system-out><![CDATA[OUTPUT:",
308 GATE_PRINT_NEWLINE,
309 290 GATE_PRINT_CSTR, (gate_strbuilder_length(success_lines) > 0)
310 290 ? gate_strbuilder_ptr(success_lines, 0) : "",
311 GATE_PRINT_CSTR, "]]></system-out>",
312 GATE_PRINT_NEWLINE,
313 GATE_PRINT_END);
314 }
315 290 gate_stream_print(stream,
316 GATE_PRINT_CSTR, "</testcase>",
317 GATE_PRINT_NEWLINE,
318 GATE_PRINT_END);
319 290 }
320
321 22 static void build_sum_of_testcases(gate_linkedlist_t* checks, unsigned* ptr_succeeded, unsigned* ptr_failed, float* ptr_duration)
322 {
323 gate_linkedentry_t const* entry;
324 22 unsigned succeeded = 0;
325 22 unsigned failed = 0;
326 22 float duration = 0.0f;
327 22 entry = gate_linkedlist_first(checks);
328
329
2/2
✓ Branch 0 taken 248353 times.
✓ Branch 1 taken 22 times.
248375 while (entry != NULL)
330 {
331 248353 gate_test_history_t const* record = (gate_test_history_t const*)entry->data;
332
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248353 times.
248353 if (record->failed)
333 {
334 ✗ ++failed;
335 }
336 else
337 {
338 248353 ++succeeded;
339 }
340 248353 duration += 0.1f;
341
342 248353 entry = gate_linkedlist_next(entry);
343 }
344
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (ptr_succeeded) *ptr_succeeded = succeeded;
345
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (ptr_failed) *ptr_failed = failed;
346
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (ptr_duration) *ptr_duration = duration;
347 22 }
348
349 248353 static void add_history_entry_text(gate_strbuilder_t* builder, gate_test_history_t const* entry)
350 {
351 248353 gate_strbuilder_append_cstr(builder, entry->origin);
352 248353 gate_strbuilder_append_cstr(builder, "(");
353 248353 gate_strbuilder_append_uint32(builder, entry->line);
354 248353 gate_strbuilder_append_cstr(builder, "): ");
355 248353 gate_strbuilder_append_cstr(builder, entry->message);
356 248353 gate_strbuilder_append_cstr(builder, GATE_STR_NEWLINE);
357 248353 }
358
359 22 static void print_history_junit(gate_stream_t* stream, gate_linkedlist_t* checks)
360 {
361 gate_linkedentry_t const* entry;
362 22 char const* current_name = NULL;
363 22 char const* current_file = NULL;
364 22 unsigned current_line = 0;
365 gate_strbuilder_t ok_text;
366 gate_strbuilder_t err_text;
367 22 unsigned succeeded = 0;
368 22 unsigned failed = 0;
369 unsigned all;
370 22 unsigned asserts = 0;
371 22 float duration = 0.0f;
372 22 char const* exe_name = "gate_test";
373
374 22 build_sum_of_testcases(checks, &succeeded, &failed, &duration);
375 22 all = succeeded + failed;
376
377 22 print_history_intro(stream, exe_name, all, 0, 0, failed, duration);
378
379 22 gate_strbuilder_create(&err_text, 512);
380 22 gate_strbuilder_create(&ok_text, 512);
381
382
2/2
✓ Branch 1 taken 248353 times.
✓ Branch 2 taken 22 times.
248375 for(entry = gate_linkedlist_first(checks); entry != NULL; entry = gate_linkedlist_next(entry))
383 {
384 248353 gate_test_history_t const* record = (gate_test_history_t const*)entry->data;
385
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 248063 times.
248353 if(record->test_name != current_name)
386 {
387
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 22 times.
290 if(current_name != NULL)
388 {
389 268 print_history_testcase(stream, exe_name, current_name, asserts, (float)asserts / 10.0f,
390 current_file, current_line, &ok_text, &err_text);
391 }
392 290 current_name = record->test_name;
393 290 current_file = record->origin;
394 290 current_line = record->line;
395 290 gate_strbuilder_discard(&ok_text, GATE_STR_NPOS);
396 290 gate_strbuilder_discard(&err_text, GATE_STR_NPOS);
397 }
398
399
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 248353 times.
248353 add_history_entry_text((record->failed ? &err_text : &ok_text), record);
400 248353 ++asserts;
401 }
402
403
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if(current_name != NULL)
404 {
405 22 print_history_testcase(stream, exe_name, current_name, asserts, (float)asserts / 10.0f,
406 current_file, current_line, &ok_text, &err_text);
407 }
408
409 22 print_history_outro(stream);
410
411 22 gate_strbuilder_release(&ok_text);
412 22 gate_strbuilder_release(&err_text);
413 22 }
414
415 22 gate_bool_t gate_test_print_history(gate_stream_t* stream, gate_enumint_t flags)
416 {
417
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (GATE_FLAG_ENABLED(flags, GATE_TEST_HISTORY_FORMAT_JUNIT))
418 {
419 22 print_history_junit(stream, &test_session.checks);
420 22 return true;
421 }
422 ✗ return false;
423 }
424
425
426 22 void gate_test_print_reports()
427 {
428 22 gate_stream_t* stream = gate_test_current_stream();
429 unsigned ndx;
430 22 gate_uint16_t total_tests = 0;
431 22 gate_uint16_t total_errors = 0;
432
433 22 gate_stream_print(stream,
434 GATE_PRINT_CSTR, "----------------------------------------",
435 GATE_PRINT_NEWLINE,
436 GATE_PRINT_END);
437
438
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 22 times.
312 for (ndx = 0; ndx != test_session.reports_used; ++ndx)
439 {
440 290 gate_test_report_t* ptr = &test_session.reports[ndx];
441 290 total_tests += ptr->test_counter;
442 290 total_errors += ptr->error_counter;
443
444
1/2
✓ Branch 0 taken 290 times.
✗ Branch 1 not taken.
290 if (ptr->error_counter == 0)
445 {
446 290 gate_stream_print_cstr(stream, "UNIT OK: ");
447 }
448 else
449 {
450 ✗ gate_stream_print_cstr(stream, "UNIT FAILED: ");
451 }
452
453 580 gate_stream_print(stream,
454 290 GATE_PRINT_CSTR, ptr->name,
455 GATE_PRINT_CSTR, ", ",
456 290 GATE_PRINT_UI16, ptr->test_counter,
457 GATE_PRINT_CSTR, " tests",
458 GATE_PRINT_END);
459
460
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 if (ptr->error_counter != 0)
461 {
462 ✗ gate_stream_print(stream,
463 GATE_PRINT_CSTR, ", ",
464 ✗ GATE_PRINT_UI16, ptr->error_counter,
465 GATE_PRINT_CSTR, " failures",
466 GATE_PRINT_END);
467 }
468
469 290 gate_stream_print(stream,
470 GATE_PRINT_NEWLINE,
471 GATE_PRINT_END);
472 }
473
474 22 gate_stream_print(stream,
475 GATE_PRINT_CSTR, "----------------------------------------",
476 GATE_PRINT_NEWLINE,
477 GATE_PRINT_CSTR, "TOTAL: ",
478 GATE_PRINT_UI16, total_tests,
479 GATE_PRINT_CSTR, " tests, ",
480 GATE_PRINT_END);
481
1/2
✓ Branch 0 taken 22 times.
✗ Branch 1 not taken.
22 if (total_errors == 0)
482 {
483 22 gate_stream_print(stream,
484 GATE_PRINT_CSTR, "No errors detected",
485 GATE_PRINT_NEWLINE,
486 GATE_PRINT_END);
487 }
488 else
489 {
490 ✗ gate_stream_print(stream,
491 GATE_PRINT_UI16, total_errors,
492 GATE_PRINT_CSTR, " errors detected",
493 GATE_PRINT_NEWLINE,
494 GATE_PRINT_END);
495 }
496
497 22 }
498
499 22 gate_bool_t gate_test_failed()
500 {
501 unsigned ndx;
502
2/2
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 22 times.
312 for (ndx = 0; ndx != test_session.reports_used; ++ndx)
503 {
504 290 gate_test_report_t* const ptr = &test_session.reports[ndx];
505
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 290 times.
290 if (ptr->error_counter != 0)
506 {
507 ✗ return true;
508 }
509 }
510 22 return false;
511 }
512
513
514 9 gate_bool_t gate_test_cases_run(gate_test_case_t const* test_cases, gate_size_t test_cases_count)
515 {
516 gate_size_t ndx;
517 9 gate_bool_t succeeded = true;
518 9 gate_test_case_t const* ptr_case = NULL;
519
520 9 GATE_TEST_INIT_DEFAULT();
521
522
2/2
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 9 times.
56 for (ndx = 0; ndx != test_cases_count; ++ndx)
523 {
524 47 ptr_case = &test_cases[ndx];
525 47 succeeded &= test_cases[ndx].test_function();
526 }
527
528
2/4
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
✗ Branch 4 not taken.
9 return !gate_test_failed() && succeeded;
529 }
530
531 47 static gate_bool_t is_test_case_selected(char const* tc_name, char const* const* patterns, gate_size_t patterns_count)
532 {
533
1/2
✓ Branch 0 taken 47 times.
✗ Branch 1 not taken.
47 if (patterns_count == 0)
534 {
535 /* no pattern defined -> all TCs are selected */
536 47 return true;
537 }
538 else
539 {
540 ✗ gate_size_t const tc_name_len = gate_str_length(tc_name);
541 gate_size_t ndx;
542
543 ✗ for (ndx = 0; ndx != patterns_count; ++ndx)
544 {
545 ✗ char const* const pattern = patterns[ndx];
546 ✗ size_t const pattern_len = gate_str_length(pattern);
547 ✗ if (gate_str_like(tc_name, tc_name_len, pattern, pattern_len))
548 {
549 /* matching pattern found */
550 ✗ return true;
551 }
552 }
553 ✗ return false;
554 }
555
556 }
557
558 11 int gate_test_main(gate_test_case_t const* test_cases, gate_size_t test_cases_count,
559 char const* const* arguments, gate_size_t argcount)
560 {
561 gate_test_case_t selected_test_cases[256];
562 11 gate_size_t selected_test_cases_count = 0;
563 11 const gate_size_t selected_test_cases_max = sizeof(selected_test_cases) / sizeof(selected_test_cases[0]);
564 char const* test_patterns[256];
565 11 gate_size_t test_patterns_count = 0;
566 11 const gate_size_t test_pattern_max = sizeof(test_patterns) / sizeof(test_patterns[0]);
567 gate_bool_t succeeded;
568 gate_size_t ndx;
569 11 gate_bool_t show_help = false;
570 11 gate_bool_t enable_trace = false;
571 11 gate_bool_t enable_junit = true;
572 11 gate_bool_t list_tests = false;
573 11 gate_stream_t* con = (gate_stream_t*)gate_console();
574
575 11 GATE_TEST_INIT_DEFAULT();
576
577
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 11 times.
13 for (ndx = 0; ndx != argcount; ++ndx)
578 {
579 2 char const* const arg = arguments[ndx];
580
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 1 times.
2 if (gate_str_comp_ic(arg, "--help") == 0)
581 {
582 1 show_help = true;
583 }
584
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 else if (gate_str_comp_ic(arg, "--list") == 0)
585 {
586 1 list_tests = true;
587 }
588 ✗ else if (gate_str_comp_ic(arg, "--trace") == 0)
589 {
590 ✗ enable_trace = true;
591 }
592 ✗ else if (gate_str_comp_ic(arg, "--junit") == 0)
593 {
594 ✗ enable_junit = true;
595 }
596 else
597 {
598 ✗ if (test_patterns_count < test_pattern_max)
599 {
600 ✗ test_patterns[test_patterns_count] = arg;
601 ✗ ++test_patterns_count;
602 }
603 }
604 }
605
606
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
11 if (show_help)
607 {
608 1 gate_stream_print(con,
609 GATE_PRINT_CSTR, "Usage:", GATE_PRINT_NEWLINE,
610 GATE_PRINT_CSTR, "testapp --help", GATE_PRINT_NEWLINE,
611 GATE_PRINT_CSTR, "\tPrint test program usage description", GATE_PRINT_NEWLINE,
612 GATE_PRINT_CSTR, "testapp --list", GATE_PRINT_NEWLINE,
613 GATE_PRINT_CSTR, "\tLists all registered test cases by their anmes", GATE_PRINT_NEWLINE,
614 GATE_PRINT_CSTR, "testapp", GATE_PRINT_NEWLINE,
615 GATE_PRINT_CSTR, "\tExecutes all registered test cases", GATE_PRINT_NEWLINE,
616 GATE_PRINT_CSTR, "testapp test_case_name1 test_case_name2", GATE_PRINT_NEWLINE,
617 GATE_PRINT_CSTR, "\tExecutes only test cases named by arguments", GATE_PRINT_NEWLINE,
618 GATE_PRINT_CSTR, "testapp --trace test_case_name1 test_case_name2", GATE_PRINT_NEWLINE,
619 GATE_PRINT_CSTR, "\tExecutes given test cases with trace-mode enabled", GATE_PRINT_NEWLINE,
620 GATE_PRINT_END);
621 1 return 0;
622 }
623
624
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 9 times.
10 if (list_tests)
625 {
626
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1 times.
15 for (ndx = 0; ndx != test_cases_count; ++ndx)
627 {
628 14 gate_test_case_t const* tc = &test_cases[ndx];
629 14 gate_stream_print(con,
630 GATE_PRINT_CSTR, tc->name, GATE_PRINT_NEWLINE,
631 GATE_PRINT_END);
632 }
633 1 return 0;
634 }
635
636
637
3/4
✓ Branch 0 taken 47 times.
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 47 times.
✗ Branch 3 not taken.
56 for (ndx = 0; (ndx != test_cases_count) && (selected_test_cases_count < selected_test_cases_max); ++ndx)
638 {
639 47 gate_test_case_t const* tc = &test_cases[ndx];
640
1/2
✓ Branch 1 taken 47 times.
✗ Branch 2 not taken.
47 if (is_test_case_selected(tc->name, test_patterns, test_patterns_count))
641 {
642 47 selected_test_cases[selected_test_cases_count] = test_cases[ndx];
643 47 ++selected_test_cases_count;
644 }
645 }
646
647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (enable_trace)
648 {
649 ✗ gate_test_trace_on();
650 }
651
652
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (enable_junit)
653 {
654 9 gate_test_history_on();
655 }
656
657 9 succeeded = gate_test_cases_run(selected_test_cases, selected_test_cases_count);
658 9 gate_test_print_reports();
659
660
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if (enable_junit)
661 {
662 9 gate_filestream_t* fs = NULL;
663 9 gate_string_t filename = GATE_STRING_INIT_EMPTY;
664 gate_result_t result;
665 char filepath[GATE_MAX_FILENAME_LENGTH];
666 9 gate_size_t filepathlen = sizeof(filepath);
667
668 9 result = gate_env_app_executable_name_str(filepath, &filepathlen);
669
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if(GATE_FAILED(result))
670 {
671 ✗ filepathlen = gate_str_print_text(filepath, sizeof(filepath), "test", 4);
672 }
673 9 gate_str_print_text(&filepath[filepathlen], sizeof(filepath) - filepathlen, ".junit.xml", 10);
674 9 gate_string_create_static(&filename, filepath);
675
676 9 result = gate_file_openstream(&filename, GATE_STREAM_OPEN_WRITE, &fs);
677
1/2
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
9 if(GATE_SUCCEEDED(result))
678 {
679 9 gate_test_print_history((gate_stream_t*)fs, GATE_TEST_HISTORY_FORMAT_JUNIT);
680 9 gate_object_release(fs);
681 }
682 }
683
684 9 gate_test_uninit();
685 9 return succeeded ? 0 : 1;
686 }
687