97 lines
3.6 KiB
C
97 lines
3.6 KiB
C
#include "c_IndexPQ.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
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;
|
|
} |