]> Git Repo - J-u-boot.git/blob - test/py/tests/test_suite.py
Merge tag 'u-boot-imx-master-20250127' of https://gitlab.denx.de/u-boot/custodians...
[J-u-boot.git] / test / py / tests / test_suite.py
1 # SPDX-License-Identifier: GPL-2.0
2 # Copyright 2024 Google LLC
3
4 import pytest
5 import re
6
7 # List of test suites we expect to find with 'ut info' and 'ut all'
8 EXPECTED_SUITES = [
9     'addrmap', 'bdinfo', 'bloblist', 'bootm', 'bootstd',
10     'cmd', 'common', 'dm', 'env', 'exit',
11     'fdt', 'font', 'hush', 'lib',
12     'loadm', 'log', 'mbr', 'measurement', 'mem',
13     'overlay', 'pci_mps', 'setexpr', 'upl',
14     ]
15
16
17 # Set this to True to aid debugging of tests
18 DEBUG_ME = False
19
20
21 def collect_info(cons, output):
22     """Process the output from 'ut all'
23
24     Args:
25         cons: U-Boot console object
26         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:
48             cons.log.info(f'line: {line}')
49         m = re.search('----Running ([^ ]*) tests----', line)
50         if m:
51             if DEBUG_ME and cur_suite and cur_suite != 'info':
52                 cons.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}')
53
54             cur_suite = m.group(1)
55             if DEBUG_ME:
56                 cons.log.info(f'cur_suite: {cur_suite}')
57             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:
68                 cons.log.info(f"test_name {test_name} msg '{msg}'")
69             if msg == ' (flat tree)' and test_name not in tests:
70                 tests.add(test_name)
71                 test_count += 1
72             if not msg or 'skipped as it is manual' in msg:
73                 tests.add(test_name)
74                 test_count += 1
75         if DEBUG_ME:
76             cons.log.info(f'test_count {test_count}')
77     if DEBUG_ME:
78         cons.log.info(f'suite: {cur_suite} expected {exp_test_count[cur_suite]} found {test_count}')
79         cons.log.info(f"Tests: {' '.join(sorted(list(tests)))}")
80
81     # Figure out what is missing, or extra
82     missing = set()
83     extra = set(suites)
84     for suite in EXPECTED_SUITES:
85         if suite in extra:
86             extra.remove(suite)
87         else:
88             missing.add(suite)
89
90     return suites, tests, exp_test_count, missing, extra
91
92
93 def process_ut_info(cons, output):
94     """Process the output of the 'ut info' command
95
96     Args:
97         cons: U-Boot console object
98         output: Output from running 'ut all'
99
100     Returns:
101         tuple:
102             int: Number of suites reported
103             int: Number of tests reported
104             dict: test count for each suite:
105                 key: suite name
106                 value: number of tests reported for the suite
107
108     """
109     suite_count = None
110     total_test_count = None
111     test_count = {}
112     for line in output.splitlines():
113         line = line.rstrip()
114         if DEBUG_ME:
115             cons.log.info(f'line: {line}')
116         m = re.match(r'Test suites: (.*)', line)
117         if m:
118             suite_count = int(m.group(1))
119         m = re.match(r'Total tests: (.*)', line)
120         if m:
121             total_test_count = int(m.group(1))
122         m = re.match(r'  *([0-9?]*)  (\w*)', line)
123         if m:
124             test_count[m.group(2)] = m.group(1)
125     return suite_count, total_test_count, test_count
126
127
128 @pytest.mark.buildconfigspec('sandbox')
129 @pytest.mark.notbuildconfigspec('sandbox_spl')
130 @pytest.mark.notbuildconfigspec('sandbox64')
131 # This test is disabled since it fails; remove the leading 'x' to try it
132 def xtest_suite(u_boot_console, u_boot_config):
133     """Perform various checks on the unit tests, including:
134
135        - The number of suites matches that reported by the 'ut info'
136        - Where available, the number of tests is each suite matches that
137          reported by 'ut info -s'
138        - The total number of tests adds up to the total that are actually run
139          with 'ut all'
140        - All suites are run with 'ut all'
141        - The expected set of suites is run (the list is hard-coded in this test)
142
143     """
144     cons = u_boot_console
145     buildconfig = u_boot_config.buildconfig
146     with cons.log.section('Run all unit tests'):
147         # ut hush hush_test_simple_dollar prints "Unknown command" on purpose.
148         with u_boot_console.disable_check('unknown_command'):
149             output = cons.run_command('ut all')
150
151     # Process the output from the run
152     with cons.log.section('Check output'):
153         suites, all_tests, exp_test_count, missing, extra = collect_info(cons,
154                                                                          output)
155     cons.log.info(f'missing {missing}')
156     cons.log.info(f'extra {extra}')
157
158     # Make sure we got a test count for each suite
159     assert not (suites - exp_test_count.keys())
160
161     # Deal with missing suites
162     with cons.log.section('Check missing suites'):
163         if 'config_cmd_seama' not in buildconfig:
164             cons.log.info("CMD_SEAMA not enabled: Ignoring suite 'seama'")
165             missing.discard('seama')
166
167     # Run 'ut info' and compare with the log results
168     with cons.log.section('Check suite test-counts'):
169         output = cons.run_command('ut info -s')
170
171         suite_count, total_test_count, test_count = process_ut_info(cons,
172                                                                     output)
173
174         if missing or extra:
175             cons.log.info(f"suites: {' '.join(sorted(list(suites)))}")
176             cons.log.error(f'missing: {sorted(list(missing))}')
177             cons.log.error(f'extra: {sorted(list(extra))}')
178
179         assert not missing, f'Missing suites {missing}'
180         assert not extra, f'Extra suites {extra}'
181
182         cons.log.info(str(exp_test_count))
183         for suite in EXPECTED_SUITES:
184             assert test_count[suite] in ['?', str(exp_test_count[suite])], \
185                 f'suite {suite} expected {exp_test_count[suite]}'
186
187         assert suite_count == len(EXPECTED_SUITES)
188         assert total_test_count == len(all_tests)
This page took 0.033714 seconds and 4 git commands to generate.