| .. | .. |
|---|
| 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"); |
|---|