Files
buildroot/support/testing/run-tests
Fiona Klute 10088b5381 support/testing: transfer config in environment instead of class variables
Passing runtime configuration to tests in BRConfigTest class variables
requires the "fork" start method for multiprocessing. With
"forkserver" (default for POSIX platforms since Python 3.14) class
variables modified in the parent process are lost, because the child
process does not inherit the full Python state. This broke the way
support/testing/run-tests sets configuration for BRConfigTest, so a
start method override was added in commit
3d2141bcee.

Instead this patch adds a settings dataclass (requires Python >= 3.7)
which is serialized into an environment variable from run-tests and
read during BRConfigTest.__init__(). Reading is skipped if the
environment variable is not set so test discovery (not execution)
works without configuration (e.g. utils/get-developers uses this).

With that, run-tests no longer relies on a specific multiprocessing
start method.

Signed-off-by: Fiona Klute <fiona.klute@gmx.de>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
2026-05-30 16:20:03 +02:00

149 lines
4.7 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import multiprocessing
import os
import sys
import nose2
from infra.basetest import BRTestSettings
import infra
def main():
parser = argparse.ArgumentParser(description='Run Buildroot tests')
parser.add_argument('testname', nargs='*',
help='list of test cases to execute')
parser.add_argument('-l', '--list', action='store_true',
help='list of available test cases')
parser.add_argument('-a', '--all', action='store_true',
help='execute all test cases')
parser.add_argument('-s', '--stdout', action='store_true',
help='log everything to stdout')
parser.add_argument('-o', '--output',
help='output directory')
parser.add_argument('-d', '--download',
help='download directory')
parser.add_argument('-p', '--prepare-only', action='store_true',
help='download emulator builtin binaries')
parser.add_argument('-k', '--keep',
help='keep build directories',
action='store_true')
parser.add_argument('-t', '--testcases', type=int, default=1,
help='number of testcases to run simultaneously')
parser.add_argument('-j', '--jlevel', type=int,
help='BR2_JLEVEL to use for each testcase')
parser.add_argument('--timeout-multiplier', type=int, default=1,
help='increase timeouts (useful for slow machines)')
parser.add_argument('-D', '--debug', action='store_true',
help='enable debug log')
args = parser.parse_args()
script_path = os.path.realpath(__file__)
test_dir = os.path.dirname(script_path)
if args.list:
print("List of tests")
nose2_args = [
script_path,
"-s", test_dir,
"-v",
"--collect-only"
]
if args.debug:
nose2_args += ["--log-level", "debug"]
nose2.discover(argv=nose2_args,
plugins=["nose2.plugins.collect"])
return 0
if args.download is None:
args.download = os.getenv("BR2_DL_DIR")
if args.download is None:
print("Missing download directory, please use -d/--download")
print("")
parser.print_help()
return 1
args.download = os.path.abspath(args.download)
if args.prepare_only:
emulator_builtin_binaries = ["kernel-vexpress-5.10.202",
"vexpress-v2p-ca9-5.10.202.dtb",
"kernel-versatile-5.10.202",
"versatile-pb-5.10.202.dtb"]
print("Downloading emulator builtin binaries")
for binary in emulator_builtin_binaries:
infra.download(args.download, binary)
return 0
if args.output is None:
print("Missing output directory, please use -o/--output")
print("")
parser.print_help()
return 1
if not os.path.exists(args.output):
os.mkdir(args.output)
if args.all is False and not args.testname:
print("No test selected")
print("")
parser.print_help()
return 1
jlevel = 0
if args.testcases != 1:
if args.testcases < 1:
print("Invalid number of testcases to run simultaneously")
print("")
parser.print_help()
return 1
# same default BR2_JLEVEL as package/Makefile.in
br2_jlevel = 1 + multiprocessing.cpu_count()
each_testcase = int((br2_jlevel + args.testcases) / args.testcases)
jlevel = each_testcase
if args.jlevel:
if args.jlevel < 0:
print("Invalid BR2_JLEVEL to use for each testcase")
print("")
parser.print_help()
return 1
# the user can override the auto calculated value
jlevel = args.jlevel
if args.timeout_multiplier < 1:
print("Invalid multiplier for timeout values")
print("")
parser.print_help()
return 1
BRTestSettings(
logtofile=not args.stdout,
downloaddir=args.download,
outputdir=os.path.abspath(args.output),
keepbuilds=args.keep,
jlevel=jlevel,
timeout_multiplier=args.timeout_multiplier
).to_env()
nose2_args = ["-v",
"-N", str(args.testcases),
"-s", test_dir,
"-c", os.path.join(test_dir, "conf/unittest.cfg")]
if args.debug:
nose2_args += ["--log-level", "debug"]
if args.testname:
nose2_args += args.testname
nose2.discover(argv=nose2_args)
if __name__ == "__main__":
sys.exit(main())