executor_test.c (6808B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * KUnit test for the KUnit executor. 4 * 5 * Copyright (C) 2021, Google LLC. 6 * Author: Daniel Latypov <dlatypov@google.com> 7 */ 8 9#include <kunit/test.h> 10 11static void kfree_at_end(struct kunit *test, const void *to_free); 12static void free_subsuite_at_end(struct kunit *test, 13 struct kunit_suite *const *to_free); 14static struct kunit_suite *alloc_fake_suite(struct kunit *test, 15 const char *suite_name, 16 struct kunit_case *test_cases); 17 18static void dummy_test(struct kunit *test) {} 19 20static struct kunit_case dummy_test_cases[] = { 21 /* .run_case is not important, just needs to be non-NULL */ 22 { .name = "test1", .run_case = dummy_test }, 23 { .name = "test2", .run_case = dummy_test }, 24 {}, 25}; 26 27static void parse_filter_test(struct kunit *test) 28{ 29 struct kunit_test_filter filter = {NULL, NULL}; 30 31 kunit_parse_filter_glob(&filter, "suite"); 32 KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); 33 KUNIT_EXPECT_FALSE(test, filter.test_glob); 34 kfree(filter.suite_glob); 35 kfree(filter.test_glob); 36 37 kunit_parse_filter_glob(&filter, "suite.test"); 38 KUNIT_EXPECT_STREQ(test, filter.suite_glob, "suite"); 39 KUNIT_EXPECT_STREQ(test, filter.test_glob, "test"); 40 kfree(filter.suite_glob); 41 kfree(filter.test_glob); 42} 43 44static void filter_subsuite_test(struct kunit *test) 45{ 46 struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; 47 struct kunit_suite * const *filtered; 48 struct kunit_test_filter filter = { 49 .suite_glob = "suite2", 50 .test_glob = NULL, 51 }; 52 53 subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); 54 subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); 55 56 /* Want: suite1, suite2, NULL -> suite2, NULL */ 57 filtered = kunit_filter_subsuite(subsuite, &filter); 58 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); 59 free_subsuite_at_end(test, filtered); 60 61 /* Validate we just have suite2 */ 62 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); 63 KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); 64 KUNIT_EXPECT_FALSE(test, filtered[1]); 65} 66 67static void filter_subsuite_test_glob_test(struct kunit *test) 68{ 69 struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; 70 struct kunit_suite * const *filtered; 71 struct kunit_test_filter filter = { 72 .suite_glob = "suite2", 73 .test_glob = "test2", 74 }; 75 76 subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); 77 subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); 78 79 /* Want: suite1, suite2, NULL -> suite2 (just test1), NULL */ 80 filtered = kunit_filter_subsuite(subsuite, &filter); 81 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered); 82 free_subsuite_at_end(test, filtered); 83 84 /* Validate we just have suite2 */ 85 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]); 86 KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->name, "suite2"); 87 KUNIT_EXPECT_FALSE(test, filtered[1]); 88 89 /* Now validate we just have test2 */ 90 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered[0]->test_cases); 91 KUNIT_EXPECT_STREQ(test, (const char *)filtered[0]->test_cases[0].name, "test2"); 92 KUNIT_EXPECT_FALSE(test, filtered[0]->test_cases[1].name); 93} 94 95static void filter_subsuite_to_empty_test(struct kunit *test) 96{ 97 struct kunit_suite *subsuite[3] = {NULL, NULL, NULL}; 98 struct kunit_suite * const *filtered; 99 struct kunit_test_filter filter = { 100 .suite_glob = "not_found", 101 .test_glob = NULL, 102 }; 103 104 subsuite[0] = alloc_fake_suite(test, "suite1", dummy_test_cases); 105 subsuite[1] = alloc_fake_suite(test, "suite2", dummy_test_cases); 106 107 filtered = kunit_filter_subsuite(subsuite, &filter); 108 free_subsuite_at_end(test, filtered); /* just in case */ 109 110 KUNIT_EXPECT_FALSE_MSG(test, filtered, 111 "should be NULL to indicate no match"); 112} 113 114static void kfree_subsuites_at_end(struct kunit *test, struct suite_set *suite_set) 115{ 116 struct kunit_suite * const * const *suites; 117 118 kfree_at_end(test, suite_set->start); 119 for (suites = suite_set->start; suites < suite_set->end; suites++) 120 free_subsuite_at_end(test, *suites); 121} 122 123static void filter_suites_test(struct kunit *test) 124{ 125 /* Suites per-file are stored as a NULL terminated array */ 126 struct kunit_suite *subsuites[2][2] = { 127 {NULL, NULL}, 128 {NULL, NULL}, 129 }; 130 /* Match the memory layout of suite_set */ 131 struct kunit_suite * const * const suites[2] = { 132 subsuites[0], subsuites[1], 133 }; 134 135 const struct suite_set suite_set = { 136 .start = suites, 137 .end = suites + 2, 138 }; 139 struct suite_set filtered = {.start = NULL, .end = NULL}; 140 int err = 0; 141 142 /* Emulate two files, each having one suite */ 143 subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases); 144 subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases); 145 146 /* Filter out suite1 */ 147 filtered = kunit_filter_suites(&suite_set, "suite0", &err); 148 kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */ 149 KUNIT_EXPECT_EQ(test, err, 0); 150 KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1); 151 152 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start); 153 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0]); 154 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0][0]); 155 KUNIT_EXPECT_STREQ(test, (const char *)filtered.start[0][0]->name, "suite0"); 156} 157 158static struct kunit_case executor_test_cases[] = { 159 KUNIT_CASE(parse_filter_test), 160 KUNIT_CASE(filter_subsuite_test), 161 KUNIT_CASE(filter_subsuite_test_glob_test), 162 KUNIT_CASE(filter_subsuite_to_empty_test), 163 KUNIT_CASE(filter_suites_test), 164 {} 165}; 166 167static struct kunit_suite executor_test_suite = { 168 .name = "kunit_executor_test", 169 .test_cases = executor_test_cases, 170}; 171 172kunit_test_suites(&executor_test_suite); 173 174/* Test helpers */ 175 176static void kfree_res_free(struct kunit_resource *res) 177{ 178 kfree(res->data); 179} 180 181/* Use the resource API to register a call to kfree(to_free). 182 * Since we never actually use the resource, it's safe to use on const data. 183 */ 184static void kfree_at_end(struct kunit *test, const void *to_free) 185{ 186 /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ 187 if (IS_ERR_OR_NULL(to_free)) 188 return; 189 kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, 190 (void *)to_free); 191} 192 193static void free_subsuite_res_free(struct kunit_resource *res) 194{ 195 kunit_free_subsuite(res->data); 196} 197 198static void free_subsuite_at_end(struct kunit *test, 199 struct kunit_suite *const *to_free) 200{ 201 if (IS_ERR_OR_NULL(to_free)) 202 return; 203 kunit_alloc_resource(test, NULL, free_subsuite_res_free, 204 GFP_KERNEL, (void *)to_free); 205} 206 207static struct kunit_suite *alloc_fake_suite(struct kunit *test, 208 const char *suite_name, 209 struct kunit_case *test_cases) 210{ 211 struct kunit_suite *suite; 212 213 /* We normally never expect to allocate suites, hence the non-const cast. */ 214 suite = kunit_kzalloc(test, sizeof(*suite), GFP_KERNEL); 215 strncpy((char *)suite->name, suite_name, sizeof(suite->name) - 1); 216 suite->test_cases = test_cases; 217 218 return suite; 219}