~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/kunit/kunit_tool_test.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /tools/testing/kunit/kunit_tool_test.py (Version linux-6.12-rc7) and /tools/testing/kunit/kunit_tool_test.py (Version linux-6.9.12)


  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()
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php