开始设计
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
#include "c_MaxPQ.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#define EXPECT_EQ(val1, val2, msg) \
|
||||
do { \
|
||||
if ((val1) != (val2)) { printf(" [X] Failed: %s (Expected %d, got %d)\n", msg, (int)(val2), (int)(val1)); return false; } \
|
||||
} while(0)
|
||||
|
||||
// Test complex entity
|
||||
typedef struct {
|
||||
int thread_id;
|
||||
int priority_level; // Primary sorting metric for MaxPQ (higher level extract first)
|
||||
char tag[16];
|
||||
} ThreadTask;
|
||||
|
||||
// Max-Heap comparator: Returns positive if a > b
|
||||
int compareTasksByPriority(const void* a, const void* b) {
|
||||
const ThreadTask* t1 = (const ThreadTask*)a;
|
||||
const ThreadTask* t2 = (const ThreadTask*)b;
|
||||
return (t1->priority_level - t2->priority_level);
|
||||
}
|
||||
|
||||
// Test Case: Validates API Errors and Basic Operations
|
||||
bool test_maxpq_lifecycle_and_errors(void) {
|
||||
c_MaxPQ_t pq;
|
||||
|
||||
// 1. Test invalid parameters during initialization
|
||||
EXPECT_EQ(c_MaxPQ_Init(NULL, 10, sizeof(ThreadTask), compareTasksByPriority), C_ERR_PARAM, "NULL instance handle validation missing");
|
||||
EXPECT_EQ(c_MaxPQ_Init(&pq, 10, 0, compareTasksByPriority), C_ERR_PARAM, "Zero element size validation missing");
|
||||
EXPECT_EQ(c_MaxPQ_Init(&pq, 10, sizeof(ThreadTask), NULL), C_ERR_PARAM, "NULL comparator validation missing");
|
||||
|
||||
// 2. Correct initialization
|
||||
EXPECT_EQ(c_MaxPQ_Init(&pq, 2, sizeof(ThreadTask), compareTasksByPriority), C_ERR_OK, "Valid configuration failed init");
|
||||
|
||||
// 3. Test empty bounds lookups
|
||||
EXPECT_EQ(c_MaxPQ_Peek(&pq) == NULL, true, "Empty queue peek did not yield NULL");
|
||||
ThreadTask output;
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &output), C_ERR_EMPTY, "Empty queue extraction did not throw C_ERR_EMPTY");
|
||||
|
||||
// Clean up
|
||||
c_MaxPQ_Destroy(&pq);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test Case: Validates Max Extraction and Dynamic Scale Limits
|
||||
bool test_maxpq_functional_flow(void) {
|
||||
c_MaxPQ_t pq;
|
||||
// Initialize with a tiny capacity of 2 to guarantee scaling logic triggers
|
||||
c_MaxPQ_Init(&pq, 2, sizeof(ThreadTask), compareTasksByPriority);
|
||||
|
||||
ThreadTask tasks[] = {
|
||||
{ 401, 12, "Low Prio" },
|
||||
{ 402, 99, "Critical" },
|
||||
{ 403, 50, "High Prio" },
|
||||
{ 404, 75, "Urgent" }
|
||||
};
|
||||
|
||||
// Push structures
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &tasks[0]), C_ERR_OK, "Failed pushing task 0");
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &tasks[1]), C_ERR_OK, "Failed pushing task 1");
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &tasks[2]), C_ERR_OK, "Failed pushing task 2 (Scale Trigger)");
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &tasks[3]), C_ERR_OK, "Failed pushing task 3");
|
||||
|
||||
// Verify Peak Element maps to highest priority (99)
|
||||
ThreadTask* peeked = (ThreadTask*)c_MaxPQ_Peek(&pq);
|
||||
EXPECT_EQ(peeked != NULL && peeked->priority_level == 99, true, "Peek failed to return max item pointer");
|
||||
|
||||
ThreadTask extracted;
|
||||
|
||||
// Pop 1: Priority 99 ("Critical")
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &extracted), C_ERR_OK, "Extraction loop 1 crashed");
|
||||
EXPECT_EQ(extracted.thread_id, 402, "Extracted sequence misaligned at item 1");
|
||||
|
||||
// Pop 2: Priority 75 ("Urgent")
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &extracted), C_ERR_OK, "Extraction loop 2 crashed");
|
||||
EXPECT_EQ(extracted.thread_id, 404, "Extracted sequence misaligned at item 2");
|
||||
|
||||
// Pop 3: Priority 50 ("High Prio")
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &extracted), C_ERR_OK, "Extraction loop 3 crashed");
|
||||
EXPECT_EQ(extracted.thread_id, 403, "Extracted sequence misaligned at item 3");
|
||||
|
||||
// Pop 4: Priority 12 ("Low Prio")
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &extracted), C_ERR_OK, "Extraction loop 4 crashed");
|
||||
EXPECT_EQ(extracted.thread_id, 401, "Extracted sequence misaligned at item 4");
|
||||
|
||||
// Confirm container has completely emptied out
|
||||
EXPECT_EQ(pq.size, 0, "Active queue tracking counter failed to reach zero index boundary");
|
||||
|
||||
c_MaxPQ_Destroy(&pq);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_maxpq_clear_and_reuse(void) {
|
||||
c_MaxPQ_t pq;
|
||||
// Initialize with a capacity of 4
|
||||
c_MaxPQ_Init(&pq, 4, sizeof(ThreadTask), compareTasksByPriority);
|
||||
|
||||
ThreadTask t1 = { 101, 10 };
|
||||
ThreadTask t2 = { 102, 50 };
|
||||
ThreadTask t3 = { 103, 30 };
|
||||
|
||||
// 1. Populate the priority queue
|
||||
c_MaxPQ_Push(&pq, &t1);
|
||||
c_MaxPQ_Push(&pq, &t2);
|
||||
c_MaxPQ_Push(&pq, &t3);
|
||||
EXPECT_EQ(pq.size, 3, "Queue size should be 3 before clearing");
|
||||
c_size_t saved_capacity = pq.capacity;
|
||||
|
||||
// 2. Execute Clear Protocol
|
||||
EXPECT_EQ(c_MaxPQ_Clear(NULL), C_ERR_PARAM, "Clearing NULL should yield C_ERR_PARAM");
|
||||
EXPECT_EQ(c_MaxPQ_Clear(&pq), C_ERR_OK, "Clearing active queue failed");
|
||||
|
||||
// 3. Assert structural properties after clearing
|
||||
EXPECT_EQ(pq.size, 0, "Queue size must be reset to 0 after clear");
|
||||
EXPECT_EQ(pq.capacity, saved_capacity, "Capacity should remain unchanged after clear");
|
||||
EXPECT_EQ(c_MaxPQ_Peek(&pq) == NULL, true, "Cleared queue peek should return NULL");
|
||||
|
||||
ThreadTask dummy;
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &dummy), C_ERR_EMPTY, "Cleared queue pop should return C_ERR_EMPTY");
|
||||
|
||||
// 4. Reuse and re-populate the same queue (Verifying memory reuse)
|
||||
ThreadTask t4 = { 201, 5 };
|
||||
ThreadTask t5 = { 202, 95 }; // This should become the new max root
|
||||
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &t4), C_ERR_OK, "Pushing to cleared queue failed");
|
||||
EXPECT_EQ(c_MaxPQ_Push(&pq, &t5), C_ERR_OK, "Pushing second item to cleared queue failed");
|
||||
EXPECT_EQ(pq.size, 2, "Size did not increment properly after reuse");
|
||||
|
||||
// Verify extraction works perfectly post-clear
|
||||
ThreadTask result;
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &result), C_ERR_OK, "Pop post-clear failed");
|
||||
EXPECT_EQ(result.thread_id, 202, "Max-Heap extraction broke after clearing and reusing queue");
|
||||
|
||||
c_MaxPQ_Destroy(&pq);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool test_maxpq_resize_behavior(void) {
|
||||
c_MaxPQ_t pq;
|
||||
// Initialize with a capacity of 4
|
||||
c_MaxPQ_Init(&pq, 4, sizeof(ThreadTask), compareTasksByPriority);
|
||||
|
||||
ThreadTask t1 = { 101, 10 };
|
||||
ThreadTask t2 = { 102, 50 };
|
||||
|
||||
c_MaxPQ_Push(&pq, &t1);
|
||||
c_MaxPQ_Push(&pq, &t2);
|
||||
EXPECT_EQ(pq.size, 2, "Initial push setup size should be 2");
|
||||
EXPECT_EQ(pq.capacity, 4, "Initial capacity should be 4");
|
||||
|
||||
// 1. Guard Check: Attempting to shrink capacity below the active item count (size=2) must fail
|
||||
EXPECT_EQ(c_MaxPQ_Resize(&pq, 1), C_ERR_PARAM, "Shrinking below current size did not fail safely");
|
||||
EXPECT_EQ(pq.capacity, 4, "Invalid resize operation altered internal capacity incorrectly");
|
||||
|
||||
// 2. Expansion Check: Expand capacity from 4 to 10
|
||||
EXPECT_EQ(c_MaxPQ_Resize(&pq, 10), C_ERR_OK, "Expanding valid memory blocks failed");
|
||||
EXPECT_EQ(pq.capacity, 10, "Capacity tracker failed to update to 10");
|
||||
EXPECT_EQ(pq.size, 2, "Active structural data sizes mutated during reallocation shift");
|
||||
|
||||
// 3. Contraction Check: Tighten memory footprints to fit data perfectly (shrink capacity to size=2)
|
||||
EXPECT_EQ(c_MaxPQ_Resize(&pq, 2), C_ERR_OK, "Clamping pool capacity limits down to active size failed");
|
||||
EXPECT_EQ(pq.capacity, 2, "Capacity tracker failed to collapse down to 2");
|
||||
|
||||
// 4. Operational Integrity Check: Verify heap extraction still works flawlessly post-resize
|
||||
ThreadTask result;
|
||||
EXPECT_EQ(c_MaxPQ_Pop(&pq, &result), C_ERR_OK, "Pop post-resize failed");
|
||||
EXPECT_EQ(result.thread_id, 102, "Max element tracking corrupted during pointer re-mapping operations");
|
||||
|
||||
c_MaxPQ_Destroy(&pq);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
printf("=== Starting Custom Framework Testing for c_MaxPQ ===\n");
|
||||
|
||||
if (test_maxpq_lifecycle_and_errors()) printf(" [PASS] Test 1: Lifecycle Management & Error Guard Protocols Verified\n");
|
||||
if (test_maxpq_functional_flow()) printf(" [PASS] Test 2: Priority Tree Sifting Loops & Data Escalation Verified\n");
|
||||
if (test_maxpq_clear_and_reuse()) {
|
||||
printf(" [PASS] Test: Clear, Capacity Preservation, and Queue Reuse Verified Successfully\n");
|
||||
}
|
||||
if (test_maxpq_resize_behavior()) {
|
||||
printf(" [PASS] Test: Manual Resize, Boundary Guard Protection, and Data Persistence Verified\n");
|
||||
}
|
||||
printf("=== All Priority Queue Framework Tests Completed ===\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user