Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions backends/arm/test/misc/test_runner_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Copyright 2026 Arm Limited and/or its affiliates.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

from pathlib import Path
from typing import Any, cast

from executorch.backends.arm.test import runner_utils


class _FakeExecutorchProgramManager:
def __init__(self, buffer: bytes) -> None:
self.buffer = buffer

def exported_program(self):
return object()


def test_run_corstone_no_target_uses_short_input_aliases_in_semihosting_cmd(
monkeypatch, tmp_path: Path
) -> None:
long_input_paths = [
str(tmp_path / ("very_long_input_name_" * 6 + "0.bin")),
str(tmp_path / ("very_long_input_name_" * 6 + "1.bin")),
]

monkeypatch.setattr(
runner_utils,
"save_inputs_to_file",
lambda exported_program, inputs, intermediate_path: long_input_paths,
)

copied_files: list[tuple[str, str]] = []

def _fake_copyfile(src: str, dst: str) -> None:
copied_files.append((src, dst))

monkeypatch.setattr(runner_utils.shutil, "copyfile", _fake_copyfile)

captured: dict[str, list[str]] = {}

def _fake_run_cmd(cmd, check=True):
captured["cmd"] = cmd
return runner_utils.subprocess.CompletedProcess(
cmd, 0, stdout=b"OK", stderr=b""
)

monkeypatch.setattr(runner_utils, "_run_cmd", _fake_run_cmd)
monkeypatch.setattr(
runner_utils,
"get_output_from_file",
lambda exported_program, intermediate_path, output_base_name: ("sentinel",),
)

elf_path = tmp_path / "arm_executor_runner"
elf_path.write_bytes(b"")

output = runner_utils.run_corstone(
executorch_program_manager=cast(
Any, _FakeExecutorchProgramManager(buffer=b"pte")
),
inputs=cast(Any, ()),
intermediate_path=tmp_path,
target_board="corstone-320",
elf_path=elf_path,
timeout=1,
)

assert output == ("sentinel",)
assert [Path(dst).name for _, dst in copied_files] == ["i0.bin", "i1.bin"]

semihosting_cmd_arg = next(
arg for arg in captured["cmd"] if "semihosting-cmd_line" in arg
)
assert "-i i0.bin" in semihosting_cmd_arg
assert "-i i1.bin" in semihosting_cmd_arg
assert long_input_paths[0] not in semihosting_cmd_arg
assert long_input_paths[1] not in semihosting_cmd_arg
18 changes: 14 additions & 4 deletions backends/arm/test/runner_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,14 +406,24 @@ def run_corstone(
f.write(executorch_program_manager.buffer)

input_paths = save_inputs_to_file(exported_program, inputs, intermediate_path)
# Keep semihosting command line short: the FVP truncates long cmd strings.
# Alias generated input files to compact names in the same directory.
aliased_input_paths = []
for idx, input_path in enumerate(input_paths):
short_name = f"i{idx}.bin"
short_path = os.path.join(intermediate_path, short_name)
if os.path.abspath(input_path) != os.path.abspath(short_path):
shutil.copyfile(input_path, short_path)
aliased_input_paths.append(short_path)

output_base_name = "out"

cmd_line = "executor_runner -m program.pte -o out"
for input_path in input_paths:
relative_path = os.path.relpath(
Path(input_path).resolve(), start=intermediate_path
)
for input_path in aliased_input_paths:
# Use local basenames to avoid '/var' -> '/private/var' resolve expansion
# on macOS, which can produce long '../../..' paths and exceed FVP's
# semihosting cmd_line limit.
relative_path = Path(input_path).name
cmd_line += f" -i {relative_path}"

if len(cmd_line) > 256:
Expand Down