Files
Sprinter-SDCC/testkit/tcheck.h
T
Александр Петров 61d4255091 testkit: модульные тесты под ucsim_z80 + планы покрытия
Обвязка для быстрых тестов plain-C логики: секунды вместо прогона в MAME,
без образа диска.  ucsim_z80 идёт в комплекте нашего SDCC — новых
зависимостей нет.

ПОЧЕМУ ПОД Z80, А НЕ ХОСТОВЫМ GCC.  У SDCC z80 int 16 бит, у хоста 32, и
расходится это НЕ в объявлениях, а в выражениях: integer promotion
повышает операнды до int независимо от того, объявлены они как uint8_t
или uint16_t.  Перевод кода на фиксированные типы разницу не убирает —
убирает только исполнение с z80-семантикой.  Побочно проверяется
кодогенерация SDCC и модули с inline-asm, которых хостовая сборка не
видит в принципе.

Устройство: crt0_ucsim.s (SP, зануление, main, halt), tcheck.* (итог в
структуру в ОЗУ), run_ucsim.py (гоняет ucsim, дампит tc_result, печатает
отчёт), host-tests.mk (общие правила).  Вывода через printf нет: тестовый
бинарь линкуется без Sprinter-libc.  Через ucsim-simif не идём — номера
его команд плавают между версиями, halt + dump работают везде.

Наборы лежат РЯДОМ с проверяемым кодом, обвязка общая:
  testkit/t_selftest.c                     — самопроверка (sizeof(int)==2)
  applications/PoP/roomtest/tests-host/    — движок PoP

Первый содержательный набор — t_geom: сверяет рукописный asm-LCG из
pop_geom.c с наивной 32-битной формулой на 128 шагах.  Заявка «бит-в-бит
как в SDLPoP» до сих пор держалась на комментарии.  Тест проверен
мутацией: порча эталонной константы даёт красный.

Планы дальнейшего покрытия:
  docs/host-tests-plan.md                    — libc и libbgi (не начато)
  applications/PoP/docs/host_tests_plan.md   — движок PoP

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 22:36:16 +03:00

57 lines
2.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* tcheck.h — микро-фреймворк для тестов, исполняемых под ucsim_z80.
*
* Почему не printf: тестовый бинарь линкуется БЕЗ Sprinter-libc (там ESTEX,
* BIOS, файлы — ничего этого в ucsim нет). Поэтому результат складывается в
* структуру tc_result в ОЗУ, а раннер (run_ucsim.py) читает её командой
* `dump` после остановки по halt и печатает по-человечески.
*
* Использование:
*
* #include "tcheck.h"
* TC_TEST(имя_теста) { ... TC_EQ(получено, ожидание); ... }
* TC_MAIN(имя_теста, другой_тест, ...)
*
* Значения сравниваются как int16_t — этого хватает на всё, чем оперирует
* движок (координаты, тайлы, кадры, счётчики).
*/
#ifndef TCHECK_H
#define TCHECK_H
#include <stdint.h>
#define TC_LOGSZ 768
#define TC_MAGIC 0x5A5Au
typedef struct {
uint16_t magic; /* TC_MAGIC — раннер убеждается, что нашёл нас */
uint16_t total; /* сколько проверок выполнено */
uint16_t failed; /* сколько провалилось */
uint16_t logn; /* занято в log */
uint8_t log[TC_LOGSZ]; /* ASCII-отчёт (только про провалы) */
} tc_result_t;
extern tc_result_t tc_result;
/* Текущий тест — чтобы в отчёте было видно, где именно упало. */
extern const char *tc_curr;
void tc_begin(const char *name);
void tc_check(int16_t got, int16_t want, const char *expr, uint16_t line);
void tc_checkp(const void *got, const void *want, const char *expr, uint16_t line);
/* Основные макросы. __LINE__ хватает для локализации: имя теста уже в
* отчёте, а выражение печатается текстом. */
#define TC_EQ(got, want) tc_check((int16_t)(got), (int16_t)(want), #got, __LINE__)
#define TC_TRUE(cond) tc_check((int16_t)((cond) ? 1 : 0), 1, #cond, __LINE__)
#define TC_FALSE(cond) tc_check((int16_t)((cond) ? 1 : 0), 0, #cond, __LINE__)
#define TC_PEQ(got, want) tc_checkp((got), (want), #got, __LINE__)
#define TC_TEST(name) static void name(void)
/* main() тестового бинаря: перечислить функции тестов. Вариадика через
* список вызовов — у SDCC нет проблем с таким раскрытием. */
#define TC_RUN(fn) do { tc_begin(#fn); fn(); } while (0)
#endif