This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nuttx-ntfc.git

commit d26aa7e46637413e77b3e32f28d8820ab5cb88d7
Author: raiden00pl <[email protected]>
AuthorDate: Tue Aug 4 17:50:28 2026 +0200

    device: resolve image paths before spawning with a custom exec_cwd
    
    With exec_cwd set, QEMU resolved a relative '-kernel' path against the
    spawn directory instead of the NTFC working directory it is expressed
    in, so boot timed out. Absolutize the image path in the qemu and sim
    start paths when a custom spawn directory is configured.
    
    Signed-off-by: raiden00pl <[email protected]>
    Assisted-by: Claude Code
---
 src/ntfc/device/host.py   | 12 ++++++++++++
 src/ntfc/device/qemu.py   |  5 +----
 src/ntfc/device/sim.py    |  6 +-----
 tests/device/test_qemu.py | 26 ++++++++++++++++++++++++++
 tests/device/test_sim.py  | 30 ++++++++++++++++++++++++++++++
 5 files changed, 70 insertions(+), 9 deletions(-)

diff --git a/src/ntfc/device/host.py b/src/ntfc/device/host.py
index d632387..e188e65 100644
--- a/src/ntfc/device/host.py
+++ b/src/ntfc/device/host.py
@@ -61,6 +61,18 @@ class DeviceHost(DeviceCommon):
         """Return the spawned child PID, or ``None`` before start."""
         return self._child.pid if self._child else None
 
+    def _image_path(self) -> str:
+        """Return the image path, absolute when spawning in another cwd.
+
+        Relative paths are relative to the NTFC working directory, not
+        to the spawn directory.
+        """
+        elf = self._conf.elf_path
+        if not elf:
+            raise IOError
+
+        return os.path.abspath(elf) if self._cwd else str(elf)
+
     def _dev_is_health_priv(self) -> bool:
         """Check if the host device is OK."""
         if not self._child:
diff --git a/src/ntfc/device/qemu.py b/src/ntfc/device/qemu.py
index a655d26..a565003 100644
--- a/src/ntfc/device/qemu.py
+++ b/src/ntfc/device/qemu.py
@@ -44,12 +44,9 @@ class DeviceQemu(DeviceHost):
 
     def _start_impl(self) -> None:
         """Start QEMU emulator implementation."""
-        elf = self._conf.elf_path
+        elf = self._image_path()
         exec_path = self._conf.exec_path
         exec_args = self._conf.exec_args
-
-        if not elf:
-            raise IOError
         if not exec_path:
             raise KeyError("no exec_path in configuration file!")
 
diff --git a/src/ntfc/device/sim.py b/src/ntfc/device/sim.py
index c48c94a..d7c7add 100644
--- a/src/ntfc/device/sim.py
+++ b/src/ntfc/device/sim.py
@@ -41,11 +41,7 @@ class DeviceSim(DeviceHost):
 
     def _start_impl(self) -> None:
         """Start sim emulator implementation."""
-        elf = self._conf.elf_path
-        if not elf:
-            raise IOError
-
-        cmd = [elf]
+        cmd = [self._image_path()]
         uptime = self._conf.uptime
 
         # open host-based emulation
diff --git a/tests/device/test_qemu.py b/tests/device/test_qemu.py
index c99741e..008fd91 100644
--- a/tests/device/test_qemu.py
+++ b/tests/device/test_qemu.py
@@ -18,6 +18,7 @@
 #
 ############################################################################
 
+import os
 from unittest.mock import patch
 
 import pytest
@@ -89,6 +90,7 @@ def test_device_qemu_open():
         config.exec_path = ""
         config.exec_args = ""
         config.elf_path = ""
+        config.exec_cwd = None
 
         qemu = DeviceQemu(config)
 
@@ -175,3 +177,27 @@ def test_device_qemu_open():
         config.uptime = 3
 
         qemu.start()
+
+
+def test_device_qemu_exec_cwd_absolute_image(tmp_path):
+
+    from ntfc.coreconfig import CoreConfig
+
+    config = CoreConfig(
+        {
+            "name": "t",
+            "device": "qemu",
+            "exec_path": "qemu-system-riscv64",
+            "exec_args": "-nographic",
+            "exec_cwd": str(tmp_path),
+        }
+    )
+    # relative image path, resolved against the NTFC cwd at spawn time
+    config._config["elf_path"] = "some/image"
+
+    qemu = DeviceQemu(config)
+    cmds = []
+    qemu.host_open = lambda cmd, uptime: cmds.append(cmd)
+    qemu.start()
+
+    assert cmds[0][2] == "-kernel " + os.path.abspath("some/image")
diff --git a/tests/device/test_sim.py b/tests/device/test_sim.py
index fdf8628..33fad22 100644
--- a/tests/device/test_sim.py
+++ b/tests/device/test_sim.py
@@ -138,3 +138,33 @@ def test_device_sim_line_buffered_write():
         sent.clear()
         sim._write(b"abc\n")
         assert sent == [b"abc\n"]
+
+
+def test_device_sim_exec_cwd_absolute_image(tmp_path):
+
+    import os
+
+    from ntfc.coreconfig import CoreConfig
+
+    config = CoreConfig(
+        {"name": "t", "device": "sim", "exec_cwd": str(tmp_path)}
+    )
+    # relative image path, resolved against the NTFC cwd at spawn time
+    config._config["elf_path"] = "some/image"
+
+    sim = DeviceSim(config)
+    cmds = []
+    sim.host_open = lambda cmd, uptime: cmds.append(cmd)
+    sim.start()
+
+    assert cmds[0] == [os.path.abspath("some/image")]
+
+    # without exec_cwd the image path is passed through unchanged
+    config = CoreConfig({"name": "t", "device": "sim"})
+    config._config["elf_path"] = "some/image"
+
+    sim = DeviceSim(config)
+    sim.host_open = lambda cmd, uptime: cmds.append(cmd)
+    sim.start()
+
+    assert cmds[1] == ["some/image"]

Reply via email to