summaryrefslogtreecommitdiffstats
path: root/tests/README.md
diff options
context:
space:
mode:
authorBruce Ashfield <bruce.ashfield@gmail.com>2026-01-01 17:15:29 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2026-02-09 03:32:52 +0000
commit1165c61f5ab8ada644c7def03e991890c4d380ca (patch)
tree1cd1c1d58039afad5a1d24b5c10d8030237e2d7c /tests/README.md
parentc32e1081c81ba27f0d5a21a1885601f04d329d21 (diff)
downloadmeta-virtualization-1165c61f5ab8ada644c7def03e991890c4d380ca.tar.gz
tests: add pytest framework for vdkr and vpdmn
Add pytest-based test suite for testing vdkr and vpdmn CLI tools. Tests use a separate state directory (~/.vdkr-test/) to avoid interfering with production images. Test files: - conftest.py: Pytest fixtures for VdkrRunner and VpdmnRunner - test_vdkr.py: Docker CLI tests (images, vimport, vrun, volumes, etc.) - test_vpdmn.py: Podman CLI tests (mirrors vdkr test coverage) - memres-test.sh: Helper script for running tests with memres - pytest.ini: Pytest configuration and markers Test categories: - Basic operations: images, info, version - Import/export: vimport, load, save - Container execution: vrun, run, exec - Storage management: system df, vstorage - Memory resident mode: memres/vmemres start/stop/status Running tests: pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer-standalone pytest tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer-standalone Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'tests/README.md')
-rw-r--r--tests/README.md569
1 files changed, 569 insertions, 0 deletions
diff --git a/tests/README.md b/tests/README.md
new file mode 100644
index 00000000..6a02678b
--- /dev/null
+++ b/tests/README.md
@@ -0,0 +1,569 @@
1# Tests for vdkr, vpdmn and container-cross-install
2
3Pytest-based test suite for:
4- **vdkr**: Docker CLI for cross-architecture emulation
5- **vpdmn**: Podman CLI for cross-architecture emulation
6- **container-cross-install**: Yocto container bundling system
7
8## Requirements
9
10```bash
11pip install pytest pytest-timeout pexpect
12```
13
14- `pytest` - Test framework
15- `pytest-timeout` - Test timeout handling
16- `pexpect` - Required for boot tests (QEMU console interaction)
17
18---
19
20## vdkr Tests
21
22### Prerequisites
23
24Before running vdkr tests, you must build the standalone tarball:
25
26```bash
27# 1. Set up your Yocto build environment
28cd /opt/bruce/poky
29source oe-init-build-env
30
31# 2. Ensure multiconfig is enabled in conf/local.conf:
32# BBMULTICONFIG = "vruntime-aarch64 vruntime-x86-64"
33
34# 3. Build the standalone SDK tarball (includes blobs + QEMU)
35MACHINE=qemux86-64 bitbake vcontainer-tarball
36# Output: tmp/deploy/sdk/vcontainer-standalone-x86_64.sh
37
38# 4. Extract the tarball (self-extracting installer)
39/opt/bruce/poky/build/tmp/deploy/sdk/vcontainer-standalone-x86_64.sh -d /tmp/vcontainer -y
40
41# 5. Set up the environment
42cd /tmp/vcontainer
43source init-env.sh
44```
45
46### Running vdkr Tests
47
48Tests use a separate state directory (`~/.vdkr-test/`) to avoid interfering with your production images in `~/.vdkr/`.
49
50```bash
51# Run all vdkr tests
52cd /opt/bruce/poky/meta-virtualization
53pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer
54
55# Run with memres pre-started (much faster - starts once, reuses for all tests)
56./tests/memres-test.sh start --vdkr-dir /tmp/vcontainer
57pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer --skip-destructive
58./tests/memres-test.sh stop --vdkr-dir /tmp/vcontainer
59
60# Run only fast tests (skip network/slow tests)
61pytest tests/test_vdkr.py -v -m "not slow and not network" --vdkr-dir /tmp/vcontainer
62
63# Run specific test class
64pytest tests/test_vdkr.py::TestMemresBasic -v --vdkr-dir /tmp/vcontainer
65
66# Run with an OCI image for import tests
67pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer \
68 --oci-image /opt/bruce/poky/build/tmp/deploy/images/qemux86-64/my-container-oci
69```
70
71### vdkr Test Options
72
73| Option | Description |
74|--------|-------------|
75| `--vdkr-dir PATH` | Path to extracted vdkr standalone directory (required) |
76| `--arch ARCH` | Target architecture: x86_64 or aarch64 (default: x86_64) |
77| `--skip-destructive` | Skip tests that stop memres or clean state (use when memres is pre-started) |
78| `--oci-image PATH` | Path to OCI image directory for import tests |
79
80### Testing ARM64 Architecture
81
82When testing ARM64 containers (e.g., after building with `MACHINE=qemuarm64`):
83
84```bash
85# Run tests for aarch64
86pytest tests/test_vdkr.py tests/test_vpdmn.py -v \
87 --vdkr-dir /tmp/vcontainer \
88 --arch aarch64 \
89 --oci-image /opt/bruce/poky/build/tmp/deploy/images/qemuarm64/container-app-base-latest-oci
90```
91
92**Important**: The `--arch` flag must match the OCI image architecture. An arm64 OCI image
93requires `--arch aarch64`, and an x86_64 OCI image requires `--arch x86_64` (the default).
94
95---
96
97## vpdmn Tests
98
99vpdmn tests mirror the vdkr tests but for Podman. They use a separate state directory (`~/.vpdmn-test/`).
100
101### Running vpdmn Tests
102
103```bash
104# Run all vpdmn tests
105cd /opt/bruce/poky/meta-virtualization
106pytest tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer
107
108# Run with memres pre-started (much faster)
109./tests/memres-test.sh start --vdkr-dir /tmp/vcontainer --tool vpdmn
110pytest tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer --skip-destructive
111./tests/memres-test.sh stop --vdkr-dir /tmp/vcontainer --tool vpdmn
112
113# Run only fast tests (skip network/slow tests)
114pytest tests/test_vpdmn.py -v -m "not slow and not network" --vdkr-dir /tmp/vcontainer
115
116# Run specific test class
117pytest tests/test_vpdmn.py::TestVrun -v --vdkr-dir /tmp/vcontainer
118```
119
120### Running Both vdkr and vpdmn Tests
121
122```bash
123# Run all tests for both tools
124pytest tests/test_vdkr.py tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer
125
126# Skip slow and network tests
127pytest tests/test_vdkr.py tests/test_vpdmn.py -v -m "not slow and not network" --vdkr-dir /tmp/vcontainer
128```
129
130---
131
132## container-cross-install Tests
133
134### Prerequisites
135
136container-cross-install tests require a fully configured Yocto build environment:
137
138```bash
139# 1. Set up your Yocto build environment
140cd /opt/bruce/poky
141source oe-init-build-env
142
143# 2. Ensure required layers are present:
144# - meta-virtualization
145# - meta-oe (openembedded-core)
146
147# 3. Enable multiconfig in conf/local.conf:
148BBMULTICONFIG = "vruntime-aarch64 vruntime-x86-64"
149
150# 4. (Optional) Build vdkr/vpdmn blobs via multiconfig if testing container bundling:
151# These are built automatically via mcdepends when building images that
152# inherit container-cross-install or container-bundle.
153```
154
155### What the Tests Check
156
157| Test Class | What It Tests | Build Required |
158|------------|---------------|----------------|
159| `TestContainerCrossTools` | container-cross-tools-native | `bitbake container-cross-tools-native` |
160| `TestContainerCrossClass` | bbclass file syntax | None (file check only) |
161| `TestOCIImageBuild` | OCI image generation | `bitbake container-app-base` (if available) |
162| `TestBundledContainers` | End-to-end bundling | Full image build with `BUNDLED_CONTAINERS` |
163| `TestVdkrRecipes` | vdkr recipe builds | `bitbake vdkr-native` |
164| `TestMulticonfig` | Multiconfig setup | `BBMULTICONFIG` configured |
165| `TestBundledContainersBoot` | **Boot image and verify containers** | Full image with Docker/Podman |
166
167### Boot Tests (TestBundledContainersBoot)
168
169Boot tests actually start the built image in QEMU and verify bundled containers are visible and runnable. This is the ultimate verification that container-cross-install worked correctly.
170
171#### Build Prerequisites
172
173Before running boot tests, you need a built image with bundled containers:
174
175```bash
176cd /opt/bruce/poky
177source oe-init-build-env
178
179# Option 1: Package-based bundling (recommended)
180# Ensure example-container-bundle is in IMAGE_INSTALL (already configured in local.conf):
181# IMAGE_INSTALL:append:pn-container-image-host = " example-container-bundle"
182
183# Build the image (includes container bundling via vrunner/QEMU)
184bitbake container-image-host
185
186# Option 2: Legacy BUNDLED_CONTAINERS variable
187# Add to local.conf:
188# BUNDLED_CONTAINERS = "container-base-latest-oci:podman"
189# Then rebuild:
190# bitbake container-image-host -C rootfs
191```
192
193#### Additional Requirements
194
195```bash
196pip install pexpect
197```
198
199#### What Boot Tests Verify
200
2011. **System boots** - Image boots successfully and reaches login prompt
2022. **Docker images visible** - If Docker containers bundled, `docker images` shows them
2033. **Podman images visible** - If Podman containers bundled, `podman images` shows them
2044. **Docker run works** - Can actually run a bundled Docker container
2055. **Podman run works** - Can actually run a bundled Podman container
206
207#### Running Boot Tests
208
209```bash
210cd /opt/bruce/poky/meta-virtualization
211
212# Run boot tests (requires built image with bundled containers)
213pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v
214
215# Run with custom image
216pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v \
217 --image container-image-host
218
219# Disable KVM (slower, but works in VMs)
220pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --no-kvm
221
222# Longer boot timeout (default: 120s)
223pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --boot-timeout 180
224```
225
226#### Boot Test Options
227
228| Option | Default | Description |
229|--------|---------|-------------|
230| `--image NAME` | container-image-host | Image name to boot |
231| `--image-fstype TYPE` | ext4 | Filesystem type (ext4, wic, etc.) |
232| `--boot-timeout SECS` | 120 | Timeout for boot to complete |
233| `--no-kvm` | (KVM enabled) | Disable KVM acceleration |
234
235#### Container Detection
236
237Boot tests automatically detect bundled containers using two methods:
238
2391. **Direct detection (preferred)**: Reads container storage in the rootfs
240 - Docker: `/var/lib/docker/image/overlay2/repositories.json`
241 - Podman: `/var/lib/containers/storage/vfs-images/images.json`
242
2432. **Legacy fallback**: Parses `BUNDLED_CONTAINERS` variable from `local.conf`
244
245#### Test Skipping Behavior
246
247Tests skip when no containers are detected:
248
249- **No Docker containers** → Docker tests skip:
250 `"No Docker containers in bundle packages or BUNDLED_CONTAINERS"`
251
252- **No Podman containers** → Podman tests skip:
253 `"No Podman containers in bundle packages or BUNDLED_CONTAINERS"`
254
255- **No containers at all** → All container tests skip:
256 `"No container bundles found (no containers in rootfs storage and no BUNDLED_CONTAINERS in local.conf)"`
257
258- **Bundle package installed but no containers** → Skip with rebuild hint:
259 `"Bundle packages installed but no containers detected in storage (image may need rebuild)"`
260
261### Freshness Checking
262
263Boot tests can detect when your rootfs is stale (older than source files) and warn or fail:
264
265```bash
266# Warn if rootfs older than OCI containers or bbclass (default: just warns)
267pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v
268
269# Fail if rootfs is stale (CI mode)
270pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --fail-stale
271
272# Adjust max age before warning (default: 24 hours)
273pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --max-age 48
274```
275
276#### Freshness Check Options
277
278| Option | Default | Description |
279|--------|---------|-------------|
280| `--fail-stale` | false | Fail (not just warn) if rootfs is stale |
281| `--max-age HOURS` | 24 | Max rootfs age in hours before warning |
282
283#### What Gets Checked
284
285The freshness check compares the rootfs mtime against:
2861. **OCI container directories** - Any container in `BUNDLED_CONTAINERS`
2872. **container-cross-install.bbclass** - The class that bundles containers
288
289If any source is newer than the rootfs, you'll see:
290
291```
292WARNING: Rootfs may be stale!
293 Rootfs: 2025-12-27 10:30:00
294 Newer sources found:
295 - container-app-base-latest-oci: 2025-12-28 14:22:33
296 Consider rebuilding: bitbake container-image-host -C rootfs
297```
298
299#### Fresh Test Workflow
300
301To ensure you're testing the latest functionality:
302
303```bash
304# 1. Rebuild containers (if changed)
305bitbake container-base container-app-base
306
307# 2. Rebuild image rootfs
308bitbake container-image-host -C rootfs
309
310# 3. Run boot tests with stale check
311pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --fail-stale
312```
313
314### Running container-cross-install Tests
315
316```bash
317cd /opt/bruce/poky/meta-virtualization
318
319# Run all container-cross-install tests (many are slow)
320pytest tests/test_container_cross_install.py -v
321
322# Run only fast tests (file checks, no building)
323pytest tests/test_container_cross_install.py -v -m "not slow"
324
325# Run with custom build directory
326pytest tests/test_container_cross_install.py -v --build-dir /path/to/build
327
328# Run specific test
329pytest tests/test_container_cross_install.py::TestContainerCrossClass -v
330```
331
332### container-cross-install Test Options
333
334| Option | Description |
335|--------|-------------|
336| `--poky-dir PATH` | Path to poky directory (default: /opt/bruce/poky) |
337| `--build-dir PATH` | Path to build directory (default: $POKY_DIR/build) |
338| `--machine MACHINE` | Target machine (default: qemux86-64) |
339| `--image NAME` | Image to boot for boot tests (default: container-image-host) |
340| `--image-fstype TYPE` | Filesystem type (default: ext4) |
341| `--boot-timeout SECS` | Boot timeout in seconds (default: 120) |
342| `--no-kvm` | Disable KVM acceleration for boot tests |
343| `--fail-stale` | Fail if rootfs is older than source files |
344| `--max-age HOURS` | Max rootfs age before warning (default: 24) |
345
346---
347
348## Capturing Test Output
349
350Test output is automatically captured to files for debugging:
351
352| File | Contents |
353|------|----------|
354| `/tmp/pytest-vcontainer.log` | Python logging (DEBUG level) |
355| `/tmp/pytest-results.xml` | JUnit XML results (for CI) |
356
357To capture full stdout/stderr (including test failures and assertions):
358
359```bash
360# Capture everything to a log file
361pytest tests/test_vpdmn.py --vdkr-dir /tmp/vcontainer 2>&1 | tee /tmp/pytest-output.log
362
363# Then share the log file for debugging
364cat /tmp/pytest-output.log
365```
366
367---
368
369## Test Markers
370
371| Marker | Description |
372|--------|-------------|
373| `slow` | Tests that take a long time (building recipes, images) |
374| `memres` | Tests requiring vdkr memory resident mode |
375| `network` | Tests requiring network access (docker pull, etc.) |
376| `boot` | Tests that boot a QEMU image (requires built image) |
377
378### Filtering by Marker
379
380```bash
381# Skip slow tests
382pytest tests/ -m "not slow"
383
384# Run only network tests
385pytest tests/ -m network
386
387# Combine markers
388pytest tests/ -m "not slow and not network"
389```
390
391---
392
393## Environment Variables
394
395| Variable | Description |
396|----------|-------------|
397| `VDKR_STANDALONE_DIR` | Default path to vdkr standalone directory |
398| `VDKR_ARCH` | Default architecture (x86_64 or aarch64) |
399| `TEST_OCI_IMAGE` | Default OCI image for import tests |
400| `POKY_DIR` | Path to poky directory |
401| `BUILD_DIR` | Path to build directory |
402| `MACHINE` | Target machine for Yocto builds |
403
404---
405
406## Test Structure
407
408```
409tests/
410├── conftest.py # Fixtures and configuration
411├── pytest.ini # Pytest settings
412├── memres-test.sh # Helper to start/stop memres for tests
413├── test_vdkr.py # vdkr (Docker) CLI tests
414│ ├── TestMemresBasic # memres start/stop/status
415│ ├── TestImages # images, pull, rmi
416│ ├── TestVimport # OCI import
417│ ├── TestSaveLoad # save/load images
418│ ├── TestVrun # container execution
419│ ├── TestInspect # inspect command
420│ ├── TestHistory # history command
421│ ├── TestClean # clean command
422│ ├── TestFallbackMode # non-memres operation
423│ ├── TestContainerLifecycle # ps, stop, rm
424│ └── TestVolumeMounts # volume mount tests
425├── test_vpdmn.py # vpdmn (Podman) CLI tests
426│ ├── TestMemresBasic # memres start/stop/status
427│ ├── TestImages # images, pull, rmi
428│ ├── TestVimport # OCI import
429│ ├── TestSaveLoad # save/load images
430│ ├── TestVrun # container execution
431│ ├── TestRun # run with entrypoint override
432│ ├── TestInspect # inspect command
433│ ├── TestHistory # history command
434│ ├── TestClean # clean command
435│ ├── TestFallbackMode # non-memres operation
436│ ├── TestContainerLifecycle # ps, stop, rm
437│ └── TestVolumeMounts # volume mount tests
438├── test_container_cross_install.py # Yocto integration tests
439│ ├── TestContainerCrossInitramfs # blob building
440│ ├── TestContainerCrossTools # tools-native
441│ ├── TestContainerCrossClass # bbclass syntax
442│ ├── TestOCIImageBuild # OCI generation
443│ ├── TestBundledContainers # end-to-end bundling
444│ ├── TestVdkrRecipes # vdkr builds
445│ ├── TestMulticonfig # multiconfig setup
446│ └── TestBundledContainersBoot # boot and verify containers
447└── README.md # This file
448```
449
450---
451
452## Quick Reference
453
454### Full vdkr + vpdmn test run (recommended)
455
456```bash
457# 1. Build the unified standalone SDK (includes both vdkr and vpdmn)
458cd /opt/bruce/poky
459source oe-init-build-env
460MACHINE=qemux86-64 bitbake vcontainer-tarball
461
462# 2. Extract the tarball (self-extracting installer)
463/opt/bruce/poky/build/tmp/deploy/sdk/vcontainer-standalone-x86_64.sh -d /tmp/vcontainer -y
464
465# 3. Run fast tests for both tools (skips network and slow tests)
466cd /opt/bruce/poky/meta-virtualization
467pytest tests/test_vdkr.py tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer -m "not network and not slow"
468
469# 4. Run ALL tests for both tools (includes network tests like pull)
470pytest tests/test_vdkr.py tests/test_vpdmn.py -v --vdkr-dir /tmp/vcontainer
471```
472
473### vdkr only test run
474
475```bash
476# Build SDK (includes both vdkr and vpdmn)
477MACHINE=qemux86-64 bitbake vcontainer-tarball
478
479# Extract
480/opt/bruce/poky/build/tmp/deploy/sdk/vcontainer-standalone-x86_64.sh -d /tmp/vcontainer -y
481
482# Run vdkr tests only
483pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer
484```
485
486### With OCI image import test
487
488```bash
489# Run tests including OCI import (requires a built OCI image)
490pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer \
491 --oci-image /opt/bruce/poky/build/tmp/deploy/images/qemux86-64/container-app-base-latest-oci
492```
493
494### Faster repeated runs (memres mode)
495
496```bash
497# Start memres once (keeps QEMU VM running)
498./tests/memres-test.sh start --vdkr-dir /tmp/vcontainer
499
500# Run tests multiple times (~1s per command vs ~30s cold boot)
501pytest tests/test_vdkr.py -v --vdkr-dir /tmp/vcontainer --skip-destructive
502
503# Stop memres when done
504./tests/memres-test.sh stop --vdkr-dir /tmp/vcontainer
505```
506
507### Minimal container-cross-install test run
508
509```bash
510# Just check files exist (no building)
511cd /opt/bruce/poky/meta-virtualization
512pytest tests/test_container_cross_install.py::TestContainerCrossClass -v
513```
514
515### Boot test (verify bundled containers)
516
517```bash
518# 1. Ensure image is built with BUNDLED_CONTAINERS in local.conf:
519# BUNDLED_CONTAINERS = "container-base-latest-oci:docker container-app-base-latest-oci:docker"
520
521# 2. Build the image
522cd /opt/bruce/poky && source oe-init-build-env
523bitbake container-image-host
524
525# 3. Run boot tests
526cd /opt/bruce/poky/meta-virtualization
527pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v
528
529# 4. Run with freshness check (CI mode)
530pytest tests/test_container_cross_install.py::TestBundledContainersBoot -v --fail-stale
531```
532
533---
534
535## Adding New Tests
536
537### vdkr tests
538
539Use the `vdkr` or `memres_session` fixture:
540
541```python
542def test_my_command(memres_session):
543 vdkr = memres_session
544 result = vdkr.run("my-command", "arg1", "arg2")
545 assert result.returncode == 0
546 assert "expected" in result.stdout
547```
548
549### vpdmn tests
550
551Use the `vpdmn` or `vpdmn_memres_session` fixture:
552
553```python
554def test_my_podman_command(vpdmn_memres_session):
555 vpdmn = vpdmn_memres_session
556 result = vpdmn.run("my-command", "arg1", "arg2")
557 assert result.returncode == 0
558 assert "expected" in result.stdout
559```
560
561### container-cross-install tests
562
563Use `run_bitbake()` helper:
564
565```python
566def test_my_recipe(build_dir):
567 result = run_bitbake(build_dir, "my-recipe")
568 assert result.returncode == 0
569```