Skip to content

Commit

Permalink
README-pytest.md: Add documentation of the implementation details
Browse files Browse the repository at this point in the history
Signed-off-by: Bernhard Kaindl <[email protected]>
  • Loading branch information
bernhardkaindl committed Nov 22, 2023
1 parent 96d9f2e commit ec1779b
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
28 changes: 27 additions & 1 deletion README-pytest.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
5 changes: 5 additions & 0 deletions tests/integration/namespace_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <command>` uses. Namespace is active even without fork():
Expand Down

0 comments on commit ec1779b

Please sign in to comment.