Coverage for tests/unit_tests/scons/testing.py: 100%
32 statements
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
« prev ^ index » next coverage.py v7.17.2, created at 2026-11-07 05:08 +0000
1# This file is part of the Apio project
2# (C) 2016-present FPGAwars
3# Project authors:
4# * Jesús Arroyo (Jesus89) (2016-2019)
5# * Juan Gonzalez (obijuan) (2019-2024)
6# * The Apio Team (2024-present)
7# License: GPLv2
9"""
10Helpers for apio's scons testing."""
12import SCons.Script.SConsOptions
13import SCons.Node.FS
14import SCons.Environment
15import SCons.Script.Main
16from google.protobuf import text_format
17from apio.scons.apio_env import ApioEnv
18from apio.common.proto.stubs.apio_scons_pb2 import (
19 SconsParams,
20 TargetParams,
21 ApioEnvParams,
22)
25TEST_PARAMS = """
26timestamp: "20123412052"
27fpga_definition {
28 arch: ice40
29 size: "8k"
30 vendor_part: "ICE40HX4K-TQ144"
31 ice40_params {
32 nextpnr_type: "hx8k"
33 nextpnr_package: "tq144:4k"
34 }
35}
36verbosity {
37 all: false
38 synth: false
39 pnr: false
40}
41environment {
42 platform_id: "darwin-arm64"
43 yosys_path: "/Users/user/.apio/packages/oss-cad-suite/share/yosys"
44 trellis_path: "/Users/user/.apio/packages/oss-cad-suite/share/trellis"
45}
46apio_env_params {
47 env_name: "default"
48 board_id: "alhambra-ii"
49 top_module: "main"
50}
51"""
54class SconsHacks:
55 """A collection of static methods that encapsulate scons access outside of
56 the official scons API. Hopefully this will not be too difficult to adapt
57 in future versions of SCons."""
59 @staticmethod
60 def reset_scons_state() -> None:
61 """Reset the relevant SCons global variables. Unfortunately scons
62 uses a few global variables to hold its state. This works well in
63 normal operation where an scons process contains a single scons
64 session but with pytest testing, where multiple independent tests
65 are running in the same process, we need to reset though variables
66 before each test."""
68 # -- The Cons.Script.Main.OptionsParser variables contains the command
69 # -- line options of scons. We reset them here and tests can access
70 # -- them using SetOption() and GetOption().
72 parser = SCons.Script.SConsOptions.Parser("my_fake_version")
73 values = SCons.Script.SConsOptions.SConsValues(
74 parser.get_default_values()
75 )
76 parser.parse_args(args=[], values=values)
77 SCons.Script.Main.OptionsParser = parser
79 # -- Reset the scons target list variable.
80 SCons.Node.FS.default_fs = None
82 # -- Clear the SCons targets
83 SCons.Environment.CleanTargets = {}
86def make_test_scons_params() -> SconsParams:
87 """Create a fake scons params for testing."""
88 return text_format.Parse(TEST_PARAMS, SconsParams())
91def make_test_apio_env(
92 *,
93 targets: list[str] | None = None,
94 platform_id: str | None = None,
95 apio_env_params: ApioEnvParams | None = None,
96 target_params: TargetParams | None = None,
97) -> ApioEnv:
98 """Creates a fresh apio env for testing. The env is created
99 with the current directory as the root dir.
100 """
102 # -- Bring scons to a starting state.
103 SconsHacks.reset_scons_state()
105 # -- Create default params.
106 scons_params = make_test_scons_params()
108 # -- Set debug level
109 # scons_params.environment.debug_level = debug_level
111 # -- Apply user overrides.
112 if platform_id is not None:
113 scons_params.environment.platform_id = platform_id
114 if apio_env_params is not None:
115 scons_params.apio_env_params.MergeFrom(apio_env_params)
116 if target_params is not None:
117 scons_params.target.MergeFrom(target_params)
119 # -- Determine scons target.
120 if targets is not None:
121 command_line_targets = targets
122 else:
123 command_line_targets = ["build"]
125 # -- Create and return the apio env.
126 return ApioEnv(
127 command_line_targets=command_line_targets, scons_params=scons_params
128 )