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

Configure Feed

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

Merge tag 'linux_kselftest-kunit-fixes-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull kunit fixes from Shuah Khan:

- Fix rust warnings when CONFIG_PRINTK is disabled

- Reduce stack usage in kunit_run_tests() to fix warnings when
CONFIG_FRAME_WARN is set to a relatively low value

- Update email address for David Gow

- Copy caller args in kunit tool in run_kernel to prevent mutation

* tag 'linux_kselftest-kunit-fixes-7.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
kunit: reduce stack usage in kunit_run_tests()
kunit: tool: copy caller args in run_kernel to prevent mutation
rust: kunit: fix warning when !CONFIG_PRINTK
MAINTAINERS: Update email address for David Gow

+166 -110
+1
.mailmap
··· 219 219 Danilo Krummrich <dakr@kernel.org> <dakr@redhat.com> 220 220 David Brownell <david-b@pacbell.net> 221 221 David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org> 222 + David Gow <david@davidgow.net> <davidgow@google.com> 222 223 David Heidelberg <david@ixit.cz> <d.okias@gmail.com> 223 224 David Hildenbrand <david@kernel.org> <david@redhat.com> 224 225 David Rheinsberg <david@readahead.eu> <dh.herrmann@gmail.com>
+2 -2
MAINTAINERS
··· 13938 13938 13939 13939 KERNEL UNIT TESTING FRAMEWORK (KUnit) 13940 13940 M: Brendan Higgins <brendan.higgins@linux.dev> 13941 - M: David Gow <davidgow@google.com> 13941 + M: David Gow <david@davidgow.net> 13942 13942 R: Rae Moar <raemoar63@gmail.com> 13943 13943 L: linux-kselftest@vger.kernel.org 13944 13944 L: kunit-dev@googlegroups.com ··· 14758 14758 F: drivers/platform/x86/hp/hp_accel.c 14759 14759 14760 14760 LIST KUNIT TEST 14761 - M: David Gow <davidgow@google.com> 14761 + M: David Gow <david@davidgow.net> 14762 14762 L: linux-kselftest@vger.kernel.org 14763 14763 L: kunit-dev@googlegroups.com 14764 14764 S: Maintained
+125 -106
lib/kunit/test.c
··· 94 94 unsigned long total; 95 95 }; 96 96 97 - static bool kunit_should_print_stats(struct kunit_result_stats stats) 97 + static bool kunit_should_print_stats(struct kunit_result_stats *stats) 98 98 { 99 99 if (kunit_stats_enabled == 0) 100 100 return false; ··· 102 102 if (kunit_stats_enabled == 2) 103 103 return true; 104 104 105 - return (stats.total > 1); 105 + return (stats->total > 1); 106 106 } 107 107 108 108 static void kunit_print_test_stats(struct kunit *test, 109 - struct kunit_result_stats stats) 109 + struct kunit_result_stats *stats) 110 110 { 111 111 if (!kunit_should_print_stats(stats)) 112 112 return; ··· 115 115 KUNIT_SUBTEST_INDENT 116 116 "# %s: pass:%lu fail:%lu skip:%lu total:%lu", 117 117 test->name, 118 - stats.passed, 119 - stats.failed, 120 - stats.skipped, 121 - stats.total); 118 + stats->passed, 119 + stats->failed, 120 + stats->skipped, 121 + stats->total); 122 122 } 123 123 124 124 /* Append formatted message to log. */ ··· 600 600 } 601 601 602 602 static void kunit_print_suite_stats(struct kunit_suite *suite, 603 - struct kunit_result_stats suite_stats, 604 - struct kunit_result_stats param_stats) 603 + struct kunit_result_stats *suite_stats, 604 + struct kunit_result_stats *param_stats) 605 605 { 606 606 if (kunit_should_print_stats(suite_stats)) { 607 607 kunit_log(KERN_INFO, suite, 608 608 "# %s: pass:%lu fail:%lu skip:%lu total:%lu", 609 609 suite->name, 610 - suite_stats.passed, 611 - suite_stats.failed, 612 - suite_stats.skipped, 613 - suite_stats.total); 610 + suite_stats->passed, 611 + suite_stats->failed, 612 + suite_stats->skipped, 613 + suite_stats->total); 614 614 } 615 615 616 616 if (kunit_should_print_stats(param_stats)) { 617 617 kunit_log(KERN_INFO, suite, 618 618 "# Totals: pass:%lu fail:%lu skip:%lu total:%lu", 619 - param_stats.passed, 620 - param_stats.failed, 621 - param_stats.skipped, 622 - param_stats.total); 619 + param_stats->passed, 620 + param_stats->failed, 621 + param_stats->skipped, 622 + param_stats->total); 623 623 } 624 624 } 625 625 ··· 681 681 } 682 682 } 683 683 684 - int kunit_run_tests(struct kunit_suite *suite) 684 + static noinline_for_stack void 685 + kunit_run_param_test(struct kunit_suite *suite, struct kunit_case *test_case, 686 + struct kunit *test, 687 + struct kunit_result_stats *suite_stats, 688 + struct kunit_result_stats *total_stats, 689 + struct kunit_result_stats *param_stats) 685 690 { 686 691 char param_desc[KUNIT_PARAM_DESC_SIZE]; 692 + const void *curr_param; 693 + 694 + kunit_init_parent_param_test(test_case, test); 695 + if (test_case->status == KUNIT_FAILURE) { 696 + kunit_update_stats(param_stats, test->status); 697 + return; 698 + } 699 + /* Get initial param. */ 700 + param_desc[0] = '\0'; 701 + /* TODO: Make generate_params try-catch */ 702 + curr_param = test_case->generate_params(test, NULL, param_desc); 703 + test_case->status = KUNIT_SKIPPED; 704 + kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 705 + "KTAP version 1\n"); 706 + kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 707 + "# Subtest: %s", test_case->name); 708 + if (test->params_array.params && 709 + test_case->generate_params == kunit_array_gen_params) { 710 + kunit_log(KERN_INFO, test, KUNIT_SUBTEST_INDENT 711 + KUNIT_SUBTEST_INDENT "1..%zd\n", 712 + test->params_array.num_params); 713 + } 714 + 715 + while (curr_param) { 716 + struct kunit param_test = { 717 + .param_value = curr_param, 718 + .param_index = ++test->param_index, 719 + .parent = test, 720 + }; 721 + kunit_init_test(&param_test, test_case->name, NULL); 722 + param_test.log = test_case->log; 723 + kunit_run_case_catch_errors(suite, test_case, &param_test); 724 + 725 + if (param_desc[0] == '\0') { 726 + snprintf(param_desc, sizeof(param_desc), 727 + "param-%d", param_test.param_index); 728 + } 729 + 730 + kunit_print_ok_not_ok(&param_test, KUNIT_LEVEL_CASE_PARAM, 731 + param_test.status, 732 + param_test.param_index, 733 + param_desc, 734 + param_test.status_comment); 735 + 736 + kunit_update_stats(param_stats, param_test.status); 737 + 738 + /* Get next param. */ 739 + param_desc[0] = '\0'; 740 + curr_param = test_case->generate_params(test, curr_param, 741 + param_desc); 742 + } 743 + /* 744 + * TODO: Put into a try catch. Since we don't need suite->exit 745 + * for it we can't reuse kunit_try_run_cleanup for this yet. 746 + */ 747 + if (test_case->param_exit) 748 + test_case->param_exit(test); 749 + /* TODO: Put this kunit_cleanup into a try-catch. */ 750 + kunit_cleanup(test); 751 + } 752 + 753 + static noinline_for_stack void 754 + kunit_run_one_test(struct kunit_suite *suite, struct kunit_case *test_case, 755 + struct kunit_result_stats *suite_stats, 756 + struct kunit_result_stats *total_stats) 757 + { 758 + struct kunit test = { .param_value = NULL, .param_index = 0 }; 759 + struct kunit_result_stats param_stats = { 0 }; 760 + 761 + kunit_init_test(&test, test_case->name, test_case->log); 762 + if (test_case->status == KUNIT_SKIPPED) { 763 + /* Test marked as skip */ 764 + test.status = KUNIT_SKIPPED; 765 + kunit_update_stats(&param_stats, test.status); 766 + } else if (!test_case->generate_params) { 767 + /* Non-parameterised test. */ 768 + test_case->status = KUNIT_SKIPPED; 769 + kunit_run_case_catch_errors(suite, test_case, &test); 770 + kunit_update_stats(&param_stats, test.status); 771 + } else { 772 + kunit_run_param_test(suite, test_case, &test, suite_stats, 773 + total_stats, &param_stats); 774 + } 775 + kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE); 776 + 777 + kunit_print_test_stats(&test, &param_stats); 778 + 779 + kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE, test_case->status, 780 + kunit_test_case_num(suite, test_case), 781 + test_case->name, 782 + test.status_comment); 783 + 784 + kunit_update_stats(suite_stats, test_case->status); 785 + kunit_accumulate_stats(total_stats, param_stats); 786 + } 787 + 788 + 789 + int kunit_run_tests(struct kunit_suite *suite) 790 + { 687 791 struct kunit_case *test_case; 688 792 struct kunit_result_stats suite_stats = { 0 }; 689 793 struct kunit_result_stats total_stats = { 0 }; 690 - const void *curr_param; 691 794 692 795 /* Taint the kernel so we know we've run tests. */ 693 796 add_taint(TAINT_TEST, LOCKDEP_STILL_OK); ··· 806 703 807 704 kunit_print_suite_start(suite); 808 705 809 - kunit_suite_for_each_test_case(suite, test_case) { 810 - struct kunit test = { .param_value = NULL, .param_index = 0 }; 811 - struct kunit_result_stats param_stats = { 0 }; 812 - 813 - kunit_init_test(&test, test_case->name, test_case->log); 814 - if (test_case->status == KUNIT_SKIPPED) { 815 - /* Test marked as skip */ 816 - test.status = KUNIT_SKIPPED; 817 - kunit_update_stats(&param_stats, test.status); 818 - } else if (!test_case->generate_params) { 819 - /* Non-parameterised test. */ 820 - test_case->status = KUNIT_SKIPPED; 821 - kunit_run_case_catch_errors(suite, test_case, &test); 822 - kunit_update_stats(&param_stats, test.status); 823 - } else { 824 - kunit_init_parent_param_test(test_case, &test); 825 - if (test_case->status == KUNIT_FAILURE) { 826 - kunit_update_stats(&param_stats, test.status); 827 - goto test_case_end; 828 - } 829 - /* Get initial param. */ 830 - param_desc[0] = '\0'; 831 - /* TODO: Make generate_params try-catch */ 832 - curr_param = test_case->generate_params(&test, NULL, param_desc); 833 - test_case->status = KUNIT_SKIPPED; 834 - kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 835 - "KTAP version 1\n"); 836 - kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT KUNIT_SUBTEST_INDENT 837 - "# Subtest: %s", test_case->name); 838 - if (test.params_array.params && 839 - test_case->generate_params == kunit_array_gen_params) { 840 - kunit_log(KERN_INFO, &test, KUNIT_SUBTEST_INDENT 841 - KUNIT_SUBTEST_INDENT "1..%zd\n", 842 - test.params_array.num_params); 843 - } 844 - 845 - while (curr_param) { 846 - struct kunit param_test = { 847 - .param_value = curr_param, 848 - .param_index = ++test.param_index, 849 - .parent = &test, 850 - }; 851 - kunit_init_test(&param_test, test_case->name, NULL); 852 - param_test.log = test_case->log; 853 - kunit_run_case_catch_errors(suite, test_case, &param_test); 854 - 855 - if (param_desc[0] == '\0') { 856 - snprintf(param_desc, sizeof(param_desc), 857 - "param-%d", param_test.param_index); 858 - } 859 - 860 - kunit_print_ok_not_ok(&param_test, KUNIT_LEVEL_CASE_PARAM, 861 - param_test.status, 862 - param_test.param_index, 863 - param_desc, 864 - param_test.status_comment); 865 - 866 - kunit_update_stats(&param_stats, param_test.status); 867 - 868 - /* Get next param. */ 869 - param_desc[0] = '\0'; 870 - curr_param = test_case->generate_params(&test, curr_param, 871 - param_desc); 872 - } 873 - /* 874 - * TODO: Put into a try catch. Since we don't need suite->exit 875 - * for it we can't reuse kunit_try_run_cleanup for this yet. 876 - */ 877 - if (test_case->param_exit) 878 - test_case->param_exit(&test); 879 - /* TODO: Put this kunit_cleanup into a try-catch. */ 880 - kunit_cleanup(&test); 881 - } 882 - test_case_end: 883 - kunit_print_attr((void *)test_case, true, KUNIT_LEVEL_CASE); 884 - 885 - kunit_print_test_stats(&test, param_stats); 886 - 887 - kunit_print_ok_not_ok(&test, KUNIT_LEVEL_CASE, test_case->status, 888 - kunit_test_case_num(suite, test_case), 889 - test_case->name, 890 - test.status_comment); 891 - 892 - kunit_update_stats(&suite_stats, test_case->status); 893 - kunit_accumulate_stats(&total_stats, param_stats); 894 - } 706 + kunit_suite_for_each_test_case(suite, test_case) 707 + kunit_run_one_test(suite, test_case, &suite_stats, &total_stats); 895 708 896 709 if (suite->suite_exit) 897 710 suite->suite_exit(suite); 898 711 899 - kunit_print_suite_stats(suite, suite_stats, total_stats); 712 + kunit_print_suite_stats(suite, &suite_stats, &total_stats); 900 713 suite_end: 901 714 kunit_print_suite_end(suite); 902 715
+8
rust/kernel/kunit.rs
··· 14 14 /// Public but hidden since it should only be used from KUnit generated code. 15 15 #[doc(hidden)] 16 16 pub fn err(args: fmt::Arguments<'_>) { 17 + // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. 18 + #[cfg(not(CONFIG_PRINTK))] 19 + let _ = args; 20 + 17 21 // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we 18 22 // are passing. 19 23 #[cfg(CONFIG_PRINTK)] ··· 34 30 /// Public but hidden since it should only be used from KUnit generated code. 35 31 #[doc(hidden)] 36 32 pub fn info(args: fmt::Arguments<'_>) { 33 + // `args` is unused if `CONFIG_PRINTK` is not set - this avoids a build-time warning. 34 + #[cfg(not(CONFIG_PRINTK))] 35 + let _ = args; 36 + 37 37 // SAFETY: The format string is null-terminated and the `%pA` specifier matches the argument we 38 38 // are passing. 39 39 #[cfg(CONFIG_PRINTK)]
+4 -2
tools/testing/kunit/kunit_kernel.py
··· 346 346 return self.validate_config(build_dir) 347 347 348 348 def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', filter: str='', filter_action: Optional[str]=None, timeout: Optional[int]=None) -> Iterator[str]: 349 - if not args: 350 - args = [] 349 + # Copy to avoid mutating the caller-supplied list. exec_tests() reuses 350 + # the same args across repeated run_kernel() calls (e.g. --run_isolated), 351 + # so appending to the original would accumulate stale flags on each call. 352 + args = list(args) if args else [] 351 353 if filter_glob: 352 354 args.append('kunit.filter_glob=' + filter_glob) 353 355 if filter:
+26
tools/testing/kunit/kunit_tool_test.py
··· 503 503 with open(kunit_kernel.get_outfile_path(build_dir), 'rt') as outfile: 504 504 self.assertEqual(outfile.read(), 'hi\nbye\n', msg='Missing some output') 505 505 506 + def test_run_kernel_args_not_mutated(self): 507 + """Verify run_kernel() copies args so callers can reuse them.""" 508 + start_calls = [] 509 + 510 + def fake_start(start_args, unused_build_dir): 511 + start_calls.append(list(start_args)) 512 + return subprocess.Popen(['printf', 'KTAP version 1\n'], 513 + text=True, stdout=subprocess.PIPE) 514 + 515 + with tempfile.TemporaryDirectory('') as build_dir: 516 + tree = kunit_kernel.LinuxSourceTree(build_dir, 517 + kunitconfig_paths=[os.devnull]) 518 + with mock.patch.object(tree._ops, 'start', side_effect=fake_start), \ 519 + mock.patch.object(kunit_kernel.subprocess, 'call'): 520 + kernel_args = ['mem=1G'] 521 + for _ in tree.run_kernel(args=kernel_args, build_dir=build_dir, 522 + filter_glob='suite.test1'): 523 + pass 524 + for _ in tree.run_kernel(args=kernel_args, build_dir=build_dir, 525 + filter_glob='suite.test2'): 526 + pass 527 + self.assertEqual(kernel_args, ['mem=1G'], 528 + 'run_kernel() should not modify caller args') 529 + self.assertIn('kunit.filter_glob=suite.test1', start_calls[0]) 530 + self.assertIn('kunit.filter_glob=suite.test2', start_calls[1]) 531 + 506 532 def test_build_reconfig_no_config(self): 507 533 with tempfile.TemporaryDirectory('') as build_dir: 508 534 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: