Moved test suites into custom linker section
This simplifies the interaction between code generation and the test-runner. In theory it also reduces compilation dependencies, but internal tests make this difficult.
This commit is contained in:
+68
-61
@@ -7,6 +7,14 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
// 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
|
// test geometries
|
||||||
struct test_geometry {
|
struct test_geometry {
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -212,24 +220,24 @@ static void summary(void) {
|
|||||||
test_types_t types = 0;
|
test_types_t types = 0;
|
||||||
size_t perms = 0;
|
size_t perms = 0;
|
||||||
size_t filtered = 0;
|
size_t filtered = 0;
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
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++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
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);
|
&perms, &filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
cases += test_suites[i]->case_count;
|
cases += test_suites[i].case_count;
|
||||||
types |= test_suites[i]->types;
|
types |= test_suites[i].types;
|
||||||
}
|
}
|
||||||
|
|
||||||
char perm_buf[64];
|
char perm_buf[64];
|
||||||
@@ -241,28 +249,28 @@ static void summary(void) {
|
|||||||
printf("%-36s %7s %7zu %7zu %11s\n",
|
printf("%-36s %7s %7zu %7zu %11s\n",
|
||||||
"TOTAL",
|
"TOTAL",
|
||||||
type_buf,
|
type_buf,
|
||||||
test_suite_count,
|
TEST_SUITE_COUNT,
|
||||||
cases,
|
cases,
|
||||||
perm_buf);
|
perm_buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_suites(void) {
|
static void list_suites(void) {
|
||||||
printf("%-36s %7s %7s %11s\n", "suite", "types", "cases", "perms");
|
printf("%-36s %7s %7s %11s\n", "suite", "types", "cases", "perms");
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
test_define_suite(test_suites[i]);
|
test_define_suite(&test_suites[i]);
|
||||||
|
|
||||||
size_t perms = 0;
|
size_t perms = 0;
|
||||||
size_t filtered = 0;
|
size_t filtered = 0;
|
||||||
for (size_t j = 0; j < test_suites[i]->case_count; j++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
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);
|
&perms, &filtered);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,35 +278,35 @@ static void list_suites(void) {
|
|||||||
sprintf(perm_buf, "%zu/%zu", filtered, perms);
|
sprintf(perm_buf, "%zu/%zu", filtered, perms);
|
||||||
char type_buf[64];
|
char type_buf[64];
|
||||||
sprintf(type_buf, "%s%s",
|
sprintf(type_buf, "%s%s",
|
||||||
(test_suites[i]->types & TEST_NORMAL) ? "n" : "",
|
(test_suites[i].types & TEST_NORMAL) ? "n" : "",
|
||||||
(test_suites[i]->types & TEST_REENTRANT) ? "r" : "");
|
(test_suites[i].types & TEST_REENTRANT) ? "r" : "");
|
||||||
printf("%-36s %7s %7zu %11s\n",
|
printf("%-36s %7s %7zu %11s\n",
|
||||||
test_suites[i]->id,
|
test_suites[i].id,
|
||||||
type_buf,
|
type_buf,
|
||||||
test_suites[i]->case_count,
|
test_suites[i].case_count,
|
||||||
perm_buf);
|
perm_buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_cases(void) {
|
static void list_cases(void) {
|
||||||
printf("%-36s %7s %11s\n", "case", "types", "perms");
|
printf("%-36s %7s %11s\n", "case", "types", "perms");
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
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++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t perms = 0;
|
size_t perms = 0;
|
||||||
size_t filtered = 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);
|
&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];
|
char perm_buf[64];
|
||||||
sprintf(perm_buf, "%zu/%zu", filtered, perms);
|
sprintf(perm_buf, "%zu/%zu", filtered, perms);
|
||||||
@@ -307,7 +315,7 @@ static void list_cases(void) {
|
|||||||
(types & TEST_NORMAL) ? "n" : "",
|
(types & TEST_NORMAL) ? "n" : "",
|
||||||
(types & TEST_REENTRANT) ? "r" : "");
|
(types & TEST_REENTRANT) ? "r" : "");
|
||||||
printf("%-36s %7s %11s\n",
|
printf("%-36s %7s %11s\n",
|
||||||
test_suites[i]->cases[j]->id,
|
test_suites[i].cases[j].id,
|
||||||
type_buf,
|
type_buf,
|
||||||
perm_buf);
|
perm_buf);
|
||||||
}
|
}
|
||||||
@@ -315,39 +323,39 @@ static void list_cases(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void list_paths(void) {
|
static void list_paths(void) {
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < test_suites[i]->case_count; j++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("%-36s %-36s\n",
|
printf("%-36s %-36s\n",
|
||||||
test_suites[i]->cases[j]->id,
|
test_suites[i].cases[j].id,
|
||||||
test_suites[i]->cases[j]->path);
|
test_suites[i].cases[j].path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void list_defines(void) {
|
static void list_defines(void) {
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
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++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t perm = 0;
|
for (size_t perm = 0;
|
||||||
perm < TEST_GEOMETRY_COUNT
|
perm < TEST_GEOMETRY_COUNT
|
||||||
* test_suites[i]->cases[j]->permutations;
|
* test_suites[i].cases[j].permutations;
|
||||||
perm++) {
|
perm++) {
|
||||||
if (test_perm_skip(perm)) {
|
if (test_perm_skip(perm)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -356,25 +364,24 @@ static void list_defines(void) {
|
|||||||
// setup defines
|
// setup defines
|
||||||
size_t case_perm = perm / TEST_GEOMETRY_COUNT;
|
size_t case_perm = perm / TEST_GEOMETRY_COUNT;
|
||||||
size_t geom_perm = perm % TEST_GEOMETRY_COUNT;
|
size_t geom_perm = perm % TEST_GEOMETRY_COUNT;
|
||||||
test_define_perm(test_suites[i],
|
test_define_perm(&test_suites[i],
|
||||||
test_suites[i]->cases[j], case_perm);
|
&test_suites[i].cases[j], case_perm);
|
||||||
test_define_geometry(&test_geometries[geom_perm]);
|
test_define_geometry(&test_geometries[geom_perm]);
|
||||||
|
|
||||||
// print the case
|
// print the case
|
||||||
char id_buf[256];
|
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);
|
printf("%-36s ", id_buf);
|
||||||
|
|
||||||
// special case for the current geometry
|
// special case for the current geometry
|
||||||
printf("GEOMETRY=%s ", test_geometries[geom_perm].name);
|
printf("GEOMETRY=%s ", test_geometries[geom_perm].name);
|
||||||
|
|
||||||
// print each define
|
// print each define
|
||||||
for (size_t k = 0; k < test_suites[i]->define_count; k++) {
|
for (size_t k = 0; k < test_suites[i].define_count; k++) {
|
||||||
if (test_suites[i]->cases[j]->defines
|
if (test_suites[i].cases[j].defines
|
||||||
&& test_suites[i]->cases[j]
|
&& test_suites[i].cases[j].defines[case_perm][k]) {
|
||||||
->defines[case_perm][k]) {
|
|
||||||
printf("%s=%jd ",
|
printf("%s=%jd ",
|
||||||
test_suites[i]->define_names[k],
|
test_suites[i].define_names[k],
|
||||||
test_define(k));
|
test_define(k));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,21 +426,21 @@ static void list_defaults(void) {
|
|||||||
|
|
||||||
static void run(void) {
|
static void run(void) {
|
||||||
size_t step = 0;
|
size_t step = 0;
|
||||||
for (size_t i = 0; i < test_suite_count; i++) {
|
for (size_t i = 0; i < TEST_SUITE_COUNT; i++) {
|
||||||
if (test_suite_skip(test_suites[i])) {
|
if (test_suite_skip(&test_suites[i])) {
|
||||||
continue;
|
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++) {
|
for (size_t j = 0; j < test_suites[i].case_count; j++) {
|
||||||
if (test_case_skip(test_suites[i]->cases[j])) {
|
if (test_case_skip(&test_suites[i].cases[j])) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t perm = 0;
|
for (size_t perm = 0;
|
||||||
perm < TEST_GEOMETRY_COUNT
|
perm < TEST_GEOMETRY_COUNT
|
||||||
* test_suites[i]->cases[j]->permutations;
|
* test_suites[i].cases[j].permutations;
|
||||||
perm++) {
|
perm++) {
|
||||||
if (test_perm_skip(perm)) {
|
if (test_perm_skip(perm)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -447,15 +454,15 @@ static void run(void) {
|
|||||||
// setup defines
|
// setup defines
|
||||||
size_t case_perm = perm / TEST_GEOMETRY_COUNT;
|
size_t case_perm = perm / TEST_GEOMETRY_COUNT;
|
||||||
size_t geom_perm = perm % TEST_GEOMETRY_COUNT;
|
size_t geom_perm = perm % TEST_GEOMETRY_COUNT;
|
||||||
test_define_perm(test_suites[i],
|
test_define_perm(&test_suites[i],
|
||||||
test_suites[i]->cases[j], case_perm);
|
&test_suites[i].cases[j], case_perm);
|
||||||
test_define_geometry(&test_geometries[geom_perm]);
|
test_define_geometry(&test_geometries[geom_perm]);
|
||||||
|
|
||||||
// filter?
|
// 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",
|
printf("skipped %s#%zu\n",
|
||||||
test_suites[i]->cases[j]->id,
|
test_suites[i].cases[j].id,
|
||||||
perm);
|
perm);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -494,11 +501,11 @@ static void run(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run the test
|
// 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
|
// cleanup
|
||||||
err = lfs_testbd_destroy(&cfg);
|
err = lfs_testbd_destroy(&cfg);
|
||||||
|
|||||||
@@ -34,13 +34,10 @@ struct test_suite {
|
|||||||
const char *const *define_names;
|
const char *const *define_names;
|
||||||
size_t define_count;
|
size_t define_count;
|
||||||
|
|
||||||
const struct test_case *const *cases;
|
const struct test_case *cases;
|
||||||
size_t case_count;
|
size_t case_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct test_suite *test_suites[];
|
|
||||||
extern const size_t test_suite_count;
|
|
||||||
|
|
||||||
|
|
||||||
// access generated test defines
|
// access generated test defines
|
||||||
intmax_t test_predefine(size_t define);
|
intmax_t test_predefine(size_t define);
|
||||||
|
|||||||
+27
-50
@@ -342,8 +342,8 @@ def compile(**args):
|
|||||||
f.writeln('#endif')
|
f.writeln('#endif')
|
||||||
f.writeln()
|
f.writeln()
|
||||||
|
|
||||||
|
# create case functions
|
||||||
for case in suite.cases:
|
for case in suite.cases:
|
||||||
# create case functions
|
|
||||||
if case.in_ is None:
|
if case.in_ is None:
|
||||||
write_case_functions(f, suite, case)
|
write_case_functions(f, suite, case)
|
||||||
else:
|
else:
|
||||||
@@ -360,39 +360,8 @@ def compile(**args):
|
|||||||
% (suite.name, case.name))
|
% (suite.name, case.name))
|
||||||
f.writeln()
|
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
|
# create suite struct
|
||||||
|
f.writeln('__attribute__((section("_test_suites")))')
|
||||||
f.writeln('const struct test_suite __test__%s__suite = {'
|
f.writeln('const struct test_suite __test__%s__suite = {'
|
||||||
% suite.name)
|
% suite.name)
|
||||||
f.writeln(4*' '+'.id = "%s",' % suite.id())
|
f.writeln(4*' '+'.id = "%s",' % suite.id())
|
||||||
@@ -403,13 +372,34 @@ def compile(**args):
|
|||||||
'TEST_NORMAL' if suite.normal else None,
|
'TEST_NORMAL' if suite.normal else None,
|
||||||
'TEST_REENTRANT' if suite.reentrant else None])))
|
'TEST_REENTRANT' if suite.reentrant else None])))
|
||||||
if suite.defines:
|
if suite.defines:
|
||||||
f.writeln(4*' '+'.define_names = __test__%s__define_names,'
|
# create suite define names
|
||||||
% suite.name)
|
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*' '+'.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:
|
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))
|
% (suite.name, case.name))
|
||||||
|
f.writeln(8*' '+'},')
|
||||||
f.writeln(4*' '+'},')
|
f.writeln(4*' '+'},')
|
||||||
f.writeln(4*' '+'.case_count = %d,' % len(suite.cases))
|
f.writeln(4*' '+'.case_count = %d,' % len(suite.cases))
|
||||||
f.writeln('};')
|
f.writeln('};')
|
||||||
@@ -456,19 +446,6 @@ def compile(**args):
|
|||||||
f.writeln('#endif')
|
f.writeln('#endif')
|
||||||
f.writeln()
|
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):
|
def runner(**args):
|
||||||
cmd = args['runner'].copy()
|
cmd = args['runner'].copy()
|
||||||
cmd.extend(args.get('test_ids'))
|
cmd.extend(args.get('test_ids'))
|
||||||
|
|||||||
Reference in New Issue
Block a user