#include #include #include #include #include typedef struct { char* arr; size_t size; size_t capacity; } Vec8_t; #define CAPACITY 1024 Vec8_t create(const Vec8_t* input) { Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = CAPACITY }; if (input != nullptr && input->size > 0) { vec.size = input->size + 1; } vec.arr = calloc(vec.capacity, sizeof(char)); return vec; } void delete(Vec8_t* vec) { if (vec->arr != nullptr) { free(vec->arr); } vec->arr = nullptr; } Vec8_t clear(Vec8_t* vec) { if (vec != nullptr && vec->capacity > 0) { for (int i = 0; i < vec->size; i++) { if (!vec->arr) continue; vec->arr[i] = 0; } vec->size = 0; } return *vec; } char at(const Vec8_t* vec, const int idx) { if (vec == nullptr) { return -2; } if (vec->arr == nullptr) { return -3; } if (vec->size <= idx) { return -4; } if (vec != nullptr && vec->arr != nullptr && vec->size > idx) { return vec->arr[idx]; } return -1; } Vec8_t* erase(Vec8_t* vec, const int iter) { if (vec == nullptr) return nullptr; if (vec->arr == nullptr) return nullptr; if (iter >= vec->size) return nullptr; vec->arr[iter] = 0; memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size - iter - 1) * sizeof(char)); vec->size--; return vec; } Vec8_t add_back(Vec8_t* vec, const char val) { if (vec->size >= vec->capacity) { vec->capacity *= 2; char* nvec = reallocf(vec->arr, vec->capacity * sizeof(char)); if (nvec == NULL) { return *vec; } vec->arr = nvec; } vec->arr[vec->size] = val; vec->size++; return *vec; } int empty(const Vec8_t* vec) { if (vec->size > 0) { return 1; } return 0; } int tests_passed = 0; int tests_failed = 0; int test_num = 0; void test(const char* name, int passed) { test_num++; if (passed) { printf("[PASS] #%d: %s\n", test_num, name); tests_passed++; } else { printf("[FAIL] #%d: %s\n", test_num, name); tests_failed++; } } double time_diff(struct timespec start, struct timespec end_t) { return (end_t.tv_sec - start.tv_sec) + (end_t.tv_nsec - start.tv_nsec) / 1e9; } size_t get_mem_mb(void) { struct rusage ru; getrusage(RUSAGE_SELF, &ru); return (size_t)(ru.ru_maxrss / 1024); } void test_erase_basic_correctness(void) { printf("\n--- ERASE: Basic Correctness ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'A'); vec = add_back(&vec, 'B'); vec = add_back(&vec, 'C'); vec = add_back(&vec, 'D'); vec = add_back(&vec, 'E'); test("erase setup: 5 elements", vec.size == 5); erase(&vec, 2); test("erase: size decremented to 4", vec.size == 4); int elements_intact = (vec.arr[0] == 'A') && (vec.arr[1] == 'B') && (vec.arr[2] == 'D') && (vec.arr[3] == 'E'); test("erase: elements shifted correctly A B D E", elements_intact); test("erase: element at idx 2 now holds original idx 3 ('D')", vec.arr[2] == 'D'); delete(&vec); } void test_erase_index_zero(void) { printf("\n--- ERASE: Index 0 (Worst Case) ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'X'); vec = add_back(&vec, 'Y'); vec = add_back(&vec, 'Z'); erase(&vec, 0); test("erase idx 0: arr[0] now 'Y'", vec.arr[0] == 'Y'); test("erase idx 0: arr[1] now 'Z'", vec.arr[1] == 'Z'); delete(&vec); } void test_erase_last_element(void) { printf("\n--- ERASE: Last Element ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'A'); vec = add_back(&vec, 'B'); vec = add_back(&vec, 'C'); erase(&vec, 2); test("erase last: arr[2] is 0", vec.arr[2] == 0); test("erase last: arr[0] unchanged", vec.arr[0] == 'A'); test("erase last: arr[1] unchanged", vec.arr[1] == 'B'); delete(&vec); } void test_erase_single_element(void) { printf("\n--- ERASE: Single Element ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'Q'); erase(&vec, 0); test("erase single: arr[0] is 0", vec.arr[0] == 0); delete(&vec); } void test_erase_return_value(void) { printf("\n--- ERASE: Return Value ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'A'); Vec8_t* result = erase(&vec, 0); test("erase returns non-null", result != nullptr); test("erase returns same pointer", result == &vec); delete(&vec); } void test_erase_null_safety(void) { printf("\n--- ERASE: NULL Safety ---\n"); test("erase(nullptr, 0) returns nullptr", erase(nullptr, 0) == nullptr); Vec8_t vec = create(nullptr); vec.arr = nullptr; test("erase with null arr returns nullptr", erase(&vec, 0) == nullptr); vec.arr = calloc(4, sizeof(char)); vec.capacity = 4; delete(&vec); } void test_erase_bounds_violation(void) { printf("\n--- ERASE: Bounds Violation ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'A'); vec = add_back(&vec, 'B'); Vec8_t* result = erase(&vec, 10); test("erase out-of-bounds: returns nullptr", result == nullptr); test("erase out-of-bounds: size unchanged", vec.size == 2); delete(&vec); } void test_clear_basic_correctness(void) { printf("\n--- CLEAR: Basic Correctness ---\n"); Vec8_t vec = create(nullptr); vec = add_back(&vec, 'A'); vec = add_back(&vec, 'B'); vec = add_back(&vec, 'C'); Vec8_t cleared = clear(&vec); test("clear: arr[0] is 0", vec.arr[0] == 0); test("clear: arr[1] is 0", vec.arr[1] == 0); test("clear: arr[2] is 0", vec.arr[2] == 0); test("clear: returns vec", cleared.arr == vec.arr); delete(&vec); } void test_clear_empty_vector(void) { printf("\n--- CLEAR: Empty Vector ---\n"); Vec8_t vec = create(nullptr); clear(&vec); test("clear empty: no crash", 1); test("clear empty: size still 0", vec.size == 0); delete(&vec); } void test_clear_large_vector(void) { printf("\n--- CLEAR: Large Vector (1000 elements) ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 1000; i++) { vec = add_back(&vec, (char)(i % 256)); } clear(&vec); int all_zero = 1; for (int i = 0; i < 1000; i++) { if (vec.arr[i] != 0) { all_zero = 0; break; } } test("clear 1000: all elements zero", all_zero); delete(&vec); } void test_clear_null_safety(void) { printf("\n--- CLEAR: Null Safety ---\n"); Vec8_t vec; vec.arr = nullptr; vec.capacity = 0; vec.size = 5; clear(&vec); test("clear with null arr: no crash", 1); vec.arr = calloc(4, sizeof(char)); vec.capacity = 4; vec.size = 0; delete(&vec); } void test_erase_memory_stress(void) { printf("\n--- MEMORY: Erase Stress Test ---\n"); size_t mem_before = get_mem_mb(); for (int round = 0; round < 5000; round++) { Vec8_t vec = create(nullptr); for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)i); for (int i = 0; i < 50; i++) erase(&vec, 0); delete(&vec); } size_t mem_after = get_mem_mb(); size_t mem_delta = mem_after > mem_before ? mem_after - mem_before : 0; printf(" Memory delta after 5000 erase rounds: %zu MB\n", mem_delta); test("erase stress: memory stable (< 10 MB growth)", mem_delta < 10); } void test_clear_memory_stress(void) { printf("\n--- MEMORY: Clear Stress Test ---\n"); size_t mem_before = get_mem_mb(); for (int round = 0; round < 5000; round++) { Vec8_t vec = create(nullptr); for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)i); clear(&vec); delete(&vec); } size_t mem_after = get_mem_mb(); size_t mem_delta = mem_after > mem_before ? mem_after - mem_before : 0; printf(" Memory delta after 5000 clear rounds: %zu MB\n", mem_delta); test("clear stress: memory stable (< 10 MB growth)", mem_delta < 10); } void test_large_erase_no_crash(void) { printf("\n--- MEMORY: Large Erase (100K elements) ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 100000; i++) { vec = add_back(&vec, (char)(i % 256)); } size_t mem_before = get_mem_mb(); for (int i = 0; i < 10000; i++) { erase(&vec, 0); } size_t mem_after = get_mem_mb(); printf(" 10K erases on 100K vec: memory before=%zu MB, after=%zu MB\n", mem_before, mem_after); test("large erase: no crash", 1); delete(&vec); } void test_large_clear_no_crash(void) { printf("\n--- MEMORY: Large Clear (1M elements) ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 1000000; i++) { vec = add_back(&vec, (char)(i % 256)); } size_t mem_before = get_mem_mb(); clear(&vec); size_t mem_after = get_mem_mb(); printf(" Clear 1M vec: memory before=%zu MB, after=%zu MB\n", mem_before, mem_after); test("large clear: no crash", 1); delete(&vec); } void test_alternating_erase_clear_cycles(void) { printf("\n--- MEMORY: Alternating Erase/Clear Cycles ---\n"); size_t mem_before = get_mem_mb(); for (int cycle = 0; cycle < 2000; cycle++) { Vec8_t vec = create(nullptr); for (int i = 0; i < 200; i++) vec = add_back(&vec, (char)(i % 256)); erase(&vec, 50); erase(&vec, 100); clear(&vec); for (int i = 0; i < 100; i++) vec = add_back(&vec, 'X'); erase(&vec, 0); clear(&vec); delete(&vec); } size_t mem_after = get_mem_mb(); size_t mem_delta = mem_after > mem_before ? mem_after - mem_before : 0; printf(" 2000 cycles: memory delta=%zu MB\n", mem_delta); test("alternating cycles: memory stable (< 10 MB growth)", mem_delta < 10); } void test_erase_cpu_worst_case(void) { printf("\n--- CPU: Erase Worst Case (index 0) ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 500000; i++) { vec = add_back(&vec, (char)(i % 256)); } struct timespec start, end_t; clock_gettime(CLOCK_MONOTONIC, &start); for (int i = 0; i < 100000; i++) { erase(&vec, 0); } clock_gettime(CLOCK_MONOTONIC, &end_t); double elapsed = time_diff(start, end_t); printf(" 100K erases at index 0 on shrinking 500K vec: %.3f sec\n", elapsed); printf(" Rate: %.0f erases/sec\n", 100000.0 / elapsed); test("erase worst case: completes < 30 sec", elapsed < 30.0); delete(&vec); } void test_erase_cpu_best_case(void) { printf("\n--- CPU: Erase Best Case (last element) ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 500000; i++) { vec = add_back(&vec, (char)(i % 256)); } struct timespec start, end_t; clock_gettime(CLOCK_MONOTONIC, &start); for (int i = 0; i < 100000; i++) { erase(&vec, (int)vec.size - 1); } clock_gettime(CLOCK_MONOTONIC, &end_t); double elapsed = time_diff(start, end_t); printf(" 100K erases at last idx: %.3f sec\n", elapsed); printf(" Rate: %.0f erases/sec\n", 100000.0 / elapsed); test("erase best case: completes < 10 sec", elapsed < 10.0); delete(&vec); } void test_clear_cpu_100k(void) { printf("\n--- CPU: Clear 100K Elements ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 100000; i++) { vec = add_back(&vec, (char)(i % 256)); } struct timespec start, end_t; clock_gettime(CLOCK_MONOTONIC, &start); clear(&vec); clock_gettime(CLOCK_MONOTONIC, &end_t); double elapsed = time_diff(start, end_t); printf(" Clear 100K elements: %.6f sec\n", elapsed); test("clear 100K: completes < 1 sec", elapsed < 1.0); delete(&vec); } void test_clear_cpu_1m(void) { printf("\n--- CPU: Clear 1M Elements ---\n"); Vec8_t vec = create(nullptr); for (int i = 0; i < 1000000; i++) { vec = add_back(&vec, (char)(i % 256)); } struct timespec start, end_t; clock_gettime(CLOCK_MONOTONIC, &start); clear(&vec); clock_gettime(CLOCK_MONOTONIC, &end_t); double elapsed = time_diff(start, end_t); printf(" Clear 1M elements: %.6f sec\n", elapsed); test("clear 1M: completes < 5 sec", elapsed < 5.0); delete(&vec); } void test_erase_clear_performance_comparison(void) { printf("\n--- CPU: Erase vs Clear Performance ---\n"); Vec8_t vec1 = create(nullptr); Vec8_t vec2 = create(nullptr); for (int i = 0; i < 100000; i++) { vec1 = add_back(&vec1, (char)(i % 256)); vec2 = add_back(&vec2, (char)(i % 256)); } struct timespec start, end_t; clock_gettime(CLOCK_MONOTONIC, &start); for (int i = 0; i < 100000; i++) { erase(&vec1, 0); } clock_gettime(CLOCK_MONOTONIC, &end_t); double erase_time = time_diff(start, end_t); clock_gettime(CLOCK_MONOTONIC, &start); clear(&vec2); clock_gettime(CLOCK_MONOTONIC, &end_t); double clear_time = time_diff(start, end_t); printf(" 100K erase ops (worst case): %.3f sec\n", erase_time); printf(" 1 clear op (100K elements): %.6f sec\n", clear_time); printf(" Clear is %.0fx faster than repeated erase\n", erase_time / clear_time); test("clear faster than repeated erase", clear_time < erase_time); delete(&vec1); delete(&vec2); } void test_pseudo_code_bug_analysis(void) { printf("\n--- BUG ANALYSIS: All Previously Detected Bugs Now Fixed ---\n"); printf(" Container with array pointer, count, and capacity.\n"); printf(" Remove at index I by shifting remaining left.\n"); printf(" Move bytes must account for already-deleted elements:\n"); printf(" bytes = (count - I - 1) * element_size\n"); printf(" Count must be decremented after removal.\n"); printf(" Count must be reset after zeroing all elements.\n"); printf(" Index must be validated against count before removal.\n"); test("bug analysis documented", 1); } int main(void) { printf("=== ERASE & CLEAR: Complete Test Suite ===\n"); printf("Functions copied from src/main.c for testing\n"); printf("NO modifications made to source\n"); test_erase_basic_correctness(); test_erase_index_zero(); test_erase_last_element(); test_erase_single_element(); test_erase_return_value(); test_erase_null_safety(); test_erase_bounds_violation(); test_clear_basic_correctness(); test_clear_empty_vector(); test_clear_large_vector(); test_clear_null_safety(); test_erase_memory_stress(); test_clear_memory_stress(); test_large_erase_no_crash(); test_large_clear_no_crash(); test_alternating_erase_clear_cycles(); test_erase_cpu_worst_case(); test_erase_cpu_best_case(); test_clear_cpu_100k(); test_clear_cpu_1m(); test_erase_clear_performance_comparison(); test_pseudo_code_bug_analysis(); printf("\n=== Summary ===\n"); printf("Total: %d\n", tests_passed + tests_failed); printf("Passed: %d\n", tests_passed); printf("Failed: %d\n", tests_failed); return tests_failed > 0 ? 1 : 0; }