tests: add a unit test suite and measure coverage - #22
Open
insatomcat wants to merge 3 commits into
Open
Conversation
insatomcat
marked this pull request as draft
August 2, 2026 18:01
insatomcat
marked this pull request as ready for review
August 3, 2026 07:56
setup_ovs.py imports yaml to read .yaml and .yml configuration files, but the project declared no dependency at all. An installed package therefore raised ModuleNotFoundError on those files unless PyYAML happened to be present for another reason. Signed-off-by: Florent Carli <florent.carli@rte-france.com>
The project had no test at all, so the two OpenSSF gold coverage criteria (test_statement_coverage90 and test_branch_coverage80) could not be evaluated: they ask for a measured figure, not for a suite that merely exists. Add a pytest suite covering the five modules. Everything that touches the system is mocked (subprocess, sysfs, /proc, the network stack), so the suite needs neither root nor a cluster and runs anywhere. It measures 99.09 percent of statements and 98.65 percent of branches. Enable branch coverage in pyproject.toml and add a test extra. No fail_under yet: the point of this commit is an honest baseline. Five tests are marked xfail(strict=True). Each pins a defect found while writing the suite rather than encoding it as expected behaviour, so the suite fails again once the defect is fixed and the marker has to go. All five predate this branch, they come from the initial import of the repository. Signed-off-by: Florent Carli <florent.carli@rte-france.com>
The repository had no CI. Add a workflow that runs the suite on python 3.9 to 3.13, publishes the coverage table in the run summary, and checks that the wheel builds reproducibly. Coverage evidence does not depend on a third party: the OpenSSF criteria are self-asserted and only require a FLOSS tool able to measure them, which coverage.py is. The run summary is therefore enough on its own. Reproducible build: two builds with SOURCE_DATE_EPOCH pinned produce byte-identical wheels, without it they differ because setuptools stamps the archive with the source mtimes. The job builds the wheel twice and compares the SHA-256. It builds outside the work tree, since the project uses a flat layout and an output directory next to setup_ovs/ would be picked up as a second top-level package. Validation happens on pull requests, which build the simulated merge commit. main is built too, but minimally, one python version and no reproducible build job: SonarCloud needs an analysis of main as the reference for the new code comparison, and that analysis needs a coverage report. Actions are pinned to full commit SHAs and the CI toolchain is pinned in requirements-ci.txt, so a run cannot silently pick up a new release. sonar-project.properties declares the coverage report path. It only takes effect once Automatic Analysis is turned off on the SonarCloud project, since that mode never runs the tests. The scanner step stays skipped while SONAR_TOKEN is unset. Signed-off-by: Florent Carli <florent.carli@rte-france.com>
insatomcat
force-pushed
the
add-tests-and-coverage
branch
from
August 3, 2026 08:00
e43b4aa to
e5917f6
Compare
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



The repository had no test and no CI. The two OpenSSF gold coverage criteria (
test_statement_coverage90andtest_branch_coverage80) could therefore not be evaluated at all: they ask for a measured figure, not for a test suite that merely exists.What this brings
A pytest suite of 219 tests over the five modules, running in about 0.2 s. Everything that touches the system is mocked (
subprocess, sysfs,/proc, the network stack), so the suite needs neither root, nor OVS, nor a cluster, and runs on any machine.Measured result:
test_statement_coverage90test_branch_coverage80build_reproducibleSOURCE_DATE_EPOCHContents
tests/, atestextra, and branch coverage enabled inpyproject.tomlsonar-project.propertiesso the report is importedrequirements-ci.txt, a pinned toolchain used as a pip constraints file, so a CI run does not silently pick up a new release of pytest or build between two runs. Every pin supports Python 3.9 to 3.13. Actions are pinned to full commit SHAs for the same reason, with the major version kept in a trailing comment.setup_ovs.pyimportsyamlto read.yamland.ymlconfigurations, but nothing required it, so an installed package crashed on those files.Reproducible build
Measured both ways rather than assumed. Two builds with
SOURCE_DATE_EPOCHpinned produce byte-for-byte identical wheels. Without it they differ: setuptools stamps the archive with the source file mtimes, which change on every checkout. Thereproducible-buildjob therefore builds the wheel twice and compares the SHA-256 of the two archives.Bugs found while writing the tests, to be fixed in a follow-up
This pull request changes no production code.
git diff main..HEAD -- setup_ovs/is empty. The five defects below were not introduced here:git log -Lputs every one of them in6c83aa0, "init repo from meta-seapath folder", 2022-05-21. They have been there since the repository was created, over four years ago.Writing the tests did not create them, it executed those code paths for the first time. That is also why the coverage is not 100 %: the four uncovered statements in
check.pyare literally the dead code these defects produce, and no input can reach them.They are deliberately left unfixed here. Correcting them means changing the behaviour of validation code that has been running on SEAPATH clusters for four years, which deserves its own pull request and its own discussion rather than being buried in a test suite. Mixing the two would also make this diff impossible to review: right now it adds tests and touches nothing else.
None of them is encoded as expected behaviour either. Each is marked
xfail(strict=True)with its reason, so the day one is fixed the suite goes red and the marker has to be removed. The cleanup cannot be forgotten. They are listed intests/test_helpers.py:180andtests/test_check.pylines 324, 382, 427 and 520, andpytest -rxprints them with their reason on every run.helpers.run_commanddoes nothing when the caller passescheck=(helpers.py:60). Thereturn subprocess.run(...)sits inside theif "check" not in kargsbranch. No caller passeschecktoday, so it is latent, but it is a trap for the next one.tagrange is never validated (check.py:283). The guard isif "vlan" in portwhile the attribute actually consumed byovs._create_bridgesistag.check.py:270): it sits insideif attribute in portand then testsattribute not in port. A vxlan port with neitherkeynorremote_ippasses the check, then raisesKeyErrorfurther down inovs.py:239.check.py:111)._attribute_is_a_portis documented as a TCP/UDP port check but enforces the VLAN tag range, 0 to 4095. A TCP/UDP port goes up to 65535.check.py:165).dpdk_interfacesandsystem_interfacesare locals of_check_port_configuration, which runs once per port, so they are always empty.SonarCloud analysis
The project now runs CI-based analysis. Automatic Analysis has been turned off
and
SONAR_TOKENis configured, so the scanner step actually runs and thecoverage report is imported. Automatic Analysis could never have done it: it
runs neither the build nor the tests, and the Sonar documentation states
plainly that
"Code coverage information is not supported".The first real analysis confirms the figures measured locally:
line_coveragebranch_coveragecoverage(combined)The quality gate passes on its five conditions.
new_coverageis notevaluated, since
new_lines_to_coveris empty: this branch adds no line tosonar.sources.Worth knowing for later: the analysis token expires. When it does, the scanner
will fail with a
403and nothing will warn beforehand. That is exactly thestate vm_manager is in today, with a token issued in 2023.
Why the CI matrix does not start at Python 3.6
pyproject.tomldeclaresrequires-python = ">=3.6". That declaration is factually wrong: the package cannot run on 3.6.subprocess.run()is called withcapture_output=Truein two places,setup_ovs/check.py:18andsetup_ovs/ovs.py:76. That argument was added in Python 3.7. On 3.6 both calls raiseTypeError, which meanssystem_check()andclear_ovs()fail immediately. So the real floor is at least 3.7, whatever the metadata says. Python 3.6 itself has been end of life since December 2021.The matrix therefore runs 3.9 to 3.13, the versions available on current GitHub runners. 3.7 and 3.8 are also end of life and are no longer provided there, so testing the declared floor is not possible even if we wanted to.
I have not changed
requires-python, because lowering or raising it is a packaging decision that depends on what SEAPATH actually deploys on, not on what the code happens to tolerate. Tell me the real floor and I will align the metadata and the matrix in one go.This is not purely cosmetic. It also blocks a deprecation: the build warns that
license = { text = "Apache-2.0" }should become a plain SPDX string, and that fix requiressetuptools>=77inbuild-system. Stable distributions ship considerably older setuptools, so raising that floor could break building the package on the SEAPATH target. The warning is not fatal before 2027-02-18, so both questions are better settled together than one at a time.