#include "c_IndexPQ.h" #include #include typedef struct { double distance; // Path distance used as priority metric (lower is more optimal) } PathCost_t; int compare_costs(const void* a, const void* b) { double distA = ((PathCost_t*)a)->distance; double distB = ((PathCost_t*)b)->distance; if (distA < distB) return -1; if (distA > distB) return 1; return 0; } void test_log(const char* name) { printf("[PASS] %s\n", name); } int main() { printf("==================================================\n"); printf(" Starting c_IndexPQ_t Min-Indexed Heap Unit Tests\n"); printf("==================================================\n\n"); c_IndexPQ_t ipq; // Track vertex node IDs from 0 to 4 (Max Size = 5) c_err_t err = c_IndexPQ_Init(&ipq, sizeof(PathCost_t), 5, compare_costs); assert(err == C_ERR_SUCCESS); assert(c_IndexPQ_IsEmpty(&ipq) == C_TRUE); test_log("1. Indexed priority queue structure initialization complete"); PathCost_t node0 = {50.5}; PathCost_t node1 = {20.1}; PathCost_t node2 = {100.0}; // ========================================== // 2. Testing Direct Indexed Push Checks // ========================================== c_IndexPQ_Push(&ipq, 0, &node0); // ID 0 -> cost 50.5 c_IndexPQ_Push(&ipq, 1, &node1); // ID 1 -> cost 20.1 (Current Min) c_IndexPQ_Push(&ipq, 2, &node2); // ID 2 -> cost 100.0 assert(c_IndexPQ_GetSize(&ipq) == 3); assert(c_IndexPQ_PeekID(&ipq) == 1); // Node ID 1 must sit on top // Duplicate index usage bounds intercept verification assert(c_IndexPQ_Push(&ipq, 1, &node0) == C_ERR_ALREADY_EXISTS); test_log("2. Key-ID bound checking and initial element mappings pass"); // ========================================== // 3. Testing Priority Mutation Updates (Change API) // ========================================== // Simulating a relaxation pass: found a shorter path to Node 2 (from 100.0 down to 5.2!) PathCost_t node2_optimized = {5.2}; err = c_IndexPQ_Change(&ipq, 2, &node2_optimized); assert(err == C_ERR_SUCCESS); // Node 2 must have bubble-up repaired straight to the top of the queue in O(log N) assert(c_IndexPQ_PeekID(&ipq) == 2); assert(((PathCost_t*)c_IndexPQ_PeekValue(&ipq))->distance == 5.2); test_log("3. Dynamic property value alteration and balance updates pass"); // ========================================== // 4. Testing Pop Execution and Integrity Mapping // ========================================== c_size_t popped_id; PathCost_t popped_data; // Pop 1: Must yield Node 2 (Cost 5.2) err = c_IndexPQ_Pop(&ipq, &popped_id, &popped_data); assert(err == C_ERR_SUCCESS); assert(popped_id == 2); assert(popped_data.distance == 5.2); // Pop 2: Must yield Node 1 (Cost 20.1) c_IndexPQ_Pop(&ipq, &popped_id, &popped_data); assert(popped_id == 1); // Pop 3: Must yield Node 0 (Cost 50.5) c_IndexPQ_Pop(&ipq, &popped_id, &popped_data); assert(popped_id == 0); assert(c_IndexPQ_IsEmpty(&ipq) == C_TRUE); // Empty boundaries fault detection assert rules assert(c_IndexPQ_Pop(&ipq, &popped_id, &popped_data) == C_ERR_EMPTY); test_log("4. FIFO priority ordering sequential readout pass"); c_IndexPQ_Destroy(&ipq); test_log("5. Lifecycle memory destruction pass"); printf("\n==================================================\n"); printf(" Success! Indexed Priority Queue operational parameters matched!\n"); printf("==================================================\n"); return 0; }