Skip to content

Commit ce8c933

Browse files
jfrimmelolofk
authored andcommitted
Add failing test for cached generator failure
When FuseSoC runs generators, the output is cached if the generator re- quests so. While this is generally a good idea, the cached output must not be used in subsequent runs if the generator fails with a non-zero exit code. In that case, the generator should be re-invoked in the next run to not need to user to manually run `fusesoc gen clean` to fix a faulty cache entry. This commit adds a test for that exact behavior, which shows, that the expectation outlined above is not upheld. Instead a failed generator run is still cached and thus never re-executed until its input changes.
1 parent 1403437 commit ce8c933

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

tests/test_usecases.py

+70
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,76 @@ def test_usage_error_leads_to_nonzero_exit_code():
6161
_fusesoc("--option_does_not_exist")
6262

6363

64+
def test_failing_generator_is_not_cached(caplog, capfd):
65+
"""
66+
When FuseSoC runs generators, the output is cached if the generator requests
67+
so. While this is generally a good idea, the cached output must not be used
68+
in subsequent runs if the generator fails with a non-zero exit code. In that
69+
case, the generator should be re-invoked in the next run to not need to user
70+
to manually run `fusesoc gen clean` to fix a faulty cache entry.
71+
72+
Therefore this tests adds a simple generator, which prints something to the
73+
console and then exist with an error. After registering this generator, two
74+
FuseSoC-runs are performed, where the generator, despited being marked as
75+
cacheable, needs to be reinvoked.
76+
"""
77+
# Register the generator
78+
with open("failing-script.py", "w") as command:
79+
command.write("import sys; print('Running generator'); sys.exit(2)")
80+
with open("test-generator.core", "w") as failing_generator:
81+
failing_generator.write(
82+
"""\
83+
CAPI=2:
84+
name: ::test-generator:0.1.0
85+
generators:
86+
failing-generator:
87+
# Run a builtin POSIX command, which prints something and then exits with a
88+
# non-zero exit code. `printf` can be used with formatting something that is
89+
# not an integer as one, causing it to fail.
90+
interpreter: python
91+
command: failing-script.py
92+
cache_type: input
93+
"""
94+
)
95+
_fusesoc("library", "add", ".")
96+
_fusesoc("gen", "clean")
97+
_fusesoc("gen", "list")
98+
captured = capfd.readouterr()
99+
assert "::test-generator:0.1.0" in captured.out
100+
101+
with open("test-user.core", "w") as using_core:
102+
using_core.write(
103+
"""\
104+
CAPI=2:
105+
name: ::test-user:0.1.0
106+
filesets:
107+
rtl:
108+
depend: ["::test-generator:0.1.0"]
109+
generate:
110+
call-generator:
111+
generator: failing-generator
112+
targets:
113+
default:
114+
filesets: [rtl]
115+
generate: [call-generator]
116+
"""
117+
)
118+
119+
# run generator the first time, which should fail
120+
with pytest.raises(SystemExit):
121+
_fusesoc("run", "--tool=icarus", "::test-user:0.1.0")
122+
captured = capfd.readouterr()
123+
assert "Found cached output for ::test-user-call-generator:0.1.0" not in caplog.text
124+
assert captured.out == "Running generator\n"
125+
126+
# run generator second time, which should fail as well despite being cached
127+
with pytest.raises(SystemExit):
128+
_fusesoc("run", "--tool=icarus", "::test-user:0.1.0")
129+
captured = capfd.readouterr()
130+
assert "Found cached output for ::test-user-call-generator:0.1.0" not in caplog.text
131+
assert captured.out == "Running generator\n"
132+
133+
64134
# region Test fixtures and helper functions
65135
@pytest.fixture(autouse=True) # this fixture will be used by all tests implicitly
66136
def run_in_temporary_directory(request):

0 commit comments

Comments
 (0)