Commit Graph
52 Commits
Author SHA1 Message Date
Michal Nowak ab5309164b Add rr-related common test artifacts
(cherry picked from commit c607237b77)
2024-12-10 18:51:21 +01:00
Nicki KřížekandMichal Nowak 972a6722de Add all env vars to jinja2 templates
Ensure that the jinja2 templates have all the environment variables
which are available to the tests present.

This omission during the original 9.18 backport caused an issue where
port numbers (determined by the pytest framework) wouldn't be available
in jinja2 templates.
2024-11-26 16:10:27 +00:00
Nicki Křížek bbd398d846 Ignore test artifacts in .libs
Some tests may leave artifacts in the .libs directory. Ignore this
directory when detecting expected artifacts.

(cherry picked from commit cf606a9ead)
2024-11-26 10:10:44 +01:00
Nicki Křížek 9f72923518 Ensure pytest runner get proper outcome from flaky reruns
When a test is re-run by the flaky plugin, the TestReport outcomes
collected in the pytest_runtest_makereport() hook should be overriden.
Each of the setup/call/teardown phases is reported again and since we
care about the overall outcome, their respective results should be
overriden so that only the outcome from the final test (re)run gets
reported.

Prior to this change, it lead to a situation where an extra_artifact
generated during the test might be ignored. This was caused because the
check was skipped, since the test was incorrectly considered as "failed"
in the case where the test would fail on the first run, but pass on a
subsequent flaky rerun.

(cherry picked from commit b66fb31dcb)
2024-11-12 10:20:34 +00:00
Nicki Křížek b2996486f0 Remove invocations and mentions of clean.sh
(cherry picked from commit f2cb2e5723)
2024-11-11 15:04:52 +01:00
Nicki Křížek 347db7c40d Replace clean.sh files with extra_artifacts mark
The artifact lists in clean.sh and extra_artifacts might be slightly
different. The list was updated for each test to reflect the current
state.

(cherry picked from commit 7c259fe254)
2024-11-11 15:04:52 +01:00
Michał KępieńandNicki Křížek ddb75fc4d8 Add pytest fixture for checking test artifacts
Prior to introducing the pytest runner, clean.sh files were used as a
list of files that the test is expected to leave around as artifacts and
check that no extra files were created.

With the pytest runner, those scripts are no longer used, but the
ability to detect extraneous files is still useful. Add a new
"extra_artifacts" mark which can be used for the same purpose.

(cherry picked from commit 3a9f4edddc)
2024-11-11 15:04:52 +01:00
Nicki Křížek 89866d148a Support jinja2 templates in pytest runner
Configuration files in system tests which require some variables (e.g.
port numbers) filled in during test setup, can now use jinja2 templates
when `jinja2` python package is available.

Any `*.j2` file found within the system test directory will be
automatically rendered with the environment variables into a file
without the `.j2` extension by the pytest runner. E.g.
`ns1/named.conf.j2` will become `ns1/named.conf` during test setup. To
avoid automatic rendering, use `.j2.manual` extension and render the
files manually at test time.

New `templates` pytest fixture has been added. Its `render()` function
can be used to render a template with custom test variables. This can be
useful to fill in different config options during the test. With
advanced jinja2 template syntax, it can also be used to include/omit
entire sections of the config file rather than using `named1.conf.in`,
`named2.conf.in` etc.

(cherry picked from commit 60e118c4fb)
2024-10-31 14:01:12 +01:00
Nicki Křížek 2a0c3c8c14 Make system tests compatible with pytest 8.0.0+
The pytest collection mechanism has been overhauled in pytest 8.0.0,
resulting in a different node tree when collecting the tests. Ensure the
paths / names we're using that are derived from the node tree are
consistent across different pytest versions.

Particularly, this has affected the convenience symlink name (which is
supposed to be in the form of e.g. dns64_sh_dns64 for the dns64 module
and tests_sh_dns64.py module) and the test name that's logged at the
start of the test, which is supposed to include the system test
directory relative to the root system test directory as well as the
module name (e.g. dns64/tests_sh_dns64.py).

Related https://github.com/pytest-dev/pytest/issues/7777

(cherry picked from commit 7118cbed98)
2024-10-24 13:57:41 +02:00
Nicki Křížek 9ca6fcc4d5 Disable too-many/too-few pylint checks
Enforcing pylint standards and default for our test code seems
counter-productive. Since most of the newly added code are tests or is
test-related, encountering these checks rarely make us refactor the code
in other ways and we just disable these checks individually. Code that
is too complex or convoluted will be pointed out in reviews anyways.

(cherry picked from commit 7639c58c48)
2024-10-17 13:42:08 +02:00
Tom Krizek 51bd0f2949 Add utility logging functions to isctest.log
Unify the different loggers (conftest, module, test) into a single
interface. Remove the need to select the proper logger by automatically
selecting the most-specific logger currently available.

This also removes the need to use the logger/mlogger fixtures manually
and pass these around. This was especially annoying and unwieldy when
splitting the test cases into functions, because logger had to always be
passed around. Instead, it is now possible to use the
isctest.log.(debug,info,warning,error) functions.

(cherry picked from commit c60975f108)
2024-02-16 16:03:50 +01:00
Michał KępieńandMichal Nowak 24fd30f7eb Add wait_for_zones_loaded fixture
The wait_for_zones_loaded fixture waits for the "all zones loaded"
message in the named log file before the test function can proceed.

(cherry picked from commit 662a88055c)
2024-01-15 17:14:06 +01:00
Michał KępieńandŠtěpán Balážik 4eadaca4b0 Implement Python helpers for using RNDC in tests
Controlling named instances using RNDC is a common action in BIND 9
system tests.  However, there is currently no standardized way of doing
that from Python-based system tests, which leads to code duplication.
Add a set of Python classes and pytest fixtures which intend to simplify
and standardize use of RNDC in Python-based system tests.

For now, RNDC commands are sent to servers by invoking the rndc binary.
However, a switch to a native Python module able to send RNDC commands
without executing external binaries is expected to happen soon.  Even
when that happens, though, having the capability to invoke the rndc
binary (in order to test it) will remain useful.  Define a common Python
interface that such "RNDC executors" should implement (RNDCExecutor), in
order to make switching between them convenient.

Co-authored-by: Štěpán Balážik <stepan@isc.org>
(cherry picked from commit c38c29e84d)
2024-01-13 11:31:51 +01:00
Tom Krizek 1fe70c6095 Add system test utility package isctest
Create a utility package for code shared by the python tests. The
utility functions should use reasonable defaults and be split up into
modules according to their functionality.

Ensure assert rewriting is enabled for the modules to get the most
useful output from pytest.

(cherry picked from commit cba5a1d62c)
2023-12-05 14:27:41 +01:00
Tom Krizek 2ad197b37d Rename convenience symlink to pytest artifacts
The previous symlink name convention was prone to name collisions If a
system test contained both a shell test and a pytest module of the same
name (e.g. dnstap test has both tests.sh and tests_dnstap.py), then
these would have the same convenience symlink, which could cause test
setup issues as well as confusion when examining test artifacts.

Update the naming convention to include the full pytest module name.
This results in a slightly more verbose names for shell tests (e.g.
dnstap_sh_dnstap instead of the previous dnstap_dnstap), but it removes
the chance of a collision.

(cherry picked from commit fd13dfb097)
2023-09-20 16:04:40 +02:00
Tom Krizek 60c4356554 Use integers for ports fixtures in pytest
Reorganize individual port fixtures and re-use the ports fixture to
obtain their number. Store it as integer and only cast it to string when
setting it as environment variable.

(cherry picked from commit 8deb026748)
2023-09-20 14:51:05 +02:00
Tom Krizek 0ac22ebc95 Reformat conftest.py with black
(cherry picked from commit 197dac55a2)
2023-09-20 14:51:05 +02:00
Tom Krizek 7a28a76885 Remove legacy runner support from conftest.py
Remove code fork for legacy runner, reorganize imports and move a
pylint-silencing snippet to the top of the file. The rest of the code
was just unindented.

(cherry picked from commit d16e5fd5e5)
2023-09-20 14:51:02 +02:00
Tom Krizek 9d9f2dcda5 Fix pytest module detection for run.sh
To allow concurrent invocations of pytest, it is necessary to assign
ports properly to avoid conflicts. In order to do that, pytest needs to
know a complete list of all test modules.

When pytest is invoked from run.sh, the current working directory is the
system test directory. To properly detect other tests, the conftest.py
has to look in the bin/tests/system directory, rather than the current
working directory.

(cherry picked from commit d4502206a1)
2023-09-20 10:32:10 +02:00
Tom Krizek ae18bc33c5 Compile system test binaries during make
Using check_PROGRAMS would postpone compiling the binaries needed by
system tests until `make check` would be called. Since it's preferable
to invoke pytest directly to run the system test suite, compile these
binaries without installing them during `make all` instead by using
noinst_PROGRAMS.

This removes the need to use TESTS= make -e check hack invoked from
pytest to work around this issue.

(cherry picked from commit 21980b43b8)
2023-08-22 15:40:44 +02:00
Tom Krizek 4b3d0c0f46 Silence pylint's refactoring suggestions for system_test_dir()
While it'd be fairly easy to split the function up into smaller ones,
the readability wouldn't be improved in this case. Silence the
suggestions instead.

(cherry picked from commit 83ddca7690)
2023-08-21 16:07:30 +02:00
Tom Krizek 4f6ea4fa1b Improve tempdir logging for pytest runner
At the end of the test, display the symlink path to the artifact
directory in case it's preserved. Log the full tempdir name in debug
log.

(cherry picked from commit f91d0b13e8)
2023-08-21 16:07:30 +02:00
Tom Krizek 89e6d1bc26 Create symlinks to test artifacts for pytest runner
While temporary directories are useful for test execution to keep
everything clean, they are difficult to work with manually. Create a
symlink for each test artifact directory with a stable and predictable
path. The symlink always either points to the latest artifacts, or is
missing in case the last run succeeded.

Ensure these symlinked directories aren't detected as test suites by the
pytest runner.

(cherry picked from commit e1ca5c8071)
2023-08-21 16:07:28 +02:00
Tom Krizek 57b2966d0b Improve pytest message when sanitizer report is found
(cherry picked from commit b1a9d1fe25)
2023-08-21 15:16:53 +02:00
Michal Nowak 577f0723e0 Detect core dumps after BIND failed to stop cleanly
With the pytest runner, when BIND crashed during test runtime, the
get_core_dumps.sh script hasn't been run, and core dumps were not
detected.

(cherry picked from commit 89c77daddb)
2023-07-13 15:14:47 +02:00
Tom Krizek 1b8f0711f2 Fix base_port calculation in pytest runner
The selected base port should be in the range <port_min, port_max), the
formula was incorrect.

Credit for discovering this fault goes to Ondrej Sury.

(cherry picked from commit e8ea6b610b)
2023-05-30 15:37:29 +02:00
Tom Krizek f3c0005257 Tear down module logger handler in system tests
The module-level logger has a handler that writes into a temporary
directory. Ensure the logging output is flushed and the handler is
closed before attempting to remove this temporary directory.

(cherry picked from commit 0f8a2b07a4)
2023-05-23 17:41:35 +02:00
Tom Krizek e2f7dbcbd1 Remove "which" declaration from env vars in EL8+ tests
EL8+ systems declare "which" function using environment variables in the
/etc/profile.d/which2.sh file. Because of our suboptimal environment
variable detection, which is required in order to support the legacy
runner, these variables are picked up by the pytest runner.

If subprocesses are spawned with these environment variables set, it
will cause the following issue when they spawn yet another subprocess:

/bin/sh: which: line 1: syntax error: unexpected end of file
/bin/sh: error importing function definition for `which'

(cherry picked from commit 68b1c6877b)
2023-05-23 17:41:34 +02:00
Tom Krizek 5b5210854d Capture log output during pytest runner setup
Instantiate a new logger that is used during pytest initialization /
configuration. This logging isn't handled by pytest itself, since it
happens outside of any tests or fixtures.

Root logger can't be reused for this purpose, because that would
duplicate the logs. Instead, create a conftest-specific logger for this
purpose.

Unfortunately, this introduces another log file,
pytest.conftest.log.txt, which contains only the logging from pytest
initialization. However, unless one is debugging the runner /
environment, there should be no need to investigate this file.

(cherry picked from commit 12c724ee07)
2023-05-23 17:41:34 +02:00
Tom Krizek 16eeb36432 Execute long running system tests first
In order to take the most advantage of parallel execution of tests,
ensure certain long running tests are scheduled first.

The list of tests considered long-running was created empirically. In
addition to the test run time, its position in the default
(alphabetical) ordering was also taken into account.

(cherry picked from commit 99e2e50c0e)
2023-05-23 17:41:34 +02:00
Tom Krizek 1acb8a3f39 Add test specific logger for pytests
The logger fixture is provided as a test-level logging facility which
can be easily passed to tests to enable capturing and/or displaying
messages from tests written in Python.

While this works optimally with the pytest runner, messages on INFO
level or above will also be visible when using the legacy runner.

(cherry picked from commit 952776b61f)
2023-05-23 17:41:34 +02:00
Tom Krizek f0db1c27ba Ensure assertions and exceptions end up in system test log
If a test fails with an assertion failure or exception, its content
along with traceback is displayed in pytest output. This information
should be preserved in the test-specific logger for a given system test
to make it easier to debug test failures.

(cherry picked from commit 3a20e8d990)
2023-05-23 17:41:34 +02:00
Petr ŠpačekandTom Krizek 0277c5098c Use raw byte format of env variables in pytest
In order to avoid issues with decoding/encoding env variables due to
different encodings on different systems, deal with the environment
variables directly as bytes.

(cherry picked from commit 37ed9ad2f8)
2023-05-23 17:41:33 +02:00
Tom Krizek 445b30b883 Handle missing test_results due to pytest runner interrupt
If pytest execution is interrupted, the hook that exposes test_results
to the pytest session is never called so the results can't be
interpreted.

(cherry picked from commit 0a063f51d3)
2023-05-23 17:41:33 +02:00
Petr ŠpačekandTom Krizek a802e84cd5 Enable live logging for non-parallel pytest runs
This provides incremental output when test is running _without xdist_,
just like the old runner did.

With xdist the live output is not available, I believe because of
https://github.com/pytest-dev/pytest-xdist/issues/402
https://github.com/pytest-dev/pytest-xdist/pull/883 might help with
that, but I'm not going to hold my breath until it is available on
distros we use.

(cherry picked from commit d0619c7a18)
2023-05-23 17:41:33 +02:00
Tom Krizek a388a689cf Ensure --dist=loadscope is used when running pytest in parallel
The loadscope setting is required for parallel execution of our system
tests using pytest. The option ensure that all tests within a single
(module) scope will be assigned to the same worker.

This is neccessary because the worker sets up the nameservers for all
the tests within a module scope. If tests from the same module would be
assigned to different workers, then the setup could happen multiple
times, causing a race condition. This happens because each module uses
deterministic port numbers for the nameservers.

(cherry picked from commit 8f57bce7af)
2023-05-23 17:41:33 +02:00
Tom Krizek 3b6ca76f46 Add pytest functions for shell system tests
In order to run the shell system tests, the pytest runner has to pick
them up somehow. Adding an extra python file with a single function
for the shell tests for each system test proved to be the most
compatible way of running the shell tests across older pytest/xdist
versions.

Modify the legacy run.sh script to ignore these pytest-runner specific
glue files when executing tests written in pytest.

(cherry picked from commit 2f5bf6d971)

(manually added host/tests_sh_host.py, tkey/tests_sh_tkey.py on top)
2023-05-23 16:55:26 +02:00
Tom Krizek 0df2ea8fab Ignore tempdirs during pytest collection phase
(cherry picked from commit 8a406b73c9)
2023-05-23 16:17:24 +02:00
Tom Krizek b8d6434d5d Ensure compatiblity with older pytest
Special care needs to be taken to support older pytest / xdist versions.
The target versions are what is available in EL8, since that seems to
have the oldest versions that can be reasonably supported.

(cherry picked from commit 527ac6ad26)
2023-05-23 16:17:24 +02:00
Tom Krizek eaf64e93aa Keep the tempdir in case test setup/teardown fails
When an issue occurs inside a fixture (e.g. servers fail to start/stop),
the test result won't be detected as failed, but rather an error will be
thrown.

To ensure the tempdir is kept even if the test itself passes but the
system_test() fixture throws an error, a different mechanism is needed.
At the start of the critical test setup section, note that the fixture
hasn't finished yet. When this is detected in the system_test_dir()
fixture, it is recognized as error in test setup/teardown and the temp
directory is kept.

This may seem cumbersome, because it is. It's basically a workaround for
the way pytest handles fixtures and test errors in general.

(cherry picked from commit 247e90c382)
2023-05-23 16:17:24 +02:00
Tom Krizek cdbdbd9eaf Ensure tempdir is kept for failed system tests
The temporary directory contains artifacts for the pytest module. That
module may contain multiple individual tests which were executed
sequentially. The artifacts should be kept if even one of these tests
failed.

Since pytest doesn't have any facility to expose test results to
fixtures, customize the pytest_runtest_makereport() hook to enable that.
It stores the test results into a session scope variable which is
available in all fixtures.

When deciding whether to remove the temporary directory, find the
relevant test results for this module and don't remove the tmpdir if any
one the tests failed.

(cherry picked from commit 2d93ed8546)
2023-05-23 16:17:24 +02:00
Tom Krizek ba922ba774 Add --noclean option to pytest runner
Support the --noclean option to allow the user to keep the artifacts
from any test run.

(cherry picked from commit 8b1a906b39)
2023-05-23 16:17:24 +02:00
Tom Krizek d1e6400d63 Run system tests inside temporary directories
For every pytest module, create a copy of its system test directory and
run the test from that directory. This makes it easier to clean up
afterwards and makes it less error-prone when re-running (failed) tests.

Configure the logger to capture the module's log output into a separate
file available from the temporary directory. This is quite convenient
for exploring failures.

Cases where temporary directory should be kept are handled in a
follow-up commits.

(cherry picked from commit c571af8c8f)
2023-05-23 16:17:24 +02:00
Tom Krizek 0ed639010c Execute the system test workflow in pytest runner
This is basically the pytest re-implementation of the run.sh script.

The fixture is applied to every module and ensures complete test
setup/teardown, such as starting/stopping servers, detecting coredumps
etc.

Note that the fixture system_test_dir is not defined yet. It is omitted
now for review readability and it's added in follow-up commits.

(cherry picked from commit 2b64618624)
2023-05-23 16:17:24 +02:00
Tom Krizek 23cecd2190 Utility fixtures for pytest runner
Add fixtures for deriving system test name from the directory name and
for a module-specific logger.

Add fixtures to execute shell and perl scripts. Similar to how run.sh
calls commands, this functionality is also needed in pytest. The
fixtures take care of switching to a proper directory, logging
everything and handling errors.

Note that the fixture system_test_dir is not defined yet. It is omitted
now for review readability and it's added in follow-up commits.

(cherry picked from commit 6886cc1826)
2023-05-23 16:17:23 +02:00
Tom Krizek aa199e2726 Assign unique ports to pytest modules
This is basically a pytest re-implementation of the get_ports.sh script.
The main difference is that ports are assigned on a module basis, rather
than a directory basis. Module is the new atomic unit for parallel
execution, therefore it needs to have unique ports to avoid collisions.

Each module gets its ports through the env fixture which is updated with
ports and other module-specific variables.

(cherry picked from commit 0061758156)
2023-05-23 16:17:23 +02:00
Tom Krizek f23ce6a37f Ensure system test programs and deps are compiled
Some system tests require extra programs and/or dependencies to be
compiled first. This is done via `make check` with the automake
framework when using check_* variables such as check_PROGRAMS.

To avoid running any tests via the automake framework, set the TESTS
env variable to empty string and utilize `make -e check` to override
default Makefile variables with environment ones. This ensures automake
will only compile the needed dependencies without running any tests.

Additional consideration needs to be taken for xdist. The compilation
command should be called just once before any tests are executed. To
achieve that, use the pytest_configure() hook and check that the
PYTEST_XDIST_WORKER env variable isn't set -- if it is, it indicates
we're in the spawned xdist worker and the compilation was already done
by the main pytest process that spawned the workers.

This is mostly done to have on-par functionality with legacy test
framework. In the future, we should get rid of the need to run "empty"
make -e check and perhaps compile test-stuff by default.

(cherry picked from commit ee26066897)
2023-05-23 16:17:23 +02:00
Tom Krizek 6000883f8d Obtain env vars from conf.sh in pytest runner
The commands executed by pytest during a system test need to have the
same environment variables set as if they were executed by the run.sh
shell script.

It was decided that for the moment, legacy way of executing system tests
with run.sh should be kept, which complicates things a bit. In order to
avoid duplicating the required variables in both conf.sh and pytest, it
was decided to use the existing conf.sh as the only authoritative
place for the variables.

It is necessary to process the environment variables from conf.sh right
when conftest.py is loaded, since they might be needed right away (e.g.
to test for feature support during test collection).

This solution is a bit hacky and is only meant to be used during the
transitory phase when both pytest and the legacy run.sh are both
supported. In the future, a superior pytest-only solution should be
used.

For discussion of other options, refer to
https://gitlab.isc.org/isc-projects/bind9/-/merge_requests/6809#note_318889

(cherry picked from commit 2f7af791a1)
2023-05-23 16:17:23 +02:00
Tom Krizek 9112b51bb9 Support both pytest and legacy system test runner
The legacy system test framework uses pytest to execute some tests.
Since it'd be quite difficult to convince pytest to decide whether to
include conftest.py (or which ones to include when launching from
subdir), it makes more sense to have a shared conftest.py which is used
by both the legacy test runner invocations of pytest and the new pytest
system test runner. It is ugly, but once we drop support for the legacy
runner, we'll get rid of it.

Properly scope the *port fixtures in order to ensure they'll work as
expected with the new pytest runner. Instead of using "session" (which
means the fixture is only evaluated once for the entire execution of
pytest), use "module" scope, which is evaluated separately for each
module. The legacy runner invoked pytest for each system test
separately, while the new pytest runner is invoked once for all system
tests -- therefore it requires the more fine-grained "module" scope to
for the fixtures to work properly.

Remove python shebang, as conftest.py isn't supposed to be an executable
script.

(cherry picked from commit 30cb9b7e28)
2023-05-23 16:17:20 +02:00
Michał Kępień 4cda066de2 Add regression test for CVE-2022-1183
If sslyze is available in PATH, run it in a loop as part of the "doth"
system test.

(cherry picked from commit e97b4697cf)
2022-06-27 23:10:00 +02:00