blob: 7fe9a90dfd3969ce609f93736e5f623c608379ba [file] [log] [blame]
Simon Glass2939e892025-01-20 14:25:31 -07001# SPDX-License-Identifier: GPL-2.0
2# Copyright 2024 Google LLC
3
4import pytest
5import re
6
7# List of test suites we expect to find with 'ut info' and 'ut all'
8EXPECTED_SUITES = [
9 'addrmap', 'bdinfo', 'bloblist', 'bootm', 'bootstd',
Simon Glass04e76d52025-02-07 11:30:39 -070010 'cmd', 'common', 'dm', 'env', 'exit', 'fdt_overlay',
Simon Glass7d4ae012025-01-20 14:25:56 -070011 'fdt', 'font', 'hush', 'lib',
Simon Glass2939e892025-01-20 14:25:31 -070012 'loadm', 'log', 'mbr', 'measurement', 'mem',
Simon Glass04e76d52025-02-07 11:30:39 -070013 'pci_mps', 'setexpr', 'upl',
Simon Glass2939e892025-01-20 14:25:31 -070014 ]
15
16
17# Set this to True to aid debugging of tests
18DEBUG_ME = False
19
20
Simon Glass32701112025-02-09 09:07:17 -070021def collect_info(ubman, output):
Simon Glass2939e892025-01-20 14:25:31 -070022 """Process the output from 'ut all'
23
24 Args:
Simon Glass32701112025-02-09 09:07:17 -070025 ubman: U-Boot console object
Simon Glass2939e892025-01-20 14:25:31 -070026 output: Output from running 'ut all'
27
28 Returns:
29 tuple:
30 set: suite names that were found in output
31 set: test names that were found in output
32 dict: test count for each suite:
33 key: suite name
34 value: number of tests for the suite found in output
35 set: missing suites (compared to EXPECTED_SUITES)
36 set: extra suites (compared to EXPECTED_SUITES)
37 """
38 suites = set()
39 tests = set()
40 cur_suite = None
41 test_count = None
42 exp_test_count = {}
43
44 # Collect suites{}
45 for line in output.splitlines():
46 line = line.rstrip()
47 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -070048 ubman.log.info(f'line: {line}')
Simon Glass2939e892025-01-20 14:25:31 -070049 m = re.search('----Running ([^ ]*) tests----', line)
50 if m:
51 if DEBUG_ME and cur_suite and cur_suite != 'info':
Simon Glass32701112025-02-09 09:07:17 -070052 ubman.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}')
Simon Glass2939e892025-01-20 14:25:31 -070053
54 cur_suite = m.group(1)
55 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -070056 ubman.log.info(f'cur_suite: {cur_suite}')
Simon Glass2939e892025-01-20 14:25:31 -070057 suites.add(cur_suite)
58
59 test_count = 0
60 m = re.match(rf'Running (\d+) {cur_suite} tests', line)
61 if m:
62 exp_test_count[cur_suite] = int(m.group(1))
63 m = re.search(r'Test: (\w*): ([-a-z0-9_]*\.c)?( .*)?', line)
64 if m:
65 test_name = m.group(1)
66 msg = m.group(3)
67 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -070068 ubman.log.info(f"test_name {test_name} msg '{msg}'")
Simon Glass598a1a52025-02-07 11:30:37 -070069 full_name = f'{cur_suite}.{test_name}'
70 if msg == ' (flat tree)' and full_name not in tests:
71 tests.add(full_name)
Simon Glass2939e892025-01-20 14:25:31 -070072 test_count += 1
73 if not msg or 'skipped as it is manual' in msg:
Simon Glass598a1a52025-02-07 11:30:37 -070074 tests.add(full_name)
Simon Glass2939e892025-01-20 14:25:31 -070075 test_count += 1
76 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -070077 ubman.log.info(f'test_count {test_count}')
Simon Glass2939e892025-01-20 14:25:31 -070078 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -070079 ubman.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}')
80 ubman.log.info(f"Tests: {' '.join(sorted(list(tests)))}")
Simon Glass2939e892025-01-20 14:25:31 -070081
82 # Figure out what is missing, or extra
83 missing = set()
84 extra = set(suites)
85 for suite in EXPECTED_SUITES:
86 if suite in extra:
87 extra.remove(suite)
88 else:
89 missing.add(suite)
90
91 return suites, tests, exp_test_count, missing, extra
92
93
Simon Glass32701112025-02-09 09:07:17 -070094def process_ut_info(ubman, output):
Simon Glass2939e892025-01-20 14:25:31 -070095 """Process the output of the 'ut info' command
96
97 Args:
Simon Glass32701112025-02-09 09:07:17 -070098 ubman: U-Boot console object
Simon Glass2939e892025-01-20 14:25:31 -070099 output: Output from running 'ut all'
100
101 Returns:
102 tuple:
103 int: Number of suites reported
104 int: Number of tests reported
105 dict: test count for each suite:
106 key: suite name
107 value: number of tests reported for the suite
108
109 """
110 suite_count = None
111 total_test_count = None
112 test_count = {}
113 for line in output.splitlines():
114 line = line.rstrip()
115 if DEBUG_ME:
Simon Glass32701112025-02-09 09:07:17 -0700116 ubman.log.info(f'line: {line}')
Simon Glass2939e892025-01-20 14:25:31 -0700117 m = re.match(r'Test suites: (.*)', line)
118 if m:
119 suite_count = int(m.group(1))
120 m = re.match(r'Total tests: (.*)', line)
121 if m:
122 total_test_count = int(m.group(1))
123 m = re.match(r' *([0-9?]*) (\w*)', line)
124 if m:
125 test_count[m.group(2)] = m.group(1)
126 return suite_count, total_test_count, test_count
127
128
129@pytest.mark.buildconfigspec('sandbox')
130@pytest.mark.notbuildconfigspec('sandbox_spl')
131@pytest.mark.notbuildconfigspec('sandbox64')
Simon Glass9dc6e292025-01-20 14:26:04 -0700132# This test is disabled since it fails; remove the leading 'x' to try it
Simon Glassddba5202025-02-09 09:07:14 -0700133def xtest_suite(ubman, u_boot_config):
Simon Glass2939e892025-01-20 14:25:31 -0700134 """Perform various checks on the unit tests, including:
135
136 - The number of suites matches that reported by the 'ut info'
137 - Where available, the number of tests is each suite matches that
Simon Glassda9925f2025-02-07 11:30:59 -0700138 reported by 'ut -s info'
Simon Glass2939e892025-01-20 14:25:31 -0700139 - The total number of tests adds up to the total that are actually run
140 with 'ut all'
141 - All suites are run with 'ut all'
142 - The expected set of suites is run (the list is hard-coded in this test)
143
144 """
Simon Glassa3ce1292025-01-20 14:25:57 -0700145 buildconfig = u_boot_config.buildconfig
Simon Glass32701112025-02-09 09:07:17 -0700146 with ubman.log.section('Run all unit tests'):
Simon Glass2939e892025-01-20 14:25:31 -0700147 # ut hush hush_test_simple_dollar prints "Unknown command" on purpose.
Simon Glassddba5202025-02-09 09:07:14 -0700148 with ubman.disable_check('unknown_command'):
Simon Glass32701112025-02-09 09:07:17 -0700149 output = ubman.run_command('ut all')
Simon Glass2939e892025-01-20 14:25:31 -0700150
151 # Process the output from the run
Simon Glass32701112025-02-09 09:07:17 -0700152 with ubman.log.section('Check output'):
153 suites, all_tests, exp_test_count, missing, extra = collect_info(ubman,
Simon Glass2939e892025-01-20 14:25:31 -0700154 output)
Simon Glass32701112025-02-09 09:07:17 -0700155 ubman.log.info(f'missing {missing}')
156 ubman.log.info(f'extra {extra}')
Simon Glass2939e892025-01-20 14:25:31 -0700157
Simon Glass7d4ae012025-01-20 14:25:56 -0700158 # Make sure we got a test count for each suite
Simon Glassa3ce1292025-01-20 14:25:57 -0700159 assert not (suites - exp_test_count.keys())
160
161 # Deal with missing suites
Simon Glass32701112025-02-09 09:07:17 -0700162 with ubman.log.section('Check missing suites'):
Simon Glassa3ce1292025-01-20 14:25:57 -0700163 if 'config_cmd_seama' not in buildconfig:
Simon Glass32701112025-02-09 09:07:17 -0700164 ubman.log.info("CMD_SEAMA not enabled: Ignoring suite 'seama'")
Simon Glassa3ce1292025-01-20 14:25:57 -0700165 missing.discard('seama')
Simon Glass2939e892025-01-20 14:25:31 -0700166
167 # Run 'ut info' and compare with the log results
Simon Glass32701112025-02-09 09:07:17 -0700168 with ubman.log.section('Check suite test-counts'):
169 output = ubman.run_command('ut -s info')
Simon Glass2939e892025-01-20 14:25:31 -0700170
Simon Glass32701112025-02-09 09:07:17 -0700171 suite_count, total_test_count, test_count = process_ut_info(ubman,
Simon Glass2939e892025-01-20 14:25:31 -0700172 output)
173
174 if missing or extra:
Simon Glass32701112025-02-09 09:07:17 -0700175 ubman.log.info(f"suites: {' '.join(sorted(list(suites)))}")
176 ubman.log.error(f'missing: {sorted(list(missing))}')
177 ubman.log.error(f'extra: {sorted(list(extra))}')
Simon Glass2939e892025-01-20 14:25:31 -0700178
179 assert not missing, f'Missing suites {missing}'
180 assert not extra, f'Extra suites {extra}'
181
Simon Glass32701112025-02-09 09:07:17 -0700182 ubman.log.info(str(exp_test_count))
Simon Glass2939e892025-01-20 14:25:31 -0700183 for suite in EXPECTED_SUITES:
Simon Glass7d4ae012025-01-20 14:25:56 -0700184 assert test_count[suite] in ['?', str(exp_test_count[suite])], \
185 f'suite {suite} expected {exp_test_count[suite]}'
Simon Glass2939e892025-01-20 14:25:31 -0700186
187 assert suite_count == len(EXPECTED_SUITES)
188 assert total_test_count == len(all_tests)
Simon Glass70737152025-02-07 11:30:57 -0700189
190 # Run three suites
Simon Glass32701112025-02-09 09:07:17 -0700191 with ubman.log.section('Check multiple suites'):
192 output = ubman.run_command('ut bloblist,setexpr,mem')
Simon Glassda9925f2025-02-07 11:30:59 -0700193 assert 'Suites run: 3' in output
194
195 # Run a particular test
Simon Glass32701112025-02-09 09:07:17 -0700196 with ubman.log.section('Check single test'):
197 output = ubman.run_command('ut bloblist reloc')
Simon Glassda9925f2025-02-07 11:30:59 -0700198 assert 'Test: reloc: bloblist.c' in output
199
200 # Run tests multiple times
Simon Glass32701112025-02-09 09:07:17 -0700201 with ubman.log.section('Check multiple runs'):
202 output = ubman.run_command('ut -r2 bloblist')
Simon Glassda9925f2025-02-07 11:30:59 -0700203 lines = output.splitlines()
204 run = len([line for line in lines if 'Test:' in line])
205 count = re.search(r'Tests run: (\d*)', lines[-1]).group(1)
206
207 assert run == 2 * int(count)