diff --git a/runners/test_runner.c b/runners/test_runner.c index 21ff1c00..cc932b73 100644 --- a/runners/test_runner.c +++ b/runners/test_runner.c @@ -7,6 +7,14 @@ #include +// test suites in a custom ld section +extern struct test_suite __start__test_suites; +extern struct test_suite __stop__test_suites; + +const struct test_suite *test_suites = &__start__test_suites; +#define TEST_SUITE_COUNT \ + ((size_t)(&__stop__test_suites - &__start__test_suites)) + // test geometries struct test_geometry { const char *name; @@ -212,24 +220,24 @@ static void summary(void) { test_types_t types = 0; size_t perms = 0; size_t filtered = 0; - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - test_define_suite(test_suites[i]); + test_define_suite(&test_suites[i]); - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } - test_case_permcount(test_suites[i], test_suites[i]->cases[j], + test_case_permcount(&test_suites[i], &test_suites[i].cases[j], &perms, &filtered); } - cases += test_suites[i]->case_count; - types |= test_suites[i]->types; + cases += test_suites[i].case_count; + types |= test_suites[i].types; } char perm_buf[64]; @@ -241,28 +249,28 @@ static void summary(void) { printf("%-36s %7s %7zu %7zu %11s\n", "TOTAL", type_buf, - test_suite_count, + TEST_SUITE_COUNT, cases, perm_buf); } static void list_suites(void) { printf("%-36s %7s %7s %11s\n", "suite", "types", "cases", "perms"); - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - test_define_suite(test_suites[i]); + test_define_suite(&test_suites[i]); size_t perms = 0; size_t filtered = 0; - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } - test_case_permcount(test_suites[i], test_suites[i]->cases[j], + test_case_permcount(&test_suites[i], &test_suites[i].cases[j], &perms, &filtered); } @@ -270,35 +278,35 @@ static void list_suites(void) { sprintf(perm_buf, "%zu/%zu", filtered, perms); char type_buf[64]; sprintf(type_buf, "%s%s", - (test_suites[i]->types & TEST_NORMAL) ? "n" : "", - (test_suites[i]->types & TEST_REENTRANT) ? "r" : ""); + (test_suites[i].types & TEST_NORMAL) ? "n" : "", + (test_suites[i].types & TEST_REENTRANT) ? "r" : ""); printf("%-36s %7s %7zu %11s\n", - test_suites[i]->id, + test_suites[i].id, type_buf, - test_suites[i]->case_count, + test_suites[i].case_count, perm_buf); } } static void list_cases(void) { printf("%-36s %7s %11s\n", "case", "types", "perms"); - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - test_define_suite(test_suites[i]); + test_define_suite(&test_suites[i]); - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } size_t perms = 0; size_t filtered = 0; - test_case_permcount(test_suites[i], test_suites[i]->cases[j], + test_case_permcount(&test_suites[i], &test_suites[i].cases[j], &perms, &filtered); - test_types_t types = test_suites[i]->cases[j]->types; + test_types_t types = test_suites[i].cases[j].types; char perm_buf[64]; sprintf(perm_buf, "%zu/%zu", filtered, perms); @@ -307,7 +315,7 @@ static void list_cases(void) { (types & TEST_NORMAL) ? "n" : "", (types & TEST_REENTRANT) ? "r" : ""); printf("%-36s %7s %11s\n", - test_suites[i]->cases[j]->id, + test_suites[i].cases[j].id, type_buf, perm_buf); } @@ -315,39 +323,39 @@ static void list_cases(void) { } static void list_paths(void) { - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } printf("%-36s %-36s\n", - test_suites[i]->cases[j]->id, - test_suites[i]->cases[j]->path); + test_suites[i].cases[j].id, + test_suites[i].cases[j].path); } } } static void list_defines(void) { - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - test_define_suite(test_suites[i]); + test_define_suite(&test_suites[i]); - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } for (size_t perm = 0; perm < TEST_GEOMETRY_COUNT - * test_suites[i]->cases[j]->permutations; + * test_suites[i].cases[j].permutations; perm++) { if (test_perm_skip(perm)) { continue; @@ -356,25 +364,24 @@ static void list_defines(void) { // setup defines size_t case_perm = perm / TEST_GEOMETRY_COUNT; size_t geom_perm = perm % TEST_GEOMETRY_COUNT; - test_define_perm(test_suites[i], - test_suites[i]->cases[j], case_perm); + test_define_perm(&test_suites[i], + &test_suites[i].cases[j], case_perm); test_define_geometry(&test_geometries[geom_perm]); // print the case char id_buf[256]; - sprintf(id_buf, "%s#%zu", test_suites[i]->cases[j]->id, perm); + sprintf(id_buf, "%s#%zu", test_suites[i].cases[j].id, perm); printf("%-36s ", id_buf); // special case for the current geometry printf("GEOMETRY=%s ", test_geometries[geom_perm].name); // print each define - for (size_t k = 0; k < test_suites[i]->define_count; k++) { - if (test_suites[i]->cases[j]->defines - && test_suites[i]->cases[j] - ->defines[case_perm][k]) { + for (size_t k = 0; k < test_suites[i].define_count; k++) { + if (test_suites[i].cases[j].defines + && test_suites[i].cases[j].defines[case_perm][k]) { printf("%s=%jd ", - test_suites[i]->define_names[k], + test_suites[i].define_names[k], test_define(k)); } } @@ -419,21 +426,21 @@ static void list_defaults(void) { static void run(void) { size_t step = 0; - for (size_t i = 0; i < test_suite_count; i++) { - if (test_suite_skip(test_suites[i])) { + for (size_t i = 0; i < TEST_SUITE_COUNT; i++) { + if (test_suite_skip(&test_suites[i])) { continue; } - test_define_suite(test_suites[i]); + test_define_suite(&test_suites[i]); - for (size_t j = 0; j < test_suites[i]->case_count; j++) { - if (test_case_skip(test_suites[i]->cases[j])) { + for (size_t j = 0; j < test_suites[i].case_count; j++) { + if (test_case_skip(&test_suites[i].cases[j])) { continue; } for (size_t perm = 0; perm < TEST_GEOMETRY_COUNT - * test_suites[i]->cases[j]->permutations; + * test_suites[i].cases[j].permutations; perm++) { if (test_perm_skip(perm)) { continue; @@ -447,15 +454,15 @@ static void run(void) { // setup defines size_t case_perm = perm / TEST_GEOMETRY_COUNT; size_t geom_perm = perm % TEST_GEOMETRY_COUNT; - test_define_perm(test_suites[i], - test_suites[i]->cases[j], case_perm); + test_define_perm(&test_suites[i], + &test_suites[i].cases[j], case_perm); test_define_geometry(&test_geometries[geom_perm]); // filter? - if (test_suites[i]->cases[j]->filter) { - if (!test_suites[i]->cases[j]->filter()) { + if (test_suites[i].cases[j].filter) { + if (!test_suites[i].cases[j].filter()) { printf("skipped %s#%zu\n", - test_suites[i]->cases[j]->id, + test_suites[i].cases[j].id, perm); continue; } @@ -494,11 +501,11 @@ static void run(void) { } // run the test - printf("running %s#%zu\n", test_suites[i]->cases[j]->id, perm); + printf("running %s#%zu\n", test_suites[i].cases[j].id, perm); - test_suites[i]->cases[j]->run(&cfg); + test_suites[i].cases[j].run(&cfg); - printf("finished %s#%zu\n", test_suites[i]->cases[j]->id, perm); + printf("finished %s#%zu\n", test_suites[i].cases[j].id, perm); // cleanup err = lfs_testbd_destroy(&cfg); diff --git a/runners/test_runner.h b/runners/test_runner.h index e0336379..64ad15d7 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -34,13 +34,10 @@ struct test_suite { const char *const *define_names; size_t define_count; - const struct test_case *const *cases; + const struct test_case *cases; size_t case_count; }; -extern const struct test_suite *test_suites[]; -extern const size_t test_suite_count; - // access generated test defines intmax_t test_predefine(size_t define); diff --git a/scripts/test.py b/scripts/test.py index 4110bbae..048b1811 100755 --- a/scripts/test.py +++ b/scripts/test.py @@ -342,8 +342,8 @@ def compile(**args): f.writeln('#endif') f.writeln() + # create case functions for case in suite.cases: - # create case functions if case.in_ is None: write_case_functions(f, suite, case) else: @@ -360,39 +360,8 @@ def compile(**args): % (suite.name, case.name)) f.writeln() - # create case struct - f.writeln('const struct test_case __test__%s__%s__case = {' - % (suite.name, case.name)) - f.writeln(4*' '+'.id = "%s",' % case.id()) - f.writeln(4*' '+'.name = "%s",' % case.name) - f.writeln(4*' '+'.path = "%s",' % case.path) - f.writeln(4*' '+'.types = %s,' - % ' | '.join(filter(None, [ - 'TEST_NORMAL' if case.normal else None, - 'TEST_REENTRANT' if case.reentrant else None]))) - f.writeln(4*' '+'.permutations = %d,' - % len(case.permutations)) - if case.defines: - f.writeln(4*' '+'.defines = __test__%s__%s__defines,' - % (suite.name, case.name)) - if suite.if_ is not None or case.if_ is not None: - f.writeln(4*' '+'.filter = __test__%s__%s__filter,' - % (suite.name, case.name)) - f.writeln(4*' '+'.run = __test__%s__%s__run,' - % (suite.name, case.name)) - f.writeln('};') - f.writeln() - - # create suite define names - if suite.defines: - f.writeln('const char *const __test__%s__define_names[] = {' - % suite.name) - for k in sorted(suite.defines): - f.writeln(4*' '+'"%s",' % k) - f.writeln('};') - f.writeln() - # create suite struct + f.writeln('__attribute__((section("_test_suites")))') f.writeln('const struct test_suite __test__%s__suite = {' % suite.name) f.writeln(4*' '+'.id = "%s",' % suite.id()) @@ -403,13 +372,34 @@ def compile(**args): 'TEST_NORMAL' if suite.normal else None, 'TEST_REENTRANT' if suite.reentrant else None]))) if suite.defines: - f.writeln(4*' '+'.define_names = __test__%s__define_names,' - % suite.name) + # create suite define names + f.writeln(4*' '+'.define_names = (const char *const[]){') + for k in sorted(suite.defines): + f.writeln(8*' '+'"%s",' % k) + f.writeln(4*' '+'},') f.writeln(4*' '+'.define_count = %d,' % len(suite.defines)) - f.writeln(4*' '+'.cases = (const struct test_case *const []){') + f.writeln(4*' '+'.cases = (const struct test_case[]){') for case in suite.cases: - f.writeln(8*' '+'&__test__%s__%s__case,' + # create case structs + f.writeln(8*' '+'{') + f.writeln(12*' '+'.id = "%s",' % case.id()) + f.writeln(12*' '+'.name = "%s",' % case.name) + f.writeln(12*' '+'.path = "%s",' % case.path) + f.writeln(12*' '+'.types = %s,' + % ' | '.join(filter(None, [ + 'TEST_NORMAL' if case.normal else None, + 'TEST_REENTRANT' if case.reentrant else None]))) + f.writeln(12*' '+'.permutations = %d,' + % len(case.permutations)) + if case.defines: + f.writeln(12*' '+'.defines = __test__%s__%s__defines,' + % (suite.name, case.name)) + if suite.if_ is not None or case.if_ is not None: + f.writeln(12*' '+'.filter = __test__%s__%s__filter,' + % (suite.name, case.name)) + f.writeln(12*' '+'.run = __test__%s__%s__run,' % (suite.name, case.name)) + f.writeln(8*' '+'},') f.writeln(4*' '+'},') f.writeln(4*' '+'.case_count = %d,' % len(suite.cases)) f.writeln('};') @@ -456,19 +446,6 @@ def compile(**args): f.writeln('#endif') f.writeln() - # add suite info to test_runner.c - if args['source'] == 'runners/test_runner.c': - f.writeln() - for suite in suites: - f.writeln('extern const struct test_suite ' - '__test__%s__suite;' % suite.name) - f.writeln('const struct test_suite *test_suites[] = {') - for suite in suites: - f.writeln(4*' '+'&__test__%s__suite,' % suite.name) - f.writeln('};') - f.writeln('const size_t test_suite_count = %d;' - % len(suites)) - def runner(**args): cmd = args['runner'].copy() cmd.extend(args.get('test_ids'))