address bot review

This commit is contained in:
J. Nick Koston
2025-11-28 09:57:34 -06:00
parent e22d78cf4c
commit cd11f31887
4 changed files with 51 additions and 12 deletions

View File

@@ -984,17 +984,20 @@ def command_analyze_memory(args: ArgsProtocol, config: ConfigType) -> int:
# Perform RAM strings analysis
_LOGGER.info("Analyzing RAM strings...")
ram_analyzer = RamStringsAnalyzer(
str(firmware_elf),
objdump_path=idedata.objdump_path,
platform=CORE.target_platform,
)
ram_analyzer.analyze()
try:
ram_analyzer = RamStringsAnalyzer(
str(firmware_elf),
objdump_path=idedata.objdump_path,
platform=CORE.target_platform,
)
ram_analyzer.analyze()
# Generate and display RAM strings report
ram_report = ram_analyzer.generate_report()
print()
print(ram_report)
# Generate and display RAM strings report
ram_report = ram_analyzer.generate_report()
print()
print(ram_report)
except Exception as e: # pylint: disable=broad-except
_LOGGER.warning("RAM strings analysis failed: %s", e)
return 0

View File

@@ -141,6 +141,16 @@ def batch_demangle(
# Process demangled output
demangled_lines = result.stdout.strip().split("\n")
# Check for output length mismatch
if len(demangled_lines) != len(symbols):
_LOGGER.warning(
"c++filt output mismatch: expected %d lines, got %d",
len(symbols),
len(demangled_lines),
)
return {s: s for s in symbols}
failed_count = 0
for original, stripped, prefix, demangled in zip(

View File

@@ -35,7 +35,10 @@ def find_tool(
"""
# Try to derive from objdump path first (most reliable)
if objdump_path and objdump_path != "objdump":
potential_path = objdump_path.replace("objdump", tool_name)
objdump_file = Path(objdump_path)
# Replace just the filename portion, preserving any prefix (e.g., xtensa-esp32-elf-)
new_name = objdump_file.name.replace("objdump", tool_name)
potential_path = str(objdump_file.with_name(new_name))
if Path(potential_path).exists():
_LOGGER.debug("Found %s at: %s", tool_name, potential_path)
return potential_path

View File

@@ -269,6 +269,16 @@ def mock_memory_analyzer_cli() -> Generator[Mock]:
yield mock_class
@pytest.fixture
def mock_ram_strings_analyzer() -> Generator[Mock]:
"""Mock RamStringsAnalyzer for testing."""
with patch("esphome.analyze_memory.ram_strings.RamStringsAnalyzer") as mock_class:
mock_analyzer = MagicMock()
mock_analyzer.generate_report.return_value = "Mock RAM Strings Report"
mock_class.return_value = mock_analyzer
yield mock_class
def test_choose_upload_log_host_with_string_default() -> None:
"""Test with a single string default device."""
setup_core()
@@ -2424,6 +2434,7 @@ def test_command_analyze_memory_success(
mock_get_idedata: Mock,
mock_get_esphome_components: Mock,
mock_memory_analyzer_cli: Mock,
mock_ram_strings_analyzer: Mock,
) -> None:
"""Test command_analyze_memory with successful compilation and analysis."""
setup_core(platform=PLATFORM_ESP32, tmp_path=tmp_path, name="test_device")
@@ -2471,9 +2482,20 @@ def test_command_analyze_memory_success(
mock_analyzer.analyze.assert_called_once()
mock_analyzer.generate_report.assert_called_once()
# Verify report was printed
# Verify RAM strings analyzer was created and run
mock_ram_strings_analyzer.assert_called_once_with(
str(firmware_elf),
objdump_path="/path/to/objdump",
platform="esp32",
)
mock_ram_analyzer = mock_ram_strings_analyzer.return_value
mock_ram_analyzer.analyze.assert_called_once()
mock_ram_analyzer.generate_report.assert_called_once()
# Verify reports were printed
captured = capfd.readouterr()
assert "Mock Memory Report" in captured.out
assert "Mock RAM Strings Report" in captured.out
def test_command_analyze_memory_with_external_components(
@@ -2483,6 +2505,7 @@ def test_command_analyze_memory_with_external_components(
mock_get_idedata: Mock,
mock_get_esphome_components: Mock,
mock_memory_analyzer_cli: Mock,
mock_ram_strings_analyzer: Mock,
) -> None:
"""Test command_analyze_memory detects external components."""
setup_core(platform=PLATFORM_ESP32, tmp_path=tmp_path, name="test_device")