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
The following commit(s) were added to refs/heads/main by this push:
new 272cdc8 core: refuse commands longer than the target line buffer
272cdc8 is described below
commit 272cdc814b864f6542c92f21718ecff40d6969b8
Author: raiden00pl <[email protected]>
AuthorDate: Mon Oct 12 16:03:24 2026 +0200
core: refuse commands longer than the target line buffer
---
CHANGES.md | 1 +
Documentation/writing-test-cases.rst | 4 +++-
src/ntfc/core.py | 24 ++++++++++++++++++++++++
tests/test_core.py | 35 +++++++++++++++++++++++++++++++++++
4 files changed, 63 insertions(+), 1 deletion(-)
diff --git a/CHANGES.md b/CHANGES.md
index 408554e..56f7b7b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -3,6 +3,7 @@
## Unreleased
- Add Renode device support.
+- Refuse commands longer than the target CONFIG_LINE_MAX.
## 0.0.3
diff --git a/Documentation/writing-test-cases.rst
b/Documentation/writing-test-cases.rst
index 1f3a30e..cce9e14 100644
--- a/Documentation/writing-test-cases.rst
+++ b/Documentation/writing-test-cases.rst
@@ -201,7 +201,9 @@ Decorators:
enabled
The :meth:`~ntfc.products.ProductsHandler.sendCommand` method handles
-execution and verification.
+execution and verification. A command that does not fit the target shell
+line buffer (``CONFIG_LINE_MAX`` minus one character) is refused with a
+``ValueError`` instead of being split by the shell.
Parametrized Command Test
--------------------------
diff --git a/src/ntfc/core.py b/src/ntfc/core.py
index 9de18fc..8f2ddc5 100644
--- a/src/ntfc/core.py
+++ b/src/ntfc/core.py
@@ -127,6 +127,28 @@ class ProductCore:
matched = matched.decode("utf-8", errors="ignore")
return self._device.no_cmd in matched
+ def _check_line_max(self, cmd: bytes) -> None:
+ """Refuse a command the target shell cannot buffer in one line.
+
+ NSH reads at most ``CONFIG_LINE_MAX - 1`` characters per line and
+ executes the overflow as a second command, which fails in
+ confusing ways. The limit is only known when the Kconfig of the
+ image is available.
+
+ :param cmd: Encoded command including its line terminator.
+ :raises ValueError: Command does not fit the target line buffer.
+ """
+ limit = self._conf.kv_check("CONFIG_LINE_MAX")
+ if not limit:
+ return
+ length = len(cmd.rstrip(b"\r\n"))
+ if length >= int(limit):
+ raise ValueError(
+ f"command is {length} characters, the target buffers at "
+ f"most {int(limit) - 1} (CONFIG_LINE_MAX={limit}): "
+ f"{cmd.decode(errors='replace').strip()!r}"
+ )
+
def sendCommand( # noqa: N802
self,
cmd: str,
@@ -162,6 +184,7 @@ class ProductCore:
encoded = self._builder.build(
cmd, expects, args, flag, match_all, regexp, fail_pattern
)
+ self._check_line_max(encoded.cmd)
logger.debug(
f"Sending command: {encoded.cmd.decode()}, expecting: "
@@ -204,6 +227,7 @@ class ProductCore:
:return: CmdReturn : command return data
"""
encoded = self._builder.build_raw(cmd, pattern, args, fail_pattern)
+ self._check_line_max(encoded.cmd)
logger.debug(
f"Sending command: {encoded.cmd.decode()}, expecting pattern: "
diff --git a/tests/test_core.py b/tests/test_core.py
index 7439831..1b4990b 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -25,6 +25,7 @@ import pytest
from ntfc.core import CoreStatus, ProductCore
from ntfc.device.common import CmdReturn, CmdStatus
+from ntfc.envconfig import EnvConfig
def test_core_init(envconfig_dummy):
@@ -102,6 +103,40 @@ def test_core_send_command(envconfig_dummy):
assert p.sendCommand("test") == CmdStatus.NOTFOUND
+def test_core_rejects_command_longer_than_line_max(config_sim):
+ """A command the shell cannot buffer is refused instead of split."""
+
+ with patch("ntfc.device.common.DeviceCommon") as mockdevice:
+ dev = mockdevice.return_value
+ dev.prompt = b"NSH> "
+ dev.no_cmd = "command not found"
+ dev.send_cmd_read_until_pattern.return_value = CmdReturn(
+ CmdStatus.SUCCESS
+ )
+ core = EnvConfig(config_sim).product[0].cfg_core(0)
+ assert core.kv_check("CONFIG_LINE_MAX") == 80
+ p = ProductCore(dev, core)
+
+ assert p.sendCommand("x" * 79) == CmdStatus.SUCCESS
+ with pytest.raises(ValueError, match="CONFIG_LINE_MAX"):
+ p.sendCommand("x" * 80)
+ with pytest.raises(ValueError, match="CONFIG_LINE_MAX"):
+ p.sendCommandReadUntilPattern("x" * 70, args=["y" * 10])
+
+
+def test_core_line_max_unknown_is_not_checked(envconfig_dummy):
+
+ with patch("ntfc.device.common.DeviceCommon") as mockdevice:
+ dev = mockdevice.return_value
+ dev.prompt = b"NSH> "
+ dev.no_cmd = "command not found"
+ dev.send_cmd_read_until_pattern.return_value = CmdReturn(
+ CmdStatus.SUCCESS
+ )
+ p = ProductCore(dev, envconfig_dummy.product[0].cfg_core(0))
+ assert p.sendCommand("x" * 500) == CmdStatus.SUCCESS
+
+
def test_core_send_command_read_until_pattern(envconfig_dummy):
with patch("ntfc.device.common.DeviceCommon") as mockdevice:
dev = mockdevice.return_value