# Fixes: unit test mocks + small fixes
This commit is contained in:
parent
bfe4dd6033
commit
2dbe3e61ed
12 changed files with 226 additions and 111 deletions
|
|
@ -3,7 +3,7 @@
|
||||||
cmake_minimum_required(VERSION 3.20)
|
cmake_minimum_required(VERSION 3.20)
|
||||||
project(
|
project(
|
||||||
firmware_test
|
firmware_test
|
||||||
VERSION 0.1.1
|
VERSION 0.1.2
|
||||||
LANGUAGES C ASM)
|
LANGUAGES C ASM)
|
||||||
|
|
||||||
set(TARGET_NAME firmware_test)
|
set(TARGET_NAME firmware_test)
|
||||||
|
|
|
||||||
|
|
@ -254,10 +254,10 @@ static void handle_cmd_run(const char *p_line)
|
||||||
*/
|
*/
|
||||||
static void handle_cmd_run_selected(const char *p_line)
|
static void handle_cmd_run_selected(const char *p_line)
|
||||||
{
|
{
|
||||||
/* Максимальный размер реестра — не более 16 тестов */
|
/* Общий "потолок системы" — TEST_REGISTRY_MAX_SIZE (test_module.h),
|
||||||
const size_t MAX_SELECTED = 16U;
|
* тот же, что ограничивает test_runner.c::g_s_selected[]. */
|
||||||
char id_bufs[16][TEST_ID_MAX_SIZE];
|
char id_bufs[TEST_REGISTRY_MAX_SIZE][TEST_ID_MAX_SIZE];
|
||||||
const char *id_ptrs[16];
|
const char *id_ptrs[TEST_REGISTRY_MAX_SIZE];
|
||||||
|
|
||||||
const char *tests_key = strstr(p_line, K_FIELD_TESTS);
|
const char *tests_key = strstr(p_line, K_FIELD_TESTS);
|
||||||
if (tests_key == NULL)
|
if (tests_key == NULL)
|
||||||
|
|
@ -267,7 +267,7 @@ static void handle_cmd_run_selected(const char *p_line)
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t count =
|
size_t count =
|
||||||
parse_string_array(tests_key + sizeof(K_FIELD_TESTS) - 1U, id_bufs, MAX_SELECTED);
|
parse_string_array(tests_key + sizeof(K_FIELD_TESTS) - 1U, id_bufs, TEST_REGISTRY_MAX_SIZE);
|
||||||
|
|
||||||
if (count == 0U)
|
if (count == 0U)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,23 @@
|
||||||
/** @brief Максимальная длина идентификатора теста (включая NUL). */
|
/** @brief Максимальная длина идентификатора теста (включая NUL). */
|
||||||
#define TEST_ID_MAX_SIZE 24U
|
#define TEST_ID_MAX_SIZE 24U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Верхняя граница числа тест-модулей в системе.
|
||||||
|
*
|
||||||
|
* Общий "потолок" для двух независимых мест:
|
||||||
|
* - test_runner.c: compile-time ёмкость g_s_selected[] (маска выбора
|
||||||
|
* для RUNNER_MODE_SELECTED). REGISTRY_SIZE в UNIT_TEST-сборке —
|
||||||
|
* runtime-значение (g_unit_test_registry_size), не может быть
|
||||||
|
* границей массива со static storage duration.
|
||||||
|
* - cli.c: максимальный размер входящего массива "tests" в команде
|
||||||
|
* run_selected (handle_cmd_run_selected()).
|
||||||
|
*
|
||||||
|
* Реальный реестр (non-UNIT_TEST, k_registry) — 8 модулей, запас есть.
|
||||||
|
* При добавлении нового теста, если REGISTRY_SIZE превысит эту границу,
|
||||||
|
* сборка упадёт на _Static_assert в test_runner.c — увеличивать здесь.
|
||||||
|
*/
|
||||||
|
#define TEST_REGISTRY_MAX_SIZE 16U
|
||||||
|
|
||||||
/* ── Типы результата ───────────────────────────────────────────────────── */
|
/* ── Типы результата ───────────────────────────────────────────────────── */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,12 @@ extern size_t g_unit_test_registry_size;
|
||||||
|
|
||||||
#define RUNNER_CONFIRM_ID_SIZE 32U
|
#define RUNNER_CONFIRM_ID_SIZE 32U
|
||||||
|
|
||||||
|
#ifndef UNIT_TEST
|
||||||
|
_Static_assert(
|
||||||
|
REGISTRY_SIZE <= TEST_REGISTRY_MAX_SIZE,
|
||||||
|
"k_registry вырос за пределы TEST_REGISTRY_MAX_SIZE (test_module.h) — увеличь константу");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ── Типы ──────────────────────────────────────────────────────────────── */
|
/* ── Типы ──────────────────────────────────────────────────────────────── */
|
||||||
|
|
||||||
typedef enum runner_state_e
|
typedef enum runner_state_e
|
||||||
|
|
@ -92,12 +98,10 @@ static uint8_t g_s_skipped;
|
||||||
static bool g_s_critical_failed;
|
static bool g_s_critical_failed;
|
||||||
|
|
||||||
/* Маска выбранных тестов для RUNNER_MODE_SELECTED */
|
/* Маска выбранных тестов для RUNNER_MODE_SELECTED */
|
||||||
static bool g_s_selected[REGISTRY_SIZE];
|
static bool g_s_selected[TEST_REGISTRY_MAX_SIZE];
|
||||||
|
|
||||||
/* ── Forward declaration ───────────────────────────────────────────────── */
|
/* ── Forward declaration ───────────────────────────────────────────────── */
|
||||||
|
|
||||||
static void start_test_at(size_t idx);
|
static void start_test_at(size_t idx);
|
||||||
|
|
||||||
/* ── Внутренние вспомогательные функции ────────────────────────────────── */
|
/* ── Внутренние вспомогательные функции ────────────────────────────────── */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -171,6 +171,7 @@ add_host_test(
|
||||||
INCLUDES
|
INCLUDES
|
||||||
${CMAKE_SOURCE_DIR}/firmware/test/src/
|
${CMAKE_SOURCE_DIR}/firmware/test/src/
|
||||||
${CMAKE_SOURCE_DIR}/bsp/common/include
|
${CMAKE_SOURCE_DIR}/bsp/common/include
|
||||||
|
${CMAKE_SOURCE_DIR}/bsp/provisioning/include
|
||||||
MOCKS
|
MOCKS
|
||||||
${BSP_MOCKS_DIR})
|
${BSP_MOCKS_DIR})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@
|
||||||
DEFINE_FFF_GLOBALS;
|
DEFINE_FFF_GLOBALS;
|
||||||
|
|
||||||
#include "clock_config.h"
|
#include "clock_config.h"
|
||||||
|
#include "fsl_clock.h"
|
||||||
#include "fsl_flexcan.h"
|
#include "fsl_flexcan.h"
|
||||||
|
|
||||||
/* ══════════════════════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════════════════════
|
||||||
* fff-фейки SDK-функций
|
* fff-фейки SDK-функций
|
||||||
* ══════════════════════════════════════════════════════════════════════ */
|
* ══════════════════════════════════════════════════════════════════════ */
|
||||||
|
|
@ -47,6 +47,9 @@ FAKE_VOID_FUNC(FLEXCAN_ClearMbStatusFlags, CAN_Type *, uint64_t);
|
||||||
/* bsp_tick — управляемый «таймер» для тестов таймаутов */
|
/* bsp_tick — управляемый «таймер» для тестов таймаутов */
|
||||||
FAKE_VALUE_FUNC(uint32_t, bsp_tick_get_ms);
|
FAKE_VALUE_FUNC(uint32_t, bsp_tick_get_ms);
|
||||||
|
|
||||||
|
/* ERRATA 50235 workaround (см. bsp_can_init()) */
|
||||||
|
FAKE_VOID_FUNC(CLOCK_EnableClock, clock_ip_name_t);
|
||||||
|
|
||||||
/* ══════════════════════════════════════════════════════════════════════
|
/* ══════════════════════════════════════════════════════════════════════
|
||||||
* Тестируемый модуль (после всех фейков!)
|
* Тестируемый модуль (после всех фейков!)
|
||||||
* ══════════════════════════════════════════════════════════════════════ */
|
* ══════════════════════════════════════════════════════════════════════ */
|
||||||
|
|
@ -132,6 +135,7 @@ void setUp(void)
|
||||||
RESET_FAKE(FLEXCAN_GetMbStatusFlags);
|
RESET_FAKE(FLEXCAN_GetMbStatusFlags);
|
||||||
RESET_FAKE(FLEXCAN_ClearMbStatusFlags);
|
RESET_FAKE(FLEXCAN_ClearMbStatusFlags);
|
||||||
RESET_FAKE(bsp_tick_get_ms);
|
RESET_FAKE(bsp_tick_get_ms);
|
||||||
|
RESET_FAKE(CLOCK_EnableClock);
|
||||||
FFF_RESET_HISTORY();
|
FFF_RESET_HISTORY();
|
||||||
|
|
||||||
s_mb_flags_call_count = 0U;
|
s_mb_flags_call_count = 0U;
|
||||||
|
|
@ -162,6 +166,8 @@ void test_init_success(void)
|
||||||
TEST_ASSERT_EQUAL(1, FLEXCAN_Init_fake.call_count);
|
TEST_ASSERT_EQUAL(1, FLEXCAN_Init_fake.call_count);
|
||||||
/* MB0 = reserved (ERR005829), MB1 = TX */
|
/* MB0 = reserved (ERR005829), MB1 = TX */
|
||||||
TEST_ASSERT_EQUAL(1, FLEXCAN_SetTxMbConfig_fake.call_count);
|
TEST_ASSERT_EQUAL(1, FLEXCAN_SetTxMbConfig_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL(1, CLOCK_EnableClock_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL(kCLOCK_Lpuart1, CLOCK_EnableClock_fake.arg0_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_init_null_config(void)
|
void test_init_null_config(void)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@
|
||||||
* пока стек ещё жив (аргументы — указатели на локальные буферы cli.c).
|
* пока стек ещё жив (аргументы — указатели на локальные буферы cli.c).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "bsp/provisioning.h"
|
||||||
|
#include "bsp/status.h"
|
||||||
#include "fff.h"
|
#include "fff.h"
|
||||||
|
#include "test_module.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -28,7 +31,11 @@ FAKE_VOID_FUNC(protocol_send_error, const char *);
|
||||||
FAKE_VOID_FUNC(test_runner_run_all);
|
FAKE_VOID_FUNC(test_runner_run_all);
|
||||||
FAKE_VOID_FUNC(test_runner_run_single, const char *);
|
FAKE_VOID_FUNC(test_runner_run_single, const char *);
|
||||||
FAKE_VOID_FUNC(test_runner_on_confirm, const char *, bool);
|
FAKE_VOID_FUNC(test_runner_on_confirm, const char *, bool);
|
||||||
|
FAKE_VOID_FUNC(protocol_send_uid_response, const uint8_t *);
|
||||||
|
FAKE_VOID_FUNC(protocol_send_version_response);
|
||||||
|
FAKE_VOID_FUNC(test_runner_run_selected, const char *const *, size_t);
|
||||||
|
FAKE_VOID_FUNC(test_runner_send_list);
|
||||||
|
FAKE_VALUE_FUNC(bsp_status_t, bsp_prov_read_uid, uint8_t *, size_t);
|
||||||
/* ── Модуль под тестом ─────────────────────────────────────────────────── */
|
/* ── Модуль под тестом ─────────────────────────────────────────────────── */
|
||||||
|
|
||||||
#include "cli.h"
|
#include "cli.h"
|
||||||
|
|
@ -72,6 +79,16 @@ static char s_run_single_id[32U];
|
||||||
static char s_confirm_id[32U];
|
static char s_confirm_id[32U];
|
||||||
static bool s_confirm_value;
|
static bool s_confirm_value;
|
||||||
|
|
||||||
|
/* get_uid: cli.c передаёт указатель на СВОЙ стековый буфер — копируем
|
||||||
|
* по значению внутри custom_fake, иначе после возврата cli_process()
|
||||||
|
* указатель уже dangling (см. "Ловушка" в HOST_CREATE_TEST.md). */
|
||||||
|
static uint8_t s_captured_uid[BSP_PROV_UID_LEN];
|
||||||
|
|
||||||
|
/* run_selected: id_ptrs[] в cli.c указывает на локальный id_bufs[][] —
|
||||||
|
* та же ловушка, копируем строки, а не указатели. */
|
||||||
|
static size_t s_run_selected_count;
|
||||||
|
static char s_run_selected_ids[TEST_REGISTRY_MAX_SIZE][TEST_ID_MAX_SIZE];
|
||||||
|
|
||||||
static void capture_run_single(const char *p_id)
|
static void capture_run_single(const char *p_id)
|
||||||
{
|
{
|
||||||
(void) snprintf(s_run_single_id, sizeof(s_run_single_id), "%s", p_id);
|
(void) snprintf(s_run_single_id, sizeof(s_run_single_id), "%s", p_id);
|
||||||
|
|
@ -83,6 +100,31 @@ static void capture_on_confirm(const char *p_id, bool confirmed)
|
||||||
s_confirm_value = confirmed;
|
s_confirm_value = confirmed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void capture_uid_response(const uint8_t *p_uid)
|
||||||
|
{
|
||||||
|
memcpy(s_captured_uid, p_uid, BSP_PROV_UID_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void capture_run_selected(const char *const *pp_ids, size_t count)
|
||||||
|
{
|
||||||
|
s_run_selected_count = count;
|
||||||
|
for (size_t i = 0U; i < count && i < TEST_REGISTRY_MAX_SIZE; i++)
|
||||||
|
{
|
||||||
|
(void) snprintf(s_run_selected_ids[i], sizeof(s_run_selected_ids[i]), "%s", pp_ids[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Фиксированный UID, который "читает" bsp_prov_read_uid в тестах успеха. */
|
||||||
|
static const uint8_t K_TEST_UID[BSP_PROV_UID_LEN] = {
|
||||||
|
0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22
|
||||||
|
};
|
||||||
|
|
||||||
|
static bsp_status_t prov_read_uid_success(uint8_t *p_uid, size_t len)
|
||||||
|
{
|
||||||
|
(void) len;
|
||||||
|
memcpy(p_uid, K_TEST_UID, BSP_PROV_UID_LEN);
|
||||||
|
return BSP_OK;
|
||||||
|
}
|
||||||
/* ── setUp / tearDown ──────────────────────────────────────────────────── */
|
/* ── setUp / tearDown ──────────────────────────────────────────────────── */
|
||||||
|
|
||||||
void setUp(void)
|
void setUp(void)
|
||||||
|
|
@ -94,16 +136,27 @@ void setUp(void)
|
||||||
RESET_FAKE(test_runner_run_all);
|
RESET_FAKE(test_runner_run_all);
|
||||||
RESET_FAKE(test_runner_run_single);
|
RESET_FAKE(test_runner_run_single);
|
||||||
RESET_FAKE(test_runner_on_confirm);
|
RESET_FAKE(test_runner_on_confirm);
|
||||||
|
RESET_FAKE(protocol_send_uid_response);
|
||||||
|
RESET_FAKE(protocol_send_version_response);
|
||||||
|
RESET_FAKE(bsp_prov_read_uid);
|
||||||
|
RESET_FAKE(protocol_send_version_response);
|
||||||
|
RESET_FAKE(bsp_prov_read_uid);
|
||||||
|
RESET_FAKE(test_runner_run_selected);
|
||||||
|
RESET_FAKE(test_runner_send_list);
|
||||||
FFF_RESET_HISTORY();
|
FFF_RESET_HISTORY();
|
||||||
|
|
||||||
bsp_usb_cdc_read_fake.custom_fake = fake_usb_read;
|
bsp_usb_cdc_read_fake.custom_fake = fake_usb_read;
|
||||||
test_runner_run_single_fake.custom_fake = capture_run_single;
|
test_runner_run_single_fake.custom_fake = capture_run_single;
|
||||||
test_runner_on_confirm_fake.custom_fake = capture_on_confirm;
|
test_runner_on_confirm_fake.custom_fake = capture_on_confirm;
|
||||||
|
protocol_send_uid_response_fake.custom_fake = capture_uid_response;
|
||||||
|
test_runner_run_selected_fake.custom_fake = capture_run_selected;
|
||||||
|
|
||||||
s_inject_len = 0U;
|
s_inject_len = 0U;
|
||||||
s_run_single_id[0] = '\0';
|
s_run_single_id[0] = '\0';
|
||||||
s_confirm_id[0] = '\0';
|
s_confirm_id[0] = '\0';
|
||||||
s_confirm_value = false;
|
s_confirm_value = false;
|
||||||
|
s_run_selected_count = 0U;
|
||||||
|
(void) memset(s_captured_uid, 0, sizeof(s_captured_uid));
|
||||||
|
|
||||||
cli_init();
|
cli_init();
|
||||||
}
|
}
|
||||||
|
|
@ -138,6 +191,62 @@ void test_run_single_dispatches_with_id(void)
|
||||||
TEST_ASSERT_EQUAL_STRING("sdram", s_run_single_id);
|
TEST_ASSERT_EQUAL_STRING("sdram", s_run_single_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_get_uid_success(void)
|
||||||
|
{
|
||||||
|
bsp_prov_read_uid_fake.custom_fake = prov_read_uid_success;
|
||||||
|
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"get_uid\"}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, bsp_prov_read_uid_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, protocol_send_uid_response_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, protocol_send_error_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_UINT8_ARRAY(K_TEST_UID, s_captured_uid, BSP_PROV_UID_LEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_get_uid_read_failure_sends_error(void)
|
||||||
|
{
|
||||||
|
bsp_prov_read_uid_fake.return_val = BSP_ERR_PARAM;
|
||||||
|
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"get_uid\"}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, protocol_send_uid_response_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, protocol_send_error_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("UID_READ_ERR", protocol_send_error_fake.arg0_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_get_version_dispatches(void)
|
||||||
|
{
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"get_version\"}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, protocol_send_version_response_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_INT(0, protocol_send_error_fake.call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_list_tests_dispatches(void)
|
||||||
|
{
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"list_tests\"}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, test_runner_send_list_fake.call_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_run_selected_dispatches_with_ids(void)
|
||||||
|
{
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"run_selected\",\"tests\":[\"sdram\",\"opto\"]}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, test_runner_run_selected_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL(2, s_run_selected_count);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("sdram", s_run_selected_ids[0]);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("opto", s_run_selected_ids[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_run_selected_missing_tests_field_sends_parse_err(void)
|
||||||
|
{
|
||||||
|
inject("{\"type\":\"cmd\",\"cmd\":\"run_selected\"}\n");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(1, protocol_send_error_fake.call_count);
|
||||||
|
TEST_ASSERT_EQUAL_STRING("PARSE_ERR", protocol_send_error_fake.arg0_val);
|
||||||
|
}
|
||||||
|
|
||||||
void test_unknown_cmd_sends_unknown_cmd_error(void)
|
void test_unknown_cmd_sends_unknown_cmd_error(void)
|
||||||
{
|
{
|
||||||
inject("{\"type\":\"cmd\",\"cmd\":\"reboot\"}\n");
|
inject("{\"type\":\"cmd\",\"cmd\":\"reboot\"}\n");
|
||||||
|
|
@ -262,5 +371,12 @@ int main(void)
|
||||||
RUN_TEST(test_crlf_handled_same_as_lf);
|
RUN_TEST(test_crlf_handled_same_as_lf);
|
||||||
RUN_TEST(test_two_lines_in_one_chunk_both_dispatched);
|
RUN_TEST(test_two_lines_in_one_chunk_both_dispatched);
|
||||||
|
|
||||||
|
RUN_TEST(test_get_uid_success);
|
||||||
|
RUN_TEST(test_get_uid_read_failure_sends_error);
|
||||||
|
RUN_TEST(test_get_version_dispatches);
|
||||||
|
RUN_TEST(test_list_tests_dispatches);
|
||||||
|
RUN_TEST(test_run_selected_dispatches_with_ids);
|
||||||
|
RUN_TEST(test_run_selected_missing_tests_field_sends_parse_err);
|
||||||
|
|
||||||
return UNITY_END();
|
return UNITY_END();
|
||||||
}
|
}
|
||||||
24
tests/host/mocks/fsl_clock.h
Normal file
24
tests/host/mocks/fsl_clock.h
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file fsl_clock.h
|
||||||
|
* @brief Stub fsl_clock.h для host-тестов.
|
||||||
|
*
|
||||||
|
* Содержит только то, что реально используется в:
|
||||||
|
* bsp/can/src/can.c — ERRATA 50235 workaround, CLOCK_EnableClock(kCLOCK_Lpuart1)
|
||||||
|
*
|
||||||
|
* fff предоставляет реализацию через FAKE_VOID_FUNC в тестовом файле.
|
||||||
|
*
|
||||||
|
* Оригинал: sdk/devices/MIMXRT1052/drivers/fsl_clock.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ── clock_ip_name_t — только используемый член ──────────────────────────── */
|
||||||
|
|
||||||
|
typedef enum _clock_ip_name
|
||||||
|
{
|
||||||
|
kCLOCK_Lpuart1 = 0,
|
||||||
|
} clock_ip_name_t;
|
||||||
|
|
||||||
|
/* ── Function signature — реализуется через fff ──────────────────────────── */
|
||||||
|
|
||||||
|
void CLOCK_EnableClock(clock_ip_name_t name);
|
||||||
19
tests/host/mocks/version.h
Normal file
19
tests/host/mocks/version.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file version.h
|
||||||
|
* @brief Stub version.h для host-тестов.
|
||||||
|
*
|
||||||
|
* Реальный version.h генерируется CMake (configure_file) из
|
||||||
|
* firmware/test/src/version.h.in только при конфигурации ARM-таргета
|
||||||
|
* firmware_test (BUILD_TESTS_TARGET=ON). В host-debug/host-release
|
||||||
|
* firmware/test/CMakeLists.txt не подключается — generated/version.h
|
||||||
|
* не существует. Значения ниже фиксированные, участвуют только
|
||||||
|
* в сериализации протокола (session_start/version_response), не в логике.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define FIRMWARE_TEST_VERSION_MAJOR 0
|
||||||
|
#define FIRMWARE_TEST_VERSION_MINOR 0
|
||||||
|
#define FIRMWARE_TEST_VERSION_PATCH 0
|
||||||
|
|
||||||
|
#define FIRMWARE_TEST_VERSION_STR "0.0.0-host-test"
|
||||||
|
|
@ -36,7 +36,7 @@ FAKE_VOID_FUNC(protocol_send_confirm_request, const confirm_params_t *);
|
||||||
FAKE_VOID_FUNC(protocol_send_error, const char *);
|
FAKE_VOID_FUNC(protocol_send_error, const char *);
|
||||||
FAKE_VOID_FUNC(protocol_send_pong);
|
FAKE_VOID_FUNC(protocol_send_pong);
|
||||||
FAKE_VOID_FUNC(protocol_send_session_start);
|
FAKE_VOID_FUNC(protocol_send_session_start);
|
||||||
|
FAKE_VOID_FUNC(protocol_send_test_list, const test_module_t *const *, size_t);
|
||||||
/* ── Модуль под тестом ─────────────────────────────────────────────────── */
|
/* ── Модуль под тестом ─────────────────────────────────────────────────── */
|
||||||
|
|
||||||
#include "test_runner.h"
|
#include "test_runner.h"
|
||||||
|
|
@ -131,6 +131,7 @@ void setUp(void)
|
||||||
RESET_FAKE(protocol_send_summary);
|
RESET_FAKE(protocol_send_summary);
|
||||||
RESET_FAKE(protocol_send_confirm_request);
|
RESET_FAKE(protocol_send_confirm_request);
|
||||||
RESET_FAKE(protocol_send_error);
|
RESET_FAKE(protocol_send_error);
|
||||||
|
RESET_FAKE(protocol_send_test_list);
|
||||||
FFF_RESET_HISTORY();
|
FFF_RESET_HISTORY();
|
||||||
|
|
||||||
protocol_send_test_result_fake.custom_fake = capture_test_result;
|
protocol_send_test_result_fake.custom_fake = capture_test_result;
|
||||||
|
|
|
||||||
|
|
@ -1,81 +1,12 @@
|
||||||
# -*- mode: python ; coding: utf-8 -*-
|
# -*- mode: python ; coding: utf-8 -*-
|
||||||
"""
|
|
||||||
service_tui.spec — PyInstaller spec для service-tui (Фаза 5, RELEASE_ROADMAP.md).
|
|
||||||
|
|
||||||
Собирает onedir-бандл (не onefile — onefile замедляет старт распаковкой,
|
|
||||||
см. MONOLITH_APP_PLAN.md §Фаза 5). Итоговая структура:
|
|
||||||
|
|
||||||
dist/service_tui/
|
|
||||||
├── service_tui[.exe]
|
|
||||||
├── _internal/
|
|
||||||
│ ├── data/ ← dcd.bin, *_fdcb.bin, ivt_flashloader.bin, spsdk data
|
|
||||||
│ └── ... ← рантайм PyInstaller, libusbsio (из Analysis)
|
|
||||||
├── firmware/ ← НЕ создаётся этим spec — см. just-рецепт (post-build copy,
|
|
||||||
│ firmware_hab_path() во frozen ждёт его рядом с exe,
|
|
||||||
│ а не внутри _internal — PyInstaller datas всегда
|
|
||||||
│ кладёт файлы внутрь _internal, сюда достать не может)
|
|
||||||
└── custom_binaries/ ← создаётся приложением само при первом запуске
|
|
||||||
(flasher.py::_resolve_custom_binaries_dir), не этим spec
|
|
||||||
|
|
||||||
Запуск: uv run --directory tools/production pyinstaller service_tui.spec
|
|
||||||
(все относительные пути ниже считаются от расположения этого файла — SPECPATH).
|
|
||||||
"""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs
|
|
||||||
|
|
||||||
_SPEC_DIR = Path(SPECPATH) # tools/production/ — переменная предоставлена PyInstaller
|
|
||||||
_REPO_ROOT = _SPEC_DIR.parents[1] # tools/production -> tools -> корень репозитория
|
|
||||||
_DCD_DIR = _REPO_ROOT / "tools" / "host" / "dcd"
|
|
||||||
|
|
||||||
# ── datas ────────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
# spsdk: ~380 файлов данных (data/devices/*/database.yaml и т.п.) — проверено,
|
|
||||||
# реально нужны (HabImage/Config резолвят family="mimxrt1050" через них),
|
|
||||||
# не декоративная предосторожность.
|
|
||||||
datas = collect_data_files("spsdk")
|
|
||||||
|
|
||||||
# app.tcss — Textual резолвит CSS_PATH относительно __file__ модуля, где
|
|
||||||
# определён App (app/app.py); во frozen эта директория виртуальна, но должна
|
|
||||||
# физически существовать в бандле по тому же относительному пути.
|
|
||||||
datas += [(str(_SPEC_DIR / "app" / "app.tcss"), "app")]
|
|
||||||
|
|
||||||
# pyproject.toml — для _read_app_version() (tomllib) во frozen; waiting.py
|
|
||||||
# резолвит parents[2] от __file__, что во frozen указывает на корень бандла.
|
|
||||||
datas += [(str(_SPEC_DIR / "pyproject.toml"), ".")]
|
|
||||||
|
|
||||||
# tools/host/dcd/*.bin — единый источник (Р6), тот же, что использует
|
|
||||||
# нетронутый flash_usb.py. Кладём в data/ внутри _internal — резолвер
|
|
||||||
# flash_backend.py (см. правку в этом же ответе) ждёт их именно там.
|
|
||||||
for _blob in sorted(_DCD_DIR.glob("*.bin")):
|
|
||||||
datas.append((str(_blob), "data"))
|
|
||||||
|
|
||||||
# ── binaries ─────────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
# libusbsio: нативный HID-транспорт (следствие Р7); libusb-1.0.* в бандле
|
|
||||||
# отсутствует. Заберёт бинарники всех платформ (см. пояснение в ответе,
|
|
||||||
# где предложен этот spec) — раздувает бандл, но не ломает.
|
|
||||||
binaries = collect_dynamic_libs("libusbsio")
|
|
||||||
|
|
||||||
# ── hiddenimports ────────────────────────────────────────────────────────
|
|
||||||
|
|
||||||
# app/ — implicit namespace package (нет __init__.py, в отличие от
|
|
||||||
# app/screens/). Перечисляем явно — цена нулевая, класс "тихо потерянного
|
|
||||||
# модуля" снимается целиком.
|
|
||||||
hiddenimports = [
|
|
||||||
"app",
|
|
||||||
"app.app",
|
|
||||||
"app.screens",
|
|
||||||
"app.widgets",
|
|
||||||
]
|
|
||||||
|
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
[str(_SPEC_DIR / "main.py")],
|
['main.py'],
|
||||||
pathex=[str(_SPEC_DIR)],
|
pathex=[],
|
||||||
binaries=binaries,
|
binaries=[],
|
||||||
datas=datas,
|
datas=[('../shared', 'shared')],
|
||||||
hiddenimports=hiddenimports,
|
hiddenimports=[],
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=[],
|
||||||
|
|
@ -83,27 +14,25 @@ a = Analysis(
|
||||||
noarchive=False,
|
noarchive=False,
|
||||||
optimize=0,
|
optimize=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
pyz = PYZ(a.pure)
|
pyz = PYZ(a.pure)
|
||||||
|
|
||||||
exe = EXE(
|
exe = EXE(
|
||||||
pyz,
|
pyz,
|
||||||
a.scripts,
|
a.scripts,
|
||||||
[],
|
|
||||||
exclude_binaries=True,
|
|
||||||
name="service_tui",
|
|
||||||
debug=False,
|
|
||||||
strip=False,
|
|
||||||
upx=False, # UPX + нативные HID-либы (libusbsio) — известный источник
|
|
||||||
# проблем с загрузкой; отключаю явно, не полагаюсь на дефолт
|
|
||||||
console=True, # Textual — терминальное приложение, без консоли не отрисуется
|
|
||||||
)
|
|
||||||
|
|
||||||
coll = COLLECT(
|
|
||||||
exe,
|
|
||||||
a.binaries,
|
a.binaries,
|
||||||
a.datas,
|
a.datas,
|
||||||
|
[],
|
||||||
|
name='service_tui',
|
||||||
|
debug=False,
|
||||||
|
bootloader_ignore_signals=False,
|
||||||
strip=False,
|
strip=False,
|
||||||
upx=False,
|
upx=True,
|
||||||
name="service_tui",
|
upx_exclude=[],
|
||||||
)
|
runtime_tmpdir=None,
|
||||||
|
console=True,
|
||||||
|
disable_windowed_traceback=False,
|
||||||
|
argv_emulation=False,
|
||||||
|
target_arch=None,
|
||||||
|
codesign_identity=None,
|
||||||
|
entitlements_file=None,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1132,7 +1132,6 @@ dependencies = [
|
||||||
{ name = "pyinstaller" },
|
{ name = "pyinstaller" },
|
||||||
{ name = "pyserial" },
|
{ name = "pyserial" },
|
||||||
{ name = "python-dotenv" },
|
{ name = "python-dotenv" },
|
||||||
{ name = "pyusb" },
|
|
||||||
{ name = "spsdk" },
|
{ name = "spsdk" },
|
||||||
{ name = "textual" },
|
{ name = "textual" },
|
||||||
]
|
]
|
||||||
|
|
@ -1147,7 +1146,6 @@ requires-dist = [
|
||||||
{ name = "pyinstaller", specifier = ">=6.0.0" },
|
{ name = "pyinstaller", specifier = ">=6.0.0" },
|
||||||
{ name = "pyserial", specifier = ">=3.5" },
|
{ name = "pyserial", specifier = ">=3.5" },
|
||||||
{ name = "python-dotenv", specifier = ">=1.0.0" },
|
{ name = "python-dotenv", specifier = ">=1.0.0" },
|
||||||
{ name = "pyusb", specifier = ">=1.0.0" },
|
|
||||||
{ name = "spsdk", specifier = "==3.7.0" },
|
{ name = "spsdk", specifier = "==3.7.0" },
|
||||||
{ name = "textual", specifier = ">=0.80.0" },
|
{ name = "textual", specifier = ">=0.80.0" },
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue