blob: 6f591f089713f8d4218930c3fb892b990d427217 [file] [log] [blame]
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001/*
2 * Copyright © 2015 Samsung Electronics Co., Ltd
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26#include "config.h"
27
28#include <errno.h>
29#include <fcntl.h>
30#include <stdarg.h>
31#include <stdbool.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <sys/types.h>
36#include <sys/wait.h>
37#include <time.h>
38#include <unistd.h>
39
40#include "zunitc/zunitc_impl.h"
41#include "zunitc/zunitc.h"
42
43#include "zuc_base_logger.h"
44#include "zuc_collector.h"
45#include "zuc_context.h"
46#include "zuc_event_listener.h"
Jon A. Cruz646aef52015-07-15 19:22:41 -070047#include "zuc_junit_reporter.h"
Jon A. Cruz5a75a412015-07-02 23:36:44 -070048
49#include "shared/config-parser.h"
50#include "shared/helpers.h"
51#include "shared/zalloc.h"
52
53/*
54 * If CLOCK_MONOTONIC is present on the system it will give us reliable
55 * results under certain edge conditions that normally require manual
56 * admin actions to trigger. If not, CLOCK_REALTIME is a reasonable
57 * fallback.
58 */
59#if _POSIX_MONOTONIC_CLOCK
60static const clockid_t TARGET_TIMER = CLOCK_MONOTONIC;
61#else
62static const clockid_t TARGET_TIMER = CLOCK_REALTIME;
63#endif
64
65static char const DISABLED_PREFIX[] = "DISABLED_";
66
67#define MS_PER_SEC 1000L
68#define NANO_PER_MS 1000000L
69
70/**
71 * Simple single-linked list structure.
72 */
73struct zuc_slinked {
74 void *data;
75 struct zuc_slinked *next;
76};
77
78static struct zuc_context g_ctx = {
79 .case_count = 0,
80 .cases = NULL,
81
82 .fatal = false,
83 .repeat = 0,
84 .random = 0,
85 .spawn = true,
86 .break_on_failure = false,
87 .fds = {-1, -1},
88
89 .listeners = NULL,
90
91 .curr_case = NULL,
92 .curr_test = NULL,
93};
94
95static char *g_progname = NULL;
96static char *g_progbasename = NULL;
97
98typedef int (*comp_pred2)(intptr_t lhs, intptr_t rhs);
99
100static bool
101test_has_skip(struct zuc_test *test)
102{
103 return test->skipped;
104}
105
106static bool
107test_has_failure(struct zuc_test *test)
108{
109 return test->fatal || test->failed;
110}
111
112bool
113zuc_has_skip(void)
114{
115 return g_ctx.curr_test ?
116 test_has_skip(g_ctx.curr_test) : false;
117}
118
119bool
120zuc_has_failure(void)
121{
122 return g_ctx.curr_test ?
123 test_has_failure(g_ctx.curr_test) : false;
124}
125
126void
127zuc_set_filter(const char *filter)
128{
129 g_ctx.filter = strdup(filter);
130}
131
132void
133zuc_set_repeat(int repeat)
134{
135 g_ctx.repeat = repeat;
136}
137
138void
139zuc_set_random(int random)
140{
141 g_ctx.random = random;
142}
143
144void
145zuc_set_spawn(bool spawn)
146{
147 g_ctx.spawn = spawn;
148}
149
150void
151zuc_set_break_on_failure(bool break_on_failure)
152{
153 g_ctx.break_on_failure = break_on_failure;
154}
155
Jon A. Cruz646aef52015-07-15 19:22:41 -0700156void
157zuc_set_output_junit(bool enable)
158{
159 g_ctx.output_junit = enable;
160}
161
Jon A. Cruz5a75a412015-07-02 23:36:44 -0700162const char *
163zuc_get_program_name(void)
164{
165 return g_progname;
166}
167
168const char *
169zuc_get_program_basename(void)
170{
171 return g_progbasename;
172}
173
174static struct zuc_test *
175create_test(int order, zucimpl_test_fn fn, zucimpl_test_fn_f fn_f,
176 char const *case_name, char const *test_name,
177 struct zuc_case *parent)
178{
179 struct zuc_test *test = zalloc(sizeof(struct zuc_test));
180 ZUC_ASSERTG_NOT_NULL(test, out);
181 test->order = order;
182 test->fn = fn;
183 test->fn_f = fn_f;
184 test->name = strdup(test_name);
185 if ((!fn && !fn_f) ||
186 (strncmp(DISABLED_PREFIX,
187 test_name, sizeof(DISABLED_PREFIX) - 1) == 0))
188 test->disabled = 1;
189
190 test->test_case = parent;
191
192out:
193 return test;
194}
195
196static int
197compare_regs(const void *lhs, const void *rhs)
198{
199 int rc = strcmp((*(struct zuc_registration **)lhs)->tcase,
200 (*(struct zuc_registration **)rhs)->tcase);
201 if (rc == 0)
202 rc = strcmp((*(struct zuc_registration **)lhs)->test,
203 (*(struct zuc_registration **)rhs)->test);
204
205 return rc;
206}
207
208/* gcc-specific markers for auto test case registration: */
209extern const struct zuc_registration __start_zuc_tsect;
210extern const struct zuc_registration __stop_zuc_tsect;
211
212static void
213register_tests(void)
214{
215 size_t case_count = 0;
216 size_t count = &__stop_zuc_tsect - &__start_zuc_tsect;
217 size_t i;
218 int idx = 0;
219 const char *last_name = NULL;
220 void **array = zalloc(sizeof(void *) * count);
221 ZUC_ASSERT_NOT_NULL(array);
222 for (i = 0; i < count; ++i)
223 array[i] = (void *)(&__start_zuc_tsect + i);
224
225 qsort(array, count, sizeof(array[0]), compare_regs);
226
227 /* Count transitions to get number of test cases. */
228 last_name = NULL;
229 for (i = 0; i < count; ++i) {
230 const struct zuc_registration *reg =
231 (const struct zuc_registration *)array[i];
232 if (!last_name || (strcmp(last_name, reg->tcase))) {
233 last_name = reg->tcase;
234 case_count++;
235 }
236 }
237
238 /* Create test case data items. */
239 struct zuc_case **case_array =
240 zalloc(sizeof(struct zuc_case *) * case_count);
241 ZUC_ASSERT_NOT_NULL(case_array);
242 struct zuc_case *last_case = NULL;
243 size_t case_num = 0;
244 for (i = 0; i < count; ++i) {
245 const struct zuc_registration *reg =
246 (const struct zuc_registration *)array[i];
247 if (!last_case || (strcmp(last_case->name, reg->tcase))) {
248 last_case = zalloc(sizeof(struct zuc_case));
249 ZUC_ASSERT_NOT_NULL(last_case);
250 last_case->order = count;
251 last_case->name = strdup(reg->tcase);
252 last_case->fxt = reg->fxt;
253 last_case->test_count = i;
254 if (case_num > 0) {
255 int tcount = i
256 - case_array[case_num - 1]->test_count;
257 case_array[case_num - 1]->test_count = tcount;
258 }
259 case_array[case_num++] = last_case;
260 }
261 }
262 case_array[case_count - 1]->test_count = count
263 - case_array[case_count - 1]->test_count;
264
265 /* Reserve space for tests per test case. */
266 for (case_num = 0; case_num < case_count; ++case_num) {
267 case_array[case_num]->tests =
268 zalloc(case_array[case_num]->test_count
269 * sizeof(struct zuc_test *));
270 ZUC_ASSERT_NOT_NULL(case_array[case_num]->tests);
271 }
272
273 last_name = NULL;
274 case_num = -1;
275 for (i = 0; i < count; ++i) {
276 const struct zuc_registration *reg =
277 (const struct zuc_registration *)array[i];
278 int order = count - (1 + (reg - &__start_zuc_tsect));
279
280 if (!last_name || (strcmp(last_name, reg->tcase))) {
281 last_name = reg->tcase;
282 case_num++;
283 idx = 0;
284 }
285 if (order < case_array[case_num]->order)
286 case_array[case_num]->order = order;
287 case_array[case_num]->tests[idx] =
288 create_test(order, reg->fn, reg->fn_f,
289 reg->tcase, reg->test,
290 case_array[case_num]);
291
292 if (case_array[case_num]->fxt != reg->fxt)
293 printf("%s:%d: error: Mismatched fixtures for '%s'\n",
294 __FILE__, __LINE__, case_array[case_num]->name);
295
296 idx++;
297 }
298 free(array);
299
300 g_ctx.case_count = case_count;
301 g_ctx.cases = case_array;
302}
303
304static int
305compare_case_order(const void *lhs, const void *rhs)
306{
307 return (*(struct zuc_case **)lhs)->order
308 - (*(struct zuc_case **)rhs)->order;
309}
310
311static int
312compare_test_order(const void *lhs, const void *rhs)
313{
314 return (*(struct zuc_test **)lhs)->order
315 - (*(struct zuc_test **)rhs)->order;
316}
317
318static void
319order_cases(int count, struct zuc_case **cases)
320{
321 int i;
322 qsort(cases, count, sizeof(*cases), compare_case_order);
323 for (i = 0; i < count; ++i) {
324 qsort(cases[i]->tests, cases[i]->test_count,
325 sizeof(*cases[i]->tests), compare_test_order);
326 }
327}
328
329static void
330free_events(struct zuc_event **events)
331{
332 struct zuc_event *evt = *events;
333 *events = NULL;
334 while (evt) {
335 struct zuc_event *old = evt;
336 evt = evt->next;
337 free(old->file);
338 if (old->valtype == ZUC_VAL_CSTR) {
339 free((void *)old->val1);
340 free((void *)old->val2);
341 }
342 free(old->expr1);
343 free(old->expr2);
344 free(old);
345 }
346}
347
348static void
349free_test(struct zuc_test *test)
350{
351 free(test->name);
352 free_events(&test->events);
353 free_events(&test->deferred);
354 free(test);
355}
356
357static void
358free_test_case(struct zuc_case *test_case)
359{
360 int i;
361 free(test_case->name);
362 for (i = test_case->test_count - 1; i >= 0; --i) {
363 free_test(test_case->tests[i]);
364 test_case->tests[i] = NULL;
365 }
366 free(test_case->tests);
367 free(test_case);
368}
369
370/**
371 * A very simple matching that is compatible with the algorithm used in
372 * Google Test.
373 *
374 * @param wildcard sequence of '?', '*' or normal characters to match.
375 * @param str string to check for matching.
376 * @return true if the wildcard matches the entire string, false otherwise.
377 */
378static bool
379wildcard_matches(char const *wildcard, char const *str)
380{
381 switch (*wildcard) {
382 case '\0':
383 return !*str;
384 case '?':
385 return *str && wildcard_matches(wildcard + 1, str + 1);
386 case '*':
387 return (*str && wildcard_matches(wildcard, str + 1))
388 || wildcard_matches(wildcard + 1, str);
389 default:
390 return (*wildcard == *str)
391 && wildcard_matches(wildcard + 1, str + 1);
392 };
393}
394
395static char**
396segment_str(char *str)
397{
398 int count = 1;
399 char **parts = NULL;
400 char *saved = NULL;
401 char *tok = NULL;
402 int i = 0;
403 for (i = 0; str[i]; ++i)
404 if (str[i] == ':')
405 count++;
406 parts = zalloc(sizeof(char*) * (count + 1));
407 ZUC_ASSERTG_NOT_NULL(parts, out);
408 tok = strtok_r(str, ":", &saved);
409 i = 0;
410 parts[i++] = tok;
411 while (tok) {
412 tok = strtok_r(NULL, ":", &saved);
413 parts[i++] = tok;
414 }
415out:
416 return parts;
417}
418
419static void
420filter_cases(int *count, struct zuc_case **cases, char const *filter)
421{
422 int i = 0;
423 int j = 0;
424 int num_pos = 0;
425 int negative = -1;
426 char *buf = strdup(filter);
427 char **parts = segment_str(buf);
428
429 for (i = 0; parts[i]; ++i) {
430 if (parts[i][0] == '-') {
431 parts[i]++;
432 negative = i;
433 break;
434 }
435 num_pos++;
436 }
437
438 for (i = 0; i < *count; ++i) {
439 /* Walk backwards for easier pruning. */
440 for (j = cases[i]->test_count - 1; j >= 0; --j) {
441 int x;
442 bool keep = num_pos == 0;
443 char *name = NULL;
444 struct zuc_test *test = cases[i]->tests[j];
445 if (asprintf(&name, "%s.%s", cases[i]->name,
446 test->name) < 0) {
447 printf("%s:%d: error: %d\n", __FILE__, __LINE__,
448 errno);
449 exit(EXIT_FAILURE);
450 }
451 for (x = 0; (x < num_pos) && !keep; ++x)
452 keep = wildcard_matches(parts[x], name);
453 if (keep && (negative >= 0))
454 for (x = negative; parts[x] && keep; ++x)
455 keep &= !wildcard_matches(parts[x],
456 name);
457 if (!keep) {
458 int w;
459 free_test(test);
460 for (w = j + 1; w < cases[i]->test_count; w++)
461 cases[i]->tests[w - 1] =
462 cases[i]->tests[w];
463 cases[i]->test_count--;
464 }
465
466 free(name);
467 }
468 }
469 free(parts);
470 parts = NULL;
471 free(buf);
472 buf = NULL;
473
474 /* Prune any cases with no more tests. */
475 for (i = *count - 1; i >= 0; --i) {
476 if (cases[i]->test_count < 1) {
477 free_test_case(cases[i]);
478 for (j = i + 1; j < *count; ++j)
479 cases[j - 1] = cases[j];
480 cases[*count - 1] = NULL;
481 (*count)--;
482 }
483 }
484}
485
486static unsigned int
487get_seed_from_time(void)
488{
489 time_t sec = time(NULL);
490 unsigned int seed = (unsigned int) sec % 100000;
491 if (seed < 2)
492 seed = 2;
493
494 return seed;
495}
496
497static void
498initialize(void)
499{
500 static bool init = false;
501 if (init)
502 return;
503
504 init = true;
505 register_tests();
506 if (g_ctx.fatal)
507 return;
508
509 if (g_ctx.random > 1) {
510 g_ctx.seed = g_ctx.random;
511 } else if (g_ctx.random == 1) {
512 g_ctx.seed = get_seed_from_time();
513 }
514
515 if (g_ctx.case_count) {
516 order_cases(g_ctx.case_count, g_ctx.cases);
517 if (g_ctx.filter && g_ctx.filter[0])
518 filter_cases(&g_ctx.case_count, g_ctx.cases,
519 g_ctx.filter);
520 }
521}
522
523int
524zuc_initialize(int *argc, char *argv[], bool *help_flagged)
525{
526 int rc = EXIT_FAILURE;
527 int opt_help = 0;
528 int opt_nofork = 0;
529 int opt_list = 0;
530 int opt_repeat = 0;
531 int opt_random = 0;
532 int opt_break_on_failure = 0;
Jon A. Cruz646aef52015-07-15 19:22:41 -0700533 int opt_junit = 0;
Jon A. Cruz5a75a412015-07-02 23:36:44 -0700534 char *opt_filter = NULL;
535
536 char *help_param = NULL;
537 int argc_in = *argc;
538
539 const struct weston_option options[] = {
540 { WESTON_OPTION_BOOLEAN, "zuc-nofork", 0, &opt_nofork },
541 { WESTON_OPTION_BOOLEAN, "zuc-list-tests", 0, &opt_list },
542 { WESTON_OPTION_INTEGER, "zuc-repeat", 0, &opt_repeat },
543 { WESTON_OPTION_INTEGER, "zuc-random", 0, &opt_random },
544 { WESTON_OPTION_BOOLEAN, "zuc-break-on-failure", 0,
545 &opt_break_on_failure },
Jon A. Cruz646aef52015-07-15 19:22:41 -0700546#if ENABLE_JUNIT_XML
547 { WESTON_OPTION_BOOLEAN, "zuc-output-xml", 0, &opt_junit },
548#endif
Jon A. Cruz5a75a412015-07-02 23:36:44 -0700549 { WESTON_OPTION_STRING, "zuc-filter", 0, &opt_filter },
550 };
551
552 /*
553 *If a test binary is linked to our libzunitcmain it might want
554 * to access the program 'name' from argv[0]
555 */
556 free(g_progname);
557 g_progname = NULL;
558 free(g_progbasename);
559 g_progbasename = NULL;
560 if ((*argc > 0) && argv) {
561 char *path = NULL;
562 char *base = NULL;
563
564 g_progname = strdup(argv[0]);
565
566 /* basename() might modify the input, so needs a writeable
567 * string.
568 * It also may return a statically allocated buffer subject to
569 * being overwritten so needs to be dup'd.
570 */
571 path = strdup(g_progname);
572 base = basename(path);
573 g_progbasename = strdup(base);
574 free(path);
575 } else {
576 g_progname = strdup("");
577 printf("%s:%d: warning: No valid argv[0] for initialization\n",
578 __FILE__, __LINE__);
579 }
580
581
582 initialize();
583 if (g_ctx.fatal)
584 return EXIT_FAILURE;
585
586 if (help_flagged)
587 *help_flagged = false;
588
589 {
590 /* Help param will be a special case and need restoring. */
591 int i = 0;
592 char **argv_in = NULL;
593 const struct weston_option help_options[] = {
594 { WESTON_OPTION_BOOLEAN, "help", 'h', &opt_help },
595 };
596 argv_in = zalloc(sizeof(char *) * argc_in);
597 if (!argv_in) {
598 printf("%s:%d: error: alloc failed.\n",
599 __FILE__, __LINE__);
600 return EXIT_FAILURE;
601 }
602 for (i = 0; i < argc_in; ++i)
603 argv_in[i] = argv[i];
604
605 parse_options(help_options, ARRAY_LENGTH(help_options),
606 argc, argv);
607 if (*argc < argc_in) {
608 for (i = 1; (i < argc_in) && !help_param; ++i) {
609 bool found = false;
610 int j = 0;
611 for (j = 0; (j < *argc) && !found; ++j)
612 found = (argv[j] == argv_in[i]);
613
614 if (!found)
615 help_param = argv_in[i];
616 }
617 }
618 free(argv_in);
619 }
620
621 parse_options(options, ARRAY_LENGTH(options), argc, argv);
622
623 if (help_param && (*argc < argc_in))
624 argv[(*argc)++] = help_param;
625
626 if (opt_filter) {
627 zuc_set_filter(opt_filter);
628 free(opt_filter);
629 }
630
631 if (opt_help) {
632 printf("Usage: %s [OPTIONS]\n"
633 " --zuc-break-on-failure\n"
634 " --zuc-filter=FILTER\n"
635 " --zuc-list-tests\n"
636 " --zuc-nofork\n"
Jon A. Cruz646aef52015-07-15 19:22:41 -0700637#if ENABLE_JUNIT_XML
638 " --zuc-output-xml\n"
639#endif
Jon A. Cruz5a75a412015-07-02 23:36:44 -0700640 " --zuc-random=N [0|1|<seed number>]\n"
641 " --zuc-repeat=N\n"
642 " --help\n",
643 argv[0]);
644 if (help_flagged)
645 *help_flagged = true;
646 rc = EXIT_SUCCESS;
647 } else if (opt_list) {
648 zuc_list_tests();
649 rc = EXIT_FAILURE;
650 } else {
651 zuc_set_repeat(opt_repeat);
652 zuc_set_random(opt_random);
653 zuc_set_spawn(!opt_nofork);
654 zuc_set_break_on_failure(opt_break_on_failure);
Jon A. Cruz646aef52015-07-15 19:22:41 -0700655 zuc_set_output_junit(opt_junit);
Jon A. Cruz5a75a412015-07-02 23:36:44 -0700656 rc = EXIT_SUCCESS;
657 }
658
659 return rc;
660}
661
662static void
663dispatch_pre_run(struct zuc_context *ctx, int pass_count, int pass_num,
664 int seed, const char *filter)
665{
666 struct zuc_slinked *curr;
667 for (curr = ctx->listeners; curr; curr = curr->next) {
668 struct zuc_event_listener *listener = curr->data;
669 if (listener->pre_run)
670 listener->pre_run(listener->data,
671 pass_count,
672 pass_num,
673 seed,
674 filter);
675 }
676}
677
678static void
679dispatch_run_started(struct zuc_context *ctx, int live_case_count,
680 int live_test_count, int disabled_count)
681{
682 struct zuc_slinked *curr;
683 for (curr = ctx->listeners; curr; curr = curr->next) {
684 struct zuc_event_listener *listener = curr->data;
685 if (listener->run_started)
686 listener->run_started(listener->data,
687 live_case_count,
688 live_test_count,
689 disabled_count);
690 }
691}
692
693static void
694dispatch_run_ended(struct zuc_context *ctx,
695 int live_case_count, int live_test_count, int total_passed,
696 int total_failed, int total_disabled, long total_elapsed)
697{
698 struct zuc_slinked *curr;
699 for (curr = ctx->listeners; curr; curr = curr->next) {
700 struct zuc_event_listener *listener = curr->data;
701 if (listener->run_ended)
702 listener->run_ended(listener->data,
703 ctx->case_count,
704 ctx->cases,
705 live_case_count,
706 live_test_count,
707 total_passed,
708 total_failed,
709 total_disabled,
710 total_elapsed);
711 }
712}
713
714static void
715dispatch_case_started(struct zuc_context *ctx,struct zuc_case *test_case,
716 int live_test_count, int disabled_count)
717{
718 struct zuc_slinked *curr;
719 for (curr = ctx->listeners; curr; curr = curr->next) {
720 struct zuc_event_listener *listener = curr->data;
721 if (listener->case_started)
722 listener->case_started(listener->data,
723 test_case,
724 live_test_count,
725 disabled_count);
726 }
727}
728
729static void
730dispatch_case_ended(struct zuc_context *ctx, struct zuc_case *test_case)
731{
732 struct zuc_slinked *curr;
733 for (curr = ctx->listeners; curr; curr = curr->next) {
734 struct zuc_event_listener *listener = curr->data;
735 if (listener->case_ended)
736 listener->case_ended(listener->data, test_case);
737 }
738}
739
740static void
741dispatch_test_started(struct zuc_context *ctx, struct zuc_test *test)
742{
743 struct zuc_slinked *curr;
744 for (curr = ctx->listeners; curr; curr = curr->next) {
745 struct zuc_event_listener *listener = curr->data;
746 if (listener->test_started)
747 listener->test_started(listener->data, test);
748 }
749}
750
751static void
752dispatch_test_ended(struct zuc_context *ctx, struct zuc_test *test)
753{
754 struct zuc_slinked *curr;
755 for (curr = ctx->listeners; curr; curr = curr->next) {
756 struct zuc_event_listener *listener = curr->data;
757 if (listener->test_ended)
758 listener->test_ended(listener->data, test);
759 }
760}
761
762static void
763dispatch_test_disabled(struct zuc_context *ctx, struct zuc_test *test)
764{
765 struct zuc_slinked *curr;
766 for (curr = ctx->listeners; curr; curr = curr->next) {
767 struct zuc_event_listener *listener = curr->data;
768 if (listener->test_disabled)
769 listener->test_disabled(listener->data, test);
770 }
771}
772
773static void
774dispatch_check_triggered(struct zuc_context *ctx, char const *file, int line,
775 enum zuc_fail_state state, enum zuc_check_op op,
776 enum zuc_check_valtype valtype,
777 intptr_t val1, intptr_t val2,
778 const char *expr1, const char *expr2)
779{
780 struct zuc_slinked *curr;
781 for (curr = ctx->listeners; curr; curr = curr->next) {
782 struct zuc_event_listener *listener = curr->data;
783 if (listener->check_triggered)
784 listener->check_triggered(listener->data,
785 file, line,
786 state, op, valtype,
787 val1, val2,
788 expr1, expr2);
789 }
790}
791
792static void
793dispatch_collect_event(struct zuc_context *ctx, char const *file, int line,
794 const char *expr1)
795{
796 struct zuc_slinked *curr;
797 for (curr = ctx->listeners; curr; curr = curr->next) {
798 struct zuc_event_listener *listener = curr->data;
799 if (listener->collect_event)
800 listener->collect_event(listener->data,
801 file, line, expr1);
802 }
803}
804
805static void
806migrate_deferred_events(struct zuc_test *test, bool transferred)
807{
808 struct zuc_event *evt = test->deferred;
809 if (!evt)
810 return;
811
812 test->deferred = NULL;
813 if (test->events) {
814 struct zuc_event *old = test->events;
815 while (old->next)
816 old = old->next;
817 old->next = evt;
818 } else {
819 test->events = evt;
820 }
821 while (evt && !transferred) {
822 dispatch_check_triggered(&g_ctx,
823 evt->file, evt->line,
824 evt->state, evt->op,
825 evt->valtype,
826 evt->val1, evt->val2,
827 evt->expr1, evt->expr2);
828 evt = evt->next;
829 }
830}
831
832static void
833mark_single_failed(struct zuc_test *test, enum zuc_fail_state state)
834{
835 switch (state) {
836 case ZUC_CHECK_OK:
837 /* no internal state to change */
838 break;
839 case ZUC_CHECK_SKIP:
840 if (test)
841 test->skipped = 1;
842 break;
843 case ZUC_CHECK_FAIL:
844 if (test)
845 test->failed = 1;
846 break;
847 case ZUC_CHECK_ERROR:
848 case ZUC_CHECK_FATAL:
849 if (test)
850 test->fatal = 1;
851 break;
852 }
853
854 if (g_ctx.break_on_failure)
855 raise(SIGABRT);
856
857}
858
859static void
860mark_failed(struct zuc_test *test, enum zuc_fail_state state)
861{
862 if (!test && g_ctx.curr_test)
863 test = g_ctx.curr_test;
864
865 if (test) {
866 mark_single_failed(test, state);
867 } else if (g_ctx.curr_case) {
868 /* In setup or tear-down of test suite */
869 int i;
870 for (i = 0; i < g_ctx.curr_case->test_count; ++i)
871 mark_single_failed(g_ctx.curr_case->tests[i], state);
872 }
873 if ((state == ZUC_CHECK_FATAL) || (state == ZUC_CHECK_ERROR))
874 g_ctx.fatal = true;
875}
876
877void
878zuc_attach_event(struct zuc_test *test, struct zuc_event *event,
879 enum zuc_event_type event_type, bool transferred)
880{
881 if (!test) {
882 /*
883 * consider adding events directly to the case.
884 * would be for use during per-suite setup and teardown.
885 */
886 printf("%s:%d: error: No current test.\n", __FILE__, __LINE__);
887 } else if (event_type == ZUC_EVENT_DEFERRED) {
888 if (test->deferred) {
889 struct zuc_event *curr = test->deferred;
890 while (curr->next)
891 curr = curr->next;
892 curr->next = event;
893 } else {
894 test->deferred = event;
895 }
896 } else {
897 if (test)
898 migrate_deferred_events(test, transferred);
899
900 if (test->events) {
901 struct zuc_event *curr = test->events;
902 while (curr->next)
903 curr = curr->next;
904 curr->next = event;
905 } else {
906 test->events = event;
907 }
908 mark_failed(test, event->state);
909 }
910}
911
912void
913zuc_add_event_listener(struct zuc_event_listener *event_listener)
914{
915 if (!event_listener) /* ensure null entries are not added */
916 return;
917
918 if (!g_ctx.listeners) {
919 g_ctx.listeners = zalloc(sizeof(struct zuc_slinked));
920 ZUC_ASSERT_NOT_NULL(g_ctx.listeners);
921 g_ctx.listeners->data = event_listener;
922 } else {
923 struct zuc_slinked *curr = g_ctx.listeners;
924 while (curr->next)
925 curr = curr->next;
926 curr->next = zalloc(sizeof(struct zuc_slinked));
927 ZUC_ASSERT_NOT_NULL(curr->next);
928 curr->next->data = event_listener;
929 }
930}
931
932
933void
934zuc_cleanup(void)
935{
936 int i;
937
938 free(g_ctx.filter);
939 g_ctx.filter = 0;
940 for (i = 0; i < 2; ++i)
941 if (g_ctx.fds[i] != -1) {
942 close(g_ctx.fds[i]);
943 g_ctx.fds[i] = -1;
944 }
945
946 if (g_ctx.listeners) {
947 struct zuc_slinked *curr = g_ctx.listeners;
948 while (curr) {
949 struct zuc_slinked *old = curr;
950 struct zuc_event_listener *listener = curr->data;
951 if (listener->destroy)
952 listener->destroy(listener->data);
953 free(listener);
954 curr = curr->next;
955 free(old);
956 }
957 g_ctx.listeners = NULL;
958 }
959
960 for (i = g_ctx.case_count - 1; i >= 0; --i) {
961 free_test_case(g_ctx.cases[i]);
962 g_ctx.cases[i] = NULL;
963 }
964 free(g_ctx.cases);
965 g_ctx.cases = NULL;
966
967 free(g_progname);
968 g_progname = NULL;
969 free(g_progbasename);
970 g_progbasename = NULL;
971}
972
973static void
974shuffle_cases(int count, struct zuc_case **cases,
975 unsigned int seed)
976{
977 int i;
978 unsigned int rseed = seed;
979 for (i = 0; i < count; ++i) {
980 int j;
981 for (j = cases[i]->test_count - 1; j > 0 ; --j) {
982 int val = rand_r(&rseed);
983 int b = ((val / (double)RAND_MAX) * j + 0.5);
984 if (j != b) {
985 struct zuc_test *tmp = cases[i]->tests[j];
986 cases[i]->tests[j] = cases[i]->tests[b];
987 cases[i]->tests[b] = tmp;
988 }
989 }
990 }
991
992 for (i = count - 1; i > 0; --i) {
993 int val = rand_r(&rseed);
994 int j = ((val / (double)RAND_MAX) * i + 0.5);
995
996 if (i != j) {
997 struct zuc_case *tmp = cases[i];
998 cases[i] = cases[j];
999 cases[j] = tmp;
1000 }
1001 }
1002}
1003
1004void
1005zuc_list_tests(void)
1006{
1007 int i;
1008 int j;
1009 initialize();
1010 if (g_ctx.fatal)
1011 return;
1012 for (i = 0; i < g_ctx.case_count; ++i) {
1013 printf("%s.\n", g_ctx.cases[i]->name);
1014 for (j = 0; j < g_ctx.cases[i]->test_count; ++j) {
1015 printf(" %s\n", g_ctx.cases[i]->tests[j]->name);
1016 }
1017 }
1018}
1019
1020static void
1021spawn_test(struct zuc_test *test, void *test_data,
1022 void (*cleanup_fn)(void *data), void *cleanup_data)
1023{
1024 pid_t pid = -1;
1025
1026 if (!test || (!test->fn && !test->fn_f))
1027 return;
1028
1029 if (pipe2(g_ctx.fds, O_CLOEXEC)) {
1030 printf("%s:%d: error: Unable to create pipe: %d\n",
1031 __FILE__, __LINE__, errno);
1032 mark_failed(test, ZUC_CHECK_ERROR);
1033 return;
1034 }
1035
1036 fflush(NULL); /* important. avoid duplication of output */
1037 pid = fork();
1038 switch (pid) {
1039 case -1: /* Error forking */
1040 printf("%s:%d: error: Problem with fork: %d\n",
1041 __FILE__, __LINE__, errno);
1042 mark_failed(test, ZUC_CHECK_ERROR);
1043 close(g_ctx.fds[0]);
1044 g_ctx.fds[0] = -1;
1045 close(g_ctx.fds[1]);
1046 g_ctx.fds[1] = -1;
1047 break;
1048 case 0: { /* child */
1049 int rc = EXIT_SUCCESS;
1050 close(g_ctx.fds[0]);
1051 g_ctx.fds[0] = -1;
1052
1053 if (test->fn_f)
1054 test->fn_f(test_data);
1055 else
1056 test->fn();
1057
1058 if (test_has_failure(test))
1059 rc = EXIT_FAILURE;
1060 else if (test_has_skip(test))
1061 rc = ZUC_EXIT_SKIP;
1062
1063 /* Avoid confusing memory tools like valgrind */
1064 if (cleanup_fn)
1065 cleanup_fn(cleanup_data);
1066
1067 zuc_cleanup();
1068 exit(rc);
1069 break;
1070 }
1071 default: { /* parent */
1072 ssize_t rc = 0;
1073 siginfo_t info = {};
1074
1075 close(g_ctx.fds[1]);
1076 g_ctx.fds[1] = -1;
1077
1078 do {
1079 rc = zuc_process_message(g_ctx.curr_test,
1080 g_ctx.fds[0]);
1081 } while (rc > 0);
1082 close(g_ctx.fds[0]);
1083 g_ctx.fds[0] = -1;
1084
1085 if (waitid(P_ALL, 0, &info, WEXITED)) {
1086 printf("%s:%d: error: waitid failed. (%d)\n",
1087 __FILE__, __LINE__, errno);
1088 mark_failed(test, ZUC_CHECK_ERROR);
1089 } else {
1090 switch (info.si_code) {
1091 case CLD_EXITED: {
1092 int exit_code = info.si_status;
1093 switch(exit_code) {
1094 case EXIT_SUCCESS:
1095 break;
1096 case ZUC_EXIT_SKIP:
1097 if (!test_has_skip(g_ctx.curr_test) &&
1098 !test_has_failure(g_ctx.curr_test))
1099 ZUC_SKIP("Child exited SKIP");
1100 break;
1101 default:
1102 /* unexpected failure */
1103 if (!test_has_failure(g_ctx.curr_test))
1104 ZUC_ASSERT_EQ(0, exit_code);
1105 }
1106 break;
1107 }
1108 case CLD_KILLED:
1109 case CLD_DUMPED:
1110 printf("%s:%d: error: signaled: %d\n",
1111 __FILE__, __LINE__, info.si_status);
1112 mark_failed(test, ZUC_CHECK_ERROR);
1113 break;
1114 }
1115 }
1116 }
1117 }
1118}
1119
1120static void
1121run_single_test(struct zuc_test *test,const struct zuc_fixture *fxt,
1122 void *case_data, bool spawn)
1123{
1124 long elapsed = 0;
1125 struct timespec begin;
1126 struct timespec end;
1127 void *test_data = NULL;
1128 void *cleanup_data = NULL;
1129 void (*cleanup_fn)(void *data) = NULL;
1130 memset(&begin, 0, sizeof(begin));
1131 memset(&end, 0, sizeof(end));
1132
1133 g_ctx.curr_test = test;
1134 dispatch_test_started(&g_ctx, test);
1135
1136 cleanup_fn = fxt ? fxt->tear_down : NULL;
1137 cleanup_data = NULL;
1138
1139 if (fxt && fxt->set_up) {
1140 test_data = fxt->set_up(case_data);
1141 cleanup_data = test_data;
1142 } else {
1143 test_data = case_data;
1144 }
1145
1146 clock_gettime(TARGET_TIMER, &begin);
1147
1148 /* Need to re-check these, as fixtures might have changed test state. */
1149 if (!test->fatal && !test->skipped) {
1150 if (spawn) {
1151 spawn_test(test, test_data,
1152 cleanup_fn, cleanup_data);
1153 } else {
1154 if (test->fn_f)
1155 test->fn_f(test_data);
1156 else
1157 test->fn();
1158 }
1159 }
1160
1161 clock_gettime(TARGET_TIMER, &end);
1162
1163 elapsed = (end.tv_sec - begin.tv_sec) * MS_PER_SEC;
1164 if (end.tv_sec != begin.tv_sec) {
1165 elapsed -= (begin.tv_nsec) / NANO_PER_MS;
1166 elapsed += (end.tv_nsec) / NANO_PER_MS;
1167 } else {
1168 elapsed += (end.tv_nsec - begin.tv_nsec) / NANO_PER_MS;
1169 }
1170 test->elapsed = elapsed;
1171
1172 if (cleanup_fn)
1173 cleanup_fn(cleanup_data);
1174
1175 if (test->deferred) {
1176 if (test_has_failure(test))
1177 migrate_deferred_events(test, false);
1178 else
1179 free_events(&test->deferred);
1180 }
1181
1182 dispatch_test_ended(&g_ctx, test);
1183
1184 g_ctx.curr_test = NULL;
1185}
1186
1187static void
1188run_single_case(struct zuc_case *test_case)
1189{
1190 int count_live = test_case->test_count - test_case->disabled;
1191 g_ctx.curr_case = test_case;
1192 if (count_live) {
1193 int i = 0;
1194 const struct zuc_fixture *fxt = test_case->fxt;
1195 void *case_data = fxt ? (void *)fxt->data : NULL;
1196
1197 dispatch_case_started(&g_ctx, test_case,
1198 count_live, test_case->disabled);
1199
1200 if (fxt && fxt->set_up_test_case)
1201 case_data = fxt->set_up_test_case(fxt->data);
1202
1203 for (i = 0; i < test_case->test_count; ++i) {
1204 struct zuc_test *curr = test_case->tests[i];
1205 if (curr->disabled) {
1206 dispatch_test_disabled(&g_ctx, curr);
1207 } else {
1208 run_single_test(curr, fxt, case_data,
1209 g_ctx.spawn);
1210 if (curr->skipped)
1211 test_case->skipped++;
1212 if (curr->failed)
1213 test_case->failed++;
1214 if (curr->fatal)
1215 test_case->fatal++;
1216 if (!curr->failed && !curr->fatal)
1217 test_case->passed++;
1218 test_case->elapsed += curr->elapsed;
1219 }
1220 }
1221
1222 if (fxt && fxt->tear_down_test_case)
1223 fxt->tear_down_test_case(case_data);
1224
1225 dispatch_case_ended(&g_ctx, test_case);
1226 }
1227 g_ctx.curr_case = NULL;
1228}
1229
1230static void
1231reset_test_values(struct zuc_case **cases, int case_count)
1232{
1233 int i;
1234 for (i = 0; i < case_count; ++i) {
1235 int j;
1236 cases[i]->disabled = 0;
1237 cases[i]->skipped = 0;
1238 cases[i]->failed = 0;
1239 cases[i]->fatal = 0;
1240 cases[i]->passed = 0;
1241 cases[i]->elapsed = 0;
1242 for (j = 0; j < cases[i]->test_count; ++j) {
1243 struct zuc_test *test = cases[i]->tests[j];
1244 if (test->disabled)
1245 cases[i]->disabled++;
1246 test->skipped = 0;
1247 test->failed = 0;
1248 test->fatal = 0;
1249 test->elapsed = 0;
1250
1251 free_events(&test->events);
1252 free_events(&test->deferred);
1253 }
1254 }
1255}
1256
1257static int
1258run_single_pass(void)
1259{
1260 long total_elapsed = 0;
1261 int total_passed = 0;
1262 int total_failed = 0;
1263 int total_skipped = 0;
1264 int live_case_count = 0;
1265 int live_test_count = 0;
1266 int disabled_test_count = 0;
1267 int i;
1268
1269 reset_test_values(g_ctx.cases, g_ctx.case_count);
1270 for (i = 0; i < g_ctx.case_count; ++i) {
1271 int live = g_ctx.cases[i]->test_count
1272 - g_ctx.cases[i]->disabled;
1273 if (live) {
1274 live_test_count += live;
1275 live_case_count++;
1276 }
1277 if (g_ctx.cases[i]->disabled)
1278 disabled_test_count++;
1279 }
1280
1281 dispatch_run_started(&g_ctx, live_case_count, live_test_count,
1282 disabled_test_count);
1283
1284 for (i = 0; i < g_ctx.case_count; ++i) {
1285 run_single_case(g_ctx.cases[i]);
1286 total_failed += g_ctx.cases[i]->test_count
1287 - (g_ctx.cases[i]->passed + g_ctx.cases[i]->disabled);
1288 total_passed += g_ctx.cases[i]->passed;
1289 total_elapsed += g_ctx.cases[i]->elapsed;
1290 total_skipped += g_ctx.cases[i]->skipped;
1291 }
1292
1293 dispatch_run_ended(&g_ctx, live_case_count, live_test_count,
1294 total_passed, total_failed, disabled_test_count,
1295 total_elapsed);
1296
1297 if (total_failed)
1298 return EXIT_FAILURE;
1299 else if (total_skipped)
1300 return ZUC_EXIT_SKIP;
1301 else
1302 return EXIT_SUCCESS;
1303}
1304
1305int
1306zucimpl_run_tests(void)
1307{
1308 int rc = EXIT_SUCCESS;
1309 int i;
1310 int limit = g_ctx.repeat > 0 ? g_ctx.repeat : 1;
1311
1312 initialize();
1313 if (g_ctx.fatal)
1314 return EXIT_FAILURE;
1315
1316 if (g_ctx.listeners == NULL) {
1317 zuc_add_event_listener(zuc_collector_create(&(g_ctx.fds[1])));
1318 zuc_add_event_listener(zuc_base_logger_create());
Jon A. Cruz646aef52015-07-15 19:22:41 -07001319 if (g_ctx.output_junit)
1320 zuc_add_event_listener(zuc_junit_reporter_create());
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001321 }
1322
1323 if (g_ctx.case_count < 1) {
1324 printf("%s:%d: error: Setup error: test tree is empty\n",
1325 __FILE__, __LINE__);
1326 rc = EXIT_FAILURE;
1327 }
1328
1329 for (i = 0; (i < limit) && (g_ctx.case_count > 0); ++i) {
1330 int pass_code = EXIT_SUCCESS;
1331 dispatch_pre_run(&g_ctx, limit, i + 1,
1332 (g_ctx.random > 0) ? g_ctx.seed : 0,
1333 g_ctx.filter);
1334
1335 order_cases(g_ctx.case_count, g_ctx.cases);
1336 if (g_ctx.random > 0)
1337 shuffle_cases(g_ctx.case_count, g_ctx.cases,
1338 g_ctx.seed);
1339
1340 pass_code = run_single_pass();
1341 if (pass_code == EXIT_FAILURE)
1342 rc = EXIT_FAILURE;
1343 else if ((pass_code == ZUC_EXIT_SKIP) && (rc == EXIT_SUCCESS))
1344 rc = ZUC_EXIT_SKIP;
1345
1346 g_ctx.seed++;
1347 }
1348
1349 return rc;
1350}
1351
1352int
1353zucimpl_tracepoint(char const *file, int line, char const *fmt, ...)
1354{
1355 int rc = -1;
1356 va_list argp;
1357 char *msg = NULL;
1358
1359
1360 va_start(argp, fmt);
1361 rc = vasprintf(&msg, fmt, argp);
1362 if (rc == -1) {
1363 msg = NULL;
1364 }
1365 va_end(argp);
1366
1367 dispatch_collect_event(&g_ctx,
1368 file, line,
1369 msg);
1370
1371 free(msg);
1372
1373 return rc;
1374}
1375
1376void
1377zucimpl_terminate(char const *file, int line,
1378 bool fail, bool fatal, const char *msg)
1379{
1380 enum zuc_fail_state state = ZUC_CHECK_SKIP;
1381 int level = 2;
1382 if (fail && fatal) {
1383 state = ZUC_CHECK_FATAL;
1384 level = 0;
1385 } else if (fail && !fatal) {
1386 state = ZUC_CHECK_FAIL;
1387 level = 0;
1388 }
1389
1390 mark_failed(g_ctx.curr_test, state);
1391
1392 if ((state != ZUC_CHECK_OK) && g_ctx.curr_test)
1393 migrate_deferred_events(g_ctx.curr_test, false);
1394
1395 dispatch_check_triggered(&g_ctx,
1396 file, line,
1397 state,
1398 ZUC_OP_TERMINATE, ZUC_VAL_INT,
1399 level, 0,
1400 msg, "");
1401}
1402
1403static void
1404validate_types(enum zuc_check_op op, enum zuc_check_valtype valtype)
1405{
1406 bool is_valid = true;
1407
1408 switch (op) {
1409 case ZUC_OP_NULL:
1410 case ZUC_OP_NOT_NULL:
1411 is_valid = is_valid && (valtype == ZUC_VAL_PTR);
1412 break;
1413 default:
1414 ; /* all rest OK */
1415 }
1416
1417 switch (valtype) {
1418 case ZUC_VAL_CSTR:
1419 is_valid = is_valid && ((op == ZUC_OP_EQ) || (op == ZUC_OP_NE));
1420 break;
1421 default:
1422 ; /* all rest OK */
1423 }
1424
1425 if (!is_valid)
1426 printf("%s:%d: warning: Unexpected op+type %d/%d.\n",
1427 __FILE__, __LINE__, op, valtype);
1428}
1429
1430static int
1431pred2_unknown(intptr_t lhs, intptr_t rhs)
1432{
1433 return 0;
1434}
1435
1436static int
1437pred2_true(intptr_t lhs, intptr_t rhs)
1438{
1439 return lhs;
1440}
1441
1442static int
1443pred2_false(intptr_t lhs, intptr_t rhs)
1444{
1445 return !lhs;
1446}
1447
1448static int
1449pred2_eq(intptr_t lhs, intptr_t rhs)
1450{
1451 return lhs == rhs;
1452}
1453
1454static int
1455pred2_streq(intptr_t lhs, intptr_t rhs)
1456{
1457 int status = 0;
1458 const char *lhptr = (const char *)lhs;
1459 const char *rhptr = (const char *)rhs;
1460
1461 if (!lhptr && !rhptr)
1462 status = 1;
1463 else if (lhptr && rhptr)
1464 status = strcmp(lhptr, rhptr) == 0;
1465
1466 return status;
1467}
1468
1469static int
1470pred2_ne(intptr_t lhs, intptr_t rhs)
1471{
1472 return lhs != rhs;
1473}
1474
1475static int
1476pred2_strne(intptr_t lhs, intptr_t rhs)
1477{
1478 int status = 0;
1479 const char *lhptr = (const char *)lhs;
1480 const char *rhptr = (const char *)rhs;
1481
1482 if (lhptr != rhptr) {
1483 if (!lhptr || !rhptr)
1484 status = 1;
1485 else
1486 status = strcmp(lhptr, rhptr) != 0;
1487 }
1488
1489 return status;
1490}
1491
1492static int
1493pred2_ge(intptr_t lhs, intptr_t rhs)
1494{
1495 return lhs >= rhs;
1496}
1497
1498static int
1499pred2_gt(intptr_t lhs, intptr_t rhs)
1500{
1501 return lhs > rhs;
1502}
1503
1504static int
1505pred2_le(intptr_t lhs, intptr_t rhs)
1506{
1507 return lhs <= rhs;
1508}
1509
1510static int
1511pred2_lt(intptr_t lhs, intptr_t rhs)
1512{
1513 return lhs < rhs;
1514}
1515
1516static comp_pred2
1517get_pred2(enum zuc_check_op op, enum zuc_check_valtype valtype)
1518{
1519 switch (op) {
1520 case ZUC_OP_TRUE:
1521 return pred2_true;
1522 break;
1523 case ZUC_OP_FALSE:
1524 return pred2_false;
1525 break;
1526 case ZUC_OP_NULL:
1527 return pred2_false;
1528 break;
1529 case ZUC_OP_NOT_NULL:
1530 return pred2_true;
1531 break;
1532 case ZUC_OP_EQ:
1533 if (valtype == ZUC_VAL_CSTR)
1534 return pred2_streq;
1535 else
1536 return pred2_eq;
1537 break;
1538 case ZUC_OP_NE:
1539 if (valtype == ZUC_VAL_CSTR)
1540 return pred2_strne;
1541 else
1542 return pred2_ne;
1543 break;
1544 case ZUC_OP_GE:
1545 return pred2_ge;
1546 break;
1547 case ZUC_OP_GT:
1548 return pred2_gt;
1549 break;
1550 case ZUC_OP_LE:
1551 return pred2_le;
1552 break;
1553 case ZUC_OP_LT:
1554 return pred2_lt;
1555 break;
1556 default:
1557 return pred2_unknown;
1558 }
1559}
1560
1561int
1562zucimpl_expect_pred2(char const *file, int line,
1563 enum zuc_check_op op, enum zuc_check_valtype valtype,
1564 bool fatal,
1565 intptr_t lhs, intptr_t rhs,
1566 const char *lhs_str, const char* rhs_str)
1567{
1568 enum zuc_fail_state state = fatal ? ZUC_CHECK_FATAL : ZUC_CHECK_FAIL;
1569 comp_pred2 pred = get_pred2(op, valtype);
1570 int failed = !pred(lhs, rhs);
1571
1572 validate_types(op, valtype);
1573
1574 if (failed) {
1575 mark_failed(g_ctx.curr_test, state);
1576
1577 if (g_ctx.curr_test)
1578 migrate_deferred_events(g_ctx.curr_test, false);
1579
1580 dispatch_check_triggered(&g_ctx,
1581 file, line,
1582 fatal ? ZUC_CHECK_FATAL
1583 : ZUC_CHECK_FAIL,
1584 op, valtype,
1585 lhs, rhs,
1586 lhs_str, rhs_str);
1587 }
1588 return failed;
1589}