diff options
| author | Rosen Penev <rosenp@gmail.com> | 2026-09-27 13:35:01 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-10-01 11:04:53 +0200 |
| commit | 8167c1f071426706c233e93ecfd13aba7d5c06c8 (patch) | |
| tree | 2c0cd5f5e1cc35eadee98d49fe034f96a88856ce /scripts/kconfig/tests | |
| download | linux-stable-8167c1f071426706c233e93ecfd13aba7d5c06c8.tar.gz linux-stable-8167c1f071426706c233e93ecfd13aba7d5c06c8.zip | |
tty: serial: mpc52xx_uart: move static declarations up.grafted
Avoid a compilation error so that they're not used before being
declared.
Fixes: 4d105880666a ("tty: serial: mpc52xx_uart: add bounds check for psc_num array index")
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202609260356.tJWbd1WU-lkp@intel.com/
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Link: https://patch.msgid.link/20260927203501.14105-1-rosenp@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'scripts/kconfig/tests')
80 files changed, 1516 insertions, 0 deletions
diff --git a/scripts/kconfig/tests/auto_submenu/Kconfig b/scripts/kconfig/tests/auto_submenu/Kconfig new file mode 100644 index 000000000..b20761edc --- /dev/null +++ b/scripts/kconfig/tests/auto_submenu/Kconfig @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 + +config A + bool "A" + default y + +config A0 + bool "A0" + depends on A + default y + help + This depends on A, so should be a submenu of A. + +config A0_0 + bool "A1_0" + depends on A0 + help + Submenus are created recursively. + This should be a submenu of A0. + +config A1 + bool "A1" + depends on A + default y + help + This should line up with A0. + +choice + prompt "choice" + depends on A1 + help + Choice should become a submenu as well. + +config A1_0 + bool "A1_0" + +config A1_1 + bool "A1_1" + +endchoice + +config B + bool "B" + help + This is independent of A. + +config C + bool "C" + depends on A + help + This depends on A, but not a consecutive item, so can/should not + be a submenu. diff --git a/scripts/kconfig/tests/auto_submenu/__init__.py b/scripts/kconfig/tests/auto_submenu/__init__.py new file mode 100644 index 000000000..25abd927f --- /dev/null +++ b/scripts/kconfig/tests/auto_submenu/__init__.py @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Create submenu for symbols that depend on the preceding one. + +If a symbols has dependency on the preceding symbol, the menu entry +should become the submenu of the preceding one, and displayed with +deeper indentation. +""" + + +def test(conf): + assert conf.oldaskconfig() == 0 + assert conf.stdout_contains('expected_stdout') diff --git a/scripts/kconfig/tests/auto_submenu/expected_stdout b/scripts/kconfig/tests/auto_submenu/expected_stdout new file mode 100644 index 000000000..bf5236f39 --- /dev/null +++ b/scripts/kconfig/tests/auto_submenu/expected_stdout @@ -0,0 +1,10 @@ +A (A) [Y/n/?] (NEW) + A0 (A0) [Y/n/?] (NEW) + A1_0 (A0_0) [N/y/?] (NEW) + A1 (A1) [Y/n/?] (NEW) + choice + > 1. A1_0 (A1_0) (NEW) + 2. A1_1 (A1_1) (NEW) + choice[1-2?]: +B (B) [N/y/?] (NEW) +C (C) [N/y/?] (NEW) diff --git a/scripts/kconfig/tests/choice/Kconfig b/scripts/kconfig/tests/choice/Kconfig new file mode 100644 index 000000000..cd252579a --- /dev/null +++ b/scripts/kconfig/tests/choice/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 + +choice + prompt "boolean choice" + default BOOL_CHOICE1 + +config BOOL_CHOICE0 + bool "choice 0" + +config BOOL_CHOICE1 + bool "choice 1" + +endchoice diff --git a/scripts/kconfig/tests/choice/__init__.py b/scripts/kconfig/tests/choice/__init__.py new file mode 100644 index 000000000..0fc7bf9b5 --- /dev/null +++ b/scripts/kconfig/tests/choice/__init__.py @@ -0,0 +1,29 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Basic choice tests. +""" + + +def test_oldask0(conf): + assert conf.oldaskconfig() == 0 + assert conf.stdout_contains('oldask0_expected_stdout') + + +def test_allyes(conf): + assert conf.allyesconfig() == 0 + assert conf.config_contains('allyes_expected_config') + + +def test_allmod(conf): + assert conf.allmodconfig() == 0 + assert conf.config_contains('allmod_expected_config') + + +def test_allno(conf): + assert conf.allnoconfig() == 0 + assert conf.config_contains('allno_expected_config') + + +def test_alldef(conf): + assert conf.alldefconfig() == 0 + assert conf.config_contains('alldef_expected_config') diff --git a/scripts/kconfig/tests/choice/alldef_expected_config b/scripts/kconfig/tests/choice/alldef_expected_config new file mode 100644 index 000000000..b359a2e64 --- /dev/null +++ b/scripts/kconfig/tests/choice/alldef_expected_config @@ -0,0 +1,2 @@ +# CONFIG_BOOL_CHOICE0 is not set +CONFIG_BOOL_CHOICE1=y diff --git a/scripts/kconfig/tests/choice/allmod_expected_config b/scripts/kconfig/tests/choice/allmod_expected_config new file mode 100644 index 000000000..b359a2e64 --- /dev/null +++ b/scripts/kconfig/tests/choice/allmod_expected_config @@ -0,0 +1,2 @@ +# CONFIG_BOOL_CHOICE0 is not set +CONFIG_BOOL_CHOICE1=y diff --git a/scripts/kconfig/tests/choice/allno_expected_config b/scripts/kconfig/tests/choice/allno_expected_config new file mode 100644 index 000000000..b359a2e64 --- /dev/null +++ b/scripts/kconfig/tests/choice/allno_expected_config @@ -0,0 +1,2 @@ +# CONFIG_BOOL_CHOICE0 is not set +CONFIG_BOOL_CHOICE1=y diff --git a/scripts/kconfig/tests/choice/allyes_expected_config b/scripts/kconfig/tests/choice/allyes_expected_config new file mode 100644 index 000000000..b359a2e64 --- /dev/null +++ b/scripts/kconfig/tests/choice/allyes_expected_config @@ -0,0 +1,2 @@ +# CONFIG_BOOL_CHOICE0 is not set +CONFIG_BOOL_CHOICE1=y diff --git a/scripts/kconfig/tests/choice/oldask0_expected_stdout b/scripts/kconfig/tests/choice/oldask0_expected_stdout new file mode 100644 index 000000000..80ec34c61 --- /dev/null +++ b/scripts/kconfig/tests/choice/oldask0_expected_stdout @@ -0,0 +1,4 @@ +boolean choice + 1. choice 0 (BOOL_CHOICE0) (NEW) +> 2. choice 1 (BOOL_CHOICE1) (NEW) +choice[1-2?]: diff --git a/scripts/kconfig/tests/choice_randomize/Kconfig b/scripts/kconfig/tests/choice_randomize/Kconfig new file mode 100644 index 000000000..93a1699ce --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize/Kconfig @@ -0,0 +1,22 @@ +choice + prompt "choose A or B" + +config A + bool "A" + +config B + bool "B" + +endchoice + +choice + prompt "choose X or Y" + depends on B + +config X + bool "X" + +config Y + bool "Y" + +endchoice diff --git a/scripts/kconfig/tests/choice_randomize/__init__.py b/scripts/kconfig/tests/choice_randomize/__init__.py new file mode 100644 index 000000000..d380045be --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize/__init__.py @@ -0,0 +1,34 @@ +# SPDX-License-Identifier: GPL-2.0-only +""" +Randomize all dependent choices + +This is a somewhat tricky case for randconfig; the visibility of one choice is +determined by a member of another choice. Randconfig should be able to generate +all possible patterns. +""" + + +def test(conf): + + expected0 = False + expected1 = False + expected2 = False + + for i in range(100): + assert conf.randconfig(seed=i) == 0 + + if conf.config_matches('expected_config0'): + expected0 = True + elif conf.config_matches('expected_config1'): + expected1 = True + elif conf.config_matches('expected_config2'): + expected2 = True + else: + assert False + + if expected0 and expected1 and expected2: + break + + assert expected0 + assert expected1 + assert expected2 diff --git a/scripts/kconfig/tests/choice_randomize/expected_config0 b/scripts/kconfig/tests/choice_randomize/expected_config0 new file mode 100644 index 000000000..f69227323 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize/expected_config0 @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_A=y +# CONFIG_B is not set diff --git a/scripts/kconfig/tests/choice_randomize/expected_config1 b/scripts/kconfig/tests/choice_randomize/expected_config1 new file mode 100644 index 000000000..bf83784c9 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize/expected_config1 @@ -0,0 +1,8 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_A is not set +CONFIG_B=y +CONFIG_X=y +# CONFIG_Y is not set diff --git a/scripts/kconfig/tests/choice_randomize/expected_config2 b/scripts/kconfig/tests/choice_randomize/expected_config2 new file mode 100644 index 000000000..38f93a8f3 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize/expected_config2 @@ -0,0 +1,8 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_A is not set +CONFIG_B=y +# CONFIG_X is not set +CONFIG_Y=y diff --git a/scripts/kconfig/tests/choice_randomize2/Kconfig b/scripts/kconfig/tests/choice_randomize2/Kconfig new file mode 100644 index 000000000..530cf2ef7 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize2/Kconfig @@ -0,0 +1,32 @@ +choice + prompt "This is always invisible" + depends on n + +config DUMMY + bool "DUMMY" + +endchoice + +choice + prompt "Choose A or B" + +config A + bool "A" + +config B + bool "B" + +endchoice + +config FOO + bool "FOO" + depends on A + +choice + prompt "Choose X" + depends on FOO + +config X + bool "X" + +endchoice diff --git a/scripts/kconfig/tests/choice_randomize2/__init__.py b/scripts/kconfig/tests/choice_randomize2/__init__.py new file mode 100644 index 000000000..2066757b8 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize2/__init__.py @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-only +""" +Randomize choices with correct dependencies + +When shuffling a choice may potentially disrupt certain dependencies, symbol +values must be recalculated. + +Related Linux commits: + - c8fb7d7e48d11520ad24808cfce7afb7b9c9f798 +""" + + +def test(conf): + for i in range(20): + assert conf.randconfig(seed=i) == 0 + assert (conf.config_matches('expected_config0') or + conf.config_matches('expected_config1') or + conf.config_matches('expected_config2')) diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config0 b/scripts/kconfig/tests/choice_randomize2/expected_config0 new file mode 100644 index 000000000..5c9e1c172 --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize2/expected_config0 @@ -0,0 +1,8 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_A=y +# CONFIG_B is not set +CONFIG_FOO=y +CONFIG_X=y diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config1 b/scripts/kconfig/tests/choice_randomize2/expected_config1 new file mode 100644 index 000000000..5b975d91b --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize2/expected_config1 @@ -0,0 +1,7 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_A=y +# CONFIG_B is not set +# CONFIG_FOO is not set diff --git a/scripts/kconfig/tests/choice_randomize2/expected_config2 b/scripts/kconfig/tests/choice_randomize2/expected_config2 new file mode 100644 index 000000000..5a5ebb90d --- /dev/null +++ b/scripts/kconfig/tests/choice_randomize2/expected_config2 @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_A is not set +CONFIG_B=y diff --git a/scripts/kconfig/tests/conditional_dep/Kconfig b/scripts/kconfig/tests/conditional_dep/Kconfig new file mode 100644 index 000000000..2015dfbce --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/Kconfig @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0 +# Test Kconfig file for conditional dependencies. + +# Enable module support for tristate testing +config MODULES + bool "Enable loadable module support" + modules + default y + +config FOO + bool "FOO symbol" + +config BAR + bool "BAR symbol" + +config TEST_BASIC + bool "Test basic conditional dependency" + depends on FOO if BAR + default y + +config TEST_COMPLEX + bool "Test complex conditional dependency" + depends on (FOO && BAR) if (FOO || BAR) + default y + +config BAZ + tristate "BAZ symbol" + +config TEST_OPTIONAL + tristate "Test simple optional dependency" + depends on BAZ if BAZ + default y diff --git a/scripts/kconfig/tests/conditional_dep/__init__.py b/scripts/kconfig/tests/conditional_dep/__init__.py new file mode 100644 index 000000000..ab16df648 --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/__init__.py @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Correctly handle conditional dependencies. +""" + +def test(conf): + assert conf.oldconfig('test_config1') == 0 + assert conf.config_matches('expected_config1') + + assert conf.oldconfig('test_config2') == 0 + assert conf.config_matches('expected_config2') + + assert conf.oldconfig('test_config3') == 0 + assert conf.config_matches('expected_config3') diff --git a/scripts/kconfig/tests/conditional_dep/expected_config1 b/scripts/kconfig/tests/conditional_dep/expected_config1 new file mode 100644 index 000000000..826ed7f54 --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/expected_config1 @@ -0,0 +1,11 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_MODULES=y +CONFIG_FOO=y +CONFIG_BAR=y +CONFIG_TEST_BASIC=y +CONFIG_TEST_COMPLEX=y +CONFIG_BAZ=m +CONFIG_TEST_OPTIONAL=m diff --git a/scripts/kconfig/tests/conditional_dep/expected_config2 b/scripts/kconfig/tests/conditional_dep/expected_config2 new file mode 100644 index 000000000..10d2354f6 --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/expected_config2 @@ -0,0 +1,9 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_MODULES=y +# CONFIG_FOO is not set +CONFIG_BAR=y +CONFIG_BAZ=y +CONFIG_TEST_OPTIONAL=y diff --git a/scripts/kconfig/tests/conditional_dep/expected_config3 b/scripts/kconfig/tests/conditional_dep/expected_config3 new file mode 100644 index 000000000..b04fa6fdf --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/expected_config3 @@ -0,0 +1,11 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +CONFIG_MODULES=y +# CONFIG_FOO is not set +# CONFIG_BAR is not set +CONFIG_TEST_BASIC=y +CONFIG_TEST_COMPLEX=y +# CONFIG_BAZ is not set +CONFIG_TEST_OPTIONAL=y diff --git a/scripts/kconfig/tests/conditional_dep/test_config1 b/scripts/kconfig/tests/conditional_dep/test_config1 new file mode 100644 index 000000000..9b05f3ce8 --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/test_config1 @@ -0,0 +1,6 @@ +# Basic check that everything can be configured if selected. +CONFIG_FOO=y +CONFIG_BAR=y +CONFIG_BAZ=m +# Ensure that TEST_OPTIONAL=y with BAZ=m is converted to TEST_OPTIONAL=m +CONFIG_TEST_OPTIONAL=y diff --git a/scripts/kconfig/tests/conditional_dep/test_config2 b/scripts/kconfig/tests/conditional_dep/test_config2 new file mode 100644 index 000000000..5e66d230a --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/test_config2 @@ -0,0 +1,7 @@ +# If FOO is not selected, then TEST_BASIC should fail the conditional +# dependency since BAR is set. +# TEST_COMPLEX will fail dependency as it depends on both FOO and BAR +# if either of those is selected. +CONFIG_FOO=n +CONFIG_BAR=y +CONFIG_BAZ=y diff --git a/scripts/kconfig/tests/conditional_dep/test_config3 b/scripts/kconfig/tests/conditional_dep/test_config3 new file mode 100644 index 000000000..86304f3aa --- /dev/null +++ b/scripts/kconfig/tests/conditional_dep/test_config3 @@ -0,0 +1,6 @@ +# If FOO is not selected, but BAR is also not selected, then TEST_BASIC +# should pass since the dependency on FOO is conditional on BAR. +# TEST_COMPLEX should be also set since neither FOO nor BAR are selected +# so it has no dependencies. +CONFIG_FOO=n +CONFIG_BAR=n diff --git a/scripts/kconfig/tests/conftest.py b/scripts/kconfig/tests/conftest.py new file mode 100644 index 000000000..66f95e4ed --- /dev/null +++ b/scripts/kconfig/tests/conftest.py @@ -0,0 +1,318 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2018 Masahiro Yamada <yamada.masahiro@socionext.com> +# + +""" +Kconfig unit testing framework. + +This provides fixture functions commonly used from test files. +""" + +import os +import pytest +import shutil +import subprocess +import tempfile + +CONF_PATH = os.path.abspath(os.path.join('scripts', 'kconfig', 'conf')) + + +class Conf: + """Kconfig runner and result checker. + + This class provides methods to run text-based interface of Kconfig + (scripts/kconfig/conf) and retrieve the resulted configuration, + stdout, and stderr. It also provides methods to compare those + results with expectations. + """ + + def __init__(self, request): + """Create a new Conf instance. + + request: object to introspect the requesting test module + """ + # the directory of the test being run + self._test_dir = os.path.dirname(str(request.fspath)) + + # runners + def _run_conf(self, mode, dot_config=None, out_file='.config', + interactive=False, in_keys=None, extra_env={}, + silent=False): + """Run text-based Kconfig executable and save the result. + + mode: input mode option (--oldaskconfig, --defconfig=<file> etc.) + dot_config: .config file to use for configuration base + out_file: file name to contain the output config data + interactive: flag to specify the interactive mode + in_keys: key inputs for interactive modes + extra_env: additional environments + returncode: exit status of the Kconfig executable + """ + command = [CONF_PATH] + if silent: + command.append('-s') + command += [mode, 'Kconfig'] + + # Override 'srctree' environment to make the test as the top directory + extra_env['srctree'] = self._test_dir + + # Clear KCONFIG_DEFCONFIG_LIST to keep unit tests from being affected + # by the user's environment. + extra_env['KCONFIG_DEFCONFIG_LIST'] = '' + + # Run Kconfig in a temporary directory. + # This directory is automatically removed when done. + with tempfile.TemporaryDirectory() as temp_dir: + + # if .config is given, copy it to the working directory + if dot_config: + shutil.copyfile(os.path.join(self._test_dir, dot_config), + os.path.join(temp_dir, '.config')) + + ps = subprocess.Popen(command, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + cwd=temp_dir, + env=dict(os.environ, **extra_env)) + + # If input key sequence is given, feed it to stdin. + if in_keys: + ps.stdin.write(in_keys.encode('utf-8')) + + while ps.poll() is None: + # For interactive modes such as oldaskconfig, oldconfig, + # send 'Enter' key until the program finishes. + if interactive: + try: + ps.stdin.write(b'\n') + ps.stdin.flush() + except (BrokenPipeError, OSError): + # Process has exited, stop sending input + break + + # Close stdin gracefully + try: + ps.stdin.close() + except (BrokenPipeError, OSError): + # Ignore broken pipe on close + pass + + # Wait for process to complete + ps.wait() + + self.retcode = ps.returncode + self.stdout = ps.stdout.read().decode() + self.stderr = ps.stderr.read().decode() + + # Retrieve the resulted config data only when .config is supposed + # to exist. If the command fails, the .config does not exist. + # 'listnewconfig' does not produce .config in the first place. + if self.retcode == 0 and out_file: + with open(os.path.join(temp_dir, out_file)) as f: + self.config = f.read() + else: + self.config = None + + # Logging: + # Pytest captures the following information by default. In failure + # of tests, the captured log will be displayed. This will be useful to + # figure out what has happened. + + print("[command]\n{}\n".format(' '.join(command))) + + print("[retcode]\n{}\n".format(self.retcode)) + + print("[stdout]") + print(self.stdout) + + print("[stderr]") + print(self.stderr) + + if self.config is not None: + print("[output for '{}']".format(out_file)) + print(self.config) + + return self.retcode + + def oldaskconfig(self, dot_config=None, in_keys=None): + """Run oldaskconfig. + + dot_config: .config file to use for configuration base (optional) + in_key: key inputs (optional) + returncode: exit status of the Kconfig executable + """ + return self._run_conf('--oldaskconfig', dot_config=dot_config, + interactive=True, in_keys=in_keys) + + def oldconfig(self, dot_config=None, in_keys=None): + """Run oldconfig. + + dot_config: .config file to use for configuration base (optional) + in_key: key inputs (optional) + returncode: exit status of the Kconfig executable + """ + return self._run_conf('--oldconfig', dot_config=dot_config, + interactive=True, in_keys=in_keys) + + def olddefconfig(self, dot_config=None): + """Run olddefconfig. + + dot_config: .config file to use for configuration base (optional) + returncode: exit status of the Kconfig executable + """ + return self._run_conf('--olddefconfig', dot_config=dot_config) + + def defconfig(self, defconfig): + """Run defconfig. + + defconfig: defconfig file for input + returncode: exit status of the Kconfig executable + """ + defconfig_path = os.path.join(self._test_dir, defconfig) + return self._run_conf('--defconfig={}'.format(defconfig_path)) + + def _allconfig(self, mode, all_config, extra_env={}): + if all_config: + all_config_path = os.path.join(self._test_dir, all_config) + extra_env['KCONFIG_ALLCONFIG'] = all_config_path + + return self._run_conf('--{}config'.format(mode), extra_env=extra_env) + + def allyesconfig(self, all_config=None): + """Run allyesconfig. + + all_config: fragment config file for KCONFIG_ALLCONFIG (optional) + returncode: exit status of the Kconfig executable + """ + return self._allconfig('allyes', all_config) + + def allmodconfig(self, all_config=None): + """Run allmodconfig. + + all_config: fragment config file for KCONFIG_ALLCONFIG (optional) + returncode: exit status of the Kconfig executable + """ + return self._allconfig('allmod', all_config) + + def allnoconfig(self, all_config=None): + """Run allnoconfig. + + all_config: fragment config file for KCONFIG_ALLCONFIG (optional) + returncode: exit status of the Kconfig executable + """ + return self._allconfig('allno', all_config) + + def alldefconfig(self, all_config=None): + """Run alldefconfig. + + all_config: fragment config file for KCONFIG_ALLCONFIG (optional) + returncode: exit status of the Kconfig executable + """ + return self._allconfig('alldef', all_config) + + def randconfig(self, all_config=None, seed=None): + """Run randconfig. + + all_config: fragment config file for KCONFIG_ALLCONFIG (optional) + seed: the seed for randconfig (optional) + returncode: exit status of the Kconfig executable + """ + if seed is not None: + extra_env = {'KCONFIG_SEED': hex(seed)} + else: + extra_env = {} + + return self._allconfig('rand', all_config, extra_env=extra_env) + + def savedefconfig(self, dot_config): + """Run savedefconfig. + + dot_config: .config file for input + returncode: exit status of the Kconfig executable + """ + return self._run_conf('--savedefconfig', out_file='defconfig') + + def listnewconfig(self, dot_config=None): + """Run listnewconfig. + + dot_config: .config file to use for configuration base (optional) + returncode: exit status of the Kconfig executable + """ + return self._run_conf('--listnewconfig', dot_config=dot_config, + out_file=None) + + # checkers + def _read_and_compare(self, compare, expected): + """Compare the result with expectation. + + compare: function to compare the result with expectation + expected: file that contains the expected data + """ + with open(os.path.join(self._test_dir, expected)) as f: + expected_data = f.read() + return compare(self, expected_data) + + def _contains(self, attr, expected): + return self._read_and_compare( + lambda s, e: getattr(s, attr).find(e) >= 0, + expected) + + def _matches(self, attr, expected): + return self._read_and_compare(lambda s, e: getattr(s, attr) == e, + expected) + + def config_contains(self, expected): + """Check if resulted configuration contains expected data. + + expected: file that contains the expected data + returncode: True if result contains the expected data, False otherwise + """ + return self._contains('config', expected) + + def config_matches(self, expected): + """Check if resulted configuration exactly matches expected data. + + expected: file that contains the expected data + returncode: True if result matches the expected data, False otherwise + """ + return self._matches('config', expected) + + def stdout_contains(self, expected): + """Check if resulted stdout contains expected data. + + expected: file that contains the expected data + returncode: True if result contains the expected data, False otherwise + """ + return self._contains('stdout', expected) + + def stdout_matches(self, expected): + """Check if resulted stdout exactly matches expected data. + + expected: file that contains the expected data + returncode: True if result matches the expected data, False otherwise + """ + return self._matches('stdout', expected) + + def stderr_contains(self, expected): + """Check if resulted stderr contains expected data. + + expected: file that contains the expected data + returncode: True if result contains the expected data, False otherwise + """ + return self._contains('stderr', expected) + + def stderr_matches(self, expected): + """Check if resulted stderr exactly matches expected data. + + expected: file that contains the expected data + returncode: True if result matches the expected data, False otherwise + """ + return self._matches('stderr', expected) + + +@pytest.fixture(scope="module") +def conf(request): + """Create a Conf instance and provide it to test functions.""" + return Conf(request) diff --git a/scripts/kconfig/tests/err_recursive_dep/Kconfig b/scripts/kconfig/tests/err_recursive_dep/Kconfig new file mode 100644 index 000000000..ebdb3ffd8 --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_dep/Kconfig @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 + +# depends on itself + +config A + bool "A" + depends on A + +# select itself + +config B + bool + select B + +# depends on each other + +config C1 + bool "C1" + depends on C2 + +config C2 + bool "C2" + depends on C1 + +# depends on and select + +config D1 + bool "D1" + depends on D2 + select D2 + +config D2 + bool + +# depends on and imply + +config E1 + bool "E1" + depends on E2 + imply E2 + +config E2 + bool "E2" + +# property + +config F1 + bool "F1" + default F2 + +config F2 + bool "F2" + depends on F1 + +# menu + +menu "menu depending on its content" + depends on G + +config G + bool "G" + +endmenu diff --git a/scripts/kconfig/tests/err_recursive_dep/__init__.py b/scripts/kconfig/tests/err_recursive_dep/__init__.py new file mode 100644 index 000000000..5f3821b43 --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_dep/__init__.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Detect recursive dependency error. + +Recursive dependency should be treated as an error. +""" + +def test(conf): + assert conf.oldaskconfig() == 1 + assert conf.stderr_contains('expected_stderr') diff --git a/scripts/kconfig/tests/err_recursive_dep/expected_stderr b/scripts/kconfig/tests/err_recursive_dep/expected_stderr new file mode 100644 index 000000000..fc2e860af --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_dep/expected_stderr @@ -0,0 +1,38 @@ +error: recursive dependency detected! + symbol A depends on A +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol B is selected by B +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol C1 depends on C2 + symbol C2 depends on C1 +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol D1 depends on D2 + symbol D2 is selected by D1 +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol E1 depends on E2 + symbol E2 is implied by E1 +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol F1 default value contains F2 + symbol F2 depends on F1 +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" + +error: recursive dependency detected! + symbol G depends on G +For a resolution refer to Documentation/kbuild/kconfig-language.rst +subsection "Kconfig recursive dependency limitations" diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig b/scripts/kconfig/tests/err_recursive_inc/Kconfig new file mode 100644 index 000000000..c6f4adec7 --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +source "Kconfig.inc1" diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1 new file mode 100644 index 000000000..01cbf0d69 --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc1 @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-only + + + +source "Kconfig.inc2" diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2 new file mode 100644 index 000000000..82351075a --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc2 @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + + +source "Kconfig.inc3" diff --git a/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3 b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3 new file mode 100644 index 000000000..c6f4adec7 --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/Kconfig.inc3 @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0-only +source "Kconfig.inc1" diff --git a/scripts/kconfig/tests/err_recursive_inc/__init__.py b/scripts/kconfig/tests/err_recursive_inc/__init__.py new file mode 100644 index 000000000..27aa1895a --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/__init__.py @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Detect recursive inclusion error. + +If recursive inclusion is detected, it should fail with error messages. +""" + + +def test(conf): + assert conf.oldaskconfig() != 0 + assert conf.stderr_contains('expected_stderr') diff --git a/scripts/kconfig/tests/err_recursive_inc/expected_stderr b/scripts/kconfig/tests/err_recursive_inc/expected_stderr new file mode 100644 index 000000000..b070a31fd --- /dev/null +++ b/scripts/kconfig/tests/err_recursive_inc/expected_stderr @@ -0,0 +1,6 @@ +Recursive inclusion detected. +Inclusion path: + current file : Kconfig.inc1 + included from: Kconfig.inc3:2 + included from: Kconfig.inc2:4 + included from: Kconfig.inc1:5 diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig b/scripts/kconfig/tests/err_repeated_inc/Kconfig new file mode 100644 index 000000000..09a88fd29 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc1" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 new file mode 100644 index 000000000..495dc3831 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc1 @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc2" +source "Kconfig.inc3" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 new file mode 100644 index 000000000..2b630eec2 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc2 @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +source "Kconfig.inc3" diff --git a/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 new file mode 100644 index 000000000..a4e40e534 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/Kconfig.inc3 @@ -0,0 +1 @@ +# SPDX-License-Identifier: GPL-2.0-only diff --git a/scripts/kconfig/tests/err_repeated_inc/__init__.py b/scripts/kconfig/tests/err_repeated_inc/__init__.py new file mode 100644 index 000000000..129d740a8 --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/__init__.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Detect repeated inclusion error. + +If repeated inclusion is detected, it should fail with error message. +""" + +def test(conf): + assert conf.oldaskconfig() != 0 + assert conf.stderr_contains('expected_stderr') diff --git a/scripts/kconfig/tests/err_repeated_inc/expected_stderr b/scripts/kconfig/tests/err_repeated_inc/expected_stderr new file mode 100644 index 000000000..53071430e --- /dev/null +++ b/scripts/kconfig/tests/err_repeated_inc/expected_stderr @@ -0,0 +1,2 @@ +Kconfig.inc1:4: error: repeated inclusion of Kconfig.inc3 +Kconfig.inc2:3: note: location of first inclusion of Kconfig.inc3 diff --git a/scripts/kconfig/tests/err_transitional/Kconfig b/scripts/kconfig/tests/err_transitional/Kconfig new file mode 100644 index 000000000..a75ed3b2f --- /dev/null +++ b/scripts/kconfig/tests/err_transitional/Kconfig @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: GPL-2.0 +# Test that transitional symbols cannot have properties other than help + +config BAD_DEFAULT + bool + transitional + default y + help + This transitional symbol illegally has a default property. + +config BAD_PROMPT + bool + transitional + prompt "Bad prompt" + help + This transitional symbol illegally has a prompt. + +config BAD_SELECT + bool + transitional + select OTHER_SYMBOL + help + This transitional symbol illegally has a select. + +config BAD_IMPLY + bool + transitional + imply OTHER_SYMBOL + help + This transitional symbol illegally has an imply. + +config BAD_DEPENDS + bool + transitional + depends on OTHER_SYMBOL + help + This transitional symbol illegally has a depends. + +config BAD_RANGE + int + transitional + range 1 10 + help + This transitional symbol illegally has a range. + +config BAD_NO_TYPE + transitional + help + This transitional symbol illegally has no type specified. + +config OTHER_SYMBOL + bool diff --git a/scripts/kconfig/tests/err_transitional/__init__.py b/scripts/kconfig/tests/err_transitional/__init__.py new file mode 100644 index 000000000..7dffb5b08 --- /dev/null +++ b/scripts/kconfig/tests/err_transitional/__init__.py @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Test that transitional symbols with invalid properties are rejected. + +Transitional symbols can only have help sections. Any other properties +(default, select, depends, etc.) should cause a parser error. +""" + +def test(conf): + # This should fail with exit code 1 due to invalid transitional symbol + assert conf.olddefconfig() == 1 + + # Check that the error message is about transitional symbols + assert conf.stderr_contains('expected_stderr') diff --git a/scripts/kconfig/tests/err_transitional/expected_stderr b/scripts/kconfig/tests/err_transitional/expected_stderr new file mode 100644 index 000000000..b52db4f68 --- /dev/null +++ b/scripts/kconfig/tests/err_transitional/expected_stderr @@ -0,0 +1,7 @@ +Kconfig:46:warning: config symbol defined without type +Kconfig:7: error: transitional symbols can only have help sections +Kconfig:14: error: transitional symbols can only have help sections +Kconfig:21: error: transitional symbols can only have help sections +Kconfig:28: error: transitional symbols can only have help sections +Kconfig:32: error: transitional symbols can only have help sections +Kconfig:42: error: transitional symbols can only have help sections diff --git a/scripts/kconfig/tests/new_choice_with_dep/Kconfig b/scripts/kconfig/tests/new_choice_with_dep/Kconfig new file mode 100644 index 000000000..127731c04 --- /dev/null +++ b/scripts/kconfig/tests/new_choice_with_dep/Kconfig @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: GPL-2.0 + +config A + bool "A" + help + This is a new symbol. + +choice + prompt "Choice ?" + depends on A + help + "depends on A" has been newly added. + +config CHOICE_B + bool "Choice B" + +config CHOICE_C + bool "Choice C" + help + This is a new symbol, so should be asked. + +endchoice + +choice + prompt "Choice2 ?" + +config CHOICE_D + bool "Choice D" + +config CHOICE_E + bool "Choice E" + +config CHOICE_F + bool "Choice F" + depends on A + help + This is a new symbol, so should be asked. + +endchoice diff --git a/scripts/kconfig/tests/new_choice_with_dep/__init__.py b/scripts/kconfig/tests/new_choice_with_dep/__init__.py new file mode 100644 index 000000000..fe9d32253 --- /dev/null +++ b/scripts/kconfig/tests/new_choice_with_dep/__init__.py @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Ask new choice values when they become visible. + +If new choice values are added with new dependency, and they become +visible during user configuration, oldconfig should recognize them +as (NEW), and ask the user for choice. + +Related Linux commit: 5d09598d488f081e3be23f885ed65cbbe2d073b5 +""" + + +def test(conf): + assert conf.oldconfig('config', 'y') == 0 + assert conf.stdout_contains('expected_stdout') diff --git a/scripts/kconfig/tests/new_choice_with_dep/config b/scripts/kconfig/tests/new_choice_with_dep/config new file mode 100644 index 000000000..47ef95d56 --- /dev/null +++ b/scripts/kconfig/tests/new_choice_with_dep/config @@ -0,0 +1,3 @@ +CONFIG_CHOICE_B=y +# CONFIG_CHOICE_D is not set +CONFIG_CHOICE_E=y diff --git a/scripts/kconfig/tests/new_choice_with_dep/expected_stdout b/scripts/kconfig/tests/new_choice_with_dep/expected_stdout new file mode 100644 index 000000000..74dc0bcb2 --- /dev/null +++ b/scripts/kconfig/tests/new_choice_with_dep/expected_stdout @@ -0,0 +1,10 @@ +A (A) [N/y/?] (NEW) y + Choice ? + > 1. Choice B (CHOICE_B) + 2. Choice C (CHOICE_C) (NEW) + choice[1-2?]: +Choice2 ? + 1. Choice D (CHOICE_D) +> 2. Choice E (CHOICE_E) + 3. Choice F (CHOICE_F) (NEW) +choice[1-3?]: diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig new file mode 100644 index 000000000..4767aab6d --- /dev/null +++ b/scripts/kconfig/tests/no_write_if_dep_unmet/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 + +config A + bool "A" + +choice + prompt "Choice ?" + depends on A + +config CHOICE_B + bool "Choice B" + +config CHOICE_C + bool "Choice C" + +endchoice diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py new file mode 100644 index 000000000..791ed659c --- /dev/null +++ b/scripts/kconfig/tests/no_write_if_dep_unmet/__init__.py @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Do not write choice values to .config if the dependency is unmet. + +"# CONFIG_... is not set" should not be written into the .config file +for symbols with unmet dependency. + +This was not working correctly for choice values because choice needs +a bit different symbol computation. + +This checks that no unneeded "# CONFIG_... is not set" is contained in +the .config file. + +Related Linux commit: cb67ab2cd2b8abd9650292c986c79901e3073a59 +""" + + +def test(conf): + assert conf.oldaskconfig('config', 'n') == 0 + assert conf.config_matches('expected_config') diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/config b/scripts/kconfig/tests/no_write_if_dep_unmet/config new file mode 100644 index 000000000..abd280e2f --- /dev/null +++ b/scripts/kconfig/tests/no_write_if_dep_unmet/config @@ -0,0 +1 @@ +CONFIG_A=y diff --git a/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config new file mode 100644 index 000000000..473228810 --- /dev/null +++ b/scripts/kconfig/tests/no_write_if_dep_unmet/expected_config @@ -0,0 +1,5 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_A is not set diff --git a/scripts/kconfig/tests/preprocess/builtin_func/Kconfig b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig new file mode 100644 index 000000000..baa328827 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/builtin_func/Kconfig @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: GPL-2.0 + +# 'info' prints the argument to stdout. +$(info,hello world 0) + +# 'warning-if', if the first argument is y, sends the second argument to stderr, +# and the message is prefixed with the current file name and line number. +$(warning-if,y,hello world 1) + +# 'error-if' is similar, but it terminates the parsing immediately. +# The following is just no-op since the first argument is not y. +$(error-if,n,this should not be printed) + +# Shorthand +warning = $(warning-if,y,$(1)) + +# 'shell' executes a command, and returns its stdout. +$(warning,$(shell,echo hello world 3)) + +# Every newline in the output is replaced with a space, +# but any trailing newlines are deleted. +$(warning,$(shell,printf 'hello\nworld\n\n4\n\n\n')) + +# 'filename' is expanded to the currently parsed file name, +# 'lineno' to the line number. +$(warning,filename=$(filename)) +$(warning,lineno=$(lineno)) diff --git a/scripts/kconfig/tests/preprocess/builtin_func/__init__.py b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py new file mode 100644 index 000000000..2e53ba08f --- /dev/null +++ b/scripts/kconfig/tests/preprocess/builtin_func/__init__.py @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Built-in function tests. +""" + +def test(conf): + assert conf.oldaskconfig() == 0 + assert conf.stdout_contains('expected_stdout') + assert conf.stderr_matches('expected_stderr') diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr new file mode 100644 index 000000000..33ea9ca38 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stderr @@ -0,0 +1,5 @@ +Kconfig:8: hello world 1 +Kconfig:18: hello world 3 +Kconfig:22: hello world 4 +Kconfig:26: filename=Kconfig +Kconfig:27: lineno=27 diff --git a/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout new file mode 100644 index 000000000..82de3a7e9 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/builtin_func/expected_stdout @@ -0,0 +1 @@ +hello world 0 diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig new file mode 100644 index 000000000..6838997c2 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/circular_expansion/Kconfig @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +X = $(Y) +Y = $(X) +$(info $(X)) diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py new file mode 100644 index 000000000..419bda3e0 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/circular_expansion/__init__.py @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Detect circular variable expansion. + +If a recursively expanded variable references itself (eventually), +it should fail with an error message. +""" + +def test(conf): + assert conf.oldaskconfig() != 0 + assert conf.stderr_matches('expected_stderr') diff --git a/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr new file mode 100644 index 000000000..cde68fa98 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/circular_expansion/expected_stderr @@ -0,0 +1 @@ +Kconfig:5: Recursive variable 'X' references itself (eventually) diff --git a/scripts/kconfig/tests/preprocess/escape/Kconfig b/scripts/kconfig/tests/preprocess/escape/Kconfig new file mode 100644 index 000000000..4e3f44445 --- /dev/null +++ b/scripts/kconfig/tests/preprocess/escape/Kconfig @@ -0,0 +1,44 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Shorthand +warning = $(warning-if,y,$(1)) + +# You can not pass commas directly to a function since they are treated as +# delimiters. You can use the following trick to do so. +comma := , +$(warning,hello$(comma) world) + +# Like Make, single quotes, double quotes, spaces are treated verbatim. +# The following prints the text as-is. +$(warning, ' " '" ' ''' "'") + +# Unlike Make, '$' has special meaning only when it is followed by '('. +# No need to escape '$' itself. +$(warning,$) +$(warning,$$) +$ := 1 +$(warning,$($)) + +# You need a trick to escape '$' followed by '(' +# The following should print "$(X)". It should not be expanded further. +dollar := $ +$(warning,$(dollar)(X)) + +# You need a trick to treat unbalanced parentheses. +# The following should print "(". +left_paren := ( +$(warning,$(left_paren)) + +# A simple expanded should not be expanded multiple times. +# The following should print "$(X)". It should not be expanded further. +Y := $(dollar)(X) +$(warning,$(Y)) + +# The following should print "$(X)" as well. +Y = $(dollar)(X) +$(warning,$(Y)) + +# The following should print "$(". +# It should not be emit "unterminated reference" error. +unterminated := $(dollar)( +$(warning,$(unterminated)) diff --git a/scripts/kconfig/tests/preprocess/escape/__init__.py b/scripts/kconfig/tests/preprocess/escape/__init__.py new file mode 100644 index 000000000..7ee8e747f --- /dev/null +++ b/scripts/kconfig/tests/preprocess/escape/__init__.py @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Escape sequence tests. +""" + +def test(conf): + assert conf.oldaskconfig() == 0 + assert conf.stderr_matches('expected_stderr') diff --git a/scripts/kconfig/tests/preprocess/escape/expected_stderr b/scripts/kconfig/tests/preprocess/escape/expected_stderr new file mode 100644 index 000000000..1c00957dd --- /dev/null +++ b/scripts/kconfig/tests/preprocess/escape/expected_stderr @@ -0,0 +1,10 @@ +Kconfig:9: hello, world +Kconfig:13: ' " '" ' ''' "'" +Kconfig:17: $ +Kconfig:18: $$ +Kconfig:20: 1 +Kconfig:25: $(X) +Kconfig:30: ( +Kconfig:35: $(X) +Kconfig:39: $(X) +Kconfig:44: $( diff --git a/scripts/kconfig/tests/preprocess/variable/Kconfig b/scripts/kconfig/tests/preprocess/variable/Kconfig new file mode 100644 index 000000000..9ce2f95cb --- /dev/null +++ b/scripts/kconfig/tests/preprocess/variable/Kconfig @@ -0,0 +1,53 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Shorthand +warning = $(warning-if,y,$(1)) + +# Simply expanded variable. +X := 1 +SIMPLE := $(X) +X := 2 +$(warning,SIMPLE = $(SIMPLE)) + +# Recursively expanded variable. +X := 1 +RECURSIVE = $(X) +X := 2 +$(warning,RECURSIVE = $(RECURSIVE)) + +# Append something to a simply expanded variable. +Y := 3 +SIMPLE += $(Y) +Y := 4 +$(warning,SIMPLE = $(SIMPLE)) + +# Append something to a recursively expanded variable. +Y := 3 +RECURSIVE += $(Y) +Y := 4 +$(warning,RECURSIVE = $(RECURSIVE)) + +# Use += operator to an undefined variable. +# This works as a recursively expanded variable. +Y := 3 +UNDEFINED_VARIABLE += $(Y) +Y := 4 +$(warning,UNDEFINED_VARIABLE = $(UNDEFINED_VARIABLE)) + +# You can use variable references for the lefthand side of assignment statement. +X := A +Y := B +$(X)$(Y) := 5 +$(warning,AB = $(AB)) + +# User-defined function. +greeting = $(1), my name is $(2). +$(warning,$(greeting,Hello,John)) + +# The number of arguments is not checked for user-defined functions. +# If some arguments are optional, it is useful to pass fewer parameters. +# $(2) will be blank in this case. +$(warning,$(greeting,Hello)) + +# Unreferenced parameters are just ignored. +$(warning,$(greeting,Hello,John,ignored,ignored)) diff --git a/scripts/kconfig/tests/preprocess/variable/__init__.py b/scripts/kconfig/tests/preprocess/variable/__init__.py new file mode 100644 index 000000000..e88b1708d --- /dev/null +++ b/scripts/kconfig/tests/preprocess/variable/__init__.py @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Variable and user-defined function tests. +""" + +def test(conf): + assert conf.oldaskconfig() == 0 + assert conf.stderr_matches('expected_stderr') diff --git a/scripts/kconfig/tests/preprocess/variable/expected_stderr b/scripts/kconfig/tests/preprocess/variable/expected_stderr new file mode 100644 index 000000000..a4841c3fd --- /dev/null +++ b/scripts/kconfig/tests/preprocess/variable/expected_stderr @@ -0,0 +1,9 @@ +Kconfig:10: SIMPLE = 1 +Kconfig:16: RECURSIVE = 2 +Kconfig:22: SIMPLE = 1 3 +Kconfig:28: RECURSIVE = 2 4 +Kconfig:35: UNDEFINED_VARIABLE = 4 +Kconfig:41: AB = 5 +Kconfig:45: Hello, my name is John. +Kconfig:50: Hello, my name is . +Kconfig:53: Hello, my name is John. diff --git a/scripts/kconfig/tests/pytest.ini b/scripts/kconfig/tests/pytest.ini new file mode 100644 index 000000000..85d7ce8e4 --- /dev/null +++ b/scripts/kconfig/tests/pytest.ini @@ -0,0 +1,7 @@ +[pytest] +addopts = --verbose + +# Pytest requires that test files have unique names, because pytest imports +# them as top-level modules. It is silly to prefix or suffix a test file with +# the directory name that contains it. Use __init__.py for all test files. +python_files = __init__.py diff --git a/scripts/kconfig/tests/transitional/Kconfig b/scripts/kconfig/tests/transitional/Kconfig new file mode 100644 index 000000000..faa4d396f --- /dev/null +++ b/scripts/kconfig/tests/transitional/Kconfig @@ -0,0 +1,132 @@ +# SPDX-License-Identifier: GPL-2.0 +# Test transitional symbols for config migration with all Kconfig types + +# Enable module support for tristate testing +config MODULES + bool "Enable loadable module support" + modules + default y + +# Basic migration tests for all types +config NEW_BOOL + bool "New bool option" + default OLD_BOOL + +config OLD_BOOL + bool + transitional + +config NEW_TRISTATE + tristate "New tristate option" + default OLD_TRISTATE + +config OLD_TRISTATE + tristate + transitional + +config NEW_STRING + string "New string option" + default OLD_STRING + +config OLD_STRING + string + transitional + +config NEW_HEX + hex "New hex option" + default OLD_HEX + +config OLD_HEX + hex + transitional + +config NEW_INT + int "New int option" + default OLD_INT + +config OLD_INT + int + transitional + +# Precedence tests for all types +config NEW_BOOL_PRECEDENCE + bool "New bool option with precedence" + default OLD_BOOL_PRECEDENCE + +config OLD_BOOL_PRECEDENCE + bool + transitional + +config NEW_STRING_PRECEDENCE + string "New string option with precedence" + default OLD_STRING_PRECEDENCE + +config OLD_STRING_PRECEDENCE + string + transitional + +config NEW_TRISTATE_PRECEDENCE + tristate "New tristate option with precedence" + default OLD_TRISTATE_PRECEDENCE + +config OLD_TRISTATE_PRECEDENCE + tristate + transitional + +config NEW_HEX_PRECEDENCE + hex "New hex option with precedence" + default OLD_HEX_PRECEDENCE + +config OLD_HEX_PRECEDENCE + hex + transitional + +config NEW_INT_PRECEDENCE + int "New int option with precedence" + default OLD_INT_PRECEDENCE + +config OLD_INT_PRECEDENCE + int + transitional + +# Test that help sections are allowed for transitional symbols +config OLD_WITH_HELP + bool + transitional + help + This transitional symbol has a help section to validate that help is allowed. + +# Test that we can set something to =n via transitional symbol +config NEW_DISABLED + tristate "Check for setting to disabled" + default OLD_DISABLED + +config OLD_DISABLED + tristate + transitional + +# Test that a potential new value disappears if it lacks a prompt +config NEW_DISABLED_UNSAVED + tristate + default OLD_DISABLED + +config OLD_DISABLED_UNSAVED + tristate + transitional + +# Test conditional default: transitional value should not prevent prompting +# when default visibility makes the expression evaluate to 'no' +config DEPENDENCY_TEST + bool "Dependency for testing" + default n + +config NEW_CONDITIONAL_DEFAULT + bool "New option with conditional default" + default OLD_CONDITIONAL_DEFAULT if DEPENDENCY_TEST + +config OLD_CONDITIONAL_DEFAULT + bool + transitional + +config REGULAR_OPTION + bool "Regular option" diff --git a/scripts/kconfig/tests/transitional/__init__.py b/scripts/kconfig/tests/transitional/__init__.py new file mode 100644 index 000000000..b50ba2397 --- /dev/null +++ b/scripts/kconfig/tests/transitional/__init__.py @@ -0,0 +1,25 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Test transitional symbol migration functionality for all Kconfig types. + +This tests that: +- OLD_* options in existing .config cause NEW_* options to be set +- OLD_* options are not written to the new .config file +- NEW_* options appear in the new .config file with correct values +- NEW_* options with defaults from transitional symbols are not prompted +- All Kconfig types work correctly: bool, tristate, string, hex, int +- User-set NEW values take precedence over conflicting OLD transitional values +""" + +def test(conf): + # Run olddefconfig to process the migration with the initial config + assert conf.olddefconfig(dot_config='initial_config') == 0 + + # Check that the configuration matches expected output + assert conf.config_contains('expected_config') + + # Test oldconfig to ensure symbols with transitional defaults are not prompted + assert conf.oldconfig(dot_config='initial_config', in_keys='n\n') == 0 + + # Except for when conditional default evaluates to 'no' + assert conf.stdout_contains('expected_stdout') diff --git a/scripts/kconfig/tests/transitional/expected_config b/scripts/kconfig/tests/transitional/expected_config new file mode 100644 index 000000000..e01f5f070 --- /dev/null +++ b/scripts/kconfig/tests/transitional/expected_config @@ -0,0 +1,15 @@ +CONFIG_MODULES=y +CONFIG_NEW_BOOL=y +CONFIG_NEW_TRISTATE=m +CONFIG_NEW_STRING="test string" +CONFIG_NEW_HEX=0x1234 +CONFIG_NEW_INT=42 +# CONFIG_NEW_BOOL_PRECEDENCE is not set +CONFIG_NEW_STRING_PRECEDENCE="user value" +CONFIG_NEW_TRISTATE_PRECEDENCE=y +CONFIG_NEW_HEX_PRECEDENCE=0xABCD +CONFIG_NEW_INT_PRECEDENCE=100 +# CONFIG_NEW_DISABLED is not set +# CONFIG_DEPENDENCY_TEST is not set +# CONFIG_NEW_CONDITIONAL_DEFAULT is not set +# CONFIG_REGULAR_OPTION is not set diff --git a/scripts/kconfig/tests/transitional/expected_stdout b/scripts/kconfig/tests/transitional/expected_stdout new file mode 100644 index 000000000..6f0b285d6 --- /dev/null +++ b/scripts/kconfig/tests/transitional/expected_stdout @@ -0,0 +1 @@ +New option with conditional default (NEW_CONDITIONAL_DEFAULT) [N/y/?] (NEW) n diff --git a/scripts/kconfig/tests/transitional/initial_config b/scripts/kconfig/tests/transitional/initial_config new file mode 100644 index 000000000..68b7da672 --- /dev/null +++ b/scripts/kconfig/tests/transitional/initial_config @@ -0,0 +1,20 @@ +CONFIG_MODULES=y +CONFIG_OLD_BOOL=y +CONFIG_OLD_TRISTATE=m +CONFIG_OLD_STRING="test string" +CONFIG_OLD_HEX=0x1234 +CONFIG_OLD_INT=42 +# CONFIG_NEW_BOOL_PRECEDENCE is not set +CONFIG_OLD_BOOL_PRECEDENCE=y +CONFIG_NEW_STRING_PRECEDENCE="user value" +CONFIG_OLD_STRING_PRECEDENCE="old value" +CONFIG_NEW_TRISTATE_PRECEDENCE=y +CONFIG_OLD_TRISTATE_PRECEDENCE=m +CONFIG_NEW_HEX_PRECEDENCE=0xABCD +CONFIG_OLD_HEX_PRECEDENCE=0x5678 +CONFIG_NEW_INT_PRECEDENCE=100 +CONFIG_OLD_INT_PRECEDENCE=200 +# CONFIG_OLD_DISABLED is not set +# CONFIG_OLD_DISABLED_UNSAVED is not set +# CONFIG_DEPENDENCY_TEST is not set +CONFIG_OLD_CONDITIONAL_DEFAULT=y diff --git a/scripts/kconfig/tests/warn_changed_input/Kconfig b/scripts/kconfig/tests/warn_changed_input/Kconfig new file mode 100644 index 000000000..69845e2f3 --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/Kconfig @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: GPL-2.0 + +config DEP + bool "DEP" + help + Test dependency symbol for Kconfig warning coverage. + This is used by the warn_changed_input selftest. + It intentionally stays unset in the input fragment. + The test checks how dependent user input is adjusted. + +config A + bool "A" + depends on DEP + help + Test bool symbol for changed-input diagnostics. + The input fragment requests this symbol as built-in. + The unmet dependency on DEP forces the final value to n. + The warning should report that downgrade. + +config NUM + int "NUM" + range 10 20 + help + Test integer symbol for changed-input diagnostics. + The input fragment requests a value outside the allowed range. + Kconfig resolves it to the constrained in-range value. + The warning should report that adjustment. + +config DUP + bool "DUP" + depends on DEP + help + Test duplicate-definition handling for changed-input diagnostics. + The input fragment requests this symbol as built-in. + The duplicate definition below must not produce a duplicate warning. + This keeps the warning output stable for repeated menu entries. + +config DUP + bool + depends on DEP diff --git a/scripts/kconfig/tests/warn_changed_input/__init__.py b/scripts/kconfig/tests/warn_changed_input/__init__.py new file mode 100644 index 000000000..4c3bca6af --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/__init__.py @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Test optional warnings for user-provided values changed by Kconfig. + +Warnings should stay disabled by default, and should only appear when +KCONFIG_WARN_CHANGED_INPUT is enabled. +""" + + +def test(conf): + assert conf.olddefconfig('config') == 0 + assert 'user-provided values changed by Kconfig' not in conf.stderr + + assert conf._run_conf('--olddefconfig', dot_config='config', + extra_env={ + 'KCONFIG_WARN_CHANGED_INPUT': '1', + }) == 0 + assert conf.stderr_contains('expected_stderr') + assert conf.config_matches('expected_config') + + assert conf._run_conf('--olddefconfig', dot_config='config', + extra_env={ + 'KCONFIG_WARN_CHANGED_INPUT': '1', + }, silent=True) == 0 + assert conf.stderr_contains('expected_stderr') + + assert conf._run_conf('--savedefconfig=defconfig', dot_config='config', + out_file='defconfig', + extra_env={ + 'KCONFIG_WARN_CHANGED_INPUT': '1', + }) == 0 + assert conf.stderr_contains('expected_stderr') + assert conf.config_matches('expected_defconfig') diff --git a/scripts/kconfig/tests/warn_changed_input/config b/scripts/kconfig/tests/warn_changed_input/config new file mode 100644 index 000000000..dbe93ff26 --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/config @@ -0,0 +1,3 @@ +CONFIG_A=y +CONFIG_NUM=30 +CONFIG_DUP=y diff --git a/scripts/kconfig/tests/warn_changed_input/expected_config b/scripts/kconfig/tests/warn_changed_input/expected_config new file mode 100644 index 000000000..fe8bbec66 --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/expected_config @@ -0,0 +1,6 @@ +# +# Automatically generated file; DO NOT EDIT. +# Main menu +# +# CONFIG_DEP is not set +CONFIG_NUM=20 diff --git a/scripts/kconfig/tests/warn_changed_input/expected_defconfig b/scripts/kconfig/tests/warn_changed_input/expected_defconfig new file mode 100644 index 000000000..af9e34851 --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/expected_defconfig @@ -0,0 +1 @@ +CONFIG_NUM=20 diff --git a/scripts/kconfig/tests/warn_changed_input/expected_stderr b/scripts/kconfig/tests/warn_changed_input/expected_stderr new file mode 100644 index 000000000..9ec8446b4 --- /dev/null +++ b/scripts/kconfig/tests/warn_changed_input/expected_stderr @@ -0,0 +1,4 @@ +warning: user-provided values changed by Kconfig: + CONFIG_A: y -> n + CONFIG_NUM: 30 -> 20 + CONFIG_DUP: y -> n |
