Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.7-rc7 372 lines 9.8 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * KUnit test for core test infrastructure. 4 * 5 * Copyright (C) 2019, Google LLC. 6 * Author: Brendan Higgins <brendanhiggins@google.com> 7 */ 8#include <kunit/test.h> 9 10#include "try-catch-impl.h" 11 12struct kunit_try_catch_test_context { 13 struct kunit_try_catch *try_catch; 14 bool function_called; 15}; 16 17static void kunit_test_successful_try(void *data) 18{ 19 struct kunit *test = data; 20 struct kunit_try_catch_test_context *ctx = test->priv; 21 22 ctx->function_called = true; 23} 24 25static void kunit_test_no_catch(void *data) 26{ 27 struct kunit *test = data; 28 29 KUNIT_FAIL(test, "Catch should not be called\n"); 30} 31 32static void kunit_test_try_catch_successful_try_no_catch(struct kunit *test) 33{ 34 struct kunit_try_catch_test_context *ctx = test->priv; 35 struct kunit_try_catch *try_catch = ctx->try_catch; 36 37 kunit_try_catch_init(try_catch, 38 test, 39 kunit_test_successful_try, 40 kunit_test_no_catch); 41 kunit_try_catch_run(try_catch, test); 42 43 KUNIT_EXPECT_TRUE(test, ctx->function_called); 44} 45 46static void kunit_test_unsuccessful_try(void *data) 47{ 48 struct kunit *test = data; 49 struct kunit_try_catch_test_context *ctx = test->priv; 50 struct kunit_try_catch *try_catch = ctx->try_catch; 51 52 kunit_try_catch_throw(try_catch); 53 KUNIT_FAIL(test, "This line should never be reached\n"); 54} 55 56static void kunit_test_catch(void *data) 57{ 58 struct kunit *test = data; 59 struct kunit_try_catch_test_context *ctx = test->priv; 60 61 ctx->function_called = true; 62} 63 64static void kunit_test_try_catch_unsuccessful_try_does_catch(struct kunit *test) 65{ 66 struct kunit_try_catch_test_context *ctx = test->priv; 67 struct kunit_try_catch *try_catch = ctx->try_catch; 68 69 kunit_try_catch_init(try_catch, 70 test, 71 kunit_test_unsuccessful_try, 72 kunit_test_catch); 73 kunit_try_catch_run(try_catch, test); 74 75 KUNIT_EXPECT_TRUE(test, ctx->function_called); 76} 77 78static int kunit_try_catch_test_init(struct kunit *test) 79{ 80 struct kunit_try_catch_test_context *ctx; 81 82 ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL); 83 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 84 test->priv = ctx; 85 86 ctx->try_catch = kunit_kmalloc(test, 87 sizeof(*ctx->try_catch), 88 GFP_KERNEL); 89 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx->try_catch); 90 91 return 0; 92} 93 94static struct kunit_case kunit_try_catch_test_cases[] = { 95 KUNIT_CASE(kunit_test_try_catch_successful_try_no_catch), 96 KUNIT_CASE(kunit_test_try_catch_unsuccessful_try_does_catch), 97 {} 98}; 99 100static struct kunit_suite kunit_try_catch_test_suite = { 101 .name = "kunit-try-catch-test", 102 .init = kunit_try_catch_test_init, 103 .test_cases = kunit_try_catch_test_cases, 104}; 105 106/* 107 * Context for testing test managed resources 108 * is_resource_initialized is used to test arbitrary resources 109 */ 110struct kunit_test_resource_context { 111 struct kunit test; 112 bool is_resource_initialized; 113 int allocate_order[2]; 114 int free_order[2]; 115}; 116 117static int fake_resource_init(struct kunit_resource *res, void *context) 118{ 119 struct kunit_test_resource_context *ctx = context; 120 121 res->allocation = &ctx->is_resource_initialized; 122 ctx->is_resource_initialized = true; 123 return 0; 124} 125 126static void fake_resource_free(struct kunit_resource *res) 127{ 128 bool *is_resource_initialized = res->allocation; 129 130 *is_resource_initialized = false; 131} 132 133static void kunit_resource_test_init_resources(struct kunit *test) 134{ 135 struct kunit_test_resource_context *ctx = test->priv; 136 137 kunit_init_test(&ctx->test, "testing_test_init_test", NULL); 138 139 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 140} 141 142static void kunit_resource_test_alloc_resource(struct kunit *test) 143{ 144 struct kunit_test_resource_context *ctx = test->priv; 145 struct kunit_resource *res; 146 kunit_resource_free_t free = fake_resource_free; 147 148 res = kunit_alloc_and_get_resource(&ctx->test, 149 fake_resource_init, 150 fake_resource_free, 151 GFP_KERNEL, 152 ctx); 153 154 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, res); 155 KUNIT_EXPECT_PTR_EQ(test, 156 &ctx->is_resource_initialized, 157 (bool *) res->allocation); 158 KUNIT_EXPECT_TRUE(test, list_is_last(&res->node, &ctx->test.resources)); 159 KUNIT_EXPECT_PTR_EQ(test, free, res->free); 160} 161 162static void kunit_resource_test_destroy_resource(struct kunit *test) 163{ 164 struct kunit_test_resource_context *ctx = test->priv; 165 struct kunit_resource *res = kunit_alloc_and_get_resource( 166 &ctx->test, 167 fake_resource_init, 168 fake_resource_free, 169 GFP_KERNEL, 170 ctx); 171 172 KUNIT_ASSERT_FALSE(test, 173 kunit_resource_destroy(&ctx->test, 174 kunit_resource_instance_match, 175 res->free, 176 res->allocation)); 177 178 KUNIT_EXPECT_FALSE(test, ctx->is_resource_initialized); 179 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 180} 181 182static void kunit_resource_test_cleanup_resources(struct kunit *test) 183{ 184 int i; 185 struct kunit_test_resource_context *ctx = test->priv; 186 struct kunit_resource *resources[5]; 187 188 for (i = 0; i < ARRAY_SIZE(resources); i++) { 189 resources[i] = kunit_alloc_and_get_resource(&ctx->test, 190 fake_resource_init, 191 fake_resource_free, 192 GFP_KERNEL, 193 ctx); 194 } 195 196 kunit_cleanup(&ctx->test); 197 198 KUNIT_EXPECT_TRUE(test, list_empty(&ctx->test.resources)); 199} 200 201static void kunit_resource_test_mark_order(int order_array[], 202 size_t order_size, 203 int key) 204{ 205 int i; 206 207 for (i = 0; i < order_size && order_array[i]; i++) 208 ; 209 210 order_array[i] = key; 211} 212 213#define KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, order_field, key) \ 214 kunit_resource_test_mark_order(ctx->order_field, \ 215 ARRAY_SIZE(ctx->order_field), \ 216 key) 217 218static int fake_resource_2_init(struct kunit_resource *res, void *context) 219{ 220 struct kunit_test_resource_context *ctx = context; 221 222 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 2); 223 224 res->allocation = ctx; 225 226 return 0; 227} 228 229static void fake_resource_2_free(struct kunit_resource *res) 230{ 231 struct kunit_test_resource_context *ctx = res->allocation; 232 233 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 2); 234} 235 236static int fake_resource_1_init(struct kunit_resource *res, void *context) 237{ 238 struct kunit_test_resource_context *ctx = context; 239 240 kunit_alloc_and_get_resource(&ctx->test, 241 fake_resource_2_init, 242 fake_resource_2_free, 243 GFP_KERNEL, 244 ctx); 245 246 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, allocate_order, 1); 247 248 res->allocation = ctx; 249 250 return 0; 251} 252 253static void fake_resource_1_free(struct kunit_resource *res) 254{ 255 struct kunit_test_resource_context *ctx = res->allocation; 256 257 KUNIT_RESOURCE_TEST_MARK_ORDER(ctx, free_order, 1); 258} 259 260/* 261 * TODO(brendanhiggins@google.com): replace the arrays that keep track of the 262 * order of allocation and freeing with strict mocks using the IN_SEQUENCE macro 263 * to assert allocation and freeing order when the feature becomes available. 264 */ 265static void kunit_resource_test_proper_free_ordering(struct kunit *test) 266{ 267 struct kunit_test_resource_context *ctx = test->priv; 268 269 /* fake_resource_1 allocates a fake_resource_2 in its init. */ 270 kunit_alloc_and_get_resource(&ctx->test, 271 fake_resource_1_init, 272 fake_resource_1_free, 273 GFP_KERNEL, 274 ctx); 275 276 /* 277 * Since fake_resource_2_init calls KUNIT_RESOURCE_TEST_MARK_ORDER 278 * before returning to fake_resource_1_init, it should be the first to 279 * put its key in the allocate_order array. 280 */ 281 KUNIT_EXPECT_EQ(test, ctx->allocate_order[0], 2); 282 KUNIT_EXPECT_EQ(test, ctx->allocate_order[1], 1); 283 284 kunit_cleanup(&ctx->test); 285 286 /* 287 * Because fake_resource_2 finishes allocation before fake_resource_1, 288 * fake_resource_1 should be freed first since it could depend on 289 * fake_resource_2. 290 */ 291 KUNIT_EXPECT_EQ(test, ctx->free_order[0], 1); 292 KUNIT_EXPECT_EQ(test, ctx->free_order[1], 2); 293} 294 295static int kunit_resource_test_init(struct kunit *test) 296{ 297 struct kunit_test_resource_context *ctx = 298 kzalloc(sizeof(*ctx), GFP_KERNEL); 299 300 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx); 301 302 test->priv = ctx; 303 304 kunit_init_test(&ctx->test, "test_test_context", NULL); 305 306 return 0; 307} 308 309static void kunit_resource_test_exit(struct kunit *test) 310{ 311 struct kunit_test_resource_context *ctx = test->priv; 312 313 kunit_cleanup(&ctx->test); 314 kfree(ctx); 315} 316 317static struct kunit_case kunit_resource_test_cases[] = { 318 KUNIT_CASE(kunit_resource_test_init_resources), 319 KUNIT_CASE(kunit_resource_test_alloc_resource), 320 KUNIT_CASE(kunit_resource_test_destroy_resource), 321 KUNIT_CASE(kunit_resource_test_cleanup_resources), 322 KUNIT_CASE(kunit_resource_test_proper_free_ordering), 323 {} 324}; 325 326static struct kunit_suite kunit_resource_test_suite = { 327 .name = "kunit-resource-test", 328 .init = kunit_resource_test_init, 329 .exit = kunit_resource_test_exit, 330 .test_cases = kunit_resource_test_cases, 331}; 332 333static void kunit_log_test(struct kunit *test); 334 335static struct kunit_case kunit_log_test_cases[] = { 336 KUNIT_CASE(kunit_log_test), 337 {} 338}; 339 340static struct kunit_suite kunit_log_test_suite = { 341 .name = "kunit-log-test", 342 .test_cases = kunit_log_test_cases, 343}; 344 345static void kunit_log_test(struct kunit *test) 346{ 347 struct kunit_suite *suite = &kunit_log_test_suite; 348 349 kunit_log(KERN_INFO, test, "put this in log."); 350 kunit_log(KERN_INFO, test, "this too."); 351 kunit_log(KERN_INFO, suite, "add to suite log."); 352 kunit_log(KERN_INFO, suite, "along with this."); 353 354#ifdef CONFIG_KUNIT_DEBUGFS 355 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 356 strstr(test->log, "put this in log.")); 357 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 358 strstr(test->log, "this too.")); 359 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 360 strstr(suite->log, "add to suite log.")); 361 KUNIT_EXPECT_NOT_ERR_OR_NULL(test, 362 strstr(suite->log, "along with this.")); 363#else 364 KUNIT_EXPECT_PTR_EQ(test, test->log, (char *)NULL); 365 KUNIT_EXPECT_PTR_EQ(test, suite->log, (char *)NULL); 366#endif 367} 368 369kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite, 370 &kunit_log_test_suite); 371 372MODULE_LICENSE("GPL v2");