.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Test cases for printf facility. |
---|
3 | 4 | */ |
---|
.. | .. |
---|
9 | 10 | #include <linux/module.h> |
---|
10 | 11 | #include <linux/printk.h> |
---|
11 | 12 | #include <linux/random.h> |
---|
| 13 | +#include <linux/rtc.h> |
---|
12 | 14 | #include <linux/slab.h> |
---|
13 | 15 | #include <linux/string.h> |
---|
14 | 16 | |
---|
.. | .. |
---|
20 | 22 | #include <linux/gfp.h> |
---|
21 | 23 | #include <linux/mm.h> |
---|
22 | 24 | |
---|
| 25 | +#include <linux/property.h> |
---|
| 26 | + |
---|
| 27 | +#include "../tools/testing/selftests/kselftest_module.h" |
---|
| 28 | + |
---|
23 | 29 | #define BUF_SIZE 256 |
---|
24 | 30 | #define PAD_SIZE 16 |
---|
25 | 31 | #define FILL_CHAR '$' |
---|
26 | 32 | |
---|
27 | | -static unsigned total_tests __initdata; |
---|
28 | | -static unsigned failed_tests __initdata; |
---|
| 33 | +KSTM_MODULE_GLOBALS(); |
---|
| 34 | + |
---|
29 | 35 | static char *test_buffer __initdata; |
---|
30 | 36 | static char *alloced_buffer __initdata; |
---|
| 37 | + |
---|
| 38 | +extern bool no_hash_pointers; |
---|
31 | 39 | |
---|
32 | 40 | static int __printf(4, 0) __init |
---|
33 | 41 | do_test(int bufsize, const char *expect, int elen, |
---|
.. | .. |
---|
208 | 216 | #define PTR_STR "ffff0123456789ab" |
---|
209 | 217 | #define PTR_VAL_NO_CRNG "(____ptrval____)" |
---|
210 | 218 | #define ZEROS "00000000" /* hex 32 zero bits */ |
---|
| 219 | +#define ONES "ffffffff" /* hex 32 one bits */ |
---|
211 | 220 | |
---|
212 | 221 | static int __init |
---|
213 | 222 | plain_format(void) |
---|
.. | .. |
---|
238 | 247 | #define PTR ((void *)0x456789ab) |
---|
239 | 248 | #define PTR_STR "456789ab" |
---|
240 | 249 | #define PTR_VAL_NO_CRNG "(ptrval)" |
---|
| 250 | +#define ZEROS "" |
---|
| 251 | +#define ONES "" |
---|
241 | 252 | |
---|
242 | 253 | static int __init |
---|
243 | 254 | plain_format(void) |
---|
.. | .. |
---|
249 | 260 | #endif /* BITS_PER_LONG == 64 */ |
---|
250 | 261 | |
---|
251 | 262 | static int __init |
---|
252 | | -plain_hash(void) |
---|
| 263 | +plain_hash_to_buffer(const void *p, char *buf, size_t len) |
---|
253 | 264 | { |
---|
254 | | - char buf[PLAIN_BUF_SIZE]; |
---|
255 | 265 | int nchars; |
---|
256 | 266 | |
---|
257 | | - nchars = snprintf(buf, PLAIN_BUF_SIZE, "%p", PTR); |
---|
| 267 | + nchars = snprintf(buf, len, "%p", p); |
---|
258 | 268 | |
---|
259 | 269 | if (nchars != PTR_WIDTH) |
---|
260 | 270 | return -1; |
---|
.. | .. |
---|
264 | 274 | PTR_VAL_NO_CRNG); |
---|
265 | 275 | return 0; |
---|
266 | 276 | } |
---|
| 277 | + |
---|
| 278 | + return 0; |
---|
| 279 | +} |
---|
| 280 | + |
---|
| 281 | +static int __init |
---|
| 282 | +plain_hash(void) |
---|
| 283 | +{ |
---|
| 284 | + char buf[PLAIN_BUF_SIZE]; |
---|
| 285 | + int ret; |
---|
| 286 | + |
---|
| 287 | + ret = plain_hash_to_buffer(PTR, buf, PLAIN_BUF_SIZE); |
---|
| 288 | + if (ret) |
---|
| 289 | + return ret; |
---|
267 | 290 | |
---|
268 | 291 | if (strncmp(buf, PTR_STR, PTR_WIDTH) == 0) |
---|
269 | 292 | return -1; |
---|
.. | .. |
---|
280 | 303 | { |
---|
281 | 304 | int err; |
---|
282 | 305 | |
---|
| 306 | + if (no_hash_pointers) { |
---|
| 307 | + pr_warn("skipping plain 'p' tests"); |
---|
| 308 | + skipped_tests += 2; |
---|
| 309 | + return; |
---|
| 310 | + } |
---|
| 311 | + |
---|
283 | 312 | err = plain_hash(); |
---|
284 | 313 | if (err) { |
---|
285 | 314 | pr_warn("plain 'p' does not appear to be hashed\n"); |
---|
.. | .. |
---|
292 | 321 | pr_warn("hashing plain 'p' has unexpected format\n"); |
---|
293 | 322 | failed_tests++; |
---|
294 | 323 | } |
---|
| 324 | +} |
---|
| 325 | + |
---|
| 326 | +static void __init |
---|
| 327 | +test_hashed(const char *fmt, const void *p) |
---|
| 328 | +{ |
---|
| 329 | + char buf[PLAIN_BUF_SIZE]; |
---|
| 330 | + int ret; |
---|
| 331 | + |
---|
| 332 | + /* |
---|
| 333 | + * No need to increase failed test counter since this is assumed |
---|
| 334 | + * to be called after plain(). |
---|
| 335 | + */ |
---|
| 336 | + ret = plain_hash_to_buffer(p, buf, PLAIN_BUF_SIZE); |
---|
| 337 | + if (ret) |
---|
| 338 | + return; |
---|
| 339 | + |
---|
| 340 | + test(buf, fmt, p); |
---|
| 341 | +} |
---|
| 342 | + |
---|
| 343 | +/* |
---|
| 344 | + * NULL pointers aren't hashed. |
---|
| 345 | + */ |
---|
| 346 | +static void __init |
---|
| 347 | +null_pointer(void) |
---|
| 348 | +{ |
---|
| 349 | + test(ZEROS "00000000", "%p", NULL); |
---|
| 350 | + test(ZEROS "00000000", "%px", NULL); |
---|
| 351 | + test("(null)", "%pE", NULL); |
---|
| 352 | +} |
---|
| 353 | + |
---|
| 354 | +/* |
---|
| 355 | + * Error pointers aren't hashed. |
---|
| 356 | + */ |
---|
| 357 | +static void __init |
---|
| 358 | +error_pointer(void) |
---|
| 359 | +{ |
---|
| 360 | + test(ONES "fffffff5", "%p", ERR_PTR(-11)); |
---|
| 361 | + test(ONES "fffffff5", "%px", ERR_PTR(-11)); |
---|
| 362 | + test("(efault)", "%pE", ERR_PTR(-11)); |
---|
| 363 | +} |
---|
| 364 | + |
---|
| 365 | +#define PTR_INVALID ((void *)0x000000ab) |
---|
| 366 | + |
---|
| 367 | +static void __init |
---|
| 368 | +invalid_pointer(void) |
---|
| 369 | +{ |
---|
| 370 | + test_hashed("%p", PTR_INVALID); |
---|
| 371 | + test(ZEROS "000000ab", "%px", PTR_INVALID); |
---|
| 372 | + test("(efault)", "%pE", PTR_INVALID); |
---|
295 | 373 | } |
---|
296 | 374 | |
---|
297 | 375 | static void __init |
---|
.. | .. |
---|
403 | 481 | test("foo", "%pd", &test_dentry[0]); |
---|
404 | 482 | test("foo", "%pd2", &test_dentry[0]); |
---|
405 | 483 | |
---|
| 484 | + test("(null)", "%pd", NULL); |
---|
| 485 | + test("(efault)", "%pd", PTR_INVALID); |
---|
| 486 | + test("(null)", "%pD", NULL); |
---|
| 487 | + test("(efault)", "%pD", PTR_INVALID); |
---|
| 488 | + |
---|
406 | 489 | test("romeo", "%pd", &test_dentry[3]); |
---|
407 | 490 | test("alfa/romeo", "%pd2", &test_dentry[3]); |
---|
408 | 491 | test("bravo/alfa/romeo", "%pd3", &test_dentry[3]); |
---|
.. | .. |
---|
419 | 502 | } |
---|
420 | 503 | |
---|
421 | 504 | static void __init |
---|
| 505 | +time_and_date(void) |
---|
| 506 | +{ |
---|
| 507 | + /* 1543210543 */ |
---|
| 508 | + const struct rtc_time tm = { |
---|
| 509 | + .tm_sec = 43, |
---|
| 510 | + .tm_min = 35, |
---|
| 511 | + .tm_hour = 5, |
---|
| 512 | + .tm_mday = 26, |
---|
| 513 | + .tm_mon = 10, |
---|
| 514 | + .tm_year = 118, |
---|
| 515 | + }; |
---|
| 516 | + /* 2019-01-04T15:32:23 */ |
---|
| 517 | + time64_t t = 1546615943; |
---|
| 518 | + |
---|
| 519 | + test("(%pt?)", "%pt", &tm); |
---|
| 520 | + test("2018-11-26T05:35:43", "%ptR", &tm); |
---|
| 521 | + test("0118-10-26T05:35:43", "%ptRr", &tm); |
---|
| 522 | + test("05:35:43|2018-11-26", "%ptRt|%ptRd", &tm, &tm); |
---|
| 523 | + test("05:35:43|0118-10-26", "%ptRtr|%ptRdr", &tm, &tm); |
---|
| 524 | + test("05:35:43|2018-11-26", "%ptRttr|%ptRdtr", &tm, &tm); |
---|
| 525 | + test("05:35:43 tr|2018-11-26 tr", "%ptRt tr|%ptRd tr", &tm, &tm); |
---|
| 526 | + |
---|
| 527 | + test("2019-01-04T15:32:23", "%ptT", &t); |
---|
| 528 | + test("0119-00-04T15:32:23", "%ptTr", &t); |
---|
| 529 | + test("15:32:23|2019-01-04", "%ptTt|%ptTd", &t, &t); |
---|
| 530 | + test("15:32:23|0119-00-04", "%ptTtr|%ptTdr", &t, &t); |
---|
| 531 | +} |
---|
| 532 | + |
---|
| 533 | +static void __init |
---|
422 | 534 | struct_clk(void) |
---|
423 | 535 | { |
---|
424 | 536 | } |
---|
.. | .. |
---|
427 | 539 | large_bitmap(void) |
---|
428 | 540 | { |
---|
429 | 541 | const int nbits = 1 << 16; |
---|
430 | | - unsigned long *bits = kcalloc(BITS_TO_LONGS(nbits), sizeof(long), GFP_KERNEL); |
---|
| 542 | + unsigned long *bits = bitmap_zalloc(nbits, GFP_KERNEL); |
---|
431 | 543 | if (!bits) |
---|
432 | 544 | return; |
---|
433 | 545 | |
---|
434 | 546 | bitmap_set(bits, 1, 20); |
---|
435 | 547 | bitmap_set(bits, 60000, 15); |
---|
436 | 548 | test("1-20,60000-60014", "%*pbl", nbits, bits); |
---|
437 | | - kfree(bits); |
---|
| 549 | + bitmap_free(bits); |
---|
438 | 550 | } |
---|
439 | 551 | |
---|
440 | 552 | static void __init |
---|
.. | .. |
---|
514 | 626 | kfree(cmp_buffer); |
---|
515 | 627 | } |
---|
516 | 628 | |
---|
| 629 | +static void __init fwnode_pointer(void) |
---|
| 630 | +{ |
---|
| 631 | + const struct software_node softnodes[] = { |
---|
| 632 | + { .name = "first", }, |
---|
| 633 | + { .name = "second", .parent = &softnodes[0], }, |
---|
| 634 | + { .name = "third", .parent = &softnodes[1], }, |
---|
| 635 | + { NULL /* Guardian */ } |
---|
| 636 | + }; |
---|
| 637 | + const char * const full_name = "first/second/third"; |
---|
| 638 | + const char * const full_name_second = "first/second"; |
---|
| 639 | + const char * const second_name = "second"; |
---|
| 640 | + const char * const third_name = "third"; |
---|
| 641 | + int rval; |
---|
| 642 | + |
---|
| 643 | + rval = software_node_register_nodes(softnodes); |
---|
| 644 | + if (rval) { |
---|
| 645 | + pr_warn("cannot register softnodes; rval %d\n", rval); |
---|
| 646 | + return; |
---|
| 647 | + } |
---|
| 648 | + |
---|
| 649 | + test(full_name_second, "%pfw", software_node_fwnode(&softnodes[1])); |
---|
| 650 | + test(full_name, "%pfw", software_node_fwnode(&softnodes[2])); |
---|
| 651 | + test(full_name, "%pfwf", software_node_fwnode(&softnodes[2])); |
---|
| 652 | + test(second_name, "%pfwP", software_node_fwnode(&softnodes[1])); |
---|
| 653 | + test(third_name, "%pfwP", software_node_fwnode(&softnodes[2])); |
---|
| 654 | + |
---|
| 655 | + software_node_unregister(&softnodes[2]); |
---|
| 656 | + software_node_unregister(&softnodes[1]); |
---|
| 657 | + software_node_unregister(&softnodes[0]); |
---|
| 658 | +} |
---|
| 659 | + |
---|
| 660 | +static void __init |
---|
| 661 | +errptr(void) |
---|
| 662 | +{ |
---|
| 663 | + test("-1234", "%pe", ERR_PTR(-1234)); |
---|
| 664 | + |
---|
| 665 | + /* Check that %pe with a non-ERR_PTR gets treated as ordinary %p. */ |
---|
| 666 | + BUILD_BUG_ON(IS_ERR(PTR)); |
---|
| 667 | + test_hashed("%pe", PTR); |
---|
| 668 | + |
---|
| 669 | +#ifdef CONFIG_SYMBOLIC_ERRNAME |
---|
| 670 | + test("(-ENOTSOCK)", "(%pe)", ERR_PTR(-ENOTSOCK)); |
---|
| 671 | + test("(-EAGAIN)", "(%pe)", ERR_PTR(-EAGAIN)); |
---|
| 672 | + BUILD_BUG_ON(EAGAIN != EWOULDBLOCK); |
---|
| 673 | + test("(-EAGAIN)", "(%pe)", ERR_PTR(-EWOULDBLOCK)); |
---|
| 674 | + test("[-EIO ]", "[%-8pe]", ERR_PTR(-EIO)); |
---|
| 675 | + test("[ -EIO]", "[%8pe]", ERR_PTR(-EIO)); |
---|
| 676 | + test("-EPROBE_DEFER", "%pe", ERR_PTR(-EPROBE_DEFER)); |
---|
| 677 | +#endif |
---|
| 678 | +} |
---|
| 679 | + |
---|
517 | 680 | static void __init |
---|
518 | 681 | test_pointer(void) |
---|
519 | 682 | { |
---|
520 | 683 | plain(); |
---|
| 684 | + null_pointer(); |
---|
| 685 | + error_pointer(); |
---|
| 686 | + invalid_pointer(); |
---|
521 | 687 | symbol_ptr(); |
---|
522 | 688 | kernel_ptr(); |
---|
523 | 689 | struct_resource(); |
---|
.. | .. |
---|
529 | 695 | uuid(); |
---|
530 | 696 | dentry(); |
---|
531 | 697 | struct_va_format(); |
---|
| 698 | + time_and_date(); |
---|
532 | 699 | struct_clk(); |
---|
533 | 700 | bitmap(); |
---|
534 | 701 | netdev_features(); |
---|
535 | 702 | flags(); |
---|
| 703 | + errptr(); |
---|
| 704 | + fwnode_pointer(); |
---|
536 | 705 | } |
---|
537 | 706 | |
---|
538 | | -static int __init |
---|
539 | | -test_printf_init(void) |
---|
| 707 | +static void __init selftest(void) |
---|
540 | 708 | { |
---|
541 | 709 | alloced_buffer = kmalloc(BUF_SIZE + 2*PAD_SIZE, GFP_KERNEL); |
---|
542 | 710 | if (!alloced_buffer) |
---|
543 | | - return -ENOMEM; |
---|
| 711 | + return; |
---|
544 | 712 | test_buffer = alloced_buffer + PAD_SIZE; |
---|
545 | 713 | |
---|
546 | 714 | test_basic(); |
---|
.. | .. |
---|
549 | 717 | test_pointer(); |
---|
550 | 718 | |
---|
551 | 719 | kfree(alloced_buffer); |
---|
552 | | - |
---|
553 | | - if (failed_tests == 0) |
---|
554 | | - pr_info("all %u tests passed\n", total_tests); |
---|
555 | | - else |
---|
556 | | - pr_warn("failed %u out of %u tests\n", failed_tests, total_tests); |
---|
557 | | - |
---|
558 | | - return failed_tests ? -EINVAL : 0; |
---|
559 | 720 | } |
---|
560 | 721 | |
---|
561 | | -module_init(test_printf_init); |
---|
562 | | - |
---|
| 722 | +KSTM_MODULE_LOADERS(test_printf); |
---|
563 | 723 | MODULE_AUTHOR("Rasmus Villemoes <linux@rasmusvillemoes.dk>"); |
---|
564 | 724 | MODULE_LICENSE("GPL"); |
---|