/* * p6_sort_probe.c — target-регрессия четырёх ключей сортировки панели. * * Проверяет реальный EMM-store и банковый sc_sort.c. Записи намеренно * перемешаны; `..` и маркер DSS обязаны сохранять крайние позиции, а * каталоги — оставаться перед файлами при любом направлении. */ #include #include #include #include #include #include #include "sc_panel.h" #include "sc_sort.h" #include "sc_store.h" static int result_fd = -1; static uint8_t failures; static void log_text(const char *text) { const char *end = text; uint16_t length; while (*end != '\0') end++; length = (uint16_t)(end - text); if (result_fd >= 0) (void)write(result_fd, text, length); } static void check(uint8_t condition, const char *name) { log_text(condition ? "PASS " : "FAIL "); if (!condition) failures++; log_text(name); log_text("\r\n"); } /* sc_sort_set() вызывает общий panel-инвариант. В probe достаточно той же * нормализации cursor/top без подтягивания файлового source-модуля. */ void sc_panel_normalize_view(ScPanel *panel) { if (panel->count == 0u) { panel->cursor = 0u; panel->top = 0u; return; } if (panel->cursor >= panel->count) panel->cursor = panel->count - 1u; if (panel->top > panel->cursor) panel->top = panel->cursor; if (panel->cursor >= (uint16_t)(panel->top + 27u)) { panel->top = (uint16_t)(panel->cursor - 26u); } } static void put_entry(ScPanel *panel, uint16_t index, const char *name, uint32_t size, uint16_t date, uint8_t attr, uint8_t flags) { ScDirEntry entry; memset(&entry, 0, sizeof(entry)); strcpy(entry.name, name); entry.size = size; entry.date = date; entry.time = (uint16_t)(index << 5); entry.attr = attr; entry.flags = flags; (void)sc_store_put(panel, index, &entry); } static void fill_panel(ScPanel *panel, uint8_t page) { memset(panel, 0, sizeof(*panel)); panel->phys_page = page; panel->count = 8u; panel->sort_key = SC_SORT_NAME; put_entry(panel, 0u, "BETA.TXT", 20ul, 0x5621u, 0u, 0u); put_entry(panel, 1u, ">>> MORE...", 0ul, 0u, 0u, SC_ENTRY_DSS_LIMIT); put_entry(panel, 2u, "ZDIR", 0ul, 0x5A21u, FA_DIREC, 0u); put_entry(panel, 3u, "ALPHA.BIN", 50ul, 0x5A21u, 0u, 0u); put_entry(panel, 4u, "..", 0ul, 0u, FA_DIREC, SC_ENTRY_PARENT); put_entry(panel, 5u, "GAMMA.TXT", 10ul, 0x5821u, 0u, 0u); put_entry(panel, 6u, "ADIR", 0ul, 0x5421u, FA_DIREC, 0u); put_entry(panel, 7u, "DELTA.EXE", 30ul, 0x5421u, 0u, 0u); } static uint8_t order_is(const ScPanel *panel, const char *const *names) { ScDirEntry entry; uint16_t i; for (i = 0u; i < panel->count; i++) { if (sc_store_get(panel, i, &entry) != 0 || strcmp(entry.name, names[i]) != 0) return 0u; } return 1u; } static uint8_t selected_is(const ScPanel *panel, const char *name) { ScDirEntry entry; return sc_store_get(panel, panel->cursor, &entry) == 0 && strcmp(entry.name, name) == 0; } int main(void) { static const char *const name_up[] = { "..", "ADIR", "ZDIR", "ALPHA.BIN", "BETA.TXT", "DELTA.EXE", "GAMMA.TXT", ">>> MORE..." }; static const char *const name_down[] = { "..", "ZDIR", "ADIR", "GAMMA.TXT", "DELTA.EXE", "BETA.TXT", "ALPHA.BIN", ">>> MORE..." }; static const char *const ext_up[] = { "..", "ADIR", "ZDIR", "ALPHA.BIN", "DELTA.EXE", "BETA.TXT", "GAMMA.TXT", ">>> MORE..." }; static const char *const ext_down[] = { "..", "ZDIR", "ADIR", "GAMMA.TXT", "BETA.TXT", "DELTA.EXE", "ALPHA.BIN", ">>> MORE..." }; static const char *const size_up[] = { "..", "ADIR", "ZDIR", "GAMMA.TXT", "BETA.TXT", "DELTA.EXE", "ALPHA.BIN", ">>> MORE..." }; static const char *const size_down[] = { "..", "ZDIR", "ADIR", "ALPHA.BIN", "DELTA.EXE", "BETA.TXT", "GAMMA.TXT", ">>> MORE..." }; static const char *const date_up[] = { "..", "ADIR", "ZDIR", "DELTA.EXE", "BETA.TXT", "GAMMA.TXT", "ALPHA.BIN", ">>> MORE..." }; static const char *const date_down[] = { "..", "ZDIR", "ADIR", "ALPHA.BIN", "GAMMA.TXT", "BETA.TXT", "DELTA.EXE", ">>> MORE..." }; ScPanel left; ScPanel right; uint8_t block; uint8_t left_page; uint8_t right_page; result_fd = open("D:\\SORTRES.TXT", O_WRONLY | O_CREAT | O_TRUNC); block = mem_alloc_pages(2u); if (block == 0u) { log_text("FAIL EMM allocation\r\n"); if (result_fd >= 0) (void)close(result_fd); return 1; } left_page = mem_get_page(block, 0u); right_page = mem_get_page(block, 1u); fill_panel(&left, left_page); fill_panel(&right, right_page); check(sc_sort_panel(&left) == 0 && order_is(&left, name_up), "name ascending and fixed groups"); left.cursor = 4u; /* BETA.TXT в уже отсортированном списке. */ check(selected_is(&left, "BETA.TXT"), "selection fixture points to BETA"); check(sc_sort_set(&left, SC_SORT_NAME) == 0 && left.sort_descending && order_is(&left, name_down), "name descending toggle"); check(selected_is(&left, "BETA.TXT"), "selection preserved after sort"); check(sc_sort_set(&left, SC_SORT_EXTENSION) == 0 && !left.sort_descending && order_is(&left, ext_up), "extension ascending"); check(sc_sort_set(&left, SC_SORT_EXTENSION) == 0 && left.sort_descending && order_is(&left, ext_down), "extension descending toggle"); check(sc_sort_set(&left, SC_SORT_SIZE) == 0 && !left.sort_descending && order_is(&left, size_up), "size ascending"); check(sc_sort_set(&left, SC_SORT_SIZE) == 0 && left.sort_descending && order_is(&left, size_down), "size descending toggle"); check(sc_sort_set(&left, SC_SORT_DATE) == 0 && !left.sort_descending && order_is(&left, date_up), "date ascending"); check(sc_sort_set(&left, SC_SORT_DATE) == 0 && left.sort_descending && order_is(&left, date_down), "date descending toggle"); check(sc_sort_set(&right, SC_SORT_EXTENSION) == 0 && right.sort_key == SC_SORT_EXTENSION && !right.sort_descending && left.sort_key == SC_SORT_DATE && left.sort_descending, "panel sort modes are independent"); check(order_is(&right, ext_up), "second EMM page sorted independently"); mem_free_block(block); if (failures == 0u) log_text("ALL PASS\r\n"); if (result_fd >= 0) (void)close(result_fd); return failures; }