From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH 2/3] test: test boot with Debian netinstaller CDROM image
Date: Fri, 13 Feb 2026 11:35:57 +0100 [thread overview]
Message-ID: <20260213103626.2807840-3-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20260213103626.2807840-1-a.fatoum@pengutronix.de>
The nocloud image takes quite long to boot and now includes
systemd-firstboot, which doesn't lend itself that well to automated
testing.
Switch to the CDROM image instead. That one doesn't autoboot
unfortunately and opens a screen, so we need a few workarounds for that,
but the tests work again now.
The end goal remains building a dedicated image for testing instead.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
.github/workflows/test-labgrid-pytest.yml | 2 +-
scripts/fetch-os.sh | 2 +-
test/arm/multi_v8_efiloader_defconfig.yaml | 12 ++--
test/py/helper.py | 39 +++++++++++++
test/py/test_linux_efiloader.py | 33 ++++++-----
test/py/test_linux_smbios.py | 16 +++++-
test/strategy.py | 64 +++++++++++++++++-----
7 files changed, 133 insertions(+), 35 deletions(-)
diff --git a/.github/workflows/test-labgrid-pytest.yml b/.github/workflows/test-labgrid-pytest.yml
index 7e385af65245..9f459fe2c30e 100644
--- a/.github/workflows/test-labgrid-pytest.yml
+++ b/.github/workflows/test-labgrid-pytest.yml
@@ -35,7 +35,7 @@ jobs:
- ARCH: arm
lgenv: test/arm/multi_v8_efiloader_defconfig.yaml
defconfig: multi_v8_efiloader_defconfig
- osimg: debian-13-nocloud-arm64.qcow2
+ osimg: debian-13.3.0-arm64-netinst.iso
- ARCH: mips
lgenv: test/mips/qemu-malta_defconfig.yaml
diff --git a/scripts/fetch-os.sh b/scripts/fetch-os.sh
index 649e4efe9a05..e22185af2a00 100755
--- a/scripts/fetch-os.sh
+++ b/scripts/fetch-os.sh
@@ -8,7 +8,7 @@ fi
set -euo pipefail
declare -A images=(
- ["debian-13-nocloud-arm64.qcow2"]="https://cloud.debian.org/images/cloud/trixie/latest/debian-13-nocloud-arm64.qcow2"
+ ["debian-13.3.0-arm64-netinst.iso"]="https://cloud.debian.org/images/release/current/arm64/iso-cd/debian-13.3.0-arm64-netinst.iso"
)
found=0
diff --git a/test/arm/multi_v8_efiloader_defconfig.yaml b/test/arm/multi_v8_efiloader_defconfig.yaml
index b24058da8e99..579ac9f50d25 100644
--- a/test/arm/multi_v8_efiloader_defconfig.yaml
+++ b/test/arm/multi_v8_efiloader_defconfig.yaml
@@ -9,17 +9,18 @@ targets:
kernel: barebox-dt-2nd.img
display: qemu-default
extra_args: >
- -drive if=virtio,snapshot=on,file=debian-13-nocloud-arm64.qcow2
+ -drive if=virtio,snapshot=on,file=debian-13.3.0-arm64-netinst.iso
-device virtio-rng
BareboxDriver:
prompt: 'barebox@[^:]+:[^ ]+ '
autoboot: 'stop autoboot'
bootstring: 'commandline:|Starting EFI payload at'
ShellDriver:
- prompt: '\x1b\[\?2004hroot@[^:]+:[^ ]+'
+ prompt: '~ # '
login_prompt: ' login: '
login_timeout: 300
await_login_timeout: 20
+ post_login_settle_time: 3
username: 'root'
BareboxTestStrategy: {}
features:
@@ -27,12 +28,13 @@ targets:
- smbios
- bootable
- efi
+ - testfs
options:
- root_dev: virtioblk0.0
- bootm.image: 'boot/vmlinuz-*'
- bootm.initrd: 'boot/initrd.img-*'
+ bootm.image: 'install.a64/vmlinuz'
+ bootm.initrd: 'install.a64/initrd.gz'
images:
barebox-dt-2nd.img: !template "$LG_BUILDDIR/images/barebox-dt-2nd.img"
+ debian_iso: !template "../../debian-13.3.0-arm64-netinst.iso"
imports:
- ../strategy.py
diff --git a/test/py/helper.py b/test/py/helper.py
index 17d40c584679..ab615280048f 100644
--- a/test/py/helper.py
+++ b/test/py/helper.py
@@ -5,6 +5,7 @@ import pytest
import os
import re
import shlex
+import subprocess
def parse_config(lines):
@@ -197,3 +198,41 @@ def skip_disabled(config, *options):
if bool(undefined):
pytest.skip("skipping test due to disabled " + (",".join(undefined)) + " dependency")
+
+
+def ensure_debian_iso(env, destdir):
+ """
+ Extract Debian kernel and initrd from ISO into destdir.
+
+ The debian_iso specified under images in the YAML will be used
+ Files are extracted into destdir/install.a64/{vmlinuz,initrd.gz}
+ and skipped if they already exist.
+
+ Returns destdir, or None if the ISO doesn't exist.
+ """
+ iso_path = env.config.get_image_path("debian_iso")
+ if iso_path is None:
+ return None
+
+ outdir = os.path.join(destdir, "install.a64")
+ vmlinuz_path = os.path.join(outdir, "vmlinuz")
+ initrd_path = os.path.join(outdir, "initrd.gz")
+
+ if os.path.exists(vmlinuz_path) and os.path.exists(initrd_path):
+ return destdir
+
+ os.makedirs(outdir, exist_ok=True)
+
+ with open(vmlinuz_path, "wb") as f:
+ subprocess.run(
+ ["isoinfo", "-i", iso_path, "-x", "/INSTALL.A64/VMLINUZ.;1"],
+ stdout=f, check=True,
+ )
+
+ with open(initrd_path, "wb") as f:
+ subprocess.run(
+ ["isoinfo", "-i", iso_path, "-x", "/INSTALL.A64/INITRD.GZ;1"],
+ stdout=f, check=True,
+ )
+
+ return destdir
diff --git a/test/py/test_linux_efiloader.py b/test/py/test_linux_efiloader.py
index 385f3fde4c30..df50f21bffc0 100644
--- a/test/py/test_linux_efiloader.py
+++ b/test/py/test_linux_efiloader.py
@@ -1,8 +1,21 @@
# SPDX-License-Identifier: GPL-2.0-only
+# Boot to Linux via EFI CDROM installer image
import re
import pytest
+from .helper import ensure_debian_iso
+
+fetchdir = "/mnt/9p/testfs"
+
+
+@pytest.fixture(scope="module")
+def debian_iso(env, testfs):
+ result = ensure_debian_iso(env, testfs)
+ if result is None:
+ pytest.skip("Debian ISO not found")
+ return result
+
def get_dmesg(shell, grep=None):
cmd = 'dmesg'
@@ -13,9 +26,9 @@ def get_dmesg(shell, grep=None):
return stdout
-@pytest.mark.lg_feature(['bootable', 'efi'])
+@pytest.mark.lg_feature(['bootable', 'efi', 'testfs'])
@pytest.mark.parametrize('efiloader', [False, True])
-def test_boot_manual_with_initrd(strategy, barebox, env, efiloader):
+def test_boot_manual_with_initrd(strategy, barebox, env, efiloader, debian_iso):
"""Test booting Debian kernel directly without GRUB"""
barebox.run_check(f"global.bootm.efi={'required' if efiloader else 'disabled'}")
@@ -25,27 +38,22 @@ def test_boot_manual_with_initrd(strategy, barebox, env, efiloader):
return config.get_target_option(strategy.target.name, opt)
try:
- root_dev = get_option(strategy, "root_dev")
kernel_path = get_option(strategy, "bootm.image")
except KeyError:
- pytest.fail("Feature bootable enabled, but root_dev/bootm.image option missing.") # noqa
+ pytest.fail("Feature bootable enabled, but bootm.image option missing.")
- # Detect block devices
- barebox.run_check("detect -a")
- barebox.run_check(f"ls /mnt/{root_dev}/")
-
- [kernel_path] = barebox.run_check(f"ls /mnt/{root_dev}/{kernel_path}")
+ kernel_path = f"{fetchdir}/{kernel_path}"
+ [kernel_path] = barebox.run_check(f"ls {kernel_path}")
try:
initrd_path = get_option(strategy, "bootm.initrd")
- [initrd_path] = barebox.run_check(f"ls /mnt/{root_dev}/{initrd_path}")
+ initrd_path = f"{fetchdir}/{initrd_path}"
+ [initrd_path] = barebox.run_check(f"ls {initrd_path}")
barebox.run_check(f"global.bootm.initrd={initrd_path}")
except KeyError:
pass
barebox.run_check(f"global.bootm.image={kernel_path}")
- barebox.run_check(f"global.bootm.root_dev=/dev/{root_dev}")
- barebox.run_check("global.bootm.appendroot=1")
# Speed up subsequent runs a bit
barebox.run_check("global linux.bootargs.noapparmor=apparmor=0")
@@ -90,7 +98,6 @@ def test_expected_efi_messages(shell, env):
expected_patterns = [
r"efi:\s+EFI v2\.8 by barebox",
- r"Remapping and enabling EFI services\.",
r"efivars:\s+Registered efivars operations",
]
diff --git a/test/py/test_linux_smbios.py b/test/py/test_linux_smbios.py
index 97a6ae3c80a4..48051e29d0d0 100644
--- a/test/py/test_linux_smbios.py
+++ b/test/py/test_linux_smbios.py
@@ -2,8 +2,20 @@
import pytest
+from .helper import ensure_debian_iso
-@pytest.mark.lg_feature(['bootable', 'smbios'])
+fetchdir = "/mnt/9p/testfs"
+
+
+@pytest.fixture(scope="module")
+def debian_iso(env, testfs):
+ result = ensure_debian_iso(env, testfs)
+ if result is None:
+ pytest.skip("Debian ISO not found")
+ return result
+
+
+@pytest.mark.lg_feature(['bootable', 'smbios', 'testfs'])
def test_smbios3_tables_present(shell):
_, _, ret = shell.run("test -e /sys/firmware/dmi/tables/smbios_entry_point")
assert ret == 0, "SMBIOS entry point not found"
@@ -20,7 +32,7 @@ def test_smbios3_tables_present(shell):
assert ret == 0, "SMBIOS entry point is not SMBIOS 3.x"
-@pytest.mark.lg_feature(['bootable', 'smbios'])
+@pytest.mark.lg_feature(['bootable', 'smbios', 'testfs'])
def test_smbios_contains_barebox(shell):
"""
Search raw SMBIOS/DMI tables for a barebox vendor string.
diff --git a/test/strategy.py b/test/strategy.py
index 35cda3aca498..3ad3cb2a45f2 100644
--- a/test/strategy.py
+++ b/test/strategy.py
@@ -1,16 +1,19 @@
# SPDX-License-Identifier: GPL-2.0-only
import enum
+import time
import attr
import pytest
import subprocess
import re
from contextlib import contextmanager
+import pexpect
from labgrid import target_factory, step, driver
from labgrid.strategy import Strategy, StrategyError
from labgrid.util import labgrid_version
+from labgrid.util.timeout import Timeout
match = re.match(r'^(\d+?)\.', labgrid_version())
if match is None or int(match.group(1)) < 25:
@@ -74,11 +77,7 @@ class BareboxTestStrategy(Strategy):
# interrupt barebox
self.target.activate(self.barebox)
elif status == Status.shell:
- # transition to barebox
- self.transition(Status.barebox) # pylint: disable=missing-kwoa
- self.barebox.boot("")
- self.barebox.await_boot()
- self.target.activate(self.shell)
+ self._boot_kernel("")
else:
raise StrategyError(
"no transition found from {} to {}".
@@ -113,18 +112,57 @@ class BareboxTestStrategy(Strategy):
self.power.cycle()
self.target.activate(self.barebox)
+ def skip_cdrom_installer(self):
+ # Wait for installer to boot. Send Enter every cycle to dismiss
+ # GRUB menu and any installer prompts. The screen TUI has a clock
+ # in the status bar that makes pattern matching unreliable, so
+ # avoid matching on it.
+ timeout = Timeout(float(self.shell.login_timeout))
+
+ while not timeout.expired:
+ self.console.sendline("")
+ index, _, _, _ = self.console.expect(
+ ["Starting system log daemon", pexpect.TIMEOUT],
+ timeout=self.shell.await_login_timeout)
+ if index == 0:
+ break
+
+ # Switch to screen window 3 (shell) and disable the status bar.
+ # Retry until the shell prompt appears.
+ while not timeout.expired:
+ self.console.sendline("\x013")
+ time.sleep(0.5)
+ self.console.sendline("\x01:hardstatus ignore")
+ time.sleep(0.5)
+ self.console.sendline("")
+ index, _, _, _ = self.console.expect(
+ [self.shell.prompt, pexpect.TIMEOUT],
+ timeout=self.shell.await_login_timeout)
+ if index == 0:
+ break
+
+ def _boot_kernel(self, boottarget=None, bootm=False, skip_cdrom_installer=True):
+ self.transition(Status.barebox)
+
+ if bootm:
+ self.barebox_bootm(boottarget)
+ else:
+ self.barebox.boot(boottarget)
+
+ self.barebox.await_boot()
+
+ if skip_cdrom_installer:
+ self.skip_cdrom_installer()
+
+ self.target.activate(self.shell)
+
@contextmanager
- def boot_kernel(self, boottarget=None, bootm=False):
+ def boot_kernel(self, boottarget=None, bootm=False, skip_cdrom_installer=True):
self.transition(Status.barebox)
try:
- if bootm:
- self.barebox_bootm(boottarget)
- else:
- self.barebox.boot(boottarget)
-
- self.barebox.await_boot()
- self.target.activate(self.shell)
+ self._boot_kernel(boottarget=boottarget, bootm=bootm,
+ skip_cdrom_installer=skip_cdrom_installer)
yield self.shell
finally:
self.target.deactivate(self.shell)
--
2.47.3
next prev parent reply other threads:[~2026-02-13 10:37 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-13 10:35 [PATCH 0/3] " Ahmad Fatoum
2026-02-13 10:35 ` [PATCH 1/3] test: py: linux: use utilities available in Debian netinstall images Ahmad Fatoum
2026-02-13 10:35 ` Ahmad Fatoum [this message]
2026-02-13 10:35 ` [PATCH 3/3] test: py: linux: remove test_ prefix for intermediate functions Ahmad Fatoum
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260213103626.2807840-3-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox