| # Patchtest | |
| ## Introduction | |
| Patchtest is a test framework for community patches based on the standard | |
| unittest python module. As input, it needs three elements to work properly: | |
| - one or more patches in separate, mbox-formated files | |
| - a test suite | |
| - a target repository | |
| The first test suite intended to be used with patchtest is found in the | |
| openembedded-core repository [1], targeted for patches that get into the | |
| openembedded-core mailing list [2]. This suite is also intended as a | |
| baseline for development of similar suites for other layers as needed. | |
| Patchtest can either run on a host or a guest machine, depending on | |
| which environment you prefer. If you plan to test your own patches (a | |
| good practice before these are sent to the mailing list), the easiest | |
| way is to install and execute on your local host; on the other hand, if | |
| automatic testing is intended, the guest method is strongly recommended. | |
| The guest method requires the use of the meta-patchtest layer, in | |
| addition to the tools available in oe-core: | |
| https://git.yoctoproject.org/meta-patchtest/ | |
| ## Installation | |
| Patchtest checks patches which are expected to be applied to | |
| Yocto layers. Therefore, familiarity with the Yocto Project, its | |
| functionality, and image-build processes is assumed. Otherwise the | |
| [quick start guide](https://docs.yoctoproject.org/brief-yoctoprojectqs/index.html) | |
| contains the necessary information. | |
| As a Python application, the recommended way it should be installed | |
| (following Python best practices) is to use a virtual environment. A | |
| Python virtual environment provides a convenient sandbox into which its | |
| requirements can also be installed with out affecting a user's entire | |
| system at large. Patchtest makes use of a test suite found in oe-core, | |
| so it needs to be available as well. | |
| For example, to install patchtest into a Python virtual environment | |
| called "patchtest.venv" located at some/where in your filesystem: | |
| $ mkdir -p some/where | |
| $ cd some/where | |
| $ mkdir yocto | |
| $ pushd yocto | |
| $ git clone https://git.openembedded.org/openembedded-core | |
| $ git clone https://git.openembedded.org/bitbake | |
| $ git clone https://git.yoctoproject.org/meta-patchtest | |
| $ popd | |
| $ . yocto/openembedded-core/oe-init-build-env build yocto/bitbake | |
| $ cd .. | |
| $ python3 -m venv patchtest.venv | |
| $ . patchtest.venv/bin/activate | |
| (patchtest.venv) $ pip install -r yocto/openembedded-core/meta/lib/patchtest/requirements.txt | |
| In the above list of cloned repositories, the meta-patchtest layer is | |
| only needed if you intend to use patchtest in "guest" mode. Also the | |
| oe-core + bitbake clones can be replaced with poky instead. | |
| If "guest" mode will be used, the meta-patchtest layer needs to be added | |
| to the conf/bblayers.conf file generated above. | |
| If you would like to run the patchtest selftest found in oe-core, the | |
| openembedded-core/meta-selftest (or poky/meta-selftest, if using poky) | |
| layer also needs to be added to bblayers.conf. | |
| Once the installation is done, your directory layout will look like: | |
| . | |
| ├── build | |
| │ └── conf | |
| ├── yocto | |
| │ ├── bitbake | |
| │ ├── meta-patchtest | |
| │ └── openembedded-core | |
| └── patchtest.venv | |
| ├── bin | |
| ├── include | |
| ├── lib | |
| ├── lib64 -> lib | |
| ├── pyvenv.cfg | |
| └── share | |
| For git-pw (and therefore scripts such as patchtest-get-series) to work, you need | |
| to provide a Patchwork instance in your user's .gitconfig, like so (alternatively | |
| the project can be specified using the --project argument to git-pw on its | |
| cmdline): | |
| git config --global pw.server "https://patchwork.yoctoproject.org/api/1.2/" | |
| ## Usage | |
| ### Obtaining Patches | |
| Separate, mbox-formatted patch files can be obtained in a number of | |
| ways: | |
| - using b4 to obtain patches from a lore server | |
| - using git-pw to obtain patches from a patchwork server | |
| - using "git format-patch ..." to create patches from a git | |
| repository | |
| - using an email program, such as mutt or thunderbird, to obtain | |
| patches from a mailing list | |
| Alternatively, `scripts/patchtest-get-series` can be used to pull mbox files from | |
| the Patchwork instance configured previously in .gitconfig. It uses a log file | |
| called ".series_test.log" to store and compare series IDs so that the same | |
| versions of a patch are not tested multiple times unintentionally. By default, | |
| it will pull up to five patch series from the last 30 minutes using oe-core as | |
| the target project, but these parameters can be configured using the `--limit`, | |
| `--interval`, and `--project` arguments respectively. For more information, run | |
| `patchtest-get-series -h`. | |
| #### git-pw | |
| git-pw can be used with filters for users, patch/series IDs, and | |
| timeboxes if specific patches are desired. For more information, see the | |
| git-pw [documentation](https://patchwork.readthedocs.io/projects/git-pw/en/latest/). | |
| For example, to download a single patch from the Yocto Project's | |
| Patchwork server (and to demonstrate not having modified ~/.gitconfig): | |
| (patchtest.venv) $ mkdir gawk | |
| (patchtest.venv) $ git-pw --server https://patchwork.yoctoproject.org/api/1.2/ --project oe-core patch download --mbox 70101 gawk/ | |
| To download a series, for example, try: | |
| (patchtest.venv) $ mkdir clang | |
| (patchtest.venv) $ git-pw --server https://patchwork.yoctoproject.org/api/1.2 --project oe-core series download --separate 38107 clang/ | |
| #### git format-patch | |
| Patch files can be obtained directly from a git repository using `git | |
| format-patch -N` (where N is the number of patches starting from HEAD to | |
| generate) or using any other way of specifying a range of commit SHAs to | |
| git. | |
| This method would be the most likely used when testing patches in local | |
| mode before emailing them for review. | |
| #### b4 | |
| In order to use b4, it needs to be installed. Fortunately it is a Python | |
| program that is hosted on pypi and can easily be installed into the same | |
| Python virtual environment that was created to run patchwork: | |
| (patchtest.venv) $ pip install b4 | |
| (patchtest.venv) $ b4 --version | |
| 0.14.2 | |
| To fetch the same single patch using b4 that was fetched with git-pw | |
| earlier, use: | |
| (patchtest.venv) $ mkdir gawk-2 | |
| (patchtest.venv) $ b4 am -o gawk-2 https://lore.kernel.org/openembedded-core/20250912200740.2873851-1-Randy.MacLeod@windriver.com | |
| Fetching a patch series with b4 is a little more involved since b4 will | |
| create one mbox file with all the patches in the series in it. Given an | |
| mbox file with more than one patch in it, patchtest will only test the | |
| first one. So there needs to be a separate step to break apart the | |
| multiple patches into separate files: | |
| (patchtest.venv) $ mkdir clang-2 | |
| (patchtest.venv) $ b4 am -o ross https://lore.kernel.org/openembedded-core/20250914133258.2625735-1-ross.burton@arm.com | |
| (patchtest.venv) $ cat clang-2/v2_20250914_ross_burton_clang_improve_opt_viewer_packageconfig.mbx | formail -ds sh -c 'cat > ross/msg.$FILENO' | |
| NOTE: the formail utility is part of the procmail package for most Linux | |
| distributions. | |
| #### mail user agents (MUA) | |
| Most email applications have a way of saving patch emails. Details for | |
| each MUA is beyond the scope of this document, but it is possible in | |
| most cases. The only catch is that each patch has to be saved in mbox | |
| format in its own individual file. Some client applications prefer to | |
| save emails in the Maildir format, and some programs will save a set of | |
| patches into one mbox file. The formail program from the procmail | |
| package is useful for manipulating and converting between formats and | |
| storage formats. | |
| ### Host Mode | |
| To run patchtest in "host" mode, do the following: | |
| 1. Using openembedded-core or poky, do the following if re-using the | |
| installation given in the installation procedure above: | |
| $ . yocto/openembedded-core/oe-init-build-env build yocto/bitbake | |
| or | |
| $ . yocto/poky/oe-init-build-env | |
| 2. Activate the Python virtual environment that was created using the | |
| steps from the installation procedure given above: | |
| $ . patchtest.venv/bin/activate | |
| 3. Obtain one or more patches (see section above) | |
| 4. Run patchtest on a patch file by doing the following: | |
| (patchtest.venv) $ patchtest --patch /path/to/patch/file | |
| or, if you have stored the patch files in a directory, do: | |
| (patchtest.venv) $ patchtest --directory /path/to/patch/directory | |
| For example, to test | |
| `master-gcc-Fix--fstack-protector-issue-on-aarch64.patch` against the | |
| oe-core test suite: | |
| (patchtest.venv) $ patchtest --patch master-gcc-Fix--fstack-protector-issue-on-aarch64.patch | |
| If you want to use a different test suite or target repository, you | |
| can use the --testdir and --repodir flags: | |
| (patchtest.venv) $ patchtest --patch /path/to/patch/file --repodir /path/to/repo --testdir /path/to/test/dir | |
| ### Guest Mode | |
| Patchtest's guest mode has been refactored to more closely mirror the | |
| typical Yocto Project image build workflow, but there are still some key | |
| differences to keep in mind. The primary objective is to provide a level | |
| of isolation from the host when testing patches pulled automatically | |
| from the mailing lists. When executed this way, the test process is | |
| essentially running random code from the internet and could be | |
| catastrophic if malicious bits or even poorly-handled edge cases aren't | |
| protected against. In order to use this mode, the | |
| https://git.yoctoproject.org/meta-patchtest/ repository must be cloned | |
| and added to bblayers.conf. | |
| The general flow of guest mode is: | |
| 1. Run patchtest-setup-sharedir --directory <dirname> to create a | |
| directory for mounting | |
| 2. Collect patches via patchtest-get-series (or other manual step) into the | |
| <dirname>/mboxes path | |
| 3. Ensure that a user with ID 1200 has appropriate read/write | |
| permissions to <dirname> and <dirname>/mboxes, so that the | |
| "patchtest" user in the core-image-patchtest image can function | |
| 4. Build the core-image-patchtest image | |
| 5. Run the core-image-patchtest image with the mounted sharedir, like | |
| so: | |
| `runqemu kvm nographic qemuparams="-snapshot -fsdev | |
| local,id=test_mount,path=/workspace/yocto/poky/build/patchtestdir,security_model=mapped | |
| -device virtio-9p-pci,fsdev=test_mount,mount_tag=test_mount -smp 4 -m | |
| 2048"` | |
| Patchtest is run by an initscript for the core-image-patchtest image and | |
| shuts down after completion, so there is no input required from a user | |
| during operation. Unlike in host mode, the guest is designed to | |
| automatically generate test result files, in the same directory as the | |
| targeted patch files but with .testresult as an extension. These contain | |
| the entire output of the patchtest run for each respective pass, | |
| including the PASS, FAIL, and SKIP indicators for each test run. | |
| ### Running Patchtest Selftests | |
| Patchtest also includes selftests, which are currently in the form of | |
| several contrived patch files and a runner script found in | |
| `meta/lib/patchtest/selftest/`. In order to run these, the | |
| `meta-selftest` layer must be added to bblayers.conf. It is also | |
| recommended to set BB_SERVER_TIMEOUT (and thus enable memory-resident | |
| bitbake) in local.conf to reduce runtime, as the bitbake startup process | |
| will otherwise add to it significantly when restarted for each test | |
| patch. | |
| If you have setup a Python virtual environment and sourced the | |
| oe-init-build-env script to run patchtest following the directions | |
| provided above in the "Installation" section, and you have added the | |
| meta-selftest layer (from oe-core or poky) to your build, running the | |
| patchtest selftest is as simple as: | |
| (patchtest.venv) $ yocto/openembedded-core/meta/lib/patchtest/selftest/selftest | |
| or: | |
| (patchtest.venv) $ yocto/poky/meta/lib/patchtest/selftest/selftest | |
| ## Contributing | |
| The yocto mailing list (openembedded-core@lists.openembedded.org) is used for questions, | |
| comments and patch review. It is subscriber only, so please register before | |
| posting. | |
| When sending single patches, please use something like: | |
| git send-email -M -1 --to=openembedded-core@lists.openembedded.org --subject-prefix=OE-core][PATCH | |
| ## Maintenance | |
| ----------- | |
| Maintainers: | |
| Trevor Gamblin <tgamblin@baylibre.com> | |
| ## Links | |
| ----- | |
| [1] https://git.openembedded.org/openembedded-core/ | |
| [2] https://www.yoctoproject.org/community/mailing-lists/ |