Files
wadamesh/test/test_merge_bin.py
T
Michael A. CojocariandClaude Opus 5.5 dbecef0b6f feat(crowpanel-35): add Elecrow CrowPanel 3.5" (ESP32-S3, ILI9488 + GT911) touch target
- New crowpanel_35 variant: display, SD, board and target files, plus board JSON
- Portrait mode is drawn rotated 180°; landscape stays at rotation 3
- Share the GT911 touch driver between Wio Tracker L2 and CrowPanel
  (WioTrackerL2Touch.cpp -> src/helpers/input/LgfxGt911Touch.cpp)
- platformio envs, flasher/site entries, release and merge-bin support
- Tests for the CrowPanel SD codec and merge-bin

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0132MkJ7RUV32mV9F7o4PJMm
2026-10-02 20:16:06 -04:00

87 lines
3.3 KiB
Python

#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0-or-later
import os
from pathlib import Path
import runpy
import unittest
from unittest.mock import MagicMock, patch
SCRIPT = Path(__file__).resolve().parents[1] / "merge-bin.py"
class MergeBinTests(unittest.TestCase):
def load_action(self, output=None):
self.build_dir = "/project with spaces/board's build"
self.app_path = self.build_dir + "/firmware.bin"
self.images = [
("0x0", self.build_dir + "/bootloader.bin"),
("0x8000", self.build_dir + "/partitions.bin"),
("0xe000", "/framework with spaces/boot_app0.bin"),
]
self.process_env = {"PATH": "/tools with spaces"}
env = MagicMock()
env.BoardConfig.return_value = {
"build.mcu": "esp32s3",
"build.flash_mode": "qio",
"upload.flash_size": "16MB",
}
env.get.return_value = self.images
env.Flatten.side_effect = lambda images: [value for pair in images for value in pair]
substitutions = {
"$PYTHONEXE": "/python with spaces/python",
"$OBJCOPY": "/tools with spaces/esptool.py",
"${BUILD_DIR}/${PROGNAME}-merged.bin": self.build_dir + "/firmware-merged.bin",
"${__get_board_f_flash(__env__)}": "80m",
"$ESP32_APP_OFFSET": "0x10000",
}
env.subst.side_effect = lambda value: substitutions.get(value, value)
env.__getitem__.return_value = self.process_env
environ = {} if output is None else {"MERGED_BIN_PATH": output}
with patch.dict(os.environ, environ, clear=True):
script = runpy.run_path(str(SCRIPT), init_globals={
"Import": lambda *args: None,
"env": env,
"projenv": env,
})
source = MagicMock()
source.get_abspath.return_value = self.app_path
return script["merge_bin_action"], [source], env
@patch("subprocess.run")
def test_paths_and_flash_offsets_are_preserved(self, run):
action, source, env = self.load_action()
run.return_value.returncode = 0
self.assertEqual(action(source, [], env), 0)
run.assert_called_once_with([
"/python with spaces/python",
"/tools with spaces/esptool.py",
"--chip", "esp32s3",
"merge_bin",
"-o", self.build_dir + "/firmware-merged.bin",
"--flash_mode", "qio",
"--flash_freq", "80m",
"--flash_size", "16MB",
*[value for pair in self.images for value in pair],
"0x10000", self.app_path,
], env=self.process_env)
@patch("subprocess.run")
def test_output_override_is_preserved(self, run):
output = "/custom output/owner's merged image.bin"
action, source, env = self.load_action(output)
run.return_value.returncode = 0
self.assertEqual(action(source, [], env), 0)
args = run.call_args.args[0]
self.assertEqual(args[args.index("-o") + 1], output)
@patch("subprocess.run")
def test_merge_failure_is_returned(self, run):
action, source, env = self.load_action()
run.return_value.returncode = 2
self.assertEqual(action(source, [], env), 2)
if __name__ == "__main__":
unittest.main()