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

kunit: tool: redo how we construct and mock LinuxSourceTree

Our main function currently has an optional `linux` argument which is
used to by our unit tests to inject a mock.
We currently have the same code copy-pasted several times to do
if not linux:
linux = MakeRealInstance(cli_args.foo, cli_args.bar, ...)

But in python, dependency injection isn't necessary or idiomatic when we
can just use mock.patch() to mock things out.

This change
1. adds a helper to create a LinuxSourceTree from the cli_args
2. drops the `linux` parameter in favor of mocking the __init__ func.

Signed-off-by: Daniel Latypov <dlatypov@google.com>
Reviewed-by: David Gow <davidgow@google.com>
Reviewed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Daniel Latypov and committed by
Shuah Khan
8a04930f 76f0d6f5

+63 -85
+16 -33
tools/testing/kunit/kunit.py
··· 365 365 'filename is specified', 366 366 type=str, const='stdout', default=None, metavar='FILE') 367 367 368 - def main(argv, linux=None): 368 + 369 + def tree_from_args(cli_args: argparse.Namespace) -> kunit_kernel.LinuxSourceTree: 370 + """Returns a LinuxSourceTree based on the user's arguments.""" 371 + return kunit_kernel.LinuxSourceTree(cli_args.build_dir, 372 + kunitconfig_path=cli_args.kunitconfig, 373 + kconfig_add=cli_args.kconfig_add, 374 + arch=cli_args.arch, 375 + cross_compile=cli_args.cross_compile, 376 + qemu_config_path=cli_args.qemu_config) 377 + 378 + 379 + def main(argv): 369 380 parser = argparse.ArgumentParser( 370 381 description='Helps writing and running KUnit tests.') 371 382 subparser = parser.add_subparsers(dest='subcommand') ··· 423 412 if not os.path.exists(cli_args.build_dir): 424 413 os.mkdir(cli_args.build_dir) 425 414 426 - if not linux: 427 - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 428 - kunitconfig_path=cli_args.kunitconfig, 429 - kconfig_add=cli_args.kconfig_add, 430 - arch=cli_args.arch, 431 - cross_compile=cli_args.cross_compile, 432 - qemu_config_path=cli_args.qemu_config) 433 - 415 + linux = tree_from_args(cli_args) 434 416 request = KunitRequest(build_dir=cli_args.build_dir, 435 417 make_options=cli_args.make_options, 436 418 jobs=cli_args.jobs, ··· 442 438 not os.path.exists(cli_args.build_dir)): 443 439 os.mkdir(cli_args.build_dir) 444 440 445 - if not linux: 446 - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 447 - kunitconfig_path=cli_args.kunitconfig, 448 - kconfig_add=cli_args.kconfig_add, 449 - arch=cli_args.arch, 450 - cross_compile=cli_args.cross_compile, 451 - qemu_config_path=cli_args.qemu_config) 452 - 441 + linux = tree_from_args(cli_args) 453 442 request = KunitConfigRequest(build_dir=cli_args.build_dir, 454 443 make_options=cli_args.make_options) 455 444 result = config_tests(linux, request) ··· 452 455 if result.status != KunitStatus.SUCCESS: 453 456 sys.exit(1) 454 457 elif cli_args.subcommand == 'build': 455 - if not linux: 456 - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 457 - kunitconfig_path=cli_args.kunitconfig, 458 - kconfig_add=cli_args.kconfig_add, 459 - arch=cli_args.arch, 460 - cross_compile=cli_args.cross_compile, 461 - qemu_config_path=cli_args.qemu_config) 462 - 458 + linux = tree_from_args(cli_args) 463 459 request = KunitBuildRequest(build_dir=cli_args.build_dir, 464 460 make_options=cli_args.make_options, 465 461 jobs=cli_args.jobs, ··· 464 474 if result.status != KunitStatus.SUCCESS: 465 475 sys.exit(1) 466 476 elif cli_args.subcommand == 'exec': 467 - if not linux: 468 - linux = kunit_kernel.LinuxSourceTree(cli_args.build_dir, 469 - kunitconfig_path=cli_args.kunitconfig, 470 - kconfig_add=cli_args.kconfig_add, 471 - arch=cli_args.arch, 472 - cross_compile=cli_args.cross_compile, 473 - qemu_config_path=cli_args.qemu_config) 474 - 477 + linux = tree_from_args(cli_args) 475 478 exec_request = KunitExecRequest(raw_output=cli_args.raw_output, 476 479 build_dir=cli_args.build_dir, 477 480 json=cli_args.json,
+47 -52
tools/testing/kunit/kunit_tool_test.py
··· 503 503 self.print_mock = mock.patch('builtins.print').start() 504 504 self.addCleanup(mock.patch.stopall) 505 505 506 - self.linux_source_mock = mock.Mock() 507 - self.linux_source_mock.build_reconfig = mock.Mock(return_value=True) 508 - self.linux_source_mock.build_kernel = mock.Mock(return_value=True) 509 - self.linux_source_mock.run_kernel = mock.Mock(return_value=all_passed_log) 506 + self.mock_linux_init = mock.patch.object(kunit_kernel, 'LinuxSourceTree').start() 507 + self.linux_source_mock = self.mock_linux_init.return_value 508 + self.linux_source_mock.build_reconfig.return_value = True 509 + self.linux_source_mock.build_kernel.return_value = True 510 + self.linux_source_mock.run_kernel.return_value = all_passed_log 510 511 511 512 def test_config_passes_args_pass(self): 512 - kunit.main(['config', '--build_dir=.kunit'], self.linux_source_mock) 513 + kunit.main(['config', '--build_dir=.kunit']) 513 514 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 514 515 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0) 515 516 516 517 def test_build_passes_args_pass(self): 517 - kunit.main(['build'], self.linux_source_mock) 518 + kunit.main(['build']) 518 519 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 519 520 self.linux_source_mock.build_kernel.assert_called_once_with(False, kunit.get_default_jobs(), '.kunit', None) 520 521 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0) 521 522 522 523 def test_exec_passes_args_pass(self): 523 - kunit.main(['exec'], self.linux_source_mock) 524 + kunit.main(['exec']) 524 525 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 0) 525 526 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 526 527 self.linux_source_mock.run_kernel.assert_called_once_with( ··· 529 528 self.print_mock.assert_any_call(StrContains('Testing complete.')) 530 529 531 530 def test_run_passes_args_pass(self): 532 - kunit.main(['run'], self.linux_source_mock) 531 + kunit.main(['run']) 533 532 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 534 533 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 535 534 self.linux_source_mock.run_kernel.assert_called_once_with( ··· 539 538 def test_exec_passes_args_fail(self): 540 539 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 541 540 with self.assertRaises(SystemExit) as e: 542 - kunit.main(['exec'], self.linux_source_mock) 541 + kunit.main(['exec']) 543 542 self.assertEqual(e.exception.code, 1) 544 543 545 544 def test_run_passes_args_fail(self): 546 545 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 547 546 with self.assertRaises(SystemExit) as e: 548 - kunit.main(['run'], self.linux_source_mock) 547 + kunit.main(['run']) 549 548 self.assertEqual(e.exception.code, 1) 550 549 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 551 550 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) ··· 554 553 def test_exec_no_tests(self): 555 554 self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0']) 556 555 with self.assertRaises(SystemExit) as e: 557 - kunit.main(['run'], self.linux_source_mock) 556 + kunit.main(['run']) 558 557 self.assertEqual(e.exception.code, 1) 559 558 self.linux_source_mock.run_kernel.assert_called_once_with( 560 559 args=None, build_dir='.kunit', filter_glob='', timeout=300) ··· 562 561 563 562 def test_exec_raw_output(self): 564 563 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 565 - kunit.main(['exec', '--raw_output'], self.linux_source_mock) 564 + kunit.main(['exec', '--raw_output']) 566 565 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 567 566 for call in self.print_mock.call_args_list: 568 567 self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) ··· 570 569 571 570 def test_run_raw_output(self): 572 571 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 573 - kunit.main(['run', '--raw_output'], self.linux_source_mock) 572 + kunit.main(['run', '--raw_output']) 574 573 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 575 574 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 576 575 for call in self.print_mock.call_args_list: ··· 579 578 580 579 def test_run_raw_output_kunit(self): 581 580 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 582 - kunit.main(['run', '--raw_output=kunit'], self.linux_source_mock) 581 + kunit.main(['run', '--raw_output=kunit']) 583 582 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 584 583 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 585 584 for call in self.print_mock.call_args_list: ··· 589 588 def test_run_raw_output_invalid(self): 590 589 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 591 590 with self.assertRaises(SystemExit) as e: 592 - kunit.main(['run', '--raw_output=invalid'], self.linux_source_mock) 591 + kunit.main(['run', '--raw_output=invalid']) 593 592 self.assertNotEqual(e.exception.code, 0) 594 593 595 594 def test_run_raw_output_does_not_take_positional_args(self): 596 595 # --raw_output is a string flag, but we don't want it to consume 597 596 # any positional arguments, only ones after an '=' 598 597 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 599 - kunit.main(['run', '--raw_output', 'filter_glob'], self.linux_source_mock) 598 + kunit.main(['run', '--raw_output', 'filter_glob']) 600 599 self.linux_source_mock.run_kernel.assert_called_once_with( 601 600 args=None, build_dir='.kunit', filter_glob='filter_glob', timeout=300) 602 601 603 602 def test_exec_timeout(self): 604 603 timeout = 3453 605 - kunit.main(['exec', '--timeout', str(timeout)], self.linux_source_mock) 604 + kunit.main(['exec', '--timeout', str(timeout)]) 606 605 self.linux_source_mock.run_kernel.assert_called_once_with( 607 606 args=None, build_dir='.kunit', filter_glob='', timeout=timeout) 608 607 self.print_mock.assert_any_call(StrContains('Testing complete.')) 609 608 610 609 def test_run_timeout(self): 611 610 timeout = 3453 612 - kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock) 611 + kunit.main(['run', '--timeout', str(timeout)]) 613 612 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 614 613 self.linux_source_mock.run_kernel.assert_called_once_with( 615 614 args=None, build_dir='.kunit', filter_glob='', timeout=timeout) ··· 617 616 618 617 def test_run_builddir(self): 619 618 build_dir = '.kunit' 620 - kunit.main(['run', '--build_dir=.kunit'], self.linux_source_mock) 619 + kunit.main(['run', '--build_dir=.kunit']) 621 620 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 622 621 self.linux_source_mock.run_kernel.assert_called_once_with( 623 622 args=None, build_dir=build_dir, filter_glob='', timeout=300) ··· 625 624 626 625 def test_config_builddir(self): 627 626 build_dir = '.kunit' 628 - kunit.main(['config', '--build_dir', build_dir], self.linux_source_mock) 627 + kunit.main(['config', '--build_dir', build_dir]) 629 628 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 630 629 631 630 def test_build_builddir(self): 632 631 build_dir = '.kunit' 633 632 jobs = kunit.get_default_jobs() 634 - kunit.main(['build', '--build_dir', build_dir], self.linux_source_mock) 633 + kunit.main(['build', '--build_dir', build_dir]) 635 634 self.linux_source_mock.build_kernel.assert_called_once_with(False, jobs, build_dir, None) 636 635 637 636 def test_exec_builddir(self): 638 637 build_dir = '.kunit' 639 - kunit.main(['exec', '--build_dir', build_dir], self.linux_source_mock) 638 + kunit.main(['exec', '--build_dir', build_dir]) 640 639 self.linux_source_mock.run_kernel.assert_called_once_with( 641 640 args=None, build_dir=build_dir, filter_glob='', timeout=300) 642 641 self.print_mock.assert_any_call(StrContains('Testing complete.')) 643 642 644 - @mock.patch.object(kunit_kernel, 'LinuxSourceTree') 645 - def test_run_kunitconfig(self, mock_linux_init): 646 - mock_linux_init.return_value = self.linux_source_mock 643 + def test_run_kunitconfig(self): 647 644 kunit.main(['run', '--kunitconfig=mykunitconfig']) 648 645 # Just verify that we parsed and initialized it correctly here. 649 - mock_linux_init.assert_called_once_with('.kunit', 650 - kunitconfig_path='mykunitconfig', 651 - kconfig_add=None, 652 - arch='um', 653 - cross_compile=None, 654 - qemu_config_path=None) 646 + self.mock_linux_init.assert_called_once_with('.kunit', 647 + kunitconfig_path='mykunitconfig', 648 + kconfig_add=None, 649 + arch='um', 650 + cross_compile=None, 651 + qemu_config_path=None) 655 652 656 - @mock.patch.object(kunit_kernel, 'LinuxSourceTree') 657 - def test_config_kunitconfig(self, mock_linux_init): 658 - mock_linux_init.return_value = self.linux_source_mock 653 + def test_config_kunitconfig(self): 659 654 kunit.main(['config', '--kunitconfig=mykunitconfig']) 660 655 # Just verify that we parsed and initialized it correctly here. 661 - mock_linux_init.assert_called_once_with('.kunit', 662 - kunitconfig_path='mykunitconfig', 663 - kconfig_add=None, 664 - arch='um', 665 - cross_compile=None, 666 - qemu_config_path=None) 656 + self.mock_linux_init.assert_called_once_with('.kunit', 657 + kunitconfig_path='mykunitconfig', 658 + kconfig_add=None, 659 + arch='um', 660 + cross_compile=None, 661 + qemu_config_path=None) 667 662 668 - @mock.patch.object(kunit_kernel, 'LinuxSourceTree') 669 - def test_run_kconfig_add(self, mock_linux_init): 670 - mock_linux_init.return_value = self.linux_source_mock 663 + def test_run_kconfig_add(self): 671 664 kunit.main(['run', '--kconfig_add=CONFIG_KASAN=y', '--kconfig_add=CONFIG_KCSAN=y']) 672 665 # Just verify that we parsed and initialized it correctly here. 673 - mock_linux_init.assert_called_once_with('.kunit', 674 - kunitconfig_path=None, 675 - kconfig_add=['CONFIG_KASAN=y', 'CONFIG_KCSAN=y'], 676 - arch='um', 677 - cross_compile=None, 678 - qemu_config_path=None) 666 + self.mock_linux_init.assert_called_once_with('.kunit', 667 + kunitconfig_path=None, 668 + kconfig_add=['CONFIG_KASAN=y', 'CONFIG_KCSAN=y'], 669 + arch='um', 670 + cross_compile=None, 671 + qemu_config_path=None) 679 672 680 673 def test_run_kernel_args(self): 681 - kunit.main(['run', '--kernel_args=a=1', '--kernel_args=b=2'], self.linux_source_mock) 674 + kunit.main(['run', '--kernel_args=a=1', '--kernel_args=b=2']) 682 675 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 683 676 self.linux_source_mock.run_kernel.assert_called_once_with( 684 677 args=['a=1','b=2'], build_dir='.kunit', filter_glob='', timeout=300) ··· 694 699 @mock.patch.object(kunit, '_list_tests') 695 700 def test_run_isolated_by_suite(self, mock_tests): 696 701 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1'] 697 - kunit.main(['exec', '--run_isolated=suite', 'suite*.test*'], self.linux_source_mock) 702 + kunit.main(['exec', '--run_isolated=suite', 'suite*.test*']) 698 703 699 704 # Should respect the user's filter glob when listing tests. 700 705 mock_tests.assert_called_once_with(mock.ANY, ··· 707 712 @mock.patch.object(kunit, '_list_tests') 708 713 def test_run_isolated_by_test(self, mock_tests): 709 714 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1'] 710 - kunit.main(['exec', '--run_isolated=test', 'suite*'], self.linux_source_mock) 715 + kunit.main(['exec', '--run_isolated=test', 'suite*']) 711 716 712 717 # Should respect the user's filter glob when listing tests. 713 718 mock_tests.assert_called_once_with(mock.ANY,