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 60fadbc1ad7bfcc5e71274a5637f27fc60a75040 Author: raiden00pl <[email protected]> AuthorDate: Tue Aug 4 17:42:22 2026 +0200 core.py: route runtime check_cmd through config on kernel builds Runtime checks searched the core ELF or the NSH help output, neither of which lists kernel-mode applications. Route check_cmd through CoreConfig.cmd_check when the core is a kernel build with a known application directory, so runtime checks agree with collection-time filtering. Signed-off-by: raiden00pl <[email protected]> Assisted-by: Claude Code --- src/ntfc/core.py | 57 ++++++++++++++++++++++++------------------------------ tests/test_core.py | 36 ++++++++++++++++++++++++++++++++-- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/ntfc/core.py b/src/ntfc/core.py index 239b541..bc58dd1 100644 --- a/src/ntfc/core.py +++ b/src/ntfc/core.py @@ -28,6 +28,7 @@ from typing import ( Any, List, Optional, + Pattern, Tuple, Union, ) @@ -528,66 +529,58 @@ class ProductCore: self._device.start() def check_cmd(self, cmd_pattern: str) -> bool: - """Check if a command pattern is available in the ELF binary. + """Check if a command pattern is available on the core. - This method validates whether a specific command or set of - commands is present in the core's ELF binary by searching for - corresponding symbols. It supports both single commands and - alternative command patterns separated by '|'. + Commands are resolved from the core configuration when it knows + the application binaries, from the device ELF parser or the + shell help output otherwise. It supports both single commands + and alternative command patterns separated by '|'. :param cmd_pattern: Command pattern to check for. Can contain alternatives separated by '|' (e.g., 'test1|test2') :return: True if the command pattern is found, False otherwise - - Note: - - Requires ELF parser to be available in device - - Supports alternative patterns with '|' - - Used to validate core capabilities before executing """ - # Check if device supports command checking + # Kernel-mode: resolve against the application binary directory + # so runtime checks agree with collection-time filtering + if self._conf.has_app_bindir: + return self._conf.cmd_check(cmd_pattern) + + # Devices that expose their own ELF parser resolve the command + # from its symbols if hasattr(self._device, "elf_parser") and self._device.elf_parser: logger.debug(f"Checking command pattern: {cmd_pattern}") - # Split by '|' to support alternative patterns - alternatives = ( - cmd_pattern.split("|") if "|" in cmd_pattern else [cmd_pattern] - ) - - for pattern in alternatives: + for pattern in cmd_pattern.split("|"): # For cmocka tests, append _main to symbol name - symbol_pattern_str: str = ( + symbol_str = ( f"{pattern}_main" if "cmocka" in pattern else pattern ) # Support regex wildcards - if ".*" in symbol_pattern_str: - symbol_pattern = re.compile(symbol_pattern_str) - else: - tmp = symbol_pattern_str - symbol_pattern = tmp # type: ignore[assignment] + symbol: Union[str, Pattern[str]] = ( + re.compile(symbol_str) + if ".*" in symbol_str + else symbol_str + ) - if self._device.elf_parser.has_symbol(symbol_pattern): + if self._device.elf_parser.has_symbol(symbol): return True return False - # Fallback: try to execute the command and check if it exists + # Fallback: check the command against the shell help output logger.warning( "ELF parser not available, trying command check for: " f"{cmd_pattern}" ) - # Send 'help' command to check if command exists result = self.sendCommandReadUntilPattern("help", timeout=5) if result.status == CmdStatus.SUCCESS: - # Check if any of the command alternatives are in the help output - alternatives = ( - cmd_pattern.split("|") if "|" in cmd_pattern else [cmd_pattern] + return any( + pattern.lower() in result.output.lower() + for pattern in cmd_pattern.split("|") ) - for pattern in alternatives: - if pattern.lower() in result.output.lower(): - return True return False diff --git a/tests/test_core.py b/tests/test_core.py index 838513d..ef67281 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -585,8 +585,6 @@ def test_core_check_cmd_with_elf_parser(envconfig_dummy): # Test regex wildcard pattern mock_elf_parser.has_symbol.side_effect = None mock_elf_parser.has_symbol.return_value = True - import re - assert p.check_cmd("test.*") is True # The pattern should be compiled as regex call_args = mock_elf_parser.has_symbol.call_args @@ -595,3 +593,37 @@ def test_core_check_cmd_with_elf_parser(envconfig_dummy): # Test all alternatives not found mock_elf_parser.has_symbol.return_value = False assert p.check_cmd("nonexistent1|nonexistent2") is False + + # Test with failed help command + dev.send_cmd_read_until_pattern.return_value = CmdReturn( + CmdStatus.TIMEOUT + ) + assert p.check_cmd("test") is False + + +def test_core_check_cmd_kernel_mode(tmp_path): + """Test check_cmd resolves via app_bindir on kernel builds.""" + from ntfc.coreconfig import CoreConfig + + kernel_cfg = tmp_path / "kv_config" + kernel_cfg.write_text("CONFIG_BUILD_KERNEL=y\n") + bindir = tmp_path / "bin" + bindir.mkdir() + (bindir / "hello").write_bytes(b"\x7fELF" + b"\x00" * 12) + + conf = CoreConfig( + { + "name": "t", + "conf_path": str(kernel_cfg), + "app_bindir": str(bindir), + } + ) + + with patch("ntfc.device.common.DeviceCommon") as mockdevice: + p = ProductCore(mockdevice.return_value, conf) + + # resolved from the application directory, device is not queried + assert p.check_cmd("hello") is True + assert p.check_cmd("hello_main") is True + assert p.check_cmd("nonexistent") is False + mockdevice.return_value.send_cmd_read_until_pattern.assert_not_called()
