[Concept,12/17] ulib: test: Add a pytest for efi-x86_app64 demo

Message ID 20260216013511.4079770-13-sjg@u-boot.org
State New
Headers
Series ulib: Add multi-arch demo and EFI app support |

Commit Message

Simon Glass Feb. 16, 2026, 1:35 a.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Add test_ulib_demo_efi_x86() which boots demo-app.efi under QEMU x86_64
with OVMF firmware. The test writes a startup.nsh script next to
demo-app.efi in the build directory, then boots QEMU with the FAT
directory and checks for the expected demo output.

Also add a timeout parameter to run_qemu_demo() since OVMF boot takes
longer than bare-metal demos.

Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 test/py/tests/test_ulib.py | 37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)
  

Patch

diff --git a/test/py/tests/test_ulib.py b/test/py/tests/test_ulib.py
index 71fe751efc9..1c98b8b6880 100644
--- a/test/py/tests/test_ulib.py
+++ b/test/py/tests/test_ulib.py
@@ -234,12 +234,13 @@  def assert_demo_output(out):
     assert '=================================' in out
     assert 'Demo complete' in out
 
-def run_qemu_demo(qemu_cmd):
+def run_qemu_demo(qemu_cmd, timeout=5):
     """Run a ulib demo under QEMU and return output.
 
     Args:
         qemu_cmd (list): QEMU command and arguments (e.g.
                   ['qemu-system-i386', '-bios', 'demo.rom', ...])
+        timeout (int): Seconds to wait before killing QEMU (default 5)
 
     Returns:
         str: Decoded stdout from QEMU
@@ -247,7 +248,7 @@  def run_qemu_demo(qemu_cmd):
     with subprocess.Popen(qemu_cmd, stdout=subprocess.PIPE,
                           stderr=subprocess.PIPE) as proc:
         try:
-            stdout, _ = proc.communicate(timeout=5)
+            stdout, _ = proc.communicate(timeout=timeout)
         except subprocess.TimeoutExpired:
             proc.kill()
             stdout, _ = proc.communicate()
@@ -331,3 +332,35 @@  def test_ulib_demo_arm64(ubman):
 def test_ulib_demo_riscv64(ubman):
     """Test the ulib demo binary under QEMU RISC-V 64."""
     run_bios_demo(ubman, 'qemu-system-riscv64')
+
+@pytest.mark.localqemu
+@pytest.mark.boardspec('efi-x86_app64')
+@pytest.mark.buildconfigspec("examples")
+def test_ulib_demo_efi_x86(ubman):
+    """Test the ulib demo EFI application under QEMU x86_64 with OVMF."""
+    build = ubman.config.build_dir
+    efi_dir = os.path.join(build, 'examples', 'ulib')
+    demo_efi = os.path.join(efi_dir, 'demo-app.efi')
+
+    assert os.path.exists(demo_efi), 'demo-app.efi not found in build directory'
+    assert shutil.which('qemu-system-x86_64'), 'qemu-system-x86_64 not found'
+
+    ovmf_code = '/usr/share/OVMF/OVMF_CODE_4M.fd'
+    ovmf_vars = '/usr/share/OVMF/OVMF_VARS_4M.fd'
+    assert os.path.exists(ovmf_code), 'OVMF firmware not found'
+
+    with open(os.path.join(efi_dir, 'startup.nsh'), 'w',
+              encoding='utf-8') as nsh:
+        nsh.write('fs0:demo-app.efi\n')
+
+    # OVMF needs a writable copy of the vars file
+    vars_copy = os.path.join(efi_dir, 'OVMF_VARS_4M.fd')
+    shutil.copy(ovmf_vars, vars_copy)
+
+    cmd = ['qemu-system-x86_64',
+           '-drive', f'if=pflash,format=raw,file={ovmf_code},readonly=on',
+           '-drive', f'if=pflash,format=raw,file={vars_copy}',
+           '-drive', f'file=fat:rw:{efi_dir},format=raw',
+           '-nographic', '-no-reboot', '-nic', 'none']
+    out = run_qemu_demo(cmd, timeout=15)
+    assert_demo_output(out)