blob: e78ff35c9217cd9c8a028d0c501412b9fdc01783 [file] [log] [blame]
Gilles Peskine693611e2024-06-11 19:32:22 +02001#!/usr/bin/env python3
2"""Generate test data for configuration reporting.
3"""
4
5# Copyright The Mbed TLS Contributors
6# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7
8import re
9import sys
10from typing import Iterable, Iterator, List, Optional, Tuple
11
12import project_scripts # pylint: disable=unused-import
13import config
14from mbedtls_framework import test_case
15from mbedtls_framework import test_data_generation
16
17
18def single_option_case(setting: config.Setting, when_on: bool,
19 dependencies: List[str],
20 note: Optional[str]) -> test_case.TestCase:
21 """Construct a test case for a boolean setting.
22
23 This test case passes if the setting and its dependencies are enabled,
24 and is skipped otherwise.
25
26 * setting: the setting to be tested.
27 * when_on: True to test with the setting enabled, or False to test
28 with the setting disabled.
29 * dependencies: extra dependencies for the test case.
30 * note: a note to add after the option name in the test description.
31 This is generally a summary of dependencies, and is generally empty
32 if the given setting is only tested once.
33 """
34 base = setting.name if when_on else '!' + setting.name
35 tc = test_case.TestCase()
36 tc.set_function('pass')
37 description_suffix = ' (' + note + ')' if note else ''
38 tc.set_description('Config: ' + base + description_suffix)
39 tc.set_dependencies([base] + dependencies)
40 return tc
41
42
43def conditions_for_option(cfg: config.Config,
44 setting: config.Setting
45 ) -> Iterator[Tuple[List[str], str]]:
46 """Enumerate the conditions under which to test the given setting.
47
48 * cfg: all configuration options.
49 * setting: the setting to be tested.
50
51 Generate a stream of conditions, i.e. extra dependencies to test with
52 together with a human-readable explanation of each dependency. Some
53 typical cases:
54
55 * By default, generate a one-element stream with no extra dependencies.
56 * If the setting is ignored unless some other option is enabled, generate
57 a one-element stream with that other option as an extra dependency.
58 * If the setting is known to interact with some other option, generate
59 a stream with one element where this option is on and one where it's off.
60 * To skip the setting altogether, generate an empty stream.
61 """
62 name = setting.name
63 if name.endswith('_ALT') and not config.is_seamless_alt(name):
64 # We don't test alt implementations, except (most) platform alts
65 return
66 yield [], ''
67
68
69def enumerate_boolean_option_cases(cfg: config.Config
70 ) -> Iterable[test_case.TestCase]:
71 """Emit test cases for all boolean options."""
72 for name in sorted(cfg.settings.keys()):
73 setting = cfg.settings[name]
74 if not name.startswith('PSA_WANT_') and setting.value:
75 continue # non-boolean setting
76 for when_on in True, False:
77 for deps, note in conditions_for_option(cfg, setting):
78 yield single_option_case(setting, when_on, deps, note)
79
80
81
82class ConfigTestGenerator(test_data_generation.TestGenerator):
83 """Generate test cases for configuration reporting."""
84
85 def __init__(self, options):
86 self.mbedtls_config = config.ConfigFile()
87 self.targets['test_suite_config.mbedtls_boolean'] = \
88 lambda: enumerate_boolean_option_cases(self.mbedtls_config)
89 self.psa_config = config.ConfigFile('include/psa/crypto_config.h')
90 self.targets['test_suite_config.psa_boolean'] = \
91 lambda: enumerate_boolean_option_cases(self.psa_config)
92 super().__init__(options)
93
94
95if __name__ == '__main__':
96 test_data_generation.main(sys.argv[1:], __doc__, ConfigTestGenerator)