CIRCT 24.0.0git
Loading...
Searching...
No Matches
test_macro_definitions.py
Go to the documentation of this file.
1"""Unit tests for RTL macro definition loading and propagation."""
2
3from __future__ import annotations
4
5import importlib.util
6import json
7from pathlib import Path
8import sys
9from unittest.mock import MagicMock, patch
10
11import pytest
12
13_accel_mock = MagicMock()
14sys.modules["esiaccel.esiCppAccel"] = _accel_mock
15
16from esiaccel.cosim import simulator # noqa: E402
17from esiaccel.cosim import pytest as cosim_pytest # noqa: E402
18
19
21 script = (Path(__file__).parents[2] / "cosim_dpi_server" / "esi-cosim.py")
22 spec = importlib.util.spec_from_file_location("esi_cosim", script)
23 assert spec is not None
24 assert spec.loader is not None
25 module = importlib.util.module_from_spec(spec)
26 spec.loader.exec_module(module)
27 return module
28
29
31
33 definitions_file = tmp_path / "macros.json"
34 definitions_file.write_text(
35 json.dumps({
36 "STRING": "value",
37 "INTEGER": 42,
38 "FLOAT": 1.5,
39 "BOOLEAN": True,
40 "FLAG": None,
41 }))
42
43 assert simulator.load_macro_definitions(definitions_file) == {
44 "STRING": "value",
45 "INTEGER": "42",
46 "FLOAT": "1.5",
47 "BOOLEAN": "True",
48 "FLAG": None,
49 }
50
51 def test_missing_file_raises(self, tmp_path):
52 with pytest.raises(FileNotFoundError,
53 match="Macro definitions file not found"):
54 simulator.load_macro_definitions(tmp_path / "missing.json")
55
56 def test_invalid_json_raises(self, tmp_path):
57 definitions_file = tmp_path / "macros.json"
58 definitions_file.write_text("{")
59
60 with pytest.raises(ValueError, match="is not valid JSON"):
61 simulator.load_macro_definitions(definitions_file)
62
63 @pytest.mark.parametrize("contents", ["[]", '"macro"', "null"])
64 def test_non_object_json_raises(self, tmp_path, contents):
65 definitions_file = tmp_path / "macros.json"
66 definitions_file.write_text(contents)
67
68 with pytest.raises(ValueError, match="must contain a JSON object"):
69 simulator.load_macro_definitions(definitions_file)
70
71 def test_non_scalar_value_raises(self, tmp_path):
72 definitions_file = tmp_path / "macros.json"
73 definitions_file.write_text(json.dumps({"BAD": ["value"]}))
74
75 with pytest.raises(ValueError, match="expected a scalar or null"):
76 simulator.load_macro_definitions(definitions_file)
77
78
80
82 sources_dir = tmp_path / "sources"
83 sources_dir.mkdir()
84 (sources_dir / "macros.json").write_text(
85 json.dumps({
86 "FROM_FILE": "file",
87 "OVERRIDE": "file",
88 }))
89 config = cosim_pytest.CosimPytestConfig(
90 source_generator=lambda _config, _tmp_dir: sources_dir,
91 macro_definitions={
92 "OVERRIDE": "explicit",
93 "FROM_CONFIG": None
94 },
95 macro_definitions_file="macros.json",
96 )
97
98 assert cosim_pytest._resolve_macro_definitions(config, sources_dir) == {
99 "FROM_FILE": "file",
100 "OVERRIDE": "explicit",
101 "FROM_CONFIG": None,
102 }
103
104 def test_resolves_absolute_file(self, tmp_path):
105 sources_dir = tmp_path / "sources"
106 sources_dir.mkdir()
107 definitions_file = tmp_path / "macros.json"
108 definitions_file.write_text(json.dumps({"FROM_FILE": "absolute"}))
109 config = cosim_pytest.CosimPytestConfig(
110 source_generator=lambda _config, _tmp_dir: sources_dir,
111 macro_definitions_file=definitions_file,
112 )
113
114 assert cosim_pytest._resolve_macro_definitions(config, sources_dir) == {
115 "FROM_FILE": "absolute",
116 }
117
119 sources_dir = tmp_path / "sources"
120 sources_dir.mkdir()
121 (sources_dir / "macros.json").write_text(json.dumps({"FROM_FILE": "1"}))
122 config = cosim_pytest.CosimPytestConfig(
123 source_generator=lambda _config, _tmp_dir: sources_dir,
124 macro_definitions={"FROM_CONFIG": None},
125 macro_definitions_file="macros.json",
126 )
127 expected_simulator = object()
128
129 with patch.object(cosim_pytest,
130 "get_simulator",
131 return_value=expected_simulator) as get_simulator:
132 result = cosim_pytest._create_simulator(config, sources_dir,
133 tmp_path / "run")
134
135 assert result is expected_simulator
136 assert get_simulator.call_args.args[-1] == {
137 "FROM_FILE": "1",
138 "FROM_CONFIG": None,
139 }
140
141
143
145 self, tmp_path):
146 cli = _load_cosim_cli()
147 source_dir = tmp_path / "hw"
148 source_dir.mkdir()
149 definitions_file = tmp_path / "macros.json"
150 definitions_file.write_text(
151 json.dumps({
152 "FROM_FILE": "file",
153 "OVERRIDE": "file",
154 }))
155 fake_simulator = MagicMock()
156 fake_simulator.compile.return_value = 0
157 fake_simulator.run.return_value = 17
158
159 with patch.object(cli, "get_simulator",
160 return_value=fake_simulator) as get_simulator:
161 result = cli.__main__([
162 "esi-cosim.py",
163 "--define-file",
164 str(definitions_file),
165 "--source",
166 str(source_dir),
167 "--define",
168 "OVERRIDE=command-line",
169 "--define",
170 "FLAG",
171 "--no-compile",
172 "inner-command",
173 "argument",
174 ])
175
176 assert result == 17
177 assert get_simulator.call_args.kwargs["macro_definitions"] == {
178 "FROM_FILE": "file",
179 "OVERRIDE": "command-line",
180 "FLAG": None,
181 }
182 fake_simulator.run.assert_called_once_with(["argument"],
183 gui=False,
184 server_only=False)
Dict[str, Optional[str]] load_macro_definitions(Path path)
Definition simulator.py:528