diff --git a/src/qemu_runner/layer.py b/src/qemu_runner/layer.py index 8bd73b3..b488b83 100644 --- a/src/qemu_runner/layer.py +++ b/src/qemu_runner/layer.py @@ -1,4 +1,5 @@ -import os.path +import os.path +import re from configparser import ConfigParser from dataclasses import dataclass, replace from pathlib import Path @@ -234,7 +235,13 @@ def _yield_args(): yield layer.general.kernel if layer.general.kernel_cmdline: - yield '-append' - yield layer.general.kernel_cmdline + if not layer.general.mode or layer.general.mode == Mode.System: + yield '-append' + yield layer.general.kernel_cmdline + else: + pattern = re.compile(r"\"[^\"]*\"|\'[^\']*\'|\S+") + args = pattern.findall(layer.general.kernel_cmdline) + for arg in args: + yield arg.strip('"\'') return list(_yield_args()) diff --git a/tests/test_layer_cmdline.py b/tests/test_layer_cmdline.py index b65633c..14a5bff 100644 --- a/tests/test_layer_cmdline.py +++ b/tests/test_layer_cmdline.py @@ -46,6 +46,18 @@ Layer(GeneralSettings(engine='my-engine', kernel='abc.elf', kernel_cmdline='a b c')), ['my-engine', '-kernel', 'abc.elf', '-append', 'a b c'] ), + ( + Layer(GeneralSettings(engine='my-engine', kernel='abc.elf', mode=Mode.User, kernel_cmdline='a b c')), + ['my-engine', 'abc.elf', 'a', 'b', 'c'] + ), + ( + Layer(GeneralSettings(engine='my-engine', kernel='abc.elf', mode=Mode.User, kernel_cmdline='a "b c d" e')), + ['my-engine', 'abc.elf', 'a', 'b c d', 'e'] + ), + ( + Layer(GeneralSettings(engine='my-engine', kernel='abc.elf', mode=Mode.User, kernel_cmdline='a \'b c d\' e')), + ['my-engine', 'abc.elf', 'a', 'b c d', 'e'] + ), ( Layer( GeneralSettings(engine='my-engine', halted=True, gdb=True, kernel='abc.elf', kernel_cmdline='a b c'), diff --git a/tests/test_runner_flow.py b/tests/test_runner_flow.py index 9c97a7a..dd0fa30 100644 --- a/tests/test_runner_flow.py +++ b/tests/test_runner_flow.py @@ -91,6 +91,76 @@ def test_runner_flow_no_args(tmp_path: Path, test_layer: Path): '-kernel', str(tmp_path / 'abc.elf'), ] +@pytest.fixture() +def test_user_mode_layer(tmp_path: Path) -> Path: + with open(tmp_path / 'test-layer', 'w') as f: + f.write(""" + [general] + engine = qemu-aarch64 + mode = user + + [L] + @ = /some/path + """) + + return tmp_path / 'test-layer' + + +def test_runner_flow_user_mode(tmp_path: Path, test_user_mode_layer: Path): + engine = place_echo_args(tmp_path / 'qemu' / 'qemu-aarch64') + + run_make_runner('-l', test_user_mode_layer, '-o', tmp_path / 'test.pyz', cwd=tmp_path) + with with_cwd(tmp_path): + cmdline = capture_runner_cmdline(tmp_path / 'test.pyz', 'abc.elf', 'arg1', 'arg2') + + assert cmdline == [ + engine, + '-L', '/some/path', + str(tmp_path / 'abc.elf'), + 'arg1', 'arg2' + ] + +def test_runner_flow_user_mode_double_quoted_args(tmp_path: Path, test_user_mode_layer: Path): + engine = place_echo_args(tmp_path / 'qemu' / 'qemu-aarch64') + + run_make_runner('-l', test_user_mode_layer, '-o', tmp_path / 'test.pyz', cwd=tmp_path) + with with_cwd(tmp_path): + cmdline = capture_runner_cmdline(tmp_path / 'test.pyz', 'abc.elf', 'arg1', '"arg2 arg3"', 'arg4') + + assert cmdline == [ + engine, + '-L', '/some/path', + str(tmp_path / 'abc.elf'), + 'arg1', 'arg2 arg3', 'arg4' + ] + +def test_runner_flow_user_mode_single_quoted_args(tmp_path: Path, test_user_mode_layer: Path): + engine = place_echo_args(tmp_path / 'qemu' / 'qemu-aarch64') + + run_make_runner('-l', test_user_mode_layer, '-o', tmp_path / 'test.pyz', cwd=tmp_path) + with with_cwd(tmp_path): + cmdline = capture_runner_cmdline(tmp_path / 'test.pyz', 'abc.elf', 'arg1', '\'arg2 arg3\'', 'arg4') + + assert cmdline == [ + engine, + '-L', '/some/path', + str(tmp_path / 'abc.elf'), + 'arg1', 'arg2 arg3', 'arg4' + ] + +def test_runner_flow_no_args(tmp_path: Path, test_user_mode_layer: Path): + engine = place_echo_args(tmp_path / 'qemu' / 'qemu-aarch64') + + run_make_runner('-l', test_user_mode_layer, '-o', tmp_path / 'test.pyz', cwd=tmp_path) + with with_cwd(tmp_path): + cmdline = capture_runner_cmdline(tmp_path / 'test.pyz', 'abc.elf') + + assert cmdline == [ + engine, + '-L', '/some/path', + str(tmp_path / 'abc.elf') + ] + def assert_arg_set_in_cmdline(arg_set: List[str], cmdline: List[str]): if len(arg_set) == 1: