Размещать основной SCI8-комплект F2812 в flash, включая BIN, OUT, HEX, карты, manifest и SHA-256. Передавать выбранный путь в указатель последней сборки и экспорт; сохранить раскладку остальных процессоров. Добавить проверку раскладки, паспортов и экспорта и описать правило. Проверка: пять тестов общей сборки и реальный postbuild текущего OUT; побайтовая сверка BIN после переноса.
75 lines
12 KiB
Python
75 lines
12 KiB
Python
import importlib.util # Загружает общий модуль подготовки непосредственно из проверяемой копии templates.
|
||
import json # Проверяет сохранение пользовательских полей при резервировании версии 166.
|
||
from pathlib import Path # Все файлы теста находятся в изолированном временном каталоге.
|
||
import tempfile # Исключает запись версий и паспортов в рабочие прошивки пользователя.
|
||
import unittest # Запускает проверки без зависимостей SETGUI и Qt.
|
||
|
||
TOOLS = Path(__file__).resolve().parents[1] / "tools" # Тест переносится вместе с c/firmware-info в полный checkout templates.
|
||
SPEC = importlib.util.spec_from_file_location("checked_c2000_build", TOOLS / "c2000_build.py") # Выбирает одну реализацию общего процесса.
|
||
BUILD = importlib.util.module_from_spec(SPEC) # Импорт не выполняет prebuild и не меняет счётчики версии.
|
||
SPEC.loader.exec_module(BUILD) # Проверяет реальный модуль, а не копию функций внутри теста.
|
||
|
||
|
||
class LegacyVersionTests(unittest.TestCase): # Подтверждает совместимость общей подготовки с JSON-конфигурацией 166.
|
||
def test_json_counter_increments_once_and_keeps_settings(self): # Перенос в templates не должен удваивать резервирование версии.
|
||
with tempfile.TemporaryDirectory() as temporary: # Версия настоящего проекта 166 остаётся неизменной.
|
||
project = Path(temporary) # Минимальный проект использует прежние настройки без нового аппаратного профиля.
|
||
settings = {"product": "Balsam-166-PM35", "target": "TMS320F28335", "version": [1, 0, 999], "increment_version": True, "max_image_bytes": 32508, "copy_to": "../Bin"} # Patch 999 проверяет перенос в minor по общему контракту версии.
|
||
config = project / "firmware_identity.json" # Сохраняемый счётчик расположен в том же JSON, что в ветке 166.
|
||
config.write_text(json.dumps(settings), encoding="utf-8") # Русские данные и настройки сохраняются как UTF-8.
|
||
templates = TOOLS.parents[2] # Полный путь templates восстанавливается из c/firmware-info/tools.
|
||
metadata = BUILD.prepare(project, templates, project / "Debug/generated") # Выполняет настоящий общий prebuild без компиляции и сети.
|
||
saved = json.loads(config.read_text(encoding="utf-8")) # Проверяет именно сохранённую версию, а не только возвращённые метаданные.
|
||
self.assertEqual(saved["version"], [1, 1, 0]) # Номер увеличен один раз с переносом patch в minor.
|
||
self.assertEqual(metadata["version"], saved["version"]) # Паспорт и сохраняемый счётчик описывают одну попытку компиляции.
|
||
self.assertEqual(metadata["max_image_bytes"], 32508) # Историческая граница EEPROM 166 остаётся обязательной для postbuild.
|
||
self.assertEqual(saved["copy_to"], settings["copy_to"]) # Общий генератор сохраняет пользовательские поля, даже если сеть выполняет Публикатор.
|
||
|
||
|
||
class ReleaseLayoutTests(unittest.TestCase): # Проверяет назначение комплекта F2812 и совместимость экспорта для остальных процессоров.
|
||
def test_primary_package_follows_target_and_exports_with_receipt(self): # Проверяет пути, байты и паспорта полного комплекта после раскладки и экспорта.
|
||
identity = BUILD.load_identity(TOOLS.parents[2]) # Использует действующие функции подписи и копирования общей библиотеки.
|
||
for target, purpose in ((None, "eeprom"), ("TMS320F2812", "flash"), ("TMS320F28335", "eeprom")): # Старые вызовы и F28335 сохраняют EEPROM; F2812 использует внешнюю Flash.
|
||
with self.subTest(target=target), tempfile.TemporaryDirectory() as temporary: # Каждый вариант получает независимый выпуск и отдельную диагностику.
|
||
root = Path(temporary) # Файлы теста не попадают в действующий проект или каталог загрузок.
|
||
stage = root / "stage" # Воспроизводит временный каталог защищённого postbuild.
|
||
archive_name = "current-build" # Имя архива здесь фиксировано: проверяется раскладка, а не генерация даты.
|
||
archive = stage / archive_name # Полная копия компиляции должна получить те же папки, что текущие результаты.
|
||
archive.mkdir(parents=True) # Создаёт только каталоги данного проверочного выпуска.
|
||
metadata = {"target": target, "version": [1, 2, 3]} # Проверка паспорта должна сохранить процессор и версию конкретного сценария.
|
||
metadata_path = archive / "firmware_identity.json" # Общий паспорт остаётся в корне архива после раскладки.
|
||
metadata_path.write_text(json.dumps(metadata), encoding="utf-8") # Записывает метаданные в штатной кодировке общей библиотеки.
|
||
artifact, image_name = "Firmware", "Firmware_NOGIT000.bin" # Различает исходный OUT и BIN с идентификатором сборки.
|
||
companions = {"Firmware.out": b"original OUT", "Firmware.hex": b"original HEX", image_name + ".map": b"original map"} # Сопроводительные файлы обязаны следовать за основным образом без изменения байтов.
|
||
variants = {"Firmware_flash.out": "flash", "Firmware_flash_rs.bin": "rs", "Firmware_NOGIT000_can.bin": "can"} # Именованные дополнительные варианты сохраняют прежние независимые назначения.
|
||
for folder in (stage, archive): # Готовит одинаковые результаты для текущего выпуска и полного архива.
|
||
image = folder / image_name # Каждый экземпляр BIN получает собственные настоящие manifest и SHA-256.
|
||
image.write_bytes(b"primary SCI8 payload") # Узнаваемые байты выявляют подмену образа при переносе или экспорте.
|
||
identity.seal(image, metadata_path) # Вычисляет контрольные суммы штатной реализацией, а не подставляет фиктивный manifest.
|
||
for name, content in companions.items(): # Подготавливает OUT, HEX и карту того же основного комплекта.
|
||
(folder / name).write_bytes(content) # Сохраняет эталон для проверки точности переноса.
|
||
for name in variants: # Дополнительные образы нужны для проверки сохранения маршрутов flash, rs и can.
|
||
(folder / name).write_bytes(name.encode("ascii")) # Отличимые имена в содержимом исключают случайную перестановку файлов.
|
||
relative = BUILD.arrange_release(stage, archive_name, artifact, image_name, Path("Firmware_NOGIT000_can.bin"), target=target) # Вызывает ту же раскладку, что действующий postbuild.
|
||
self.assertEqual(relative, purpose + "/" + image_name) # Возвращаемый путь должен вести к основному образу в назначении выбранного процессора.
|
||
BUILD.write_receipt(stage, archive_name, relative) # Проверяет связь раскладки с указателем последнего выпуска.
|
||
receipt = json.loads((stage / "latest_build.json").read_text(encoding="utf-8")) # Читает записанный указатель как его потребитель.
|
||
self.assertEqual(receipt["manifest"], relative + ".manifest.json") # Путь импорта должен учитывать flash у F2812 и eeprom у остальных.
|
||
exported = identity.export_build(archive, root / "export", relative) # Выполняет настоящий экспорт всего архива в отдельный каталог.
|
||
for folder in (stage, archive, exported): # Одновременно проверяет локальный результат, архив и копию для пользователя.
|
||
BUILD.verify_package(folder / relative, metadata) # Сверяет реальные байты BIN, размер, SHA-256 и поля паспорта после всех переносов.
|
||
self.assertEqual((folder / relative).read_bytes(), b"primary SCI8 payload") # Основной образ сохраняется побайтово.
|
||
for suffix in (".manifest.json", ".sha256"): # Оба сопроводительных файла должны лежать рядом с BIN.
|
||
self.assertTrue((folder / (relative + suffix)).is_file()) # Обнаруживает потерю manifest или контрольной суммы при раскладке.
|
||
for name, content in companions.items(): # OUT, HEX и карта должны повторять назначение основного BIN.
|
||
self.assertEqual((folder / purpose / name).read_bytes(), content) # Проверяет путь и точное содержимое каждого файла.
|
||
for name, destination in variants.items(): # Проверяет неизменность маршрутов дополнительных вариантов.
|
||
self.assertEqual((folder / destination / name).read_bytes(), name.encode("ascii")) # Отдельные flash, rs и can не должны уйти в папку основного образа.
|
||
self.assertTrue((folder / "firmware_identity.json").is_file()) # Общий паспорт остаётся доступен в корне каждого комплекта.
|
||
if target == "TMS320F2812": # Только для F2812 проверяет отсутствие вводящей в заблуждение папки EEPROM.
|
||
self.assertFalse((folder / "eeprom").exists()) # Новый выпуск F2812 должен содержать основной комплект исключительно в flash.
|
||
|
||
|
||
if __name__ == "__main__": # Импорт набора проверок не запускает их повторно.
|
||
unittest.main() # Позволяет проверить совместимость прямой командой Python.
|