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