From ec1779b6f155350167ff2a1990b4c03aabfee23a Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Wed, 22 Nov 2023 01:01:37 +0100 Subject: [PATCH] README-pytest.md: Add documentation of the implementation details Signed-off-by: Bernhard Kaindl --- README-pytest.md | 28 +++++++++++++++++++++++- tests/integration/namespace_container.py | 5 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/README-pytest.md b/README-pytest.md index 17f84491..6ec1b648 100644 --- a/README-pytest.md +++ b/README-pytest.md @@ -8,7 +8,8 @@ Also, care needed to be taken to check their logs: There can be errors in such shell scripts which go unnoticed. And these can make the test pass even when the `bugtool` output was not properly verified. -This `pytest` test framework which runs `xen-bugtool` with simulated `root` capabilities, can be run by any regular user and does not need special system configuration. +This `pytest` test framework which runs `xen-bugtool` with simulated `root` capabilities. +It can be run by any regular user and does not need special system configuration. ### Installing packages to run the `pytest`-based test suite @@ -45,3 +46,28 @@ tests/integration/test_xenserver_config.py::test_bugtool_entries_xenserver_confi ====================================== 1 passed in 0.19s ====================================== ``` + +### Implementation Details +#### Namespace container implementation +The container is provided by [tests/integration/namespace_container.py](tests/integration/namespace_container.py). +Implements what `/usr/bin/unshare --map-root-user --mount --net` does, and mounts test directories: +- `--map-root-user` Creates a Linux user namespace: + In it, the effective user and group IDs of the current user are mapped to the superuser UID and GID. + - Because this is done in a new user namespace, this "fakes" the effective user ID to be root. + - It does not elevate the capabilities of the real user in any way, it only appears to look like it. + - This is what `xen-bugtool ` needs: It checks if it is called by the root user. + - It also makes it possible to isolating the network and mount file systems in the mount namespace. +- `--mount`: Creates a Linux mount namespace for mounting temporary file systems and bind-mounting test data. +- `--net`: Creates a Linux network namespace for ensuring that `bugtool` works without outside connectivity. +- Then, it bind-mounts the directory trees below `tests/integration/dom0-templates` into the container. + +That means it runs the object under test (`xen-bugtool`) runs in an isolated test environment. + +For each test case, the test fixture and the test case code do the following: +- The fixture mounts a `tmpfs` directory for `bugtool` to use for its output at the static path it uses. +- The fixture yields to let the test case code execute. +- The test case code can run `xen-bugtool`. +- The function to run it checks that the `inventory.xml` in the output archive conforms to the XML schema. +- The test case checks all output files and removes all files that it successfully verified. +- The fixture then assert that the test case has not left any remaining unexpected files in the output tree. +- The fixture then unmounts the temporary output directory for the next test case to start afresh. diff --git a/tests/integration/namespace_container.py b/tests/integration/namespace_container.py index 4500f879..4db0ac1f 100644 --- a/tests/integration/namespace_container.py +++ b/tests/integration/namespace_container.py @@ -47,6 +47,11 @@ def umount(target): raise OSError(errno, "umount " + target + ": " + os.strerror(errno)) + # Create a temporary namespace for the pytest session. The xen-bugtool processes will run in it as well. + # The tests run inside a Linux user- and mount namespace. This is needed because xen-bugtool requires to + # be run as root and checks it. The mount namespace with a tmpfs mount for the output data also enables + # `xen-bugtool` to have it's own private "/var/opt/xen/bug-report output directory. It allows us to + # bind-mount the directory trees with test files at the places where `xen-bugtool` collects them from: def activate_private_test_namespace(bindmount_root, bindmount_mountpoints): """Activate a new private mount, network and user namespace with the user behaving like uid 0 (root)""" # Implements the sequence that `unshare -rmn ` uses. Namespace is active even without fork():