1 #!/usr/bin/env python3 1 #!/usr/bin/env python3 2 # SPDX-License-Identifier: GPL-2.0 2 # SPDX-License-Identifier: GPL-2.0 3 # 3 # 4 # A collection of tests for tools/testing/kuni 4 # A collection of tests for tools/testing/kunit/kunit.py 5 # 5 # 6 # Copyright (C) 2019, Google LLC. 6 # Copyright (C) 2019, Google LLC. 7 # Author: Brendan Higgins <brendanhiggins@googl 7 # Author: Brendan Higgins <brendanhiggins@google.com> 8 8 9 import unittest 9 import unittest 10 from unittest import mock 10 from unittest import mock 11 11 12 import tempfile, shutil # Handling test_tmpdir 12 import tempfile, shutil # Handling test_tmpdir 13 13 14 import itertools 14 import itertools 15 import json 15 import json 16 import os 16 import os 17 import signal 17 import signal 18 import subprocess 18 import subprocess 19 from typing import Iterable 19 from typing import Iterable 20 20 21 import kunit_config 21 import kunit_config 22 import kunit_parser 22 import kunit_parser 23 import kunit_kernel 23 import kunit_kernel 24 import kunit_json 24 import kunit_json 25 import kunit 25 import kunit 26 26 27 test_tmpdir = '' 27 test_tmpdir = '' 28 abs_test_data_dir = '' 28 abs_test_data_dir = '' 29 29 30 def setUpModule(): 30 def setUpModule(): 31 global test_tmpdir, abs_test_data_dir 31 global test_tmpdir, abs_test_data_dir 32 test_tmpdir = tempfile.mkdtemp() 32 test_tmpdir = tempfile.mkdtemp() 33 abs_test_data_dir = os.path.abspath(os 33 abs_test_data_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test_data')) 34 34 35 def tearDownModule(): 35 def tearDownModule(): 36 shutil.rmtree(test_tmpdir) 36 shutil.rmtree(test_tmpdir) 37 37 38 def test_data_path(path): 38 def test_data_path(path): 39 return os.path.join(abs_test_data_dir, 39 return os.path.join(abs_test_data_dir, path) 40 40 41 class KconfigTest(unittest.TestCase): 41 class KconfigTest(unittest.TestCase): 42 42 43 def test_is_subset_of(self): 43 def test_is_subset_of(self): 44 kconfig0 = kunit_config.Kconfi 44 kconfig0 = kunit_config.Kconfig() 45 self.assertTrue(kconfig0.is_su 45 self.assertTrue(kconfig0.is_subset_of(kconfig0)) 46 46 47 kconfig1 = kunit_config.Kconfi 47 kconfig1 = kunit_config.Kconfig() 48 kconfig1.add_entry('TEST', 'y' 48 kconfig1.add_entry('TEST', 'y') 49 self.assertTrue(kconfig1.is_su 49 self.assertTrue(kconfig1.is_subset_of(kconfig1)) 50 self.assertTrue(kconfig0.is_su 50 self.assertTrue(kconfig0.is_subset_of(kconfig1)) 51 self.assertFalse(kconfig1.is_s 51 self.assertFalse(kconfig1.is_subset_of(kconfig0)) 52 52 53 def test_read_from_file(self): 53 def test_read_from_file(self): 54 kconfig_path = test_data_path( 54 kconfig_path = test_data_path('test_read_from_file.kconfig') 55 55 56 kconfig = kunit_config.parse_f 56 kconfig = kunit_config.parse_file(kconfig_path) 57 57 58 expected_kconfig = kunit_confi 58 expected_kconfig = kunit_config.Kconfig() 59 expected_kconfig.add_entry('UM 59 expected_kconfig.add_entry('UML', 'y') 60 expected_kconfig.add_entry('MM 60 expected_kconfig.add_entry('MMU', 'y') 61 expected_kconfig.add_entry('TE 61 expected_kconfig.add_entry('TEST', 'y') 62 expected_kconfig.add_entry('EX 62 expected_kconfig.add_entry('EXAMPLE_TEST', 'y') 63 expected_kconfig.add_entry('MK 63 expected_kconfig.add_entry('MK8', 'n') 64 64 65 self.assertEqual(kconfig, expe 65 self.assertEqual(kconfig, expected_kconfig) 66 66 67 def test_write_to_file(self): 67 def test_write_to_file(self): 68 kconfig_path = os.path.join(te 68 kconfig_path = os.path.join(test_tmpdir, '.config') 69 69 70 expected_kconfig = kunit_confi 70 expected_kconfig = kunit_config.Kconfig() 71 expected_kconfig.add_entry('UM 71 expected_kconfig.add_entry('UML', 'y') 72 expected_kconfig.add_entry('MM 72 expected_kconfig.add_entry('MMU', 'y') 73 expected_kconfig.add_entry('TE 73 expected_kconfig.add_entry('TEST', 'y') 74 expected_kconfig.add_entry('EX 74 expected_kconfig.add_entry('EXAMPLE_TEST', 'y') 75 expected_kconfig.add_entry('MK 75 expected_kconfig.add_entry('MK8', 'n') 76 76 77 expected_kconfig.write_to_file 77 expected_kconfig.write_to_file(kconfig_path) 78 78 79 actual_kconfig = kunit_config. 79 actual_kconfig = kunit_config.parse_file(kconfig_path) 80 self.assertEqual(actual_kconfi 80 self.assertEqual(actual_kconfig, expected_kconfig) 81 81 82 class KUnitParserTest(unittest.TestCase): 82 class KUnitParserTest(unittest.TestCase): 83 def setUp(self): 83 def setUp(self): 84 self.print_mock = mock.patch(' 84 self.print_mock = mock.patch('kunit_printer.Printer.print').start() 85 self.addCleanup(mock.patch.sto 85 self.addCleanup(mock.patch.stopall) 86 86 87 def noPrintCallContains(self, substr: 87 def noPrintCallContains(self, substr: str): 88 for call in self.print_mock.mo 88 for call in self.print_mock.mock_calls: 89 self.assertNotIn(subst 89 self.assertNotIn(substr, call.args[0]) 90 90 91 def assertContains(self, needle: str, 91 def assertContains(self, needle: str, haystack: kunit_parser.LineStream): 92 # Clone the iterator so we can 92 # Clone the iterator so we can print the contents on failure. 93 copy, backup = itertools.tee(h 93 copy, backup = itertools.tee(haystack) 94 for line in copy: 94 for line in copy: 95 if needle in line: 95 if needle in line: 96 return 96 return 97 raise AssertionError(f'"{needl 97 raise AssertionError(f'"{needle}" not found in {list(backup)}!') 98 98 99 def test_output_isolated_correctly(sel 99 def test_output_isolated_correctly(self): 100 log_path = test_data_path('tes 100 log_path = test_data_path('test_output_isolated_correctly.log') 101 with open(log_path) as file: 101 with open(log_path) as file: 102 result = kunit_parser. 102 result = kunit_parser.extract_tap_lines(file.readlines()) 103 self.assertContains('TAP versi 103 self.assertContains('TAP version 14', result) 104 self.assertContains('# Subtest 104 self.assertContains('# Subtest: example', result) 105 self.assertContains('1..2', re 105 self.assertContains('1..2', result) 106 self.assertContains('ok 1 - ex 106 self.assertContains('ok 1 - example_simple_test', result) 107 self.assertContains('ok 2 - ex 107 self.assertContains('ok 2 - example_mock_test', result) 108 self.assertContains('ok 1 - ex 108 self.assertContains('ok 1 - example', result) 109 109 110 def test_output_with_prefix_isolated_c 110 def test_output_with_prefix_isolated_correctly(self): 111 log_path = test_data_path('tes 111 log_path = test_data_path('test_pound_sign.log') 112 with open(log_path) as file: 112 with open(log_path) as file: 113 result = kunit_parser. 113 result = kunit_parser.extract_tap_lines(file.readlines()) 114 self.assertContains('TAP versi 114 self.assertContains('TAP version 14', result) 115 self.assertContains('# Subtest 115 self.assertContains('# Subtest: kunit-resource-test', result) 116 self.assertContains('1..5', re 116 self.assertContains('1..5', result) 117 self.assertContains('ok 1 - ku 117 self.assertContains('ok 1 - kunit_resource_test_init_resources', result) 118 self.assertContains('ok 2 - ku 118 self.assertContains('ok 2 - kunit_resource_test_alloc_resource', result) 119 self.assertContains('ok 3 - ku 119 self.assertContains('ok 3 - kunit_resource_test_destroy_resource', result) 120 self.assertContains('foo bar 120 self.assertContains('foo bar #', result) 121 self.assertContains('ok 4 - ku 121 self.assertContains('ok 4 - kunit_resource_test_cleanup_resources', result) 122 self.assertContains('ok 5 - ku 122 self.assertContains('ok 5 - kunit_resource_test_proper_free_ordering', result) 123 self.assertContains('ok 1 - ku 123 self.assertContains('ok 1 - kunit-resource-test', result) 124 self.assertContains('foo bar 124 self.assertContains('foo bar # non-kunit output', result) 125 self.assertContains('# Subtest 125 self.assertContains('# Subtest: kunit-try-catch-test', result) 126 self.assertContains('1..2', re 126 self.assertContains('1..2', result) 127 self.assertContains('ok 1 - ku 127 self.assertContains('ok 1 - kunit_test_try_catch_successful_try_no_catch', 128 result) 128 result) 129 self.assertContains('ok 2 - ku 129 self.assertContains('ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch', 130 result) 130 result) 131 self.assertContains('ok 2 - ku 131 self.assertContains('ok 2 - kunit-try-catch-test', result) 132 self.assertContains('# Subtest 132 self.assertContains('# Subtest: string-stream-test', result) 133 self.assertContains('1..3', re 133 self.assertContains('1..3', result) 134 self.assertContains('ok 1 - st 134 self.assertContains('ok 1 - string_stream_test_empty_on_creation', result) 135 self.assertContains('ok 2 - st 135 self.assertContains('ok 2 - string_stream_test_not_empty_after_add', result) 136 self.assertContains('ok 3 - st 136 self.assertContains('ok 3 - string_stream_test_get_string', result) 137 self.assertContains('ok 3 - st 137 self.assertContains('ok 3 - string-stream-test', result) 138 138 139 def test_parse_successful_test_log(sel 139 def test_parse_successful_test_log(self): 140 all_passed_log = test_data_pat 140 all_passed_log = test_data_path('test_is_test_passed-all_passed.log') 141 with open(all_passed_log) as f 141 with open(all_passed_log) as file: 142 result = kunit_parser. 142 result = kunit_parser.parse_run_tests(file.readlines()) 143 self.assertEqual(kunit_parser. 143 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 144 self.assertEqual(result.counts 144 self.assertEqual(result.counts.errors, 0) 145 145 146 def test_parse_successful_nested_tests 146 def test_parse_successful_nested_tests_log(self): 147 all_passed_log = test_data_pat 147 all_passed_log = test_data_path('test_is_test_passed-all_passed_nested.log') 148 with open(all_passed_log) as f 148 with open(all_passed_log) as file: 149 result = kunit_parser. 149 result = kunit_parser.parse_run_tests(file.readlines()) 150 self.assertEqual(kunit_parser. 150 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 151 self.assertEqual(result.counts 151 self.assertEqual(result.counts.errors, 0) 152 152 153 def test_kselftest_nested(self): 153 def test_kselftest_nested(self): 154 kselftest_log = test_data_path 154 kselftest_log = test_data_path('test_is_test_passed-kselftest.log') 155 with open(kselftest_log) as fi 155 with open(kselftest_log) as file: 156 result = kunit_parser. 156 result = kunit_parser.parse_run_tests(file.readlines()) 157 self.assertEqual(kunit_parser. 157 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 158 self.assertEqual(result.counts 158 self.assertEqual(result.counts.errors, 0) 159 159 160 def test_parse_failed_test_log(self): 160 def test_parse_failed_test_log(self): 161 failed_log = test_data_path('t 161 failed_log = test_data_path('test_is_test_passed-failure.log') 162 with open(failed_log) as file: 162 with open(failed_log) as file: 163 result = kunit_parser. 163 result = kunit_parser.parse_run_tests(file.readlines()) 164 self.assertEqual(kunit_parser. 164 self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 165 self.assertEqual(result.counts 165 self.assertEqual(result.counts.errors, 0) 166 166 167 def test_no_header(self): 167 def test_no_header(self): 168 empty_log = test_data_path('te 168 empty_log = test_data_path('test_is_test_passed-no_tests_run_no_header.log') 169 with open(empty_log) as file: 169 with open(empty_log) as file: 170 result = kunit_parser. 170 result = kunit_parser.parse_run_tests( 171 kunit_parser.e 171 kunit_parser.extract_tap_lines(file.readlines())) 172 self.assertEqual(0, len(result 172 self.assertEqual(0, len(result.subtests)) 173 self.assertEqual(kunit_parser. 173 self.assertEqual(kunit_parser.TestStatus.FAILURE_TO_PARSE_TESTS, result.status) 174 self.assertEqual(result.counts 174 self.assertEqual(result.counts.errors, 1) 175 175 176 def test_missing_test_plan(self): 176 def test_missing_test_plan(self): 177 missing_plan_log = test_data_p 177 missing_plan_log = test_data_path('test_is_test_passed-' 178 'missing_plan.log') 178 'missing_plan.log') 179 with open(missing_plan_log) as 179 with open(missing_plan_log) as file: 180 result = kunit_parser. 180 result = kunit_parser.parse_run_tests( 181 kunit_parser.e 181 kunit_parser.extract_tap_lines( 182 file.readlines 182 file.readlines())) 183 # A missing test plan is not a 183 # A missing test plan is not an error. 184 self.assertEqual(result.counts 184 self.assertEqual(result.counts, kunit_parser.TestCounts(passed=10, errors=0)) 185 self.assertEqual(kunit_parser. 185 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 186 186 187 def test_no_tests(self): 187 def test_no_tests(self): 188 header_log = test_data_path('t 188 header_log = test_data_path('test_is_test_passed-no_tests_run_with_header.log') 189 with open(header_log) as file: 189 with open(header_log) as file: 190 result = kunit_parser. 190 result = kunit_parser.parse_run_tests( 191 kunit_parser.e 191 kunit_parser.extract_tap_lines(file.readlines())) 192 self.assertEqual(0, len(result 192 self.assertEqual(0, len(result.subtests)) 193 self.assertEqual(kunit_parser. 193 self.assertEqual(kunit_parser.TestStatus.NO_TESTS, result.status) 194 self.assertEqual(result.counts 194 self.assertEqual(result.counts.errors, 1) 195 195 196 def test_no_tests_no_plan(self): 196 def test_no_tests_no_plan(self): 197 no_plan_log = test_data_path(' 197 no_plan_log = test_data_path('test_is_test_passed-no_tests_no_plan.log') 198 with open(no_plan_log) as file 198 with open(no_plan_log) as file: 199 result = kunit_parser. 199 result = kunit_parser.parse_run_tests( 200 kunit_parser.e 200 kunit_parser.extract_tap_lines(file.readlines())) 201 self.assertEqual(0, len(result 201 self.assertEqual(0, len(result.subtests[0].subtests[0].subtests)) 202 self.assertEqual( 202 self.assertEqual( 203 kunit_parser.TestStatu 203 kunit_parser.TestStatus.NO_TESTS, 204 result.subtests[0].sub 204 result.subtests[0].subtests[0].status) 205 self.assertEqual(result.counts 205 self.assertEqual(result.counts, kunit_parser.TestCounts(passed=1, errors=1)) 206 206 207 207 208 def test_no_kunit_output(self): 208 def test_no_kunit_output(self): 209 crash_log = test_data_path('te 209 crash_log = test_data_path('test_insufficient_memory.log') 210 print_mock = mock.patch('kunit 210 print_mock = mock.patch('kunit_printer.Printer.print').start() 211 with open(crash_log) as file: 211 with open(crash_log) as file: 212 result = kunit_parser. 212 result = kunit_parser.parse_run_tests( 213 kunit_parser.e 213 kunit_parser.extract_tap_lines(file.readlines())) 214 print_mock.assert_any_call(Str 214 print_mock.assert_any_call(StrContains('Could not find any KTAP output.')) 215 print_mock.stop() 215 print_mock.stop() 216 self.assertEqual(0, len(result 216 self.assertEqual(0, len(result.subtests)) 217 self.assertEqual(result.counts 217 self.assertEqual(result.counts.errors, 1) 218 218 219 def test_skipped_test(self): 219 def test_skipped_test(self): 220 skipped_log = test_data_path(' 220 skipped_log = test_data_path('test_skip_tests.log') 221 with open(skipped_log) as file 221 with open(skipped_log) as file: 222 result = kunit_parser. 222 result = kunit_parser.parse_run_tests(file.readlines()) 223 223 224 # A skipped test does not fail 224 # A skipped test does not fail the whole suite. 225 self.assertEqual(kunit_parser. 225 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 226 self.assertEqual(result.counts 226 self.assertEqual(result.counts, kunit_parser.TestCounts(passed=4, skipped=1)) 227 227 228 def test_skipped_all_tests(self): 228 def test_skipped_all_tests(self): 229 skipped_log = test_data_path(' 229 skipped_log = test_data_path('test_skip_all_tests.log') 230 with open(skipped_log) as file 230 with open(skipped_log) as file: 231 result = kunit_parser. 231 result = kunit_parser.parse_run_tests(file.readlines()) 232 232 233 self.assertEqual(kunit_parser. 233 self.assertEqual(kunit_parser.TestStatus.SKIPPED, result.status) 234 self.assertEqual(result.counts 234 self.assertEqual(result.counts, kunit_parser.TestCounts(skipped=5)) 235 235 236 def test_ignores_hyphen(self): 236 def test_ignores_hyphen(self): 237 hyphen_log = test_data_path('t 237 hyphen_log = test_data_path('test_strip_hyphen.log') 238 with open(hyphen_log) as file: 238 with open(hyphen_log) as file: 239 result = kunit_parser. 239 result = kunit_parser.parse_run_tests(file.readlines()) 240 240 241 # A skipped test does not fail 241 # A skipped test does not fail the whole suite. 242 self.assertEqual(kunit_parser. 242 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 243 self.assertEqual( 243 self.assertEqual( 244 "sysctl_test", 244 "sysctl_test", 245 result.subtests[0].nam 245 result.subtests[0].name) 246 self.assertEqual( 246 self.assertEqual( 247 "example", 247 "example", 248 result.subtests[1].nam 248 result.subtests[1].name) 249 249 250 def test_ignores_prefix_printk_time(se 250 def test_ignores_prefix_printk_time(self): 251 prefix_log = test_data_path('t 251 prefix_log = test_data_path('test_config_printk_time.log') 252 with open(prefix_log) as file: 252 with open(prefix_log) as file: 253 result = kunit_parser. 253 result = kunit_parser.parse_run_tests(file.readlines()) 254 self.assertEqual(kunit_parser. 254 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 255 self.assertEqual('kunit-resour 255 self.assertEqual('kunit-resource-test', result.subtests[0].name) 256 self.assertEqual(result.counts 256 self.assertEqual(result.counts.errors, 0) 257 257 258 def test_ignores_multiple_prefixes(sel 258 def test_ignores_multiple_prefixes(self): 259 prefix_log = test_data_path('t 259 prefix_log = test_data_path('test_multiple_prefixes.log') 260 with open(prefix_log) as file: 260 with open(prefix_log) as file: 261 result = kunit_parser. 261 result = kunit_parser.parse_run_tests(file.readlines()) 262 self.assertEqual(kunit_parser. 262 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 263 self.assertEqual('kunit-resour 263 self.assertEqual('kunit-resource-test', result.subtests[0].name) 264 self.assertEqual(result.counts 264 self.assertEqual(result.counts.errors, 0) 265 265 266 def test_prefix_mixed_kernel_output(se 266 def test_prefix_mixed_kernel_output(self): 267 mixed_prefix_log = test_data_p 267 mixed_prefix_log = test_data_path('test_interrupted_tap_output.log') 268 with open(mixed_prefix_log) as 268 with open(mixed_prefix_log) as file: 269 result = kunit_parser. 269 result = kunit_parser.parse_run_tests(file.readlines()) 270 self.assertEqual(kunit_parser. 270 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 271 self.assertEqual('kunit-resour 271 self.assertEqual('kunit-resource-test', result.subtests[0].name) 272 self.assertEqual(result.counts 272 self.assertEqual(result.counts.errors, 0) 273 273 274 def test_prefix_poundsign(self): 274 def test_prefix_poundsign(self): 275 pound_log = test_data_path('te 275 pound_log = test_data_path('test_pound_sign.log') 276 with open(pound_log) as file: 276 with open(pound_log) as file: 277 result = kunit_parser. 277 result = kunit_parser.parse_run_tests(file.readlines()) 278 self.assertEqual(kunit_parser. 278 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 279 self.assertEqual('kunit-resour 279 self.assertEqual('kunit-resource-test', result.subtests[0].name) 280 self.assertEqual(result.counts 280 self.assertEqual(result.counts.errors, 0) 281 281 282 def test_kernel_panic_end(self): 282 def test_kernel_panic_end(self): 283 panic_log = test_data_path('te 283 panic_log = test_data_path('test_kernel_panic_interrupt.log') 284 with open(panic_log) as file: 284 with open(panic_log) as file: 285 result = kunit_parser. 285 result = kunit_parser.parse_run_tests(file.readlines()) 286 self.assertEqual(kunit_parser. 286 self.assertEqual(kunit_parser.TestStatus.TEST_CRASHED, result.status) 287 self.assertEqual('kunit-resour 287 self.assertEqual('kunit-resource-test', result.subtests[0].name) 288 self.assertGreaterEqual(result 288 self.assertGreaterEqual(result.counts.errors, 1) 289 289 290 def test_pound_no_prefix(self): 290 def test_pound_no_prefix(self): 291 pound_log = test_data_path('te 291 pound_log = test_data_path('test_pound_no_prefix.log') 292 with open(pound_log) as file: 292 with open(pound_log) as file: 293 result = kunit_parser. 293 result = kunit_parser.parse_run_tests(file.readlines()) 294 self.assertEqual(kunit_parser. 294 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 295 self.assertEqual('kunit-resour 295 self.assertEqual('kunit-resource-test', result.subtests[0].name) 296 self.assertEqual(result.counts 296 self.assertEqual(result.counts.errors, 0) 297 297 298 def test_summarize_failures(self): 298 def test_summarize_failures(self): 299 output = """ 299 output = """ 300 KTAP version 1 300 KTAP version 1 301 1..2 301 1..2 302 # Subtest: all_failed_ 302 # Subtest: all_failed_suite 303 1..2 303 1..2 304 not ok 1 - test1 304 not ok 1 - test1 305 not ok 2 - test2 305 not ok 2 - test2 306 not ok 1 - all_failed_suite 306 not ok 1 - all_failed_suite 307 # Subtest: some_failed 307 # Subtest: some_failed_suite 308 1..2 308 1..2 309 ok 1 - test1 309 ok 1 - test1 310 not ok 2 - test2 310 not ok 2 - test2 311 not ok 1 - some_failed_suite 311 not ok 1 - some_failed_suite 312 """ 312 """ 313 result = kunit_parser.parse_ru 313 result = kunit_parser.parse_run_tests(output.splitlines()) 314 self.assertEqual(kunit_parser. 314 self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 315 315 316 self.assertEqual(kunit_parser. 316 self.assertEqual(kunit_parser._summarize_failed_tests(result), 317 'Failures: all_failed_ 317 'Failures: all_failed_suite, some_failed_suite.test2') 318 318 319 def test_ktap_format(self): 319 def test_ktap_format(self): 320 ktap_log = test_data_path('tes 320 ktap_log = test_data_path('test_parse_ktap_output.log') 321 with open(ktap_log) as file: 321 with open(ktap_log) as file: 322 result = kunit_parser. 322 result = kunit_parser.parse_run_tests(file.readlines()) 323 self.assertEqual(result.counts 323 self.assertEqual(result.counts, kunit_parser.TestCounts(passed=3)) 324 self.assertEqual('suite', resu 324 self.assertEqual('suite', result.subtests[0].name) 325 self.assertEqual('case_1', res 325 self.assertEqual('case_1', result.subtests[0].subtests[0].name) 326 self.assertEqual('case_2', res 326 self.assertEqual('case_2', result.subtests[0].subtests[1].name) 327 327 328 def test_parse_subtest_header(self): 328 def test_parse_subtest_header(self): 329 ktap_log = test_data_path('tes 329 ktap_log = test_data_path('test_parse_subtest_header.log') 330 with open(ktap_log) as file: 330 with open(ktap_log) as file: 331 kunit_parser.parse_run 331 kunit_parser.parse_run_tests(file.readlines()) 332 self.print_mock.assert_any_cal 332 self.print_mock.assert_any_call(StrContains('suite (1 subtest)')) 333 333 334 def test_parse_attributes(self): 334 def test_parse_attributes(self): 335 ktap_log = test_data_path('tes 335 ktap_log = test_data_path('test_parse_attributes.log') 336 with open(ktap_log) as file: 336 with open(ktap_log) as file: 337 result = kunit_parser. 337 result = kunit_parser.parse_run_tests(file.readlines()) 338 338 339 # Test should pass with no err 339 # Test should pass with no errors 340 self.assertEqual(result.counts 340 self.assertEqual(result.counts, kunit_parser.TestCounts(passed=1, errors=0)) 341 self.assertEqual(kunit_parser. 341 self.assertEqual(kunit_parser.TestStatus.SUCCESS, result.status) 342 342 343 # Ensure suite header is parse 343 # Ensure suite header is parsed correctly 344 self.print_mock.assert_any_cal 344 self.print_mock.assert_any_call(StrContains('suite (1 subtest)')) 345 345 346 # Ensure attributes in correct 346 # Ensure attributes in correct test log 347 self.assertContains('# module: 347 self.assertContains('# module: example', result.subtests[0].log) 348 self.assertContains('# test.sp 348 self.assertContains('# test.speed: slow', result.subtests[0].subtests[0].log) 349 349 350 def test_show_test_output_on_failure(s 350 def test_show_test_output_on_failure(self): 351 output = """ 351 output = """ 352 KTAP version 1 352 KTAP version 1 353 1..1 353 1..1 354 Test output. 354 Test output. 355 Indented more. 355 Indented more. 356 not ok 1 test1 356 not ok 1 test1 357 """ 357 """ 358 result = kunit_parser.parse_ru 358 result = kunit_parser.parse_run_tests(output.splitlines()) 359 self.assertEqual(kunit_parser. 359 self.assertEqual(kunit_parser.TestStatus.FAILURE, result.status) 360 360 361 self.print_mock.assert_any_cal 361 self.print_mock.assert_any_call(StrContains('Test output.')) 362 self.print_mock.assert_any_cal 362 self.print_mock.assert_any_call(StrContains(' Indented more.')) 363 self.noPrintCallContains('not 363 self.noPrintCallContains('not ok 1 test1') 364 364 365 def line_stream_from_strs(strs: Iterable[str]) 365 def line_stream_from_strs(strs: Iterable[str]) -> kunit_parser.LineStream: 366 return kunit_parser.LineStream(enumera 366 return kunit_parser.LineStream(enumerate(strs, start=1)) 367 367 368 class LineStreamTest(unittest.TestCase): 368 class LineStreamTest(unittest.TestCase): 369 369 370 def test_basic(self): 370 def test_basic(self): 371 stream = line_stream_from_strs 371 stream = line_stream_from_strs(['hello', 'world']) 372 372 373 self.assertTrue(stream, msg='S 373 self.assertTrue(stream, msg='Should be more input') 374 self.assertEqual(stream.line_n 374 self.assertEqual(stream.line_number(), 1) 375 self.assertEqual(stream.peek() 375 self.assertEqual(stream.peek(), 'hello') 376 self.assertEqual(stream.pop(), 376 self.assertEqual(stream.pop(), 'hello') 377 377 378 self.assertTrue(stream, msg='S 378 self.assertTrue(stream, msg='Should be more input') 379 self.assertEqual(stream.line_n 379 self.assertEqual(stream.line_number(), 2) 380 self.assertEqual(stream.peek() 380 self.assertEqual(stream.peek(), 'world') 381 self.assertEqual(stream.pop(), 381 self.assertEqual(stream.pop(), 'world') 382 382 383 self.assertFalse(stream, msg=' 383 self.assertFalse(stream, msg='Should be no more input') 384 with self.assertRaisesRegex(Va 384 with self.assertRaisesRegex(ValueError, 'LineStream: going past EOF'): 385 stream.pop() 385 stream.pop() 386 386 387 def test_is_lazy(self): 387 def test_is_lazy(self): 388 called_times = 0 388 called_times = 0 389 def generator(): 389 def generator(): 390 nonlocal called_times 390 nonlocal called_times 391 for _ in range(1,5): 391 for _ in range(1,5): 392 called_times + 392 called_times += 1 393 yield called_t 393 yield called_times, str(called_times) 394 394 395 stream = kunit_parser.LineStre 395 stream = kunit_parser.LineStream(generator()) 396 self.assertEqual(called_times, 396 self.assertEqual(called_times, 0) 397 397 398 self.assertEqual(stream.pop(), 398 self.assertEqual(stream.pop(), '1') 399 self.assertEqual(called_times, 399 self.assertEqual(called_times, 1) 400 400 401 self.assertEqual(stream.pop(), 401 self.assertEqual(stream.pop(), '2') 402 self.assertEqual(called_times, 402 self.assertEqual(called_times, 2) 403 403 404 class LinuxSourceTreeTest(unittest.TestCase): 404 class LinuxSourceTreeTest(unittest.TestCase): 405 405 406 def setUp(self): 406 def setUp(self): 407 mock.patch.object(signal, 'sig 407 mock.patch.object(signal, 'signal').start() 408 self.addCleanup(mock.patch.sto 408 self.addCleanup(mock.patch.stopall) 409 409 410 def test_invalid_kunitconfig(self): 410 def test_invalid_kunitconfig(self): 411 with self.assertRaisesRegex(ku 411 with self.assertRaisesRegex(kunit_kernel.ConfigError, 'nonexistent.* does not exist'): 412 kunit_kernel.LinuxSour 412 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=['/nonexistent_file']) 413 413 414 def test_valid_kunitconfig(self): 414 def test_valid_kunitconfig(self): 415 with tempfile.NamedTemporaryFi 415 with tempfile.NamedTemporaryFile('wt') as kunitconfig: 416 kunit_kernel.LinuxSour 416 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[kunitconfig.name]) 417 417 418 def test_dir_kunitconfig(self): 418 def test_dir_kunitconfig(self): 419 with tempfile.TemporaryDirecto 419 with tempfile.TemporaryDirectory('') as dir: 420 with open(os.path.join 420 with open(os.path.join(dir, '.kunitconfig'), 'w'): 421 pass 421 pass 422 kunit_kernel.LinuxSour 422 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir]) 423 423 424 def test_multiple_kunitconfig(self): 424 def test_multiple_kunitconfig(self): 425 want_kconfig = kunit_config.Kc 425 want_kconfig = kunit_config.Kconfig() 426 want_kconfig.add_entry('KUNIT' 426 want_kconfig.add_entry('KUNIT', 'y') 427 want_kconfig.add_entry('KUNIT_ 427 want_kconfig.add_entry('KUNIT_TEST', 'm') 428 428 429 with tempfile.TemporaryDirecto 429 with tempfile.TemporaryDirectory('') as dir: 430 other = os.path.join(d 430 other = os.path.join(dir, 'otherkunitconfig') 431 with open(os.path.join 431 with open(os.path.join(dir, '.kunitconfig'), 'w') as f: 432 f.write('CONFI 432 f.write('CONFIG_KUNIT=y') 433 with open(other, 'w') 433 with open(other, 'w') as f: 434 f.write('CONFI 434 f.write('CONFIG_KUNIT_TEST=m') 435 pass 435 pass 436 436 437 tree = kunit_kernel.Li 437 tree = kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other]) 438 self.assertTrue(want_k 438 self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig) 439 439 440 440 441 def test_multiple_kunitconfig_invalid( 441 def test_multiple_kunitconfig_invalid(self): 442 with tempfile.TemporaryDirecto 442 with tempfile.TemporaryDirectory('') as dir: 443 other = os.path.join(d 443 other = os.path.join(dir, 'otherkunitconfig') 444 with open(os.path.join 444 with open(os.path.join(dir, '.kunitconfig'), 'w') as f: 445 f.write('CONFI 445 f.write('CONFIG_KUNIT=y') 446 with open(other, 'w') 446 with open(other, 'w') as f: 447 f.write('CONFI 447 f.write('CONFIG_KUNIT=m') 448 448 449 with self.assertRaises 449 with self.assertRaisesRegex(kunit_kernel.ConfigError, '(?s)Multiple values.*CONFIG_KUNIT'): 450 kunit_kernel.L 450 kunit_kernel.LinuxSourceTree('', kunitconfig_paths=[dir, other]) 451 451 452 452 453 def test_kconfig_add(self): 453 def test_kconfig_add(self): 454 want_kconfig = kunit_config.Kc 454 want_kconfig = kunit_config.Kconfig() 455 want_kconfig.add_entry('NOT_RE 455 want_kconfig.add_entry('NOT_REAL', 'y') 456 456 457 tree = kunit_kernel.LinuxSourc 457 tree = kunit_kernel.LinuxSourceTree('', kconfig_add=['CONFIG_NOT_REAL=y']) 458 self.assertTrue(want_kconfig.i 458 self.assertTrue(want_kconfig.is_subset_of(tree._kconfig), msg=tree._kconfig) 459 459 460 def test_invalid_arch(self): 460 def test_invalid_arch(self): 461 with self.assertRaisesRegex(ku 461 with self.assertRaisesRegex(kunit_kernel.ConfigError, 'not a valid arch, options are.*x86_64'): 462 kunit_kernel.LinuxSour 462 kunit_kernel.LinuxSourceTree('', arch='invalid') 463 463 464 def test_run_kernel_hits_exception(sel 464 def test_run_kernel_hits_exception(self): 465 def fake_start(unused_args, un 465 def fake_start(unused_args, unused_build_dir): 466 return subprocess.Pope 466 return subprocess.Popen(['echo "hi\nbye"'], shell=True, text=True, stdout=subprocess.PIPE) 467 467 468 with tempfile.TemporaryDirecto 468 with tempfile.TemporaryDirectory('') as build_dir: 469 tree = kunit_kernel.Li 469 tree = kunit_kernel.LinuxSourceTree(build_dir) 470 mock.patch.object(tree 470 mock.patch.object(tree._ops, 'start', side_effect=fake_start).start() 471 471 472 with self.assertRaises 472 with self.assertRaises(ValueError): 473 for line in tr 473 for line in tree.run_kernel(build_dir=build_dir): 474 self.a 474 self.assertEqual(line, 'hi\n') 475 raise 475 raise ValueError('uh oh, did not read all output') 476 476 477 with open(kunit_kernel 477 with open(kunit_kernel.get_outfile_path(build_dir), 'rt') as outfile: 478 self.assertEqu 478 self.assertEqual(outfile.read(), 'hi\nbye\n', msg='Missing some output') 479 479 480 def test_build_reconfig_no_config(self 480 def test_build_reconfig_no_config(self): 481 with tempfile.TemporaryDirecto 481 with tempfile.TemporaryDirectory('') as build_dir: 482 with open(kunit_kernel 482 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: 483 f.write('CONFI 483 f.write('CONFIG_KUNIT=y') 484 484 485 tree = kunit_kernel.Li 485 tree = kunit_kernel.LinuxSourceTree(build_dir) 486 # Stub out the source 486 # Stub out the source tree operations, so we don't have 487 # the defaults for any 487 # the defaults for any given architecture get in the 488 # way. 488 # way. 489 tree._ops = kunit_kern 489 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) 490 mock_build_config = mo 490 mock_build_config = mock.patch.object(tree, 'build_config').start() 491 491 492 # Should generate the 492 # Should generate the .config 493 self.assertTrue(tree.b 493 self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) 494 mock_build_config.asse 494 mock_build_config.assert_called_once_with(build_dir, []) 495 495 496 def test_build_reconfig_existing_confi 496 def test_build_reconfig_existing_config(self): 497 with tempfile.TemporaryDirecto 497 with tempfile.TemporaryDirectory('') as build_dir: 498 # Existing .config is 498 # Existing .config is a superset, should not touch it 499 with open(kunit_kernel 499 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: 500 f.write('CONFI 500 f.write('CONFIG_KUNIT=y') 501 with open(kunit_kernel 501 with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: 502 f.write('CONFI 502 f.write('CONFIG_KUNIT=y') 503 with open(kunit_kernel 503 with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: 504 f.write('CONFI 504 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') 505 505 506 tree = kunit_kernel.Li 506 tree = kunit_kernel.LinuxSourceTree(build_dir) 507 # Stub out the source 507 # Stub out the source tree operations, so we don't have 508 # the defaults for any 508 # the defaults for any given architecture get in the 509 # way. 509 # way. 510 tree._ops = kunit_kern 510 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) 511 mock_build_config = mo 511 mock_build_config = mock.patch.object(tree, 'build_config').start() 512 512 513 self.assertTrue(tree.b 513 self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) 514 self.assertEqual(mock_ 514 self.assertEqual(mock_build_config.call_count, 0) 515 515 516 def test_build_reconfig_remove_option( 516 def test_build_reconfig_remove_option(self): 517 with tempfile.TemporaryDirecto 517 with tempfile.TemporaryDirectory('') as build_dir: 518 # We removed CONFIG_KU 518 # We removed CONFIG_KUNIT_TEST=y from our .kunitconfig... 519 with open(kunit_kernel 519 with open(kunit_kernel.get_kunitconfig_path(build_dir), 'w') as f: 520 f.write('CONFI 520 f.write('CONFIG_KUNIT=y') 521 with open(kunit_kernel 521 with open(kunit_kernel.get_old_kunitconfig_path(build_dir), 'w') as f: 522 f.write('CONFI 522 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') 523 with open(kunit_kernel 523 with open(kunit_kernel.get_kconfig_path(build_dir), 'w') as f: 524 f.write('CONFI 524 f.write('CONFIG_KUNIT=y\nCONFIG_KUNIT_TEST=y') 525 525 526 tree = kunit_kernel.Li 526 tree = kunit_kernel.LinuxSourceTree(build_dir) 527 # Stub out the source 527 # Stub out the source tree operations, so we don't have 528 # the defaults for any 528 # the defaults for any given architecture get in the 529 # way. 529 # way. 530 tree._ops = kunit_kern 530 tree._ops = kunit_kernel.LinuxSourceTreeOperations('none', None) 531 mock_build_config = mo 531 mock_build_config = mock.patch.object(tree, 'build_config').start() 532 532 533 # ... so we should tri 533 # ... so we should trigger a call to build_config() 534 self.assertTrue(tree.b 534 self.assertTrue(tree.build_reconfig(build_dir, make_options=[])) 535 mock_build_config.asse 535 mock_build_config.assert_called_once_with(build_dir, []) 536 536 537 # TODO: add more test cases. 537 # TODO: add more test cases. 538 538 539 539 540 class KUnitJsonTest(unittest.TestCase): 540 class KUnitJsonTest(unittest.TestCase): 541 def setUp(self): 541 def setUp(self): 542 self.print_mock = mock.patch(' 542 self.print_mock = mock.patch('kunit_printer.Printer.print').start() 543 self.addCleanup(mock.patch.sto 543 self.addCleanup(mock.patch.stopall) 544 544 545 def _json_for(self, log_file): 545 def _json_for(self, log_file): 546 with open(test_data_path(log_f 546 with open(test_data_path(log_file)) as file: 547 test_result = kunit_pa 547 test_result = kunit_parser.parse_run_tests(file) 548 json_obj = kunit_json. 548 json_obj = kunit_json.get_json_result( 549 test=test_resu 549 test=test_result, 550 metadata=kunit 550 metadata=kunit_json.Metadata()) 551 return json.loads(json_obj) 551 return json.loads(json_obj) 552 552 553 def test_failed_test_json(self): 553 def test_failed_test_json(self): 554 result = self._json_for('test_ 554 result = self._json_for('test_is_test_passed-failure.log') 555 self.assertEqual( 555 self.assertEqual( 556 {'name': 'example_simp 556 {'name': 'example_simple_test', 'status': 'FAIL'}, 557 result["sub_groups"][1 557 result["sub_groups"][1]["test_cases"][0]) 558 558 559 def test_crashed_test_json(self): 559 def test_crashed_test_json(self): 560 result = self._json_for('test_ 560 result = self._json_for('test_kernel_panic_interrupt.log') 561 self.assertEqual( 561 self.assertEqual( 562 {'name': '', 'status': 562 {'name': '', 'status': 'ERROR'}, 563 result["sub_groups"][2 563 result["sub_groups"][2]["test_cases"][1]) 564 564 565 def test_skipped_test_json(self): 565 def test_skipped_test_json(self): 566 result = self._json_for('test_ 566 result = self._json_for('test_skip_tests.log') 567 self.assertEqual( 567 self.assertEqual( 568 {'name': 'example_skip 568 {'name': 'example_skip_test', 'status': 'SKIP'}, 569 result["sub_groups"][1 569 result["sub_groups"][1]["test_cases"][1]) 570 570 571 def test_no_tests_json(self): 571 def test_no_tests_json(self): 572 result = self._json_for('test_ 572 result = self._json_for('test_is_test_passed-no_tests_run_with_header.log') 573 self.assertEqual(0, len(result 573 self.assertEqual(0, len(result['sub_groups'])) 574 574 575 def test_nested_json(self): 575 def test_nested_json(self): 576 result = self._json_for('test_ 576 result = self._json_for('test_is_test_passed-all_passed_nested.log') 577 self.assertEqual( 577 self.assertEqual( 578 {'name': 'example_simp 578 {'name': 'example_simple_test', 'status': 'PASS'}, 579 result["sub_groups"][0 579 result["sub_groups"][0]["sub_groups"][0]["test_cases"][0]) 580 580 581 class StrContains(str): 581 class StrContains(str): 582 def __eq__(self, other): 582 def __eq__(self, other): 583 return self in other 583 return self in other 584 584 585 class KUnitMainTest(unittest.TestCase): 585 class KUnitMainTest(unittest.TestCase): 586 def setUp(self): 586 def setUp(self): 587 path = test_data_path('test_is 587 path = test_data_path('test_is_test_passed-all_passed.log') 588 with open(path) as file: 588 with open(path) as file: 589 all_passed_log = file. 589 all_passed_log = file.readlines() 590 590 591 self.print_mock = mock.patch(' 591 self.print_mock = mock.patch('kunit_printer.Printer.print').start() 592 self.addCleanup(mock.patch.sto 592 self.addCleanup(mock.patch.stopall) 593 593 594 self.mock_linux_init = mock.pa 594 self.mock_linux_init = mock.patch.object(kunit_kernel, 'LinuxSourceTree').start() 595 self.linux_source_mock = self. 595 self.linux_source_mock = self.mock_linux_init.return_value 596 self.linux_source_mock.build_r 596 self.linux_source_mock.build_reconfig.return_value = True 597 self.linux_source_mock.build_k 597 self.linux_source_mock.build_kernel.return_value = True 598 self.linux_source_mock.run_ker 598 self.linux_source_mock.run_kernel.return_value = all_passed_log 599 599 600 def test_config_passes_args_pass(self) 600 def test_config_passes_args_pass(self): 601 kunit.main(['config', '--build 601 kunit.main(['config', '--build_dir=.kunit']) 602 self.assertEqual(self.linux_so 602 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 603 self.assertEqual(self.linux_so 603 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0) 604 604 605 def test_build_passes_args_pass(self): 605 def test_build_passes_args_pass(self): 606 kunit.main(['build']) 606 kunit.main(['build']) 607 self.assertEqual(self.linux_so 607 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 608 self.linux_source_mock.build_k 608 self.linux_source_mock.build_kernel.assert_called_once_with(kunit.get_default_jobs(), '.kunit', None) 609 self.assertEqual(self.linux_so 609 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 0) 610 610 611 def test_exec_passes_args_pass(self): 611 def test_exec_passes_args_pass(self): 612 kunit.main(['exec']) 612 kunit.main(['exec']) 613 self.assertEqual(self.linux_so 613 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 0) 614 self.assertEqual(self.linux_so 614 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 615 self.linux_source_mock.run_ker 615 self.linux_source_mock.run_kernel.assert_called_once_with( 616 args=None, build_dir=' 616 args=None, build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=300) 617 self.print_mock.assert_any_cal 617 self.print_mock.assert_any_call(StrContains('Testing complete.')) 618 618 619 def test_run_passes_args_pass(self): 619 def test_run_passes_args_pass(self): 620 kunit.main(['run']) 620 kunit.main(['run']) 621 self.assertEqual(self.linux_so 621 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 622 self.assertEqual(self.linux_so 622 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 623 self.linux_source_mock.run_ker 623 self.linux_source_mock.run_kernel.assert_called_once_with( 624 args=None, build_dir=' 624 args=None, build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=300) 625 self.print_mock.assert_any_cal 625 self.print_mock.assert_any_call(StrContains('Testing complete.')) 626 626 627 def test_exec_passes_args_fail(self): 627 def test_exec_passes_args_fail(self): 628 self.linux_source_mock.run_ker 628 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 629 with self.assertRaises(SystemE 629 with self.assertRaises(SystemExit) as e: 630 kunit.main(['exec']) 630 kunit.main(['exec']) 631 self.assertEqual(e.exception.c 631 self.assertEqual(e.exception.code, 1) 632 632 633 def test_run_passes_args_fail(self): 633 def test_run_passes_args_fail(self): 634 self.linux_source_mock.run_ker 634 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 635 with self.assertRaises(SystemE 635 with self.assertRaises(SystemExit) as e: 636 kunit.main(['run']) 636 kunit.main(['run']) 637 self.assertEqual(e.exception.c 637 self.assertEqual(e.exception.code, 1) 638 self.assertEqual(self.linux_so 638 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 639 self.assertEqual(self.linux_so 639 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 640 self.print_mock.assert_any_cal 640 self.print_mock.assert_any_call(StrContains('Could not find any KTAP output.')) 641 641 642 def test_exec_no_tests(self): 642 def test_exec_no_tests(self): 643 self.linux_source_mock.run_ker 643 self.linux_source_mock.run_kernel = mock.Mock(return_value=['TAP version 14', '1..0']) 644 with self.assertRaises(SystemE 644 with self.assertRaises(SystemExit) as e: 645 kunit.main(['run']) 645 kunit.main(['run']) 646 self.assertEqual(e.exception.c 646 self.assertEqual(e.exception.code, 1) 647 self.linux_source_mock.run_ker 647 self.linux_source_mock.run_kernel.assert_called_once_with( 648 args=None, build_dir=' 648 args=None, build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=300) 649 self.print_mock.assert_any_cal 649 self.print_mock.assert_any_call(StrContains(' 0 tests run!')) 650 650 651 def test_exec_raw_output(self): 651 def test_exec_raw_output(self): 652 self.linux_source_mock.run_ker 652 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 653 kunit.main(['exec', '--raw_out 653 kunit.main(['exec', '--raw_output']) 654 self.assertEqual(self.linux_so 654 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 655 for call in self.print_mock.ca 655 for call in self.print_mock.call_args_list: 656 self.assertNotEqual(ca 656 self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) 657 self.assertNotEqual(ca 657 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run!'))) 658 658 659 def test_run_raw_output(self): 659 def test_run_raw_output(self): 660 self.linux_source_mock.run_ker 660 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 661 kunit.main(['run', '--raw_outp 661 kunit.main(['run', '--raw_output']) 662 self.assertEqual(self.linux_so 662 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 663 self.assertEqual(self.linux_so 663 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 664 for call in self.print_mock.ca 664 for call in self.print_mock.call_args_list: 665 self.assertNotEqual(ca 665 self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) 666 self.assertNotEqual(ca 666 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run!'))) 667 667 668 def test_run_raw_output_kunit(self): 668 def test_run_raw_output_kunit(self): 669 self.linux_source_mock.run_ker 669 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 670 kunit.main(['run', '--raw_outp 670 kunit.main(['run', '--raw_output=kunit']) 671 self.assertEqual(self.linux_so 671 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 672 self.assertEqual(self.linux_so 672 self.assertEqual(self.linux_source_mock.run_kernel.call_count, 1) 673 for call in self.print_mock.ca 673 for call in self.print_mock.call_args_list: 674 self.assertNotEqual(ca 674 self.assertNotEqual(call, mock.call(StrContains('Testing complete.'))) 675 self.assertNotEqual(ca 675 self.assertNotEqual(call, mock.call(StrContains(' 0 tests run'))) 676 676 677 def test_run_raw_output_invalid(self): 677 def test_run_raw_output_invalid(self): 678 self.linux_source_mock.run_ker 678 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 679 with self.assertRaises(SystemE 679 with self.assertRaises(SystemExit) as e: 680 kunit.main(['run', '-- 680 kunit.main(['run', '--raw_output=invalid']) 681 self.assertNotEqual(e.exceptio 681 self.assertNotEqual(e.exception.code, 0) 682 682 683 def test_run_raw_output_does_not_take_ 683 def test_run_raw_output_does_not_take_positional_args(self): 684 # --raw_output is a string fla 684 # --raw_output is a string flag, but we don't want it to consume 685 # any positional arguments, on 685 # any positional arguments, only ones after an '=' 686 self.linux_source_mock.run_ker 686 self.linux_source_mock.run_kernel = mock.Mock(return_value=[]) 687 kunit.main(['run', '--raw_outp 687 kunit.main(['run', '--raw_output', 'filter_glob']) 688 self.linux_source_mock.run_ker 688 self.linux_source_mock.run_kernel.assert_called_once_with( 689 args=None, build_dir=' 689 args=None, build_dir='.kunit', filter_glob='filter_glob', filter='', filter_action=None, timeout=300) 690 690 691 def test_exec_timeout(self): 691 def test_exec_timeout(self): 692 timeout = 3453 692 timeout = 3453 693 kunit.main(['exec', '--timeout 693 kunit.main(['exec', '--timeout', str(timeout)]) 694 self.linux_source_mock.run_ker 694 self.linux_source_mock.run_kernel.assert_called_once_with( 695 args=None, build_dir=' 695 args=None, build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=timeout) 696 self.print_mock.assert_any_cal 696 self.print_mock.assert_any_call(StrContains('Testing complete.')) 697 697 698 def test_run_timeout(self): 698 def test_run_timeout(self): 699 timeout = 3453 699 timeout = 3453 700 kunit.main(['run', '--timeout' 700 kunit.main(['run', '--timeout', str(timeout)]) 701 self.assertEqual(self.linux_so 701 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 702 self.linux_source_mock.run_ker 702 self.linux_source_mock.run_kernel.assert_called_once_with( 703 args=None, build_dir=' 703 args=None, build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=timeout) 704 self.print_mock.assert_any_cal 704 self.print_mock.assert_any_call(StrContains('Testing complete.')) 705 705 706 def test_run_builddir(self): 706 def test_run_builddir(self): 707 build_dir = '.kunit' 707 build_dir = '.kunit' 708 kunit.main(['run', '--build_di 708 kunit.main(['run', '--build_dir=.kunit']) 709 self.assertEqual(self.linux_so 709 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 710 self.linux_source_mock.run_ker 710 self.linux_source_mock.run_kernel.assert_called_once_with( 711 args=None, build_dir=b 711 args=None, build_dir=build_dir, filter_glob='', filter='', filter_action=None, timeout=300) 712 self.print_mock.assert_any_cal 712 self.print_mock.assert_any_call(StrContains('Testing complete.')) 713 713 714 def test_config_builddir(self): 714 def test_config_builddir(self): 715 build_dir = '.kunit' 715 build_dir = '.kunit' 716 kunit.main(['config', '--build 716 kunit.main(['config', '--build_dir', build_dir]) 717 self.assertEqual(self.linux_so 717 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 718 718 719 def test_build_builddir(self): 719 def test_build_builddir(self): 720 build_dir = '.kunit' 720 build_dir = '.kunit' 721 jobs = kunit.get_default_jobs( 721 jobs = kunit.get_default_jobs() 722 kunit.main(['build', '--build_ 722 kunit.main(['build', '--build_dir', build_dir]) 723 self.linux_source_mock.build_k 723 self.linux_source_mock.build_kernel.assert_called_once_with(jobs, build_dir, None) 724 724 725 def test_exec_builddir(self): 725 def test_exec_builddir(self): 726 build_dir = '.kunit' 726 build_dir = '.kunit' 727 kunit.main(['exec', '--build_d 727 kunit.main(['exec', '--build_dir', build_dir]) 728 self.linux_source_mock.run_ker 728 self.linux_source_mock.run_kernel.assert_called_once_with( 729 args=None, build_dir=b 729 args=None, build_dir=build_dir, filter_glob='', filter='', filter_action=None, timeout=300) 730 self.print_mock.assert_any_cal 730 self.print_mock.assert_any_call(StrContains('Testing complete.')) 731 731 732 def test_run_kunitconfig(self): 732 def test_run_kunitconfig(self): 733 kunit.main(['run', '--kunitcon 733 kunit.main(['run', '--kunitconfig=mykunitconfig']) 734 # Just verify that we parsed a 734 # Just verify that we parsed and initialized it correctly here. 735 self.mock_linux_init.assert_ca 735 self.mock_linux_init.assert_called_once_with('.kunit', 736 736 kunitconfig_paths=['mykunitconfig'], 737 737 kconfig_add=None, 738 738 arch='um', 739 739 cross_compile=None, 740 740 qemu_config_path=None, 741 741 extra_qemu_args=[]) 742 742 743 def test_config_kunitconfig(self): 743 def test_config_kunitconfig(self): 744 kunit.main(['config', '--kunit 744 kunit.main(['config', '--kunitconfig=mykunitconfig']) 745 # Just verify that we parsed a 745 # Just verify that we parsed and initialized it correctly here. 746 self.mock_linux_init.assert_ca 746 self.mock_linux_init.assert_called_once_with('.kunit', 747 747 kunitconfig_paths=['mykunitconfig'], 748 748 kconfig_add=None, 749 749 arch='um', 750 750 cross_compile=None, 751 751 qemu_config_path=None, 752 752 extra_qemu_args=[]) 753 753 754 def test_config_alltests(self): 754 def test_config_alltests(self): 755 kunit.main(['config', '--kunit 755 kunit.main(['config', '--kunitconfig=mykunitconfig', '--alltests']) 756 # Just verify that we parsed a 756 # Just verify that we parsed and initialized it correctly here. 757 self.mock_linux_init.assert_ca 757 self.mock_linux_init.assert_called_once_with('.kunit', 758 758 kunitconfig_paths=[kunit_kernel.ALL_TESTS_CONFIG_PATH, 'mykunitconfig'], 759 759 kconfig_add=None, 760 760 arch='um', 761 761 cross_compile=None, 762 762 qemu_config_path=None, 763 763 extra_qemu_args=[]) 764 764 765 765 766 @mock.patch.object(kunit_kernel, 'Linu 766 @mock.patch.object(kunit_kernel, 'LinuxSourceTree') 767 def test_run_multiple_kunitconfig(self 767 def test_run_multiple_kunitconfig(self, mock_linux_init): 768 mock_linux_init.return_value = 768 mock_linux_init.return_value = self.linux_source_mock 769 kunit.main(['run', '--kunitcon 769 kunit.main(['run', '--kunitconfig=mykunitconfig', '--kunitconfig=other']) 770 # Just verify that we parsed a 770 # Just verify that we parsed and initialized it correctly here. 771 mock_linux_init.assert_called_ 771 mock_linux_init.assert_called_once_with('.kunit', 772 772 kunitconfig_paths=['mykunitconfig', 'other'], 773 773 kconfig_add=None, 774 774 arch='um', 775 775 cross_compile=None, 776 776 qemu_config_path=None, 777 777 extra_qemu_args=[]) 778 778 779 def test_run_kconfig_add(self): 779 def test_run_kconfig_add(self): 780 kunit.main(['run', '--kconfig_ 780 kunit.main(['run', '--kconfig_add=CONFIG_KASAN=y', '--kconfig_add=CONFIG_KCSAN=y']) 781 # Just verify that we parsed a 781 # Just verify that we parsed and initialized it correctly here. 782 self.mock_linux_init.assert_ca 782 self.mock_linux_init.assert_called_once_with('.kunit', 783 783 kunitconfig_paths=[], 784 784 kconfig_add=['CONFIG_KASAN=y', 'CONFIG_KCSAN=y'], 785 785 arch='um', 786 786 cross_compile=None, 787 787 qemu_config_path=None, 788 788 extra_qemu_args=[]) 789 789 790 def test_run_qemu_args(self): 790 def test_run_qemu_args(self): 791 kunit.main(['run', '--arch=x86 791 kunit.main(['run', '--arch=x86_64', '--qemu_args', '-m 2048']) 792 # Just verify that we parsed a 792 # Just verify that we parsed and initialized it correctly here. 793 self.mock_linux_init.assert_ca 793 self.mock_linux_init.assert_called_once_with('.kunit', 794 794 kunitconfig_paths=[], 795 795 kconfig_add=None, 796 796 arch='x86_64', 797 797 cross_compile=None, 798 798 qemu_config_path=None, 799 799 extra_qemu_args=['-m', '2048']) 800 800 801 def test_run_kernel_args(self): 801 def test_run_kernel_args(self): 802 kunit.main(['run', '--kernel_a 802 kunit.main(['run', '--kernel_args=a=1', '--kernel_args=b=2']) 803 self.assertEqual(self.linux_so 803 self.assertEqual(self.linux_source_mock.build_reconfig.call_count, 1) 804 self.linux_source_mock.run_ker 804 self.linux_source_mock.run_kernel.assert_called_once_with( 805 args=['a=1','b=2'], buil 805 args=['a=1','b=2'], build_dir='.kunit', filter_glob='', filter='', filter_action=None, timeout=300) 806 self.print_mock.assert_any_cal 806 self.print_mock.assert_any_call(StrContains('Testing complete.')) 807 807 808 def test_list_tests(self): 808 def test_list_tests(self): 809 want = ['suite.test1', 'suite. 809 want = ['suite.test1', 'suite.test2', 'suite2.test1'] 810 self.linux_source_mock.run_ker 810 self.linux_source_mock.run_kernel.return_value = ['TAP version 14', 'init: random output'] + want 811 811 812 got = kunit._list_tests(self.l 812 got = kunit._list_tests(self.linux_source_mock, 813 kunit.Kun 813 kunit.KunitExecRequest(None, None, '.kunit', 300, 'suite*', '', None, None, 'suite', False, False)) 814 self.assertEqual(got, want) 814 self.assertEqual(got, want) 815 # Should respect the user's fi 815 # Should respect the user's filter glob when listing tests. 816 self.linux_source_mock.run_ker 816 self.linux_source_mock.run_kernel.assert_called_once_with( 817 args=['kunit.action=li 817 args=['kunit.action=list'], build_dir='.kunit', filter_glob='suite*', filter='', filter_action=None, timeout=300) 818 818 819 @mock.patch.object(kunit, '_list_tests 819 @mock.patch.object(kunit, '_list_tests') 820 def test_run_isolated_by_suite(self, m 820 def test_run_isolated_by_suite(self, mock_tests): 821 mock_tests.return_value = ['su 821 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1'] 822 kunit.main(['exec', '--run_iso 822 kunit.main(['exec', '--run_isolated=suite', 'suite*.test*']) 823 823 824 # Should respect the user's fi 824 # Should respect the user's filter glob when listing tests. 825 mock_tests.assert_called_once_ 825 mock_tests.assert_called_once_with(mock.ANY, 826 kunit.Kun 826 kunit.KunitExecRequest(None, None, '.kunit', 300, 'suite*.test*', '', None, None, 'suite', False, False)) 827 self.linux_source_mock.run_ker 827 self.linux_source_mock.run_kernel.assert_has_calls([ 828 mock.call(args=None, b 828 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test*', filter='', filter_action=None, timeout=300), 829 mock.call(args=None, b 829 mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test*', filter='', filter_action=None, timeout=300), 830 ]) 830 ]) 831 831 832 @mock.patch.object(kunit, '_list_tests 832 @mock.patch.object(kunit, '_list_tests') 833 def test_run_isolated_by_test(self, mo 833 def test_run_isolated_by_test(self, mock_tests): 834 mock_tests.return_value = ['su 834 mock_tests.return_value = ['suite.test1', 'suite.test2', 'suite2.test1'] 835 kunit.main(['exec', '--run_iso 835 kunit.main(['exec', '--run_isolated=test', 'suite*']) 836 836 837 # Should respect the user's fi 837 # Should respect the user's filter glob when listing tests. 838 mock_tests.assert_called_once_ 838 mock_tests.assert_called_once_with(mock.ANY, 839 kunit.Kun 839 kunit.KunitExecRequest(None, None, '.kunit', 300, 'suite*', '', None, None, 'test', False, False)) 840 self.linux_source_mock.run_ker 840 self.linux_source_mock.run_kernel.assert_has_calls([ 841 mock.call(args=None, b 841 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test1', filter='', filter_action=None, timeout=300), 842 mock.call(args=None, b 842 mock.call(args=None, build_dir='.kunit', filter_glob='suite.test2', filter='', filter_action=None, timeout=300), 843 mock.call(args=None, b 843 mock.call(args=None, build_dir='.kunit', filter_glob='suite2.test1', filter='', filter_action=None, timeout=300), 844 ]) 844 ]) 845 845 846 if __name__ == '__main__': 846 if __name__ == '__main__': 847 unittest.main() 847 unittest.main()
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.