[PATCH v6 0/4] New proof-of-concept based exeter tests
Here's a new approach to building passt tests with exeter. This new one no longer uses Avocado in the default case, although it would still be possible to manually run the exeter based tests with Avocado. Here's another draft of my work on testing passt with Avocado and the exeter library I recently created. It includes Cleber's patch adding some basic Avocado tests and builds on that. For now this only does simple tests, to show how the integration could work. It adds some new trivial "smoke tests" and converts the linter and build checks to exeter. More complex tests will require building the sinte/pesto library we've discussed. A lot of the work for that already exists in my earlier exeter test series, but it will need some rework to split it into a separate component. v6: * Use exeter's new metadata support to print nicer test names v5: * Updated according to Stefano's review - Fixed a number of whitespace errors - Improved many comments and variable names to make things clearer * New patch adding parallel test execution with BATS * Improved autodetection of exeter tests using "exetool probe" David Gibson (4): test: Extend test scripts to allow running exeter tests. test: Run static checkers as exeter tests test: Convert build tests to exeter test: Allow exeter & podman tests to be parallel executed with BATS test/.gitignore | 2 + test/Makefile | 22 ++++++- test/build/all | 61 ------------------- test/build/build.py | 109 ++++++++++++++++++++++++++++++++++ test/build/clang_tidy | 17 ------ test/build/cppcheck | 17 ------ test/build/static_checkers.sh | 26 ++++++++ test/lib/exeter | 57 ++++++++++++++++++ test/run | 18 ++++-- test/smoke/smoke.sh | 33 ++++++++++ 10 files changed, 260 insertions(+), 102 deletions(-) delete mode 100644 test/build/all create mode 100755 test/build/build.py delete mode 100644 test/build/clang_tidy delete mode 100644 test/build/cppcheck create mode 100755 test/build/static_checkers.sh create mode 100644 test/lib/exeter create mode 100755 test/smoke/smoke.sh -- 2.51.0
Introduce some trivial testcases based on the exeter library. These run
passt and pasta with --help and --version options. Extend our test
scripts to run these tests.
Signed-off-by: David Gibson
Move the static checkers from the current DSL to exeter.
Signed-off-by: David Gibson
Convert the tests in build/all to be based on exeter. The new version of
the tests is more robust than the original, since it makes a temporary copy
of the source tree so will not be affected by concurrent manual builds.
Signed-off-by: David Gibson
On Mon, 1 Sep 2025 14:25:14 +1000
David Gibson
+def test_make(target: str, expected_files: list[str]) -> None: + """Test `make {target}` + + Arguments: + target -- make target to invoke + expected_files -- files make is expected to create + + Verifies that + 1) `make target` completes successfully + 2) expected_files care created by `make target` + 3) expected_files are removed by `make clean` + """ + + ex_paths = [Path(f) for f in expected_files] + with clone_sources(): + for p in ex_paths: + assert not p.exists(), f"{p} existed before make" + sh(f'make {target} CFLAGS="-Werror"') + for p in ex_paths: + assert p.exists(), f"{p} wasn't made" + sh('make clean') + for p in ex_paths: + assert not p.exists(), f"{p} existed after make clean" + + +exeter.register('make_passt', test_make, 'passt', ['passt']) +exeter.register('make_pasta', test_make, 'pasta', ['pasta']) +exeter.register('make_qrap', test_make, 'qrap', ['qrap']) +exeter.register('make_all', test_make, 'all', ['passt', 'pasta', 'qrap'])
I guess I'm missing something, but how do you set descriptions from Python? By the way, the shell script interface you added for that looks quite convenient and obvious to me. -- Stefano
On Tue, Sep 02, 2025 at 09:39:53AM +0200, Stefano Brivio wrote:
On Mon, 1 Sep 2025 14:25:14 +1000 David Gibson
wrote: +def test_make(target: str, expected_files: list[str]) -> None: + """Test `make {target}` + + Arguments: + target -- make target to invoke + expected_files -- files make is expected to create + + Verifies that + 1) `make target` completes successfully + 2) expected_files care created by `make target` + 3) expected_files are removed by `make clean` + """ + + ex_paths = [Path(f) for f in expected_files] + with clone_sources(): + for p in ex_paths: + assert not p.exists(), f"{p} existed before make" + sh(f'make {target} CFLAGS="-Werror"') + for p in ex_paths: + assert p.exists(), f"{p} wasn't made" + sh('make clean') + for p in ex_paths: + assert not p.exists(), f"{p} existed after make clean" + + +exeter.register('make_passt', test_make, 'passt', ['passt']) +exeter.register('make_pasta', test_make, 'pasta', ['pasta']) +exeter.register('make_qrap', test_make, 'qrap', ['qrap']) +exeter.register('make_all', test_make, 'all', ['passt', 'pasta', 'qrap'])
I guess I'm missing something, but how do you set descriptions from Python?
There are two ways: 1) foo = exeter.register(...) foo.set_description("test that does the thing") 2) By default exeter will take it from the first line of the test function's docstring.
By the way, the shell script interface you added for that looks quite convenient and obvious to me.
-- Stefano
-- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson
On Tue, 2 Sep 2025 20:41:41 +1000
David Gibson
On Tue, Sep 02, 2025 at 09:39:53AM +0200, Stefano Brivio wrote:
On Mon, 1 Sep 2025 14:25:14 +1000 David Gibson
wrote: +def test_make(target: str, expected_files: list[str]) -> None: + """Test `make {target}` + + Arguments: + target -- make target to invoke + expected_files -- files make is expected to create + + Verifies that + 1) `make target` completes successfully + 2) expected_files care created by `make target` + 3) expected_files are removed by `make clean` + """ + + ex_paths = [Path(f) for f in expected_files] + with clone_sources(): + for p in ex_paths: + assert not p.exists(), f"{p} existed before make" + sh(f'make {target} CFLAGS="-Werror"') + for p in ex_paths: + assert p.exists(), f"{p} wasn't made" + sh('make clean') + for p in ex_paths: + assert not p.exists(), f"{p} existed after make clean" + + +exeter.register('make_passt', test_make, 'passt', ['passt']) +exeter.register('make_pasta', test_make, 'pasta', ['pasta']) +exeter.register('make_qrap', test_make, 'qrap', ['qrap']) +exeter.register('make_all', test_make, 'all', ['passt', 'pasta', 'qrap'])
I guess I'm missing something, but how do you set descriptions from Python?
There are two ways: 1)
foo = exeter.register(...) foo.set_description("test that does the thing")
2)
By default exeter will take it from the first line of the test function's docstring.
Ah, this is really convenient. I mean I saw it happening but I wasn't sure why. :) -- Stefano
On Tue, Sep 02, 2025 at 02:23:23PM +0200, Stefano Brivio wrote:
On Tue, 2 Sep 2025 20:41:41 +1000 David Gibson
wrote: On Tue, Sep 02, 2025 at 09:39:53AM +0200, Stefano Brivio wrote:
On Mon, 1 Sep 2025 14:25:14 +1000 David Gibson
wrote: +def test_make(target: str, expected_files: list[str]) -> None: + """Test `make {target}` + + Arguments: + target -- make target to invoke + expected_files -- files make is expected to create + + Verifies that + 1) `make target` completes successfully + 2) expected_files care created by `make target` + 3) expected_files are removed by `make clean` + """ + + ex_paths = [Path(f) for f in expected_files] + with clone_sources(): + for p in ex_paths: + assert not p.exists(), f"{p} existed before make" + sh(f'make {target} CFLAGS="-Werror"') + for p in ex_paths: + assert p.exists(), f"{p} wasn't made" + sh('make clean') + for p in ex_paths: + assert not p.exists(), f"{p} existed after make clean" + + +exeter.register('make_passt', test_make, 'passt', ['passt']) +exeter.register('make_pasta', test_make, 'pasta', ['pasta']) +exeter.register('make_qrap', test_make, 'qrap', ['qrap']) +exeter.register('make_all', test_make, 'all', ['passt', 'pasta', 'qrap'])
I guess I'm missing something, but how do you set descriptions from Python?
There are two ways: 1)
foo = exeter.register(...) foo.set_description("test that does the thing")
2)
By default exeter will take it from the first line of the test function's docstring.
Ah, this is really convenient. I mean I saw it happening but I wasn't sure why. :)
To be a little more specific here, exeter.register will introspect the docstring and put it in the description. @exeter.test calls exeter.register, so it does the same thing. If you register with parameters it will expand Python-style formatting parameters in the docstring. This is useful for something like: def test_n(n : int): """Test the thing {n} times""" ... for i in range(3): exeter.register(f'test_{i}', test_n, i) You can always overwrite the default description afterwards with set_description. register_pipe() won't set a description automatically, but you can still set one explicitly afterwards. The Scenario stuff... I haven't checked, it's probably needs some work. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson
As a proof-of-concept, this adds a "make bats" target which will execute
both the podman and exeter based testcases in parallel using BATS.
Signed-off-by: David Gibson
On Mon, 1 Sep 2025 14:25:11 +1000
David Gibson
Here's a new approach to building passt tests with exeter. This new one no longer uses Avocado in the default case, although it would still be possible to manually run the exeter based tests with Avocado.
Here's another draft of my work on testing passt with Avocado and the exeter library I recently created. It includes Cleber's patch adding some basic Avocado tests and builds on that.
For now this only does simple tests, to show how the integration could work. It adds some new trivial "smoke tests" and converts the linter and build checks to exeter. More complex tests will require building the sinte/pesto library we've discussed. A lot of the work for that already exists in my earlier exeter test series, but it will need some rework to split it into a separate component.
v6: * Use exeter's new metadata support to print nicer test names
Thanks, it looks much more readable now. And to me it looks ready to merge, but I hit something during testing that I'm not quite sure how to solve, assuming it can be considered an issue at all. Initially, I hadn't upgraded my local copy of exeter, so even smoke tests would fail, until it occurred to me that of course I needed to drop the 'exeter' directory and 'make exeter' again. It's an issue we conceptually already have with mbuto (even though it didn't get breaking changes for months now) and with Podman to some extent. With exeter, I guess we're going to hit that kind of issue pretty frequently at least in the near future. So I was wondering: should we enforce some form of up-to-date check from test/Makefile? I'm personally fine without it and, given that I plan to update test/README.md soon anyway ('make' under test/ is not mentioned at all), I can mention this kind of problem as well, so it shouldn't be a big deal for others. But I wanted to know if you have thoughts or proposals on the matter, before applying this. -- Stefano
On Wed, Sep 03, 2025 at 11:14:35PM +0200, Stefano Brivio wrote:
On Mon, 1 Sep 2025 14:25:11 +1000 David Gibson
wrote: Here's a new approach to building passt tests with exeter. This new one no longer uses Avocado in the default case, although it would still be possible to manually run the exeter based tests with Avocado.
Here's another draft of my work on testing passt with Avocado and the exeter library I recently created. It includes Cleber's patch adding some basic Avocado tests and builds on that.
For now this only does simple tests, to show how the integration could work. It adds some new trivial "smoke tests" and converts the linter and build checks to exeter. More complex tests will require building the sinte/pesto library we've discussed. A lot of the work for that already exists in my earlier exeter test series, but it will need some rework to split it into a separate component.
v6: * Use exeter's new metadata support to print nicer test names
Thanks, it looks much more readable now.
And to me it looks ready to merge, but I hit something during testing that I'm not quite sure how to solve, assuming it can be considered an issue at all.
Initially, I hadn't upgraded my local copy of exeter, so even smoke tests would fail, until it occurred to me that of course I needed to drop the 'exeter' directory and 'make exeter' again. It's an issue we conceptually already have with mbuto (even though it didn't get breaking changes for months now) and with Podman to some extent.
Yes.
With exeter, I guess we're going to hit that kind of issue pretty frequently at least in the near future. So I was wondering: should we enforce some form of up-to-date check from test/Makefile?
Good point. We actually already have a mechanism for this: the pull-% targets, which we already use for mbuto and podman. I pull a dependency on this for the "make bats" target, but not for regular "make assets" so we didn't update exeter. I'll respin for this, because I have one other trivial change to make. It does occur to me that there's another version of the problem too. Once again we already conceptually have it with mbuto and podman, but it will be much worse with exeter due to pace of development: If (for debugging) we check out an old version of the passt source tree, it will still pull the latest version of exeter, which it might not be compatible with[0]. The obvious solution - but you might not like it much - is git submodules. They (kind of rightly) have a reputation as being a pain to work with, but they do solve exactly this problem - qemu uses them heavily and pretty successfully for this.
I'm personally fine without it and, given that I plan to update test/README.md soon anyway ('make' under test/ is not mentioned at all), I can mention this kind of problem as well, so it shouldn't be a big deal for others. But I wanted to know if you have thoughts or proposals on the matter, before applying this.
-- Stefano
[0] At some point, I do want to stabilise the exeter interfaces, and be concerned with backwards compatibility, which would largely fix this. However, at present I'm still finding stuff that wants to change at the exeter level often enough that I think the effort of maintaining compatibility would be prohibitive. -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson
On Thu, 4 Sep 2025 12:42:57 +1000
David Gibson
On Wed, Sep 03, 2025 at 11:14:35PM +0200, Stefano Brivio wrote:
On Mon, 1 Sep 2025 14:25:11 +1000 David Gibson
wrote: Here's a new approach to building passt tests with exeter. This new one no longer uses Avocado in the default case, although it would still be possible to manually run the exeter based tests with Avocado.
Here's another draft of my work on testing passt with Avocado and the exeter library I recently created. It includes Cleber's patch adding some basic Avocado tests and builds on that.
For now this only does simple tests, to show how the integration could work. It adds some new trivial "smoke tests" and converts the linter and build checks to exeter. More complex tests will require building the sinte/pesto library we've discussed. A lot of the work for that already exists in my earlier exeter test series, but it will need some rework to split it into a separate component.
v6: * Use exeter's new metadata support to print nicer test names
Thanks, it looks much more readable now.
And to me it looks ready to merge, but I hit something during testing that I'm not quite sure how to solve, assuming it can be considered an issue at all.
Initially, I hadn't upgraded my local copy of exeter, so even smoke tests would fail, until it occurred to me that of course I needed to drop the 'exeter' directory and 'make exeter' again. It's an issue we conceptually already have with mbuto (even though it didn't get breaking changes for months now) and with Podman to some extent.
Yes.
With exeter, I guess we're going to hit that kind of issue pretty frequently at least in the near future. So I was wondering: should we enforce some form of up-to-date check from test/Makefile?
Good point. We actually already have a mechanism for this: the pull-% targets, which we already use for mbuto and podman. I pull a dependency on this for the "make bats" target, but not for regular "make assets" so we didn't update exeter.
Ah, right, of course. That actually looks good enough to me.
I'll respin for this, because I have one other trivial change to make.
It does occur to me that there's another version of the problem too. Once again we already conceptually have it with mbuto and podman, but it will be much worse with exeter due to pace of development:
If (for debugging) we check out an old version of the passt source tree, it will still pull the latest version of exeter, which it might not be compatible with[0]. The obvious solution - but you might not like it much - is git submodules. They (kind of rightly) have a reputation as being a pain to work with, but they do solve exactly this problem - qemu uses them heavily and pretty successfully for this.
To me it looks like a solution adding permanent complexity to solve a problem that's, in practice, temporary. Once exeter is stable enough, we'll just require a recent version. And before that day, I doubt we'll want to debug / bisect issues by running any of the exeter-based tests. Every time I'm debugging a possible regression I come up with some stand-alone reproducer or manual test. If the test suite had caught the regression at a given point, then we wouldn't have hit the regression in the first place.
I'm personally fine without it and, given that I plan to update test/README.md soon anyway ('make' under test/ is not mentioned at all), I can mention this kind of problem as well, so it shouldn't be a big deal for others. But I wanted to know if you have thoughts or proposals on the matter, before applying this.
-- Stefano
[0] At some point, I do want to stabilise the exeter interfaces, and be concerned with backwards compatibility, which would largely fix this. However, at present I'm still finding stuff that wants to change at the exeter level often enough that I think the effort of maintaining compatibility would be prohibitive.
Right, I wouldn't care, I really can't see any practical need. In practice, the kind of breakages we have right now are something much more basic: outdated test/README.md and broken test/Makefile which I couldn't find a moment to take care of, yet. And I still need to killall -9 nstool every time. -- Stefano
participants (2)
-
David Gibson
-
Stefano Brivio