Pull Kunit fixes from Shuah Khan: - Fixes to address the structleak plugin causing the stack frame size to grow immensely when used with KUnit. Fixes include adding a new makefile to disable structleak and using it from KUnit iio, device property, thunderbolt, and bitfield tests to disable it. - KUnit framework reference count leak in kfree_at_end - KUnit tool fix to resolve conflict between --json and --raw_output and generate correct test output in either case. - kernel-doc warnings due to mismatched arg names * tag 'linux-kselftest-kunit-fixes-5.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: kunit: fix kernel-doc warnings due to mismatched arg names bitfield: build kunit tests without structleak plugin thunderbolt: build kunit tests without structleak plugin device property: build kunit tests without structleak plugin iio/test-format: build kunit tests without structleak plugin gcc-plugins/structleak: add makefile var for disabling structleak kunit: fix reference count leak in kfree_at_end kunit: tool: better handling of quasi-bool args (--json, --raw_output)
Unified · Split
| @@ -2,4 +2,4 @@ · 1 unmodified line | |||
| 2 | obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o | 2 | obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o |
| 3 | 3 | ||
| 4 | obj-$(CONFIG_DRIVER_PE_KUNIT_TEST) += property-entry-test.o | 4 | obj-$(CONFIG_DRIVER_PE_KUNIT_TEST) += property-entry-test.o |
| 5 | CFLAGS_REMOVE_property-entry-test.o += -fplugin-arg-structleak_plugin-byref -fplugin-arg-structleak_plugin-byref-all | 5 | CFLAGS_property-entry-test.o += $(DISABLE_STRUCTLEAK_PLUGIN) |
| @@ -5,3 +5,4 @@ · 4 unmodified lines | |||
| 5 | 5 | ||
| 6 | # Keep in alphabetical order | 6 | # Keep in alphabetical order |
| 7 | obj-$(CONFIG_IIO_TEST_FORMAT) += iio-test-format.o | 7 | obj-$(CONFIG_IIO_TEST_FORMAT) += iio-test-format.o |
| 8 | CFLAGS_iio-test-format.o += $(DISABLE_STRUCTLEAK_PLUGIN) | ||
| @@ -7,6 +7,7 @@ thunderbolt-objs += usb4_port.o nvm.o retimer.o quirks.o · 6 unmodified lines | |||
| 7 | thunderbolt-${CONFIG_ACPI} += acpi.o | 7 | thunderbolt-${CONFIG_ACPI} += acpi.o |
| 8 | thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o | 8 | thunderbolt-$(CONFIG_DEBUG_FS) += debugfs.o |
| 9 | thunderbolt-${CONFIG_USB4_KUNIT_TEST} += test.o | 9 | thunderbolt-${CONFIG_USB4_KUNIT_TEST} += test.o |
| 10 | CFLAGS_test.o += $(DISABLE_STRUCTLEAK_PLUGIN) | ||
| 10 | 11 | ||
| 11 | thunderbolt_dma_test-${CONFIG_USB4_DMA_TEST} += dma_test.o | 12 | thunderbolt_dma_test-${CONFIG_USB4_DMA_TEST} += dma_test.o |
| 12 | obj-$(CONFIG_USB4_DMA_TEST) += thunderbolt_dma_test.o | 13 | obj-$(CONFIG_USB4_DMA_TEST) += thunderbolt_dma_test.o |
| @@ -613,7 +613,7 @@ void kunit_remove_resource(struct kunit *test, struct kunit_resource *res); · 612 unmodified lines | |||
| 613 | * and is automatically cleaned up after the test case concludes. See &struct | 613 | * and is automatically cleaned up after the test case concludes. See &struct |
| 614 | * kunit_resource for more information. | 614 | * kunit_resource for more information. |
| 615 | */ | 615 | */ |
| 616 | void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t flags); | 616 | void *kunit_kmalloc_array(struct kunit *test, size_t n, size_t size, gfp_t gfp); |
| 617 | 617 | ||
| 618 | /** | 618 | /** |
| 619 | * kunit_kmalloc() - Like kmalloc() except the allocation is *test managed*. | 619 | * kunit_kmalloc() - Like kmalloc() except the allocation is *test managed*. |
| @@ -657,9 +657,9 @@ static inline void *kunit_kzalloc(struct kunit *test, size_t size, gfp_t gfp) · 37 unmodified lines | |||
| 657 | * | 657 | * |
| 658 | * See kcalloc() and kunit_kmalloc_array() for more information. | 658 | * See kcalloc() and kunit_kmalloc_array() for more information. |
| 659 | */ | 659 | */ |
| 660 | static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp_t flags) | 660 | static inline void *kunit_kcalloc(struct kunit *test, size_t n, size_t size, gfp_t gfp) |
| 661 | { | 661 | { |
| 662 | return kunit_kmalloc_array(test, n, size, flags | __GFP_ZERO); | 662 | return kunit_kmalloc_array(test, n, size, gfp | __GFP_ZERO); |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | void kunit_cleanup(struct kunit *test); | 665 | void kunit_cleanup(struct kunit *test); |
| @@ -351,7 +351,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o · 350 unmodified lines | |||
| 351 | obj-$(CONFIG_PLDMFW) += pldmfw/ | 351 | obj-$(CONFIG_PLDMFW) += pldmfw/ |
| 352 | 352 | ||
| 353 | # KUnit tests | 353 | # KUnit tests |
| 354 | CFLAGS_bitfield_kunit.o := $(call cc-option,-Wframe-larger-than=10240) | 354 | CFLAGS_bitfield_kunit.o := $(DISABLE_STRUCTLEAK_PLUGIN) |
| 355 | obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o | 355 | obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o |
| 356 | obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o | 356 | obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o |
| 357 | obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o | 357 | obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o |
| @@ -116,8 +116,8 @@ static void kfree_at_end(struct kunit *test, const void *to_free) · 115 unmodified lines | |||
| 116 | /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ | 116 | /* kfree() handles NULL already, but avoid allocating a no-op cleanup. */ |
| 117 | if (IS_ERR_OR_NULL(to_free)) | 117 | if (IS_ERR_OR_NULL(to_free)) |
| 118 | return; | 118 | return; |
| 119 | kunit_alloc_and_get_resource(test, NULL, kfree_res_free, GFP_KERNEL, | 119 | kunit_alloc_resource(test, NULL, kfree_res_free, GFP_KERNEL, |
| 120 | (void *)to_free); | 120 | (void *)to_free); |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | static struct kunit_suite *alloc_fake_suite(struct kunit *test, | 123 | static struct kunit_suite *alloc_fake_suite(struct kunit *test, |
| @@ -19,6 +19,10 @@ gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF) \ · 18 unmodified lines | |||
| 19 | += -fplugin-arg-structleak_plugin-byref | 19 | += -fplugin-arg-structleak_plugin-byref |
| 20 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) \ | 20 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) \ |
| 21 | += -fplugin-arg-structleak_plugin-byref-all | 21 | += -fplugin-arg-structleak_plugin-byref-all |
| 22 | ifdef CONFIG_GCC_PLUGIN_STRUCTLEAK | ||
| 23 | DISABLE_STRUCTLEAK_PLUGIN += -fplugin-arg-structleak_plugin-disable | ||
| 24 | endif | ||
| 25 | export DISABLE_STRUCTLEAK_PLUGIN | ||
| 22 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \ | 26 | gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) \ |
| 23 | += -DSTRUCTLEAK_PLUGIN | 27 | += -DSTRUCTLEAK_PLUGIN |
| 24 | 28 | ||
| @@ -16,7 +16,7 @@ assert sys.version_info >= (3, 7), "Python version is too old" · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | from collections import namedtuple | 17 | from collections import namedtuple |
| 18 | from enum import Enum, auto | 18 | from enum import Enum, auto |
| 19 | from typing import Iterable | 19 | from typing import Iterable, Sequence |
| 20 | 20 | ||
| 21 | import kunit_config | 21 | import kunit_config |
| 22 | import kunit_json | 22 | import kunit_json |
| @@ -186,6 +186,26 @@ def run_tests(linux: kunit_kernel.LinuxSourceTree, · 163 unmodified lines | |||
| 186 | exec_result.elapsed_time)) | 186 | exec_result.elapsed_time)) |
| 187 | return parse_result | 187 | return parse_result |
| 188 | 188 | ||
| 189 | # Problem: | ||
| 190 | # $ kunit.py run --json | ||
| 191 | # works as one would expect and prints the parsed test results as JSON. | ||
| 192 | # $ kunit.py run --json suite_name | ||
| 193 | # would *not* pass suite_name as the filter_glob and print as json. | ||
| 194 | # argparse will consider it to be another way of writing | ||
| 195 | # $ kunit.py run --json=suite_name | ||
| 196 | # i.e. it would run all tests, and dump the json to a `suite_name` file. | ||
| 197 | # So we hackily automatically rewrite --json => --json=stdout | ||
| 198 | pseudo_bool_flag_defaults = { | ||
| 199 | '--json': 'stdout', | ||
| 200 | '--raw_output': 'kunit', | ||
| 201 | } | ||
| 202 | def massage_argv(argv: Sequence[str]) -> Sequence[str]: | ||
| 203 | def massage_arg(arg: str) -> str: | ||
| 204 | if arg not in pseudo_bool_flag_defaults: | ||
| 205 | return arg | ||
| 206 | return f'{arg}={pseudo_bool_flag_defaults[arg]}' | ||
| 207 | return list(map(massage_arg, argv)) | ||
| 208 | |||
| 189 | def add_common_opts(parser) -> None: | 209 | def add_common_opts(parser) -> None: |
| 190 | parser.add_argument('--build_dir', | 210 | parser.add_argument('--build_dir', |
| 191 | help='As in the make command, it specifies the build ' | 211 | help='As in the make command, it specifies the build ' |
| @@ -303,7 +323,7 @@ def main(argv, linux=None): · 111 unmodified lines | |||
| 303 | help='Specifies the file to read results from.', | 323 | help='Specifies the file to read results from.', |
| 304 | type=str, nargs='?', metavar='input_file') | 324 | type=str, nargs='?', metavar='input_file') |
| 305 | 325 | ||
| 306 | cli_args = parser.parse_args(argv) | 326 | cli_args = parser.parse_args(massage_argv(argv)) |
| 307 | 327 | ||
| 308 | if get_kernel_root_path(): | 328 | if get_kernel_root_path(): |
| 309 | os.chdir(get_kernel_root_path()) | 329 | os.chdir(get_kernel_root_path()) |
| @@ -408,6 +408,14 @@ class KUnitMainTest(unittest.TestCase): · 407 unmodified lines | |||
| 408 | self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) | 408 | self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) |
| 409 | self.assertNotEqual(call, mock.call(StrContains(' 0 tests run'))) | 409 | self.assertNotEqual(call, mock.call(StrContains(' 0 tests run'))) |
| 410 | 410 | ||
| 411 | def test_run_raw_output_does_not_take_positional_args(self): | ||
| 412 | # --raw_output is a string flag, but we don't want it to consume | ||
| 413 | # any positional arguments, only ones after an '=' | ||
| 414 | self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) | ||
| 415 | kunit.main(['run', '--raw_output', 'filter_glob'], self.linux_source_mock) | ||
| 416 | self.linux_source_mock.run_kernel.assert_called_once_with( | ||
| 417 | args=None, build_dir='.kunit', filter_glob='filter_glob', timeout=300) | ||
| 418 | |||
| 411 | def test_exec_timeout(self): | 419 | def test_exec_timeout(self): |
| 412 | timeout = 3453 | 420 | timeout = 3453 |
| 413 | kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock) | 421 | kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock) |