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 11 static void kfree_at_end(struct kunit *test, const void *to_free); 12 static void free_subsuite_at_end(struct kunit *test, 13 struct kunit_suite *const *to_free); 14 static struct kunit_suite *alloc_fake_suite(struct kunit *test, 15 const char *suite_name, 16 struct kunit_case *test_cases); 17 18 static void dummy_test(struct kunit *test) {} 19 20 static 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 27 static 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 44 static 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 67 static 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 95 static 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 114 static 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 123 static 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 141 /* Emulate two files, each having one suite */ 142 subsuites[0][0] = alloc_fake_suite(test, "suite0", dummy_test_cases); 143 subsuites[1][0] = alloc_fake_suite(test, "suite1", dummy_test_cases); 144 145 /* Filter out suite1 */ 146 filtered = kunit_filter_suites(&suite_set, "suite0"); 147 kfree_subsuites_at_end(test, &filtered); /* let us use ASSERTs without leaking */ 148 KUNIT_ASSERT_EQ(test, filtered.end - filtered.start, (ptrdiff_t)1); 149 150 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start); 151 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0]); 152 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, filtered.start[0][0]); 153 KUNIT_EXPECT_STREQ(test, (const char *)filtered.start[0][0]->name, "suite0"); 154 } 155 156 static struct kunit_case executor_test_cases[] = { 157 KUNIT_CASE(parse_filter_test), 158 KUNIT_CASE(filter_subsuite_test), 159 KUNIT_CASE(filter_subsuite_test_glob_test), 160 KUNIT_CASE(filter_subsuite_to_empty_test), 161 KUNIT_CASE(filter_suites_test), 162 {} 163 }; 164 165 static struct kunit_suite executor_test_suite = { 166 .name = "kunit_executor_test", 167 .test_cases = executor_test_cases, 168 }; 169 170 kunit_test_suites(&executor_test_suite); 171 172 /* Test helpers */ 173 174 static void kfree_res_free(struct kunit_resource *res) 175 { 176 kfree(res->data); 177 } 178 179 /* Use the resource API to register a call to kfree(to_free). 180 * Since we never actually use the resource, it's safe to use on const data. 181 */ 182 static void kfree_at_end(struct kunit *test, const void *to_free) 183 { 184 /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ 185 if (IS_ERR_OR_NULL(to_free)) 186 return; 187 kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, 188 (void *)to_free); 189 } 190 191 static void free_subsuite_res_free(struct kunit_resource *res) 192 { 193 kunit_free_subsuite(res->data); 194 } 195 196 static void free_subsuite_at_end(struct kunit *test, 197 struct kunit_suite *const *to_free) 198 { 199 if (IS_ERR_OR_NULL(to_free)) 200 return; 201 kunit_alloc_resource(test, NULL, free_subsuite_res_free, 202 GFP_KERNEL, (void *)to_free); 203 } 204 205 static struct kunit_suite *alloc_fake_suite(struct kunit *test, 206 const char *suite_name, 207 struct kunit_case *test_cases) 208 { 209 struct kunit_suite *suite; 210 211 /* We normally never expect to allocate suites, hence the non-const cast. */ 212 suite = kunit_kzalloc(test, sizeof(*suite), GFP_KERNEL); 213 strncpy((char *)suite->name, suite_name, sizeof(suite->name) - 1); 214 suite->test_cases = test_cases; 215 216 return suite; 217 } 218