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

Merge tag 'linux-kselftest-kunit-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull Kunit updates from Shuah Khan:

- documentation update and fix to kunit_tool to parse diagnostic
messages correctly from David Gow

- Support for Parameterized Testing and fs/ext4 test updates to use
KUnit parameterized testing feature from Arpitha Raghunandan

- Helper to derive file names depending on --build_dir argument from
Andy Shevchenko

* tag 'linux-kselftest-kunit-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
fs: ext4: Modify inode-test.c to use KUnit parameterized testing feature
kunit: Support for Parameterized Testing
kunit: kunit_tool: Correctly parse diagnostic messages
Documentation: kunit: provide guidance for testing many inputs
kunit: Introduce get_file_path() helper

+349 -191
+77 -6
Documentation/dev-tools/kunit/usage.rst
··· 15 15 Organization of this document 16 16 ============================= 17 17 18 - This document is organized into two main sections: Testing and Isolating 19 - Behavior. The first covers what unit tests are and how to use KUnit to write 20 - them. The second covers how to use KUnit to isolate code and make it possible 21 - to unit test code that was otherwise un-unit-testable. 18 + This document is organized into two main sections: Testing and Common Patterns. 19 + The first covers what unit tests are and how to use KUnit to write them. The 20 + second covers common testing patterns, e.g. how to isolate code and make it 21 + possible to unit test code that was otherwise un-unit-testable. 22 22 23 23 Testing 24 24 ======= ··· 218 218 219 219 For more information on these types of things see the :doc:`api/test`. 220 220 221 + Common Patterns 222 + =============== 223 + 221 224 Isolating Behavior 222 - ================== 225 + ------------------ 223 226 224 227 The most important aspect of unit testing that other forms of testing do not 225 228 provide is the ability to limit the amount of code under test to a single unit. ··· 236 233 at compile time. 237 234 238 235 Classes 239 - ------- 236 + ~~~~~~~ 240 237 241 238 Classes are not a construct that is built into the C programming language; 242 239 however, it is an easily derived concept. Accordingly, pretty much every project ··· 453 450 454 451 destroy_eeprom_buffer(ctx->eeprom_buffer); 455 452 } 453 + 454 + Testing against multiple inputs 455 + ------------------------------- 456 + 457 + Testing just a few inputs might not be enough to have confidence that the code 458 + works correctly, e.g. for a hash function. 459 + 460 + In such cases, it can be helpful to have a helper macro or function, e.g. this 461 + fictitious example for ``sha1sum(1)`` 462 + 463 + .. code-block:: c 464 + 465 + /* Note: the cast is to satisfy overly strict type-checking. */ 466 + #define TEST_SHA1(in, want) \ 467 + sha1sum(in, out); \ 468 + KUNIT_EXPECT_STREQ_MSG(test, (char *)out, want, "sha1sum(%s)", in); 469 + 470 + char out[40]; 471 + TEST_SHA1("hello world", "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed"); 472 + TEST_SHA1("hello world!", "430ce34d020724ed75a196dfc2ad67c77772d169"); 473 + 474 + 475 + Note the use of ``KUNIT_EXPECT_STREQ_MSG`` to give more context when it fails 476 + and make it easier to track down. (Yes, in this example, ``want`` is likely 477 + going to be unique enough on its own). 478 + 479 + The ``_MSG`` variants are even more useful when the same expectation is called 480 + multiple times (in a loop or helper function) and thus the line number isn't 481 + enough to identify what failed, like below. 482 + 483 + In some cases, it can be helpful to write a *table-driven test* instead, e.g. 484 + 485 + .. code-block:: c 486 + 487 + int i; 488 + char out[40]; 489 + 490 + struct sha1_test_case { 491 + const char *str; 492 + const char *sha1; 493 + }; 494 + 495 + struct sha1_test_case cases[] = { 496 + { 497 + .str = "hello world", 498 + .sha1 = "2aae6c35c94fcfb415dbe95f408b9ce91ee846ed", 499 + }, 500 + { 501 + .str = "hello world!", 502 + .sha1 = "430ce34d020724ed75a196dfc2ad67c77772d169", 503 + }, 504 + }; 505 + for (i = 0; i < ARRAY_SIZE(cases); ++i) { 506 + sha1sum(cases[i].str, out); 507 + KUNIT_EXPECT_STREQ_MSG(test, (char *)out, cases[i].sha1, 508 + "sha1sum(%s)", cases[i].str); 509 + } 510 + 511 + 512 + There's more boilerplate involved, but it can: 513 + 514 + * be more readable when there are multiple inputs/outputs thanks to field names, 515 + 516 + * E.g. see ``fs/ext4/inode-test.c`` for an example of both. 517 + * reduce duplication if test cases can be shared across multiple tests. 518 + 519 + * E.g. if we wanted to also test ``sha256sum``, we could add a ``sha256`` 520 + field and reuse ``cases``. 456 521 457 522 .. _kunit-on-non-uml: 458 523
+162 -154
fs/ext4/inode-test.c
··· 80 80 bool lower_bound; 81 81 }; 82 82 83 + static const struct timestamp_expectation test_data[] = { 84 + { 85 + .test_case_name = LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE, 86 + .msb_set = true, 87 + .lower_bound = true, 88 + .extra_bits = 0, 89 + .expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L}, 90 + }, 91 + 92 + { 93 + .test_case_name = UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE, 94 + .msb_set = true, 95 + .lower_bound = false, 96 + .extra_bits = 0, 97 + .expected = {.tv_sec = -1LL, .tv_nsec = 0L}, 98 + }, 99 + 100 + { 101 + .test_case_name = LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE, 102 + .msb_set = false, 103 + .lower_bound = true, 104 + .extra_bits = 0, 105 + .expected = {0LL, 0L}, 106 + }, 107 + 108 + { 109 + .test_case_name = UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE, 110 + .msb_set = false, 111 + .lower_bound = false, 112 + .extra_bits = 0, 113 + .expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L}, 114 + }, 115 + 116 + { 117 + .test_case_name = LOWER_BOUND_NEG_LO_1_CASE, 118 + .msb_set = true, 119 + .lower_bound = true, 120 + .extra_bits = 1, 121 + .expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L}, 122 + }, 123 + 124 + { 125 + .test_case_name = UPPER_BOUND_NEG_LO_1_CASE, 126 + .msb_set = true, 127 + .lower_bound = false, 128 + .extra_bits = 1, 129 + .expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L}, 130 + }, 131 + 132 + { 133 + .test_case_name = LOWER_BOUND_NONNEG_LO_1_CASE, 134 + .msb_set = false, 135 + .lower_bound = true, 136 + .extra_bits = 1, 137 + .expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L}, 138 + }, 139 + 140 + { 141 + .test_case_name = UPPER_BOUND_NONNEG_LO_1_CASE, 142 + .msb_set = false, 143 + .lower_bound = false, 144 + .extra_bits = 1, 145 + .expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L}, 146 + }, 147 + 148 + { 149 + .test_case_name = LOWER_BOUND_NEG_HI_1_CASE, 150 + .msb_set = true, 151 + .lower_bound = true, 152 + .extra_bits = 2, 153 + .expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L}, 154 + }, 155 + 156 + { 157 + .test_case_name = UPPER_BOUND_NEG_HI_1_CASE, 158 + .msb_set = true, 159 + .lower_bound = false, 160 + .extra_bits = 2, 161 + .expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L}, 162 + }, 163 + 164 + { 165 + .test_case_name = LOWER_BOUND_NONNEG_HI_1_CASE, 166 + .msb_set = false, 167 + .lower_bound = true, 168 + .extra_bits = 2, 169 + .expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L}, 170 + }, 171 + 172 + { 173 + .test_case_name = UPPER_BOUND_NONNEG_HI_1_CASE, 174 + .msb_set = false, 175 + .lower_bound = false, 176 + .extra_bits = 2, 177 + .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L}, 178 + }, 179 + 180 + { 181 + .test_case_name = UPPER_BOUND_NONNEG_HI_1_NS_1_CASE, 182 + .msb_set = false, 183 + .lower_bound = false, 184 + .extra_bits = 6, 185 + .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L}, 186 + }, 187 + 188 + { 189 + .test_case_name = LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE, 190 + .msb_set = false, 191 + .lower_bound = true, 192 + .extra_bits = 0xFFFFFFFF, 193 + .expected = {.tv_sec = 0x300000000LL, 194 + .tv_nsec = MAX_NANOSECONDS}, 195 + }, 196 + 197 + { 198 + .test_case_name = LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE, 199 + .msb_set = false, 200 + .lower_bound = true, 201 + .extra_bits = 3, 202 + .expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L}, 203 + }, 204 + 205 + { 206 + .test_case_name = UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE, 207 + .msb_set = false, 208 + .lower_bound = false, 209 + .extra_bits = 3, 210 + .expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L}, 211 + } 212 + }; 213 + 214 + static void timestamp_expectation_to_desc(const struct timestamp_expectation *t, 215 + char *desc) 216 + { 217 + strscpy(desc, t->test_case_name, KUNIT_PARAM_DESC_SIZE); 218 + } 219 + 220 + KUNIT_ARRAY_PARAM(ext4_inode, test_data, timestamp_expectation_to_desc); 221 + 83 222 static time64_t get_32bit_time(const struct timestamp_expectation * const test) 84 223 { 85 224 if (test->msb_set) { ··· 240 101 */ 241 102 static void inode_test_xtimestamp_decoding(struct kunit *test) 242 103 { 243 - const struct timestamp_expectation test_data[] = { 244 - { 245 - .test_case_name = LOWER_BOUND_NEG_NO_EXTRA_BITS_CASE, 246 - .msb_set = true, 247 - .lower_bound = true, 248 - .extra_bits = 0, 249 - .expected = {.tv_sec = -0x80000000LL, .tv_nsec = 0L}, 250 - }, 251 - 252 - { 253 - .test_case_name = UPPER_BOUND_NEG_NO_EXTRA_BITS_CASE, 254 - .msb_set = true, 255 - .lower_bound = false, 256 - .extra_bits = 0, 257 - .expected = {.tv_sec = -1LL, .tv_nsec = 0L}, 258 - }, 259 - 260 - { 261 - .test_case_name = LOWER_BOUND_NONNEG_NO_EXTRA_BITS_CASE, 262 - .msb_set = false, 263 - .lower_bound = true, 264 - .extra_bits = 0, 265 - .expected = {0LL, 0L}, 266 - }, 267 - 268 - { 269 - .test_case_name = UPPER_BOUND_NONNEG_NO_EXTRA_BITS_CASE, 270 - .msb_set = false, 271 - .lower_bound = false, 272 - .extra_bits = 0, 273 - .expected = {.tv_sec = 0x7fffffffLL, .tv_nsec = 0L}, 274 - }, 275 - 276 - { 277 - .test_case_name = LOWER_BOUND_NEG_LO_1_CASE, 278 - .msb_set = true, 279 - .lower_bound = true, 280 - .extra_bits = 1, 281 - .expected = {.tv_sec = 0x80000000LL, .tv_nsec = 0L}, 282 - }, 283 - 284 - { 285 - .test_case_name = UPPER_BOUND_NEG_LO_1_CASE, 286 - .msb_set = true, 287 - .lower_bound = false, 288 - .extra_bits = 1, 289 - .expected = {.tv_sec = 0xffffffffLL, .tv_nsec = 0L}, 290 - }, 291 - 292 - { 293 - .test_case_name = LOWER_BOUND_NONNEG_LO_1_CASE, 294 - .msb_set = false, 295 - .lower_bound = true, 296 - .extra_bits = 1, 297 - .expected = {.tv_sec = 0x100000000LL, .tv_nsec = 0L}, 298 - }, 299 - 300 - { 301 - .test_case_name = UPPER_BOUND_NONNEG_LO_1_CASE, 302 - .msb_set = false, 303 - .lower_bound = false, 304 - .extra_bits = 1, 305 - .expected = {.tv_sec = 0x17fffffffLL, .tv_nsec = 0L}, 306 - }, 307 - 308 - { 309 - .test_case_name = LOWER_BOUND_NEG_HI_1_CASE, 310 - .msb_set = true, 311 - .lower_bound = true, 312 - .extra_bits = 2, 313 - .expected = {.tv_sec = 0x180000000LL, .tv_nsec = 0L}, 314 - }, 315 - 316 - { 317 - .test_case_name = UPPER_BOUND_NEG_HI_1_CASE, 318 - .msb_set = true, 319 - .lower_bound = false, 320 - .extra_bits = 2, 321 - .expected = {.tv_sec = 0x1ffffffffLL, .tv_nsec = 0L}, 322 - }, 323 - 324 - { 325 - .test_case_name = LOWER_BOUND_NONNEG_HI_1_CASE, 326 - .msb_set = false, 327 - .lower_bound = true, 328 - .extra_bits = 2, 329 - .expected = {.tv_sec = 0x200000000LL, .tv_nsec = 0L}, 330 - }, 331 - 332 - { 333 - .test_case_name = UPPER_BOUND_NONNEG_HI_1_CASE, 334 - .msb_set = false, 335 - .lower_bound = false, 336 - .extra_bits = 2, 337 - .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 0L}, 338 - }, 339 - 340 - { 341 - .test_case_name = UPPER_BOUND_NONNEG_HI_1_NS_1_CASE, 342 - .msb_set = false, 343 - .lower_bound = false, 344 - .extra_bits = 6, 345 - .expected = {.tv_sec = 0x27fffffffLL, .tv_nsec = 1L}, 346 - }, 347 - 348 - { 349 - .test_case_name = LOWER_BOUND_NONNEG_HI_1_NS_MAX_CASE, 350 - .msb_set = false, 351 - .lower_bound = true, 352 - .extra_bits = 0xFFFFFFFF, 353 - .expected = {.tv_sec = 0x300000000LL, 354 - .tv_nsec = MAX_NANOSECONDS}, 355 - }, 356 - 357 - { 358 - .test_case_name = LOWER_BOUND_NONNEG_EXTRA_BITS_1_CASE, 359 - .msb_set = false, 360 - .lower_bound = true, 361 - .extra_bits = 3, 362 - .expected = {.tv_sec = 0x300000000LL, .tv_nsec = 0L}, 363 - }, 364 - 365 - { 366 - .test_case_name = UPPER_BOUND_NONNEG_EXTRA_BITS_1_CASE, 367 - .msb_set = false, 368 - .lower_bound = false, 369 - .extra_bits = 3, 370 - .expected = {.tv_sec = 0x37fffffffLL, .tv_nsec = 0L}, 371 - } 372 - }; 373 - 374 104 struct timespec64 timestamp; 375 - int i; 376 105 377 - for (i = 0; i < ARRAY_SIZE(test_data); ++i) { 378 - timestamp.tv_sec = get_32bit_time(&test_data[i]); 379 - ext4_decode_extra_time(&timestamp, 380 - cpu_to_le32(test_data[i].extra_bits)); 106 + struct timestamp_expectation *test_param = 107 + (struct timestamp_expectation *)(test->param_value); 381 108 382 - KUNIT_EXPECT_EQ_MSG(test, 383 - test_data[i].expected.tv_sec, 384 - timestamp.tv_sec, 385 - CASE_NAME_FORMAT, 386 - test_data[i].test_case_name, 387 - test_data[i].msb_set, 388 - test_data[i].lower_bound, 389 - test_data[i].extra_bits); 390 - KUNIT_EXPECT_EQ_MSG(test, 391 - test_data[i].expected.tv_nsec, 392 - timestamp.tv_nsec, 393 - CASE_NAME_FORMAT, 394 - test_data[i].test_case_name, 395 - test_data[i].msb_set, 396 - test_data[i].lower_bound, 397 - test_data[i].extra_bits); 398 - } 109 + timestamp.tv_sec = get_32bit_time(test_param); 110 + ext4_decode_extra_time(&timestamp, 111 + cpu_to_le32(test_param->extra_bits)); 112 + 113 + KUNIT_EXPECT_EQ_MSG(test, 114 + test_param->expected.tv_sec, 115 + timestamp.tv_sec, 116 + CASE_NAME_FORMAT, 117 + test_param->test_case_name, 118 + test_param->msb_set, 119 + test_param->lower_bound, 120 + test_param->extra_bits); 121 + KUNIT_EXPECT_EQ_MSG(test, 122 + test_param->expected.tv_nsec, 123 + timestamp.tv_nsec, 124 + CASE_NAME_FORMAT, 125 + test_param->test_case_name, 126 + test_param->msb_set, 127 + test_param->lower_bound, 128 + test_param->extra_bits); 399 129 } 400 130 401 131 static struct kunit_case ext4_inode_test_cases[] = { 402 - KUNIT_CASE(inode_test_xtimestamp_decoding), 132 + KUNIT_CASE_PARAM(inode_test_xtimestamp_decoding, ext4_inode_gen_params), 403 133 {} 404 134 }; 405 135
+51
include/kunit/test.h
··· 94 94 /* Size of log associated with test. */ 95 95 #define KUNIT_LOG_SIZE 512 96 96 97 + /* Maximum size of parameter description string. */ 98 + #define KUNIT_PARAM_DESC_SIZE 128 99 + 97 100 /* 98 101 * TAP specifies subtest stream indentation of 4 spaces, 8 spaces for a 99 102 * sub-subtest. See the "Subtests" section in ··· 110 107 * 111 108 * @run_case: the function representing the actual test case. 112 109 * @name: the name of the test case. 110 + * @generate_params: the generator function for parameterized tests. 113 111 * 114 112 * A test case is a function with the signature, 115 113 * ``void (*)(struct kunit *)`` ··· 145 141 struct kunit_case { 146 142 void (*run_case)(struct kunit *test); 147 143 const char *name; 144 + const void* (*generate_params)(const void *prev, char *desc); 148 145 149 146 /* private: internal use only. */ 150 147 bool success; ··· 167 162 * &struct kunit_case for an example on how to use it. 168 163 */ 169 164 #define KUNIT_CASE(test_name) { .run_case = test_name, .name = #test_name } 165 + 166 + /** 167 + * KUNIT_CASE_PARAM - A helper for creation a parameterized &struct kunit_case 168 + * 169 + * @test_name: a reference to a test case function. 170 + * @gen_params: a reference to a parameter generator function. 171 + * 172 + * The generator function:: 173 + * 174 + * const void* gen_params(const void *prev, char *desc) 175 + * 176 + * is used to lazily generate a series of arbitrarily typed values that fit into 177 + * a void*. The argument @prev is the previously returned value, which should be 178 + * used to derive the next value; @prev is set to NULL on the initial generator 179 + * call. When no more values are available, the generator must return NULL. 180 + * Optionally write a string into @desc (size of KUNIT_PARAM_DESC_SIZE) 181 + * describing the parameter. 182 + */ 183 + #define KUNIT_CASE_PARAM(test_name, gen_params) \ 184 + { .run_case = test_name, .name = #test_name, \ 185 + .generate_params = gen_params } 170 186 171 187 /** 172 188 * struct kunit_suite - describes a related collection of &struct kunit_case ··· 234 208 const char *name; /* Read only after initialization! */ 235 209 char *log; /* Points at case log after initialization */ 236 210 struct kunit_try_catch try_catch; 211 + /* param_value is the current parameter value for a test case. */ 212 + const void *param_value; 213 + /* param_index stores the index of the parameter in parameterized tests. */ 214 + int param_index; 237 215 /* 238 216 * success starts as true, and may only be set to false during a 239 217 * test case; thus, it is safe to update this across multiple ··· 1771 1741 ptr, \ 1772 1742 fmt, \ 1773 1743 ##__VA_ARGS__) 1744 + 1745 + /** 1746 + * KUNIT_ARRAY_PARAM() - Define test parameter generator from an array. 1747 + * @name: prefix for the test parameter generator function. 1748 + * @array: array of test parameters. 1749 + * @get_desc: function to convert param to description; NULL to use default 1750 + * 1751 + * Define function @name_gen_params which uses @array to generate parameters. 1752 + */ 1753 + #define KUNIT_ARRAY_PARAM(name, array, get_desc) \ 1754 + static const void *name##_gen_params(const void *prev, char *desc) \ 1755 + { \ 1756 + typeof((array)[0]) *__next = prev ? ((typeof(__next)) prev) + 1 : (array); \ 1757 + if (__next - (array) < ARRAY_SIZE((array))) { \ 1758 + void (*__get_desc)(typeof(__next), char *) = get_desc; \ 1759 + if (__get_desc) \ 1760 + __get_desc(__next, desc); \ 1761 + return __next; \ 1762 + } \ 1763 + return NULL; \ 1764 + } 1774 1765 1775 1766 #endif /* _KUNIT_TEST_H */
+46 -13
lib/kunit/test.c
··· 325 325 * occur in a test case and reports them as failures. 326 326 */ 327 327 static void kunit_run_case_catch_errors(struct kunit_suite *suite, 328 - struct kunit_case *test_case) 328 + struct kunit_case *test_case, 329 + struct kunit *test) 329 330 { 330 331 struct kunit_try_catch_context context; 331 332 struct kunit_try_catch *try_catch; 332 - struct kunit test; 333 333 334 - kunit_init_test(&test, test_case->name, test_case->log); 335 - try_catch = &test.try_catch; 334 + kunit_init_test(test, test_case->name, test_case->log); 335 + try_catch = &test->try_catch; 336 336 337 337 kunit_try_catch_init(try_catch, 338 - &test, 338 + test, 339 339 kunit_try_run_case, 340 340 kunit_catch_run_case); 341 - context.test = &test; 341 + context.test = test; 342 342 context.suite = suite; 343 343 context.test_case = test_case; 344 344 kunit_try_catch_run(try_catch, &context); 345 345 346 - test_case->success = test.success; 347 - 348 - kunit_print_ok_not_ok(&test, true, test_case->success, 349 - kunit_test_case_num(suite, test_case), 350 - test_case->name); 346 + test_case->success = test->success; 351 347 } 352 348 353 349 int kunit_run_tests(struct kunit_suite *suite) 354 350 { 351 + char param_desc[KUNIT_PARAM_DESC_SIZE]; 355 352 struct kunit_case *test_case; 356 353 357 354 kunit_print_subtest_start(suite); 358 355 359 - kunit_suite_for_each_test_case(suite, test_case) 360 - kunit_run_case_catch_errors(suite, test_case); 356 + kunit_suite_for_each_test_case(suite, test_case) { 357 + struct kunit test = { .param_value = NULL, .param_index = 0 }; 358 + bool test_success = true; 359 + 360 + if (test_case->generate_params) { 361 + /* Get initial param. */ 362 + param_desc[0] = '\0'; 363 + test.param_value = test_case->generate_params(NULL, param_desc); 364 + } 365 + 366 + do { 367 + kunit_run_case_catch_errors(suite, test_case, &test); 368 + test_success &= test_case->success; 369 + 370 + if (test_case->generate_params) { 371 + if (param_desc[0] == '\0') { 372 + snprintf(param_desc, sizeof(param_desc), 373 + "param-%d", test.param_index); 374 + } 375 + 376 + kunit_log(KERN_INFO, &test, 377 + KUNIT_SUBTEST_INDENT 378 + "# %s: %s %d - %s", 379 + test_case->name, 380 + kunit_status_to_string(test.success), 381 + test.param_index + 1, param_desc); 382 + 383 + /* Get next param. */ 384 + param_desc[0] = '\0'; 385 + test.param_value = test_case->generate_params(test.param_value, param_desc); 386 + test.param_index++; 387 + } 388 + } while (test.param_value); 389 + 390 + kunit_print_ok_not_ok(&test, true, test_success, 391 + kunit_test_case_num(suite, test_case), 392 + test_case->name); 393 + } 361 394 362 395 kunit_print_subtest_end(suite); 363 396
+9 -15
tools/testing/kunit/kunit_kernel.py
··· 23 23 BROKEN_ALLCONFIG_PATH = 'tools/testing/kunit/configs/broken_on_uml.config' 24 24 OUTFILE_PATH = 'test.log' 25 25 26 + def get_file_path(build_dir, default): 27 + if build_dir: 28 + default = os.path.join(build_dir, default) 29 + return default 30 + 26 31 class ConfigError(Exception): 27 32 """Represents an error trying to configure the Linux kernel.""" 28 33 ··· 102 97 103 98 def linux_bin(self, params, timeout, build_dir): 104 99 """Runs the Linux UML binary. Must be named 'linux'.""" 105 - linux_bin = './linux' 106 - if build_dir: 107 - linux_bin = os.path.join(build_dir, 'linux') 100 + linux_bin = get_file_path(build_dir, 'linux') 108 101 outfile = get_outfile_path(build_dir) 109 102 with open(outfile, 'w') as output: 110 103 process = subprocess.Popen([linux_bin] + params, ··· 111 108 process.wait(timeout) 112 109 113 110 def get_kconfig_path(build_dir): 114 - kconfig_path = KCONFIG_PATH 115 - if build_dir: 116 - kconfig_path = os.path.join(build_dir, KCONFIG_PATH) 117 - return kconfig_path 111 + return get_file_path(build_dir, KCONFIG_PATH) 118 112 119 113 def get_kunitconfig_path(build_dir): 120 - kunitconfig_path = KUNITCONFIG_PATH 121 - if build_dir: 122 - kunitconfig_path = os.path.join(build_dir, KUNITCONFIG_PATH) 123 - return kunitconfig_path 114 + return get_file_path(build_dir, KUNITCONFIG_PATH) 124 115 125 116 def get_outfile_path(build_dir): 126 - outfile_path = OUTFILE_PATH 127 - if build_dir: 128 - outfile_path = os.path.join(build_dir, OUTFILE_PATH) 129 - return outfile_path 117 + return get_file_path(build_dir, OUTFILE_PATH) 130 118 131 119 class LinuxSourceTree(object): 132 120 """Represents a Linux kernel source tree with KUnit tests."""
+4 -3
tools/testing/kunit/kunit_parser.py
··· 135 135 else: 136 136 return False 137 137 138 - SUBTEST_DIAGNOSTIC = re.compile(r'^[\s]+# .*?: (.*)$') 139 - DIAGNOSTIC_CRASH_MESSAGE = 'kunit test case crashed!' 138 + SUBTEST_DIAGNOSTIC = re.compile(r'^[\s]+# (.*)$') 139 + DIAGNOSTIC_CRASH_MESSAGE = re.compile(r'^[\s]+# .*?: kunit test case crashed!$') 140 140 141 141 def parse_diagnostic(lines: List[str], test_case: TestCase) -> bool: 142 142 save_non_diagnositic(lines, test_case) ··· 146 146 match = SUBTEST_DIAGNOSTIC.match(line) 147 147 if match: 148 148 test_case.log.append(lines.pop(0)) 149 - if match.group(1) == DIAGNOSTIC_CRASH_MESSAGE: 149 + crash_match = DIAGNOSTIC_CRASH_MESSAGE.match(line) 150 + if crash_match: 150 151 test_case.status = TestStatus.TEST_CRASHED 151 152 return True 152 153 else: