2 # SPDX-License-Identifier: GPL-2.0
4 # A collection of tests for tools/testing/kunit/kunit.py
6 # Copyright (C) 2019, Google LLC.
7 # Author: Brendan Higgins <brendanhiggins@google.com>
10 from unittest
import mock
12 import tempfile
, shutil
# Handling test_tmpdir
27 test_tmpdir
= tempfile
.mkdtemp()
30 shutil
.rmtree(test_tmpdir
)
32 def get_absolute_path(path
):
33 return os
.path
.join(os
.path
.dirname(__file__
), path
)
35 class KconfigTest(unittest
.TestCase
):
37 def test_is_subset_of(self
):
38 kconfig0
= kunit_config
.Kconfig()
39 self
.assertTrue(kconfig0
.is_subset_of(kconfig0
))
41 kconfig1
= kunit_config
.Kconfig()
42 kconfig1
.add_entry(kunit_config
.KconfigEntry('TEST', 'y'))
43 self
.assertTrue(kconfig1
.is_subset_of(kconfig1
))
44 self
.assertTrue(kconfig0
.is_subset_of(kconfig1
))
45 self
.assertFalse(kconfig1
.is_subset_of(kconfig0
))
47 def test_read_from_file(self
):
48 kconfig
= kunit_config
.Kconfig()
49 kconfig_path
= get_absolute_path(
50 'test_data/test_read_from_file.kconfig')
52 kconfig
.read_from_file(kconfig_path
)
54 expected_kconfig
= kunit_config
.Kconfig()
55 expected_kconfig
.add_entry(
56 kunit_config
.KconfigEntry('UML', 'y'))
57 expected_kconfig
.add_entry(
58 kunit_config
.KconfigEntry('MMU', 'y'))
59 expected_kconfig
.add_entry(
60 kunit_config
.KconfigEntry('TEST', 'y'))
61 expected_kconfig
.add_entry(
62 kunit_config
.KconfigEntry('EXAMPLE_TEST', 'y'))
63 expected_kconfig
.add_entry(
64 kunit_config
.KconfigEntry('MK8', 'n'))
66 self
.assertEqual(kconfig
.entries(), expected_kconfig
.entries())
68 def test_write_to_file(self
):
69 kconfig_path
= os
.path
.join(test_tmpdir
, '.config')
71 expected_kconfig
= kunit_config
.Kconfig()
72 expected_kconfig
.add_entry(
73 kunit_config
.KconfigEntry('UML', 'y'))
74 expected_kconfig
.add_entry(
75 kunit_config
.KconfigEntry('MMU', 'y'))
76 expected_kconfig
.add_entry(
77 kunit_config
.KconfigEntry('TEST', 'y'))
78 expected_kconfig
.add_entry(
79 kunit_config
.KconfigEntry('EXAMPLE_TEST', 'y'))
80 expected_kconfig
.add_entry(
81 kunit_config
.KconfigEntry('MK8', 'n'))
83 expected_kconfig
.write_to_file(kconfig_path
)
85 actual_kconfig
= kunit_config
.Kconfig()
86 actual_kconfig
.read_from_file(kconfig_path
)
88 self
.assertEqual(actual_kconfig
.entries(),
89 expected_kconfig
.entries())
91 class KUnitParserTest(unittest
.TestCase
):
93 def assertContains(self
, needle
, haystack
):
97 raise AssertionError('"' +
98 str(needle
) + '" not found in "' + str(haystack
) + '"!')
100 def test_output_isolated_correctly(self
):
101 log_path
= get_absolute_path(
102 'test_data/test_output_isolated_correctly.log')
103 file = open(log_path
)
104 result
= kunit_parser
.isolate_kunit_output(file.readlines())
105 self
.assertContains('TAP version 14', result
)
106 self
.assertContains(' # Subtest: example', result
)
107 self
.assertContains(' 1..2', result
)
108 self
.assertContains(' ok 1 - example_simple_test', result
)
109 self
.assertContains(' ok 2 - example_mock_test', result
)
110 self
.assertContains('ok 1 - example', result
)
113 def test_output_with_prefix_isolated_correctly(self
):
114 log_path
= get_absolute_path(
115 'test_data/test_pound_sign.log')
116 with
open(log_path
) as file:
117 result
= kunit_parser
.isolate_kunit_output(file.readlines())
118 self
.assertContains('TAP version 14', result
)
119 self
.assertContains(' # Subtest: kunit-resource-test', result
)
120 self
.assertContains(' 1..5', result
)
121 self
.assertContains(' ok 1 - kunit_resource_test_init_resources', result
)
122 self
.assertContains(' ok 2 - kunit_resource_test_alloc_resource', result
)
123 self
.assertContains(' ok 3 - kunit_resource_test_destroy_resource', result
)
124 self
.assertContains(' foo bar #', result
)
125 self
.assertContains(' ok 4 - kunit_resource_test_cleanup_resources', result
)
126 self
.assertContains(' ok 5 - kunit_resource_test_proper_free_ordering', result
)
127 self
.assertContains('ok 1 - kunit-resource-test', result
)
128 self
.assertContains(' foo bar # non-kunit output', result
)
129 self
.assertContains(' # Subtest: kunit-try-catch-test', result
)
130 self
.assertContains(' 1..2', result
)
131 self
.assertContains(' ok 1 - kunit_test_try_catch_successful_try_no_catch',
133 self
.assertContains(' ok 2 - kunit_test_try_catch_unsuccessful_try_does_catch',
135 self
.assertContains('ok 2 - kunit-try-catch-test', result
)
136 self
.assertContains(' # Subtest: string-stream-test', result
)
137 self
.assertContains(' 1..3', result
)
138 self
.assertContains(' ok 1 - string_stream_test_empty_on_creation', result
)
139 self
.assertContains(' ok 2 - string_stream_test_not_empty_after_add', result
)
140 self
.assertContains(' ok 3 - string_stream_test_get_string', result
)
141 self
.assertContains('ok 3 - string-stream-test', result
)
143 def test_parse_successful_test_log(self
):
144 all_passed_log
= get_absolute_path(
145 'test_data/test_is_test_passed-all_passed.log')
146 file = open(all_passed_log
)
147 result
= kunit_parser
.parse_run_tests(file.readlines())
149 kunit_parser
.TestStatus
.SUCCESS
,
153 def test_parse_failed_test_log(self
):
154 failed_log
= get_absolute_path(
155 'test_data/test_is_test_passed-failure.log')
156 file = open(failed_log
)
157 result
= kunit_parser
.parse_run_tests(file.readlines())
159 kunit_parser
.TestStatus
.FAILURE
,
163 def test_no_tests(self
):
164 empty_log
= get_absolute_path(
165 'test_data/test_is_test_passed-no_tests_run.log')
166 file = open(empty_log
)
167 result
= kunit_parser
.parse_run_tests(
168 kunit_parser
.isolate_kunit_output(file.readlines()))
169 self
.assertEqual(0, len(result
.suites
))
171 kunit_parser
.TestStatus
.NO_TESTS
,
175 def test_no_kunit_output(self
):
176 crash_log
= get_absolute_path(
177 'test_data/test_insufficient_memory.log')
178 file = open(crash_log
)
179 print_mock
= mock
.patch('builtins.print').start()
180 result
= kunit_parser
.parse_run_tests(
181 kunit_parser
.isolate_kunit_output(file.readlines()))
182 print_mock
.assert_any_call(StrContains('no tests run!'))
186 def test_crashed_test(self
):
187 crashed_log
= get_absolute_path(
188 'test_data/test_is_test_passed-crash.log')
189 file = open(crashed_log
)
190 result
= kunit_parser
.parse_run_tests(file.readlines())
192 kunit_parser
.TestStatus
.TEST_CRASHED
,
196 def test_ignores_prefix_printk_time(self
):
197 prefix_log
= get_absolute_path(
198 'test_data/test_config_printk_time.log')
199 with
open(prefix_log
) as file:
200 result
= kunit_parser
.parse_run_tests(file.readlines())
202 kunit_parser
.TestStatus
.SUCCESS
,
204 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
206 def test_ignores_multiple_prefixes(self
):
207 prefix_log
= get_absolute_path(
208 'test_data/test_multiple_prefixes.log')
209 with
open(prefix_log
) as file:
210 result
= kunit_parser
.parse_run_tests(file.readlines())
212 kunit_parser
.TestStatus
.SUCCESS
,
214 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
216 def test_prefix_mixed_kernel_output(self
):
217 mixed_prefix_log
= get_absolute_path(
218 'test_data/test_interrupted_tap_output.log')
219 with
open(mixed_prefix_log
) as file:
220 result
= kunit_parser
.parse_run_tests(file.readlines())
222 kunit_parser
.TestStatus
.SUCCESS
,
224 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
226 def test_prefix_poundsign(self
):
227 pound_log
= get_absolute_path('test_data/test_pound_sign.log')
228 with
open(pound_log
) as file:
229 result
= kunit_parser
.parse_run_tests(file.readlines())
231 kunit_parser
.TestStatus
.SUCCESS
,
233 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
235 def test_kernel_panic_end(self
):
236 panic_log
= get_absolute_path('test_data/test_kernel_panic_interrupt.log')
237 with
open(panic_log
) as file:
238 result
= kunit_parser
.parse_run_tests(file.readlines())
240 kunit_parser
.TestStatus
.TEST_CRASHED
,
242 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
244 def test_pound_no_prefix(self
):
245 pound_log
= get_absolute_path('test_data/test_pound_no_prefix.log')
246 with
open(pound_log
) as file:
247 result
= kunit_parser
.parse_run_tests(file.readlines())
249 kunit_parser
.TestStatus
.SUCCESS
,
251 self
.assertEqual('kunit-resource-test', result
.suites
[0].name
)
253 class KUnitJsonTest(unittest
.TestCase
):
255 def _json_for(self
, log_file
):
256 with(open(get_absolute_path(log_file
))) as file:
257 test_result
= kunit_parser
.parse_run_tests(file)
258 json_obj
= kunit_json
.get_json_result(
259 test_result
=test_result
,
260 def_config
='kunit_defconfig',
263 return json
.loads(json_obj
)
265 def test_failed_test_json(self
):
266 result
= self
._json
_for
(
267 'test_data/test_is_test_passed-failure.log')
269 {'name': 'example_simple_test', 'status': 'FAIL'},
270 result
["sub_groups"][1]["test_cases"][0])
272 def test_crashed_test_json(self
):
273 result
= self
._json
_for
(
274 'test_data/test_is_test_passed-crash.log')
276 {'name': 'example_simple_test', 'status': 'ERROR'},
277 result
["sub_groups"][1]["test_cases"][0])
279 def test_no_tests_json(self
):
280 result
= self
._json
_for
(
281 'test_data/test_is_test_passed-no_tests_run.log')
282 self
.assertEqual(0, len(result
['sub_groups']))
284 class StrContains(str):
285 def __eq__(self
, other
):
288 class KUnitMainTest(unittest
.TestCase
):
290 path
= get_absolute_path('test_data/test_is_test_passed-all_passed.log')
292 all_passed_log
= file.readlines()
293 self
.print_patch
= mock
.patch('builtins.print')
294 self
.print_mock
= self
.print_patch
.start()
295 self
.linux_source_mock
= mock
.Mock()
296 self
.linux_source_mock
.build_reconfig
= mock
.Mock(return_value
=True)
297 self
.linux_source_mock
.build_um_kernel
= mock
.Mock(return_value
=True)
298 self
.linux_source_mock
.run_kernel
= mock
.Mock(return_value
=all_passed_log
)
301 self
.print_patch
.stop()
304 def test_config_passes_args_pass(self
):
305 kunit
.main(['config', '--build_dir=.kunit'], self
.linux_source_mock
)
306 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
307 assert self
.linux_source_mock
.run_kernel
.call_count
== 0
309 def test_build_passes_args_pass(self
):
310 kunit
.main(['build'], self
.linux_source_mock
)
311 assert self
.linux_source_mock
.build_reconfig
.call_count
== 0
312 self
.linux_source_mock
.build_um_kernel
.assert_called_once_with(False, 8, '.kunit', None)
313 assert self
.linux_source_mock
.run_kernel
.call_count
== 0
315 def test_exec_passes_args_pass(self
):
316 kunit
.main(['exec'], self
.linux_source_mock
)
317 assert self
.linux_source_mock
.build_reconfig
.call_count
== 0
318 assert self
.linux_source_mock
.run_kernel
.call_count
== 1
319 self
.linux_source_mock
.run_kernel
.assert_called_once_with(build_dir
='.kunit', timeout
=300)
320 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
322 def test_run_passes_args_pass(self
):
323 kunit
.main(['run'], self
.linux_source_mock
)
324 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
325 assert self
.linux_source_mock
.run_kernel
.call_count
== 1
326 self
.linux_source_mock
.run_kernel
.assert_called_once_with(
327 build_dir
='.kunit', timeout
=300)
328 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
330 def test_exec_passes_args_fail(self
):
331 self
.linux_source_mock
.run_kernel
= mock
.Mock(return_value
=[])
332 with self
.assertRaises(SystemExit) as e
:
333 kunit
.main(['exec'], self
.linux_source_mock
)
334 assert type(e
.exception
) == SystemExit
335 assert e
.exception
.code
== 1
337 def test_run_passes_args_fail(self
):
338 self
.linux_source_mock
.run_kernel
= mock
.Mock(return_value
=[])
339 with self
.assertRaises(SystemExit) as e
:
340 kunit
.main(['run'], self
.linux_source_mock
)
341 assert type(e
.exception
) == SystemExit
342 assert e
.exception
.code
== 1
343 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
344 assert self
.linux_source_mock
.run_kernel
.call_count
== 1
345 self
.print_mock
.assert_any_call(StrContains(' 0 tests run'))
347 def test_exec_raw_output(self
):
348 self
.linux_source_mock
.run_kernel
= mock
.Mock(return_value
=[])
349 kunit
.main(['exec', '--raw_output'], self
.linux_source_mock
)
350 assert self
.linux_source_mock
.run_kernel
.call_count
== 1
351 for kall
in self
.print_mock
.call_args_list
:
352 assert kall
!= mock
.call(StrContains('Testing complete.'))
353 assert kall
!= mock
.call(StrContains(' 0 tests run'))
355 def test_run_raw_output(self
):
356 self
.linux_source_mock
.run_kernel
= mock
.Mock(return_value
=[])
357 kunit
.main(['run', '--raw_output'], self
.linux_source_mock
)
358 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
359 assert self
.linux_source_mock
.run_kernel
.call_count
== 1
360 for kall
in self
.print_mock
.call_args_list
:
361 assert kall
!= mock
.call(StrContains('Testing complete.'))
362 assert kall
!= mock
.call(StrContains(' 0 tests run'))
364 def test_exec_timeout(self
):
366 kunit
.main(['exec', '--timeout', str(timeout
)], self
.linux_source_mock
)
367 self
.linux_source_mock
.run_kernel
.assert_called_once_with(build_dir
='.kunit', timeout
=timeout
)
368 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
370 def test_run_timeout(self
):
372 kunit
.main(['run', '--timeout', str(timeout
)], self
.linux_source_mock
)
373 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
374 self
.linux_source_mock
.run_kernel
.assert_called_once_with(
375 build_dir
='.kunit', timeout
=timeout
)
376 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
378 def test_run_builddir(self
):
380 kunit
.main(['run', '--build_dir=.kunit'], self
.linux_source_mock
)
381 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
382 self
.linux_source_mock
.run_kernel
.assert_called_once_with(
383 build_dir
=build_dir
, timeout
=300)
384 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
386 def test_config_builddir(self
):
388 kunit
.main(['config', '--build_dir', build_dir
], self
.linux_source_mock
)
389 assert self
.linux_source_mock
.build_reconfig
.call_count
== 1
391 def test_build_builddir(self
):
393 kunit
.main(['build', '--build_dir', build_dir
], self
.linux_source_mock
)
394 self
.linux_source_mock
.build_um_kernel
.assert_called_once_with(False, 8, build_dir
, None)
396 def test_exec_builddir(self
):
398 kunit
.main(['exec', '--build_dir', build_dir
], self
.linux_source_mock
)
399 self
.linux_source_mock
.run_kernel
.assert_called_once_with(build_dir
=build_dir
, timeout
=300)
400 self
.print_mock
.assert_any_call(StrContains('Testing complete.'))
402 if __name__
== '__main__':