/* test_heat.c -- heat and anti-clock. */ #include "v4/heat.h" #include #include #include static int failures = 0; static int checks = 0; #define CHECK(cond, ...) \ do { \ checks++; \ if (!(cond)) { \ failures++; \ printf(" FAIL %s:%d: ", __FILE__, __LINE__); \ printf(__VA_ARGS__); \ printf("\n"); \ } \ } while (0) static void test_reset(void) { v4_heat h; memset(&h, 0xFF, sizeof h); v4_heat_reset(&h); for (unsigned i = 0; i < V4_OPCODE_COUNT; i++) { CHECK(h.op[i] == 0, "op %u heat non-zero after reset", i); } for (unsigned i = 0; i < V4_HEAT_MAX_CALL_TARGETS; i++) { CHECK(h.call[i] == 0, "call target %u heat non-zero after reset", i); CHECK(!v4_heat_call_is_frozen(&h, (v4_cell)i), "call target %u frozen after reset", i); } v4_uheat_t ac = 999; v4_heat_on_retire(&h, V4_OP_NOP, &ac); CHECK(ac == 1000, "anticlock not advanced"); CHECK(h.op[V4_OP_NOP] == 1, "nop heat"); } static void test_retire_advances_anticlock_and_opcode(void) { v4_heat h; v4_heat_reset(&h); v4_uheat_t ac = 0; for (int i = 0; i < 100; i++) { v4_heat_on_retire(&h, V4_OP_ADD, &ac); } CHECK(ac == 100, "anticlock"); CHECK(h.op[V4_OP_ADD] == 100, "add heat"); for (unsigned i = 0; i < V4_OPCODE_COUNT; i++) { if (i == V4_OP_ADD) continue; CHECK(h.op[i] == 0, "other op %u", i); } } static void test_call_advances_target(void) { v4_heat h; v4_heat_reset(&h); v4_heat_on_call(&h, 10); v4_heat_on_call(&h, 10); v4_heat_on_call(&h, 5); CHECK(v4_heat_call_get(&h, 10) == 2, "target 10"); CHECK(v4_heat_call_get(&h, 5) == 1, "target 5"); CHECK(v4_heat_call_get(&h, 1) == 0, "target 1"); } static void test_freeze(void) { v4_heat h; v4_heat_reset(&h); v4_heat_on_call(&h, 7); v4_heat_call_freeze(&h, 7); CHECK(v4_heat_call_is_frozen(&h, 7), "frozen"); v4_heat_on_call(&h, 7); CHECK(v4_heat_call_get(&h, 7) == 1, "still 1"); CHECK(v4_heat_call_set(&h, 7, 100) == 0, "set returns 0 when frozen"); CHECK(v4_heat_call_get(&h, 7) == 1, "unchanged"); v4_heat_call_unfreeze(&h, 7); CHECK(!v4_heat_call_is_frozen(&h, 7), "unfrozen"); CHECK(v4_heat_call_set(&h, 7, 42) == 1, "set allowed"); CHECK(v4_heat_call_get(&h, 7) == 42, "changed"); } static void test_out_of_range_ignored(void) { v4_heat h; v4_heat_reset(&h); v4_heat_on_call(&h, (v4_cell)V4_HEAT_MAX_CALL_TARGETS + 5); CHECK(v4_heat_call_get(&h, (v4_cell)V4_HEAT_MAX_CALL_TARGETS + 5) == 0, "out of range call ignored"); CHECK(v4_heat_call_set(&h, (v4_cell)-1, 123) == 0, "set out of range"); CHECK(v4_heat_call_is_frozen(&h, (v4_cell)-1) == 0, "frozen check"); } int main(void) { printf("v4 heat tests: V4_CELL_BITS=%d\n", V4_CELL_BITS); test_reset(); test_retire_advances_anticlock_and_opcode(); test_call_advances_target(); test_freeze(); test_out_of_range_ignored(); printf(" %d checks, %d failures\n", checks, failures); return failures ? 1 : 0; }