rpm/tests
Michal Domonkos 78cecdc3ab Support Fedora 41 in Dockerfile
This is needed for "make check" to work on a Fedora 41 host where the
FROM directive is overridden to fedora:41.

- Drop the workaround for gdb-headless on F41, it's no longer available
  there and the bug is fixed on F40+:
  https://bugzilla.redhat.com/show_bug.cgi?id=2310156

- Don't try to remove rpm-sign-libs and python3-rpm on F41 since dnf5 no
  longer pulls them in.

- Make sure to call "dnf clean all" before "rpm -e" as python3-rpm is
  needed by dnf4 to function (hence the duplicated call).

- Add a comment at the top saying which Fedora versions are supported by
  the Dockerfile.  This could be checked automatically during cmake
  config but let's leave that for later.

- Detect F41 vs. older by looking for the dnf5 binary, it's the easiest
  way.
2024-10-31 13:54:49 +01:00
..
data rpmKeyring: Support keys with the same key ID 2024-10-24 12:15:57 +03:00
pinned Replace per-file libmagic strings with MIME types in v6 packages 2024-09-24 11:57:12 +02:00
CMakeLists.txt brp-remove-la-files: Remove symlinks, too 2024-09-19 09:23:35 +03:00
Dockerfile
Dockerfile.fedora Support Fedora 41 in Dockerfile 2024-10-31 13:54:49 +01:00
README.md Add syntactic sugar for non-root user tests 2024-08-01 10:27:25 +03:00
atlocal.in Add syntactic sugar for non-root user tests 2024-08-01 10:27:25 +03:00
local.at Add syntactic sugar for non-root user tests 2024-08-01 10:27:25 +03:00
mktree.common
mktree.oci
mktree.rootfs
package.m4.in
rpmbrp.at brp-remove-la-files: Remove symlinks, too 2024-09-19 09:23:35 +03:00
rpmbuild.at Silence extra output on rpmspec query on Buildsystem specs 2024-10-30 11:07:16 +01:00
rpmbuildid.at
rpmconfig.at
rpmconfig2.at
rpmconfig3.at
rpmconflict.at
rpmdb.at Use full key fingerprint for gpg-pubkey version and keystore 2024-10-21 11:24:10 +02:00
rpmdepmatch.at
rpmdeps.at
rpmdevel.at
rpme.at Fix -V option usage in our tests 2024-08-21 17:05:50 +03:00
rpmgeneral.at Replace per-file libmagic strings with MIME types in v6 packages 2024-09-24 11:57:12 +02:00
rpmi.at Fix FA_TOUCH'ed files getting removed on failed update 2024-10-21 11:56:36 +02:00
rpmio.at
rpmmacro.at Require macro filenames to end in alphanum char 2024-10-28 08:31:53 +01:00
rpmorder.at
rpmpgp.at
rpmpgpcheck.c
rpmpgppubkeyfingerprint.c
rpmpkgfmt.at Drop support for installing v3 packages 2024-09-19 16:36:58 +02:00
rpmpython.at Make vfyflags API test not depend on rpm default configuration 2024-09-13 12:03:45 +02:00
rpmquery.at Use long PGP Key IDs for all outputs 2024-10-03 09:01:44 +03:00
rpmreplace.at
rpmscript.at Filter Lua deprecation warnings based on the originating rpm version 2024-09-23 19:09:45 +02:00
rpmsigdig.at Drill pubkeys one level deeper into the keystore APIs 2024-10-28 08:34:50 +01:00
rpmspec.at
rpmtests.sh
rpmvercmp.at
rpmverify.at Migrate a bunch of tests away from the early v4 hello-1.0 test packages 2024-09-13 12:03:45 +02:00
rpmvfylevel.at Don't print key ID if we have the key fingerprint 2024-10-03 09:01:44 +03:00

README.md

Tests

Introduction

This test-suite builds an OCI image matching the host OS with a fresh RPM installation layered on top (with make install), ready to be tested in a container, either automatically by a script (via make check) or in an interactive shell (via make shell).

Prerequisites

To use this test-suite, you need either of:

  1. Podman
  2. Docker

[!IMPORTANT] CMake integration (native mode) is currently only available on Fedora Linux hosts with Podman installed, on other systems a fresh build of RPM will be done as part of a Fedora-based image (non-native mode).

Running all tests

To build the image (if not built yet) and perform automated testing, run:

make check

The number of tests performed depends on features enabled at configure time, at least the CMake option ENABLE_PYTHON=<ON|OFF>. See also the INSTALL file for more information.

If the test-suite is configured in native mode, it may sometimes be useful to verify that everything passes in non-native mode too as that's what our CI uses. To do that, run:

make ci

Selective testing

To run single tests, you can run the commands:

make check TESTOPTS="$NNN $MMM"

where NNN and MMM are the numbers of the tests to be run.

You can also select tests by keywords used in their description by using the command:

 make check TESTOPTS="-k $KEYWORD"

Use multiple -k parameters to have tests with different keywords run. Use -k $KEYWORD1,$KEYWORD2 to execute tests matching both KEYWORD1 and KEYWORD2.

For all available options, see the output of the command:

./rpmtests --help

By default, tests are executed in parallel using all available cores, pass a specific -jN value to limit.

Interactive testing

To drop into an interactive GNU Autotest shell, run:

make atshell

This is like a singular, empty RPMTEST_CHECK with a shell running in it and a writable tree available at the path stored in $RPMTEST. From this shell, you can run the same commands as a normal test would, such as runroot rpm. This can be used to quickly prototype (or debug) a test.

You can also drop straight into the $RPMTEST container like so:

make shell

This is just a shorthand for make atshell followed by runroot_other bash.

To factory-reset the $RPMTEST tree, run:

make reset

To only build the OCI image, use:

make tree

You can also just use Podman or Docker directly to manage containers (the image is named rpm when built). For example, to run a shell:

podman run -it rpm

Understanding the tests

Optimizations

Since the test-suite consists of several hundreds of tests and is meant to be run repeatedly during development, it's optimized for speed.

Instead of running each test in a separate OCI container, all the tests run in a single, immutable OCI container. Mutable, disposable snapshots of its root filesystem are then created on demand for tests that need write access to it (such as those installing or removing packages). These tests perform the desired operation through a lightweight, nested container with the snapshot set as its root directory.

This reduces the number of containers needed while still ensuring that each test operates in a pristine environment, without affecting any other test or the test logic itself. Snapshots are created with OverlayFS and nested containers with Bubblewrap which heavily reduces the startup time of each test when compared to a full-blown OCI runtime.

Since this is done from the immutable OCI container, that container needs to run as --privileged in order to allow the creation of nested namespaces.

Layout

The OCI image is built from a Dockerfile.<osname> where <osname> is the host OS name (e.g. fedora). Currently, we only have Dockerfile.fedora, contributions for other distros are welcome. The Dockerfile symlink points to the file that should be used in non-native mode (see above).

The test script that's executed in the OCI container is written in GNU Autotest and is compiled from the rpmtests.at file. The individual tests are split into several files with the .at suffix, each covering a specific area within RPM, such as package building, transactions or configuration, which are then included by the top-level rpmtests.at script.

Writing tests

For the typical structure of a single test, consult GNU Autotest's documentation as well as the existing tests. Below are the specifics of RPM's test-suite:

  • Use RPMTEST_CHECK instead of AT_CHECK
  • Use RPMTEST_CLEANUP instead of AT_CLEANUP
  • Use RPMTEST_SETUP or RPMDB_INIT to create a mutable snapshot (optional)
    • The absolute path to the snapshot's root is stored in the $RPMTEST environment variable, modify the directory tree as you wish
    • To run RPM inside the snapshot, use the runroot prefix, e.g. runroot rpm ...
    • To run any other binary inside the snapshot, use runroot_other instead
    • By default, runroot and runroot_other will operate in a clean environment with only a handful of variables preset. To pass your own variable(s), use --setenv (once for each variable), e.g. runroot --setenv FOO "foo" rpm ...
  • Use RPMTEST_USER to create a regular UNIX user in a mutable snapshot
    • The username is stored in the $RPMUSER environment variable
    • To run a binary as $RPMUSER inside the snapshot, use runroot_user (this calls sudo(8) underneath)
    • You can create a custom user (or users) by supplying a list of usernames to the macro, e.g. RPMTEST_USER([user1, user2]). Then, use runroot_user -n <name> to run a binary as a specific user
  • If no snapshot was used, just call the RPM binaries normally
  • Store any working files in the current directory (it's always writable)