diff options
Diffstat (limited to 'lib/kunit/executor_test.c')
| -rw-r--r-- | lib/kunit/executor_test.c | 270 |
1 files changed, 173 insertions, 97 deletions
diff --git a/lib/kunit/executor_test.c b/lib/kunit/executor_test.c index 4ed57fd94e42..f0090c2729cd 100644 --- a/lib/kunit/executor_test.c +++ b/lib/kunit/executor_test.c @@ -7,10 +7,9 @@ */ #include <kunit/test.h> +#include <kunit/attributes.h> -static void kfree_at_end(struct kunit *test, const void *to_free); -static void free_subsuite_at_end(struct kunit *test, - struct kunit_suite *const *to_free); +static void free_suite_set_at_end(struct kunit *test, const void *to_free); static struct kunit_suite *alloc_fake_suite(struct kunit *test, const char *suite_name, struct kunit_case *test_cases); @@ -26,139 +25,225 @@ static struct kunit_case dummy_test_cases[] = { static void parse_filter_test(struct kunit *test) { - struct kunit_test_filter filter = {NULL, NULL}; + struct kunit_glob_filter filter = {NULL, NULL}; - kunit_parse_filter_glob(&filter, "suite"); + kunit_parse_glob_filter(&filter, "suite"); KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); KUNIT_EXPECT_FALSE(test, filter.test_glob); kfree(filter.suite_glob); kfree(filter.test_glob); - kunit_parse_filter_glob(&filter, "suite.test"); + kunit_parse_glob_filter(&filter, "suite.test"); KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); KUNIT_EXPECT_STREQ(test, filter.test_glob, "test"); kfree(filter.suite_glob); kfree(filter.test_glob); } -static void filter_subsuite_test(struct kunit *test) +static void filter_suites_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "suite2", - .test_glob = NULL, + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[2], }; + struct kunit_suite_set got; + int err = 0; subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); /* Want: suite1, suite2, NULL -> suite2, NULL */ - filtered = kunit_filter_subsuite(subsuite, &filter); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); - free_subsuite_at_end(test, filtered); + got = kunit_filter_suites(&suite_set, "suite2", NULL, NULL, &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); /* Validate we just have suite2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); - KUNIT_EXPECT_FALSE(test, filtered[1]); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2"); + + /* Contains one element (end is 1 past end) */ + KUNIT_ASSERT_EQ(test, got.end - got.start, 1); } -static void filter_subsuite_test_glob_test(struct kunit *test) +static void filter_suites_test_glob_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "suite2", - .test_glob = "test2", + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[2], }; + struct kunit_suite_set got; + int err = 0; subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); /* Want: suite1, suite2, NULL -> suite2 (just test1), NULL */ - filtered = kunit_filter_subsuite(subsuite, &filter); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); - free_subsuite_at_end(test, filtered); + got = kunit_filter_suites(&suite_set, "suite2.test2", NULL, NULL, &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); /* Validate we just have suite2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); - KUNIT_EXPECT_FALSE(test, filtered[1]); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->name, "suite2"); + KUNIT_ASSERT_EQ(test, got.end - got.start, 1); /* Now validate we just have test2 */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]->test_cases); - KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->test_cases[0].name, "test2"); - KUNIT_EXPECT_FALSE(test, filtered[0]->test_cases[1].name); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases); + KUNIT_EXPECT_STREQ(test, (const char *)got.start[0]->test_cases[0].name, "test2"); + KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].name); } -static void filter_subsuite_to_empty_test(struct kunit *test) +static void filter_suites_to_empty_test(struct kunit *test) { - struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; - struct kunit_suite * const *filtered; - struct kunit_test_filter filter = { - .suite_glob = "not_found", - .test_glob = NULL, + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[2], }; + struct kunit_suite_set got; + int err = 0; subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); - filtered = kunit_filter_subsuite(subsuite, &filter); - free_subsuite_at_end(test, filtered); /* just in case */ + got = kunit_filter_suites(&suite_set, "not_found", NULL, NULL, &err); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); /* just in case */ - KUNIT_EXPECT_FALSE_MSG(test, filtered, - "should be NULL to indicate no match"); + KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end, + "should be empty to indicate no match"); } -static void kfree_subsuites_at_end(struct kunit *test, struct suite_set *suite_set) +static void parse_filter_attr_test(struct kunit *test) { - struct kunit_suite * const * const *suites; - - kfree_at_end(test, suite_set->start); - for (suites = suite_set->start; suites < suite_set->end; suites++) - free_subsuite_at_end(test, *suites); + int j, filter_count; + struct kunit_attr_filter *parsed_filters; + char filters[] = "speed>slow, module!=example", *filter = filters; + int err = 0; + + filter_count = kunit_get_filter_count(filters); + KUNIT_EXPECT_EQ(test, filter_count, 2); + + parsed_filters = kunit_kcalloc(test, filter_count, sizeof(*parsed_filters), + GFP_KERNEL); + for (j = 0; j < filter_count; j++) { + parsed_filters[j] = kunit_next_attr_filter(&filter, &err); + KUNIT_ASSERT_EQ_MSG(test, err, 0, "failed to parse filter from '%s'", filters); + } + + KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[0]), "speed"); + KUNIT_EXPECT_STREQ(test, parsed_filters[0].input, ">slow"); + + KUNIT_EXPECT_STREQ(test, kunit_attr_filter_name(parsed_filters[1]), "module"); + KUNIT_EXPECT_STREQ(test, parsed_filters[1].input, "!=example"); } -static void filter_suites_test(struct kunit *test) +static struct kunit_case dummy_attr_test_cases[] = { + /* .run_case is not important, just needs to be non-NULL */ + { .name = "slow", .run_case = dummy_test, .module_name = "dummy", + .attr.speed = KUNIT_SPEED_SLOW }, + { .name = "normal", .run_case = dummy_test, .module_name = "dummy" }, + {}, +}; + +static void filter_attr_test(struct kunit *test) { - /* Suites per-file are stored as a NULL terminated array */ - struct kunit_suite *subsuites[2][2] = { - {NULL, NULL}, - {NULL, NULL}, - }; - /* Match the memory layout of suite_set */ - struct kunit_suite * const * const suites[2] = { - subsuites[0], subsuites[1], + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[2], }; + struct kunit_suite_set got; + char filter[] = "speed>slow"; + int err = 0; + + subsuite[0] = alloc_fake_suite(test, "normal_suite", dummy_attr_test_cases); + subsuite[1] = alloc_fake_suite(test, "slow_suite", dummy_attr_test_cases); + subsuite[1]->attr.speed = KUNIT_SPEED_SLOW; // Set suite attribute + + /* + * Want: normal_suite(slow, normal), slow_suite(slow, normal), + * NULL -> normal_suite(normal), NULL + * + * The normal test in slow_suite is filtered out because the speed + * attribute is unset and thus, the filtering is based on the parent attribute + * of slow. + */ + got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); + + /* Validate we just have normal_suite */ + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]); + KUNIT_EXPECT_STREQ(test, got.start[0]->name, "normal_suite"); + KUNIT_ASSERT_EQ(test, got.end - got.start, 1); + + /* Now validate we just have normal test case */ + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases); + KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[0].name, "normal"); + KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].name); +} - const struct suite_set suite_set = { - .start = suites, - .end = suites + 2, +static void filter_attr_empty_test(struct kunit *test) +{ + struct kunit_suite *subsuite[3] = {NULL, NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[2], }; - struct suite_set filtered = {.start = NULL, .end = NULL}; + struct kunit_suite_set got; + char filter[] = "module!=dummy"; + int err = 0; - /* Emulate two files, each having one suite */ - subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases); - subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases); + subsuite[0] = alloc_fake_suite(test, "suite1", dummy_attr_test_cases); + subsuite[1] = alloc_fake_suite(test, "suite2", dummy_attr_test_cases); - /* Filter out suite1 */ - filtered = kunit_filter_suites(&suite_set, "suite0"); - kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */ - KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1); + got = kunit_filter_suites(&suite_set, NULL, filter, NULL, &err); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); /* just in case */ - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0]); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0][0]); - KUNIT_EXPECT_STREQ(test, (const char *)filtered.start[0][0]->name, "suite0"); + KUNIT_EXPECT_PTR_EQ_MSG(test, got.start, got.end, + "should be empty to indicate no match"); +} + +static void filter_attr_skip_test(struct kunit *test) +{ + struct kunit_suite *subsuite[2] = {NULL}; + struct kunit_suite_set suite_set = { + .start = subsuite, .end = &subsuite[1], + }; + struct kunit_suite_set got; + char filter[] = "speed>slow"; + int err = 0; + + subsuite[0] = alloc_fake_suite(test, "suite", dummy_attr_test_cases); + + /* Want: suite(slow, normal), NULL -> suite(slow with SKIP, normal), NULL */ + got = kunit_filter_suites(&suite_set, NULL, filter, "skip", &err); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start); + KUNIT_ASSERT_EQ(test, err, 0); + free_suite_set_at_end(test, &got); + + /* Validate we have both the slow and normal test */ + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, got.start[0]->test_cases); + KUNIT_ASSERT_EQ(test, kunit_suite_num_test_cases(got.start[0]), 2); + KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[0].name, "slow"); + KUNIT_EXPECT_STREQ(test, got.start[0]->test_cases[1].name, "normal"); + + /* Now ensure slow is skipped and normal is not */ + KUNIT_EXPECT_EQ(test, got.start[0]->test_cases[0].status, KUNIT_SKIPPED); + KUNIT_EXPECT_FALSE(test, got.start[0]->test_cases[1].status); } static struct kunit_case executor_test_cases[] = { KUNIT_CASE(parse_filter_test), - KUNIT_CASE(filter_subsuite_test), - KUNIT_CASE(filter_subsuite_test_glob_test), - KUNIT_CASE(filter_subsuite_to_empty_test), KUNIT_CASE(filter_suites_test), + KUNIT_CASE(filter_suites_test_glob_test), + KUNIT_CASE(filter_suites_to_empty_test), + KUNIT_CASE(parse_filter_attr_test), + KUNIT_CASE(filter_attr_test), + KUNIT_CASE(filter_attr_empty_test), + KUNIT_CASE(filter_attr_skip_test), {} }; @@ -171,35 +256,26 @@ kunit_test_suites(&executor_test_suite); /* Test helpers */ -static void kfree_res_free(struct kunit_resource *res) +static void free_suite_set(void *suite_set) { - kfree(res->data); + kunit_free_suite_set(*(struct kunit_suite_set *)suite_set); + kfree(suite_set); } -/* Use the resource API to register a call to kfree(to_free). +/* Use the resource API to register a call to free_suite_set. * Since we never actually use the resource, it's safe to use on const data. */ -static void kfree_at_end(struct kunit *test, const void *to_free) +static void free_suite_set_at_end(struct kunit *test, const void *to_free) { - /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ - if (IS_ERR_OR_NULL(to_free)) + struct kunit_suite_set *free; + + if (!((struct kunit_suite_set *)to_free)->start) return; - kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, - (void *)to_free); -} -static void free_subsuite_res_free(struct kunit_resource *res) -{ - kunit_free_subsuite(res->data); -} + free = kzalloc(sizeof(struct kunit_suite_set), GFP_KERNEL); + *free = *(struct kunit_suite_set *)to_free; -static void free_subsuite_at_end(struct kunit *test, - struct kunit_suite *const *to_free) -{ - if (IS_ERR_OR_NULL(to_free)) - return; - kunit_alloc_resource(test, NULL, free_subsuite_res_free, - GFP_KERNEL, (void *)to_free); + kunit_add_action(test, free_suite_set, (void *)free); } static struct kunit_suite *alloc_fake_suite(struct kunit *test, @@ -210,7 +286,7 @@ static struct kunit_suite *alloc_fake_suite(struct kunit *test, /* We normally never expect to allocate suites, hence the non-const cast. */ suite = kunit_kzalloc(test, sizeof(*suite), GFP_KERNEL); - strncpy((char *)suite->name, suite_name, sizeof(suite->name) - 1); + strscpy((char *)suite->name, suite_name, sizeof(suite->name)); suite->test_cases = test_cases; return suite; |
