blob: 58a5b174416602472441b35cd6adb3a9f0b960d1 [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);
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001069 }
1070 default: { /* parent */
1071 ssize_t rc = 0;
1072 siginfo_t info = {};
1073
1074 close(g_ctx.fds[1]);
1075 g_ctx.fds[1] = -1;
1076
1077 do {
1078 rc = zuc_process_message(g_ctx.curr_test,
1079 g_ctx.fds[0]);
1080 } while (rc > 0);
1081 close(g_ctx.fds[0]);
1082 g_ctx.fds[0] = -1;
1083
1084 if (waitid(P_ALL, 0, &info, WEXITED)) {
1085 printf("%s:%d: error: waitid failed. (%d)\n",
1086 __FILE__, __LINE__, errno);
1087 mark_failed(test, ZUC_CHECK_ERROR);
1088 } else {
1089 switch (info.si_code) {
1090 case CLD_EXITED: {
1091 int exit_code = info.si_status;
1092 switch(exit_code) {
1093 case EXIT_SUCCESS:
1094 break;
1095 case ZUC_EXIT_SKIP:
1096 if (!test_has_skip(g_ctx.curr_test) &&
1097 !test_has_failure(g_ctx.curr_test))
1098 ZUC_SKIP("Child exited SKIP");
1099 break;
1100 default:
1101 /* unexpected failure */
1102 if (!test_has_failure(g_ctx.curr_test))
1103 ZUC_ASSERT_EQ(0, exit_code);
1104 }
1105 break;
1106 }
1107 case CLD_KILLED:
1108 case CLD_DUMPED:
1109 printf("%s:%d: error: signaled: %d\n",
1110 __FILE__, __LINE__, info.si_status);
1111 mark_failed(test, ZUC_CHECK_ERROR);
1112 break;
1113 }
1114 }
1115 }
1116 }
1117}
1118
1119static void
1120run_single_test(struct zuc_test *test,const struct zuc_fixture *fxt,
1121 void *case_data, bool spawn)
1122{
1123 long elapsed = 0;
1124 struct timespec begin;
1125 struct timespec end;
1126 void *test_data = NULL;
1127 void *cleanup_data = NULL;
1128 void (*cleanup_fn)(void *data) = NULL;
1129 memset(&begin, 0, sizeof(begin));
1130 memset(&end, 0, sizeof(end));
1131
1132 g_ctx.curr_test = test;
1133 dispatch_test_started(&g_ctx, test);
1134
1135 cleanup_fn = fxt ? fxt->tear_down : NULL;
1136 cleanup_data = NULL;
1137
1138 if (fxt && fxt->set_up) {
1139 test_data = fxt->set_up(case_data);
1140 cleanup_data = test_data;
1141 } else {
1142 test_data = case_data;
1143 }
1144
1145 clock_gettime(TARGET_TIMER, &begin);
1146
1147 /* Need to re-check these, as fixtures might have changed test state. */
1148 if (!test->fatal && !test->skipped) {
1149 if (spawn) {
1150 spawn_test(test, test_data,
1151 cleanup_fn, cleanup_data);
1152 } else {
1153 if (test->fn_f)
1154 test->fn_f(test_data);
1155 else
1156 test->fn();
1157 }
1158 }
1159
1160 clock_gettime(TARGET_TIMER, &end);
1161
1162 elapsed = (end.tv_sec - begin.tv_sec) * MS_PER_SEC;
1163 if (end.tv_sec != begin.tv_sec) {
1164 elapsed -= (begin.tv_nsec) / NANO_PER_MS;
1165 elapsed += (end.tv_nsec) / NANO_PER_MS;
1166 } else {
1167 elapsed += (end.tv_nsec - begin.tv_nsec) / NANO_PER_MS;
1168 }
1169 test->elapsed = elapsed;
1170
1171 if (cleanup_fn)
1172 cleanup_fn(cleanup_data);
1173
1174 if (test->deferred) {
1175 if (test_has_failure(test))
1176 migrate_deferred_events(test, false);
1177 else
1178 free_events(&test->deferred);
1179 }
1180
1181 dispatch_test_ended(&g_ctx, test);
1182
1183 g_ctx.curr_test = NULL;
1184}
1185
1186static void
1187run_single_case(struct zuc_case *test_case)
1188{
1189 int count_live = test_case->test_count - test_case->disabled;
1190 g_ctx.curr_case = test_case;
1191 if (count_live) {
1192 int i = 0;
1193 const struct zuc_fixture *fxt = test_case->fxt;
1194 void *case_data = fxt ? (void *)fxt->data : NULL;
1195
1196 dispatch_case_started(&g_ctx, test_case,
1197 count_live, test_case->disabled);
1198
1199 if (fxt && fxt->set_up_test_case)
1200 case_data = fxt->set_up_test_case(fxt->data);
1201
1202 for (i = 0; i < test_case->test_count; ++i) {
1203 struct zuc_test *curr = test_case->tests[i];
1204 if (curr->disabled) {
1205 dispatch_test_disabled(&g_ctx, curr);
1206 } else {
1207 run_single_test(curr, fxt, case_data,
1208 g_ctx.spawn);
1209 if (curr->skipped)
1210 test_case->skipped++;
1211 if (curr->failed)
1212 test_case->failed++;
1213 if (curr->fatal)
1214 test_case->fatal++;
1215 if (!curr->failed && !curr->fatal)
1216 test_case->passed++;
1217 test_case->elapsed += curr->elapsed;
1218 }
1219 }
1220
1221 if (fxt && fxt->tear_down_test_case)
1222 fxt->tear_down_test_case(case_data);
1223
1224 dispatch_case_ended(&g_ctx, test_case);
1225 }
1226 g_ctx.curr_case = NULL;
1227}
1228
1229static void
1230reset_test_values(struct zuc_case **cases, int case_count)
1231{
1232 int i;
1233 for (i = 0; i < case_count; ++i) {
1234 int j;
1235 cases[i]->disabled = 0;
1236 cases[i]->skipped = 0;
1237 cases[i]->failed = 0;
1238 cases[i]->fatal = 0;
1239 cases[i]->passed = 0;
1240 cases[i]->elapsed = 0;
1241 for (j = 0; j < cases[i]->test_count; ++j) {
1242 struct zuc_test *test = cases[i]->tests[j];
1243 if (test->disabled)
1244 cases[i]->disabled++;
1245 test->skipped = 0;
1246 test->failed = 0;
1247 test->fatal = 0;
1248 test->elapsed = 0;
1249
1250 free_events(&test->events);
1251 free_events(&test->deferred);
1252 }
1253 }
1254}
1255
1256static int
1257run_single_pass(void)
1258{
1259 long total_elapsed = 0;
1260 int total_passed = 0;
1261 int total_failed = 0;
1262 int total_skipped = 0;
1263 int live_case_count = 0;
1264 int live_test_count = 0;
1265 int disabled_test_count = 0;
1266 int i;
1267
1268 reset_test_values(g_ctx.cases, g_ctx.case_count);
1269 for (i = 0; i < g_ctx.case_count; ++i) {
1270 int live = g_ctx.cases[i]->test_count
1271 - g_ctx.cases[i]->disabled;
1272 if (live) {
1273 live_test_count += live;
1274 live_case_count++;
1275 }
1276 if (g_ctx.cases[i]->disabled)
1277 disabled_test_count++;
1278 }
1279
1280 dispatch_run_started(&g_ctx, live_case_count, live_test_count,
1281 disabled_test_count);
1282
1283 for (i = 0; i < g_ctx.case_count; ++i) {
1284 run_single_case(g_ctx.cases[i]);
1285 total_failed += g_ctx.cases[i]->test_count
1286 - (g_ctx.cases[i]->passed + g_ctx.cases[i]->disabled);
1287 total_passed += g_ctx.cases[i]->passed;
1288 total_elapsed += g_ctx.cases[i]->elapsed;
1289 total_skipped += g_ctx.cases[i]->skipped;
1290 }
1291
1292 dispatch_run_ended(&g_ctx, live_case_count, live_test_count,
1293 total_passed, total_failed, disabled_test_count,
1294 total_elapsed);
1295
1296 if (total_failed)
1297 return EXIT_FAILURE;
1298 else if (total_skipped)
1299 return ZUC_EXIT_SKIP;
1300 else
1301 return EXIT_SUCCESS;
1302}
1303
1304int
1305zucimpl_run_tests(void)
1306{
1307 int rc = EXIT_SUCCESS;
1308 int i;
1309 int limit = g_ctx.repeat > 0 ? g_ctx.repeat : 1;
1310
1311 initialize();
1312 if (g_ctx.fatal)
1313 return EXIT_FAILURE;
1314
1315 if (g_ctx.listeners == NULL) {
1316 zuc_add_event_listener(zuc_collector_create(&(g_ctx.fds[1])));
1317 zuc_add_event_listener(zuc_base_logger_create());
Jon A. Cruz646aef52015-07-15 19:22:41 -07001318 if (g_ctx.output_junit)
1319 zuc_add_event_listener(zuc_junit_reporter_create());
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001320 }
1321
1322 if (g_ctx.case_count < 1) {
1323 printf("%s:%d: error: Setup error: test tree is empty\n",
1324 __FILE__, __LINE__);
1325 rc = EXIT_FAILURE;
1326 }
1327
1328 for (i = 0; (i < limit) && (g_ctx.case_count > 0); ++i) {
1329 int pass_code = EXIT_SUCCESS;
1330 dispatch_pre_run(&g_ctx, limit, i + 1,
1331 (g_ctx.random > 0) ? g_ctx.seed : 0,
1332 g_ctx.filter);
1333
1334 order_cases(g_ctx.case_count, g_ctx.cases);
1335 if (g_ctx.random > 0)
1336 shuffle_cases(g_ctx.case_count, g_ctx.cases,
1337 g_ctx.seed);
1338
1339 pass_code = run_single_pass();
1340 if (pass_code == EXIT_FAILURE)
1341 rc = EXIT_FAILURE;
1342 else if ((pass_code == ZUC_EXIT_SKIP) && (rc == EXIT_SUCCESS))
1343 rc = ZUC_EXIT_SKIP;
1344
1345 g_ctx.seed++;
1346 }
1347
1348 return rc;
1349}
1350
1351int
1352zucimpl_tracepoint(char const *file, int line, char const *fmt, ...)
1353{
1354 int rc = -1;
1355 va_list argp;
1356 char *msg = NULL;
1357
1358
1359 va_start(argp, fmt);
1360 rc = vasprintf(&msg, fmt, argp);
1361 if (rc == -1) {
1362 msg = NULL;
1363 }
1364 va_end(argp);
1365
1366 dispatch_collect_event(&g_ctx,
1367 file, line,
1368 msg);
1369
1370 free(msg);
1371
1372 return rc;
1373}
1374
1375void
1376zucimpl_terminate(char const *file, int line,
1377 bool fail, bool fatal, const char *msg)
1378{
1379 enum zuc_fail_state state = ZUC_CHECK_SKIP;
1380 int level = 2;
1381 if (fail && fatal) {
1382 state = ZUC_CHECK_FATAL;
1383 level = 0;
1384 } else if (fail && !fatal) {
1385 state = ZUC_CHECK_FAIL;
1386 level = 0;
1387 }
1388
1389 mark_failed(g_ctx.curr_test, state);
1390
1391 if ((state != ZUC_CHECK_OK) && g_ctx.curr_test)
1392 migrate_deferred_events(g_ctx.curr_test, false);
1393
1394 dispatch_check_triggered(&g_ctx,
1395 file, line,
1396 state,
1397 ZUC_OP_TERMINATE, ZUC_VAL_INT,
1398 level, 0,
1399 msg, "");
1400}
1401
1402static void
1403validate_types(enum zuc_check_op op, enum zuc_check_valtype valtype)
1404{
1405 bool is_valid = true;
1406
1407 switch (op) {
1408 case ZUC_OP_NULL:
1409 case ZUC_OP_NOT_NULL:
1410 is_valid = is_valid && (valtype == ZUC_VAL_PTR);
1411 break;
1412 default:
1413 ; /* all rest OK */
1414 }
1415
1416 switch (valtype) {
1417 case ZUC_VAL_CSTR:
1418 is_valid = is_valid && ((op == ZUC_OP_EQ) || (op == ZUC_OP_NE));
1419 break;
1420 default:
1421 ; /* all rest OK */
1422 }
1423
1424 if (!is_valid)
1425 printf("%s:%d: warning: Unexpected op+type %d/%d.\n",
1426 __FILE__, __LINE__, op, valtype);
1427}
1428
1429static int
1430pred2_unknown(intptr_t lhs, intptr_t rhs)
1431{
1432 return 0;
1433}
1434
1435static int
1436pred2_true(intptr_t lhs, intptr_t rhs)
1437{
1438 return lhs;
1439}
1440
1441static int
1442pred2_false(intptr_t lhs, intptr_t rhs)
1443{
1444 return !lhs;
1445}
1446
1447static int
1448pred2_eq(intptr_t lhs, intptr_t rhs)
1449{
1450 return lhs == rhs;
1451}
1452
1453static int
1454pred2_streq(intptr_t lhs, intptr_t rhs)
1455{
1456 int status = 0;
1457 const char *lhptr = (const char *)lhs;
1458 const char *rhptr = (const char *)rhs;
1459
1460 if (!lhptr && !rhptr)
1461 status = 1;
1462 else if (lhptr && rhptr)
1463 status = strcmp(lhptr, rhptr) == 0;
1464
1465 return status;
1466}
1467
1468static int
1469pred2_ne(intptr_t lhs, intptr_t rhs)
1470{
1471 return lhs != rhs;
1472}
1473
1474static int
1475pred2_strne(intptr_t lhs, intptr_t rhs)
1476{
1477 int status = 0;
1478 const char *lhptr = (const char *)lhs;
1479 const char *rhptr = (const char *)rhs;
1480
1481 if (lhptr != rhptr) {
1482 if (!lhptr || !rhptr)
1483 status = 1;
1484 else
1485 status = strcmp(lhptr, rhptr) != 0;
1486 }
1487
1488 return status;
1489}
1490
1491static int
1492pred2_ge(intptr_t lhs, intptr_t rhs)
1493{
1494 return lhs >= rhs;
1495}
1496
1497static int
1498pred2_gt(intptr_t lhs, intptr_t rhs)
1499{
1500 return lhs > rhs;
1501}
1502
1503static int
1504pred2_le(intptr_t lhs, intptr_t rhs)
1505{
1506 return lhs <= rhs;
1507}
1508
1509static int
1510pred2_lt(intptr_t lhs, intptr_t rhs)
1511{
1512 return lhs < rhs;
1513}
1514
1515static comp_pred2
1516get_pred2(enum zuc_check_op op, enum zuc_check_valtype valtype)
1517{
1518 switch (op) {
1519 case ZUC_OP_TRUE:
1520 return pred2_true;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001521 case ZUC_OP_FALSE:
1522 return pred2_false;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001523 case ZUC_OP_NULL:
1524 return pred2_false;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001525 case ZUC_OP_NOT_NULL:
1526 return pred2_true;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001527 case ZUC_OP_EQ:
1528 if (valtype == ZUC_VAL_CSTR)
1529 return pred2_streq;
1530 else
1531 return pred2_eq;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001532 case ZUC_OP_NE:
1533 if (valtype == ZUC_VAL_CSTR)
1534 return pred2_strne;
1535 else
1536 return pred2_ne;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001537 case ZUC_OP_GE:
1538 return pred2_ge;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001539 case ZUC_OP_GT:
1540 return pred2_gt;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001541 case ZUC_OP_LE:
1542 return pred2_le;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001543 case ZUC_OP_LT:
1544 return pred2_lt;
Jon A. Cruz5a75a412015-07-02 23:36:44 -07001545 default:
1546 return pred2_unknown;
1547 }
1548}
1549
1550int
1551zucimpl_expect_pred2(char const *file, int line,
1552 enum zuc_check_op op, enum zuc_check_valtype valtype,
1553 bool fatal,
1554 intptr_t lhs, intptr_t rhs,
1555 const char *lhs_str, const char* rhs_str)
1556{
1557 enum zuc_fail_state state = fatal ? ZUC_CHECK_FATAL : ZUC_CHECK_FAIL;
1558 comp_pred2 pred = get_pred2(op, valtype);
1559 int failed = !pred(lhs, rhs);
1560
1561 validate_types(op, valtype);
1562
1563 if (failed) {
1564 mark_failed(g_ctx.curr_test, state);
1565
1566 if (g_ctx.curr_test)
1567 migrate_deferred_events(g_ctx.curr_test, false);
1568
1569 dispatch_check_triggered(&g_ctx,
1570 file, line,
1571 fatal ? ZUC_CHECK_FATAL
1572 : ZUC_CHECK_FAIL,
1573 op, valtype,
1574 lhs, rhs,
1575 lhs_str, rhs_str);
1576 }
1577 return failed;
1578}