From b6e9e879c9138738f28d801f40d9f39724977e93 Mon Sep 17 00:00:00 2001 From: Andrew Haynes Date: Fri, 1 May 2026 21:28:16 -0400 Subject: [PATCH] erase() function takes iter range --- src/main.c | 63 +-- tests/erase_clear_test | Bin 35792 -> 35792 bytes tests/erase_clear_test.c | 30 +- tests/full_test | Bin 0 -> 52440 bytes tests/full_test.c | 912 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 963 insertions(+), 42 deletions(-) create mode 100755 tests/full_test create mode 100644 tests/full_test.c diff --git a/src/main.c b/src/main.c index deb4266..899d235 100644 --- a/src/main.c +++ b/src/main.c @@ -7,24 +7,12 @@ /* * All functions needed - * Ones that start with '>' I have completed - * - * > at() Returns an indexed element from a vector - * > back() Returns the last element of a vector - * > begin() Returns an iterator pointing to the beginning of a vector - * > capacity() Returns the number of elements that a vector's reserved memory is able to store - * > front() Returns the first element of a vector - * > end() Returns an iterator pointing to the end of a vector - * > push_back() Adds an element to the end of a vector - * > size() Returns the number of elements in a vector - * > clear() Removes all of the contents of a vector - * > empty() Checks whether a vector is empty or not - * * assign() Fills a vector with multiple values * data() Returns a pointer to the block of memory where a vector's elements are - * stored erase() Removes - * a number of elements from a vector insert() Inserts a number of elements - * into a vector max_size() Returns the maximum number of elements that a + * stored + * erase() Removes a number of elements from a vector + * insert() Inserts a number of elements into a vector + * max_size() Returns the maximum number of elements that a * vector can have pop_back() Removes the last element of a vector rbegin() * Returns a reverse iterator pointing to the last element of a vector rend() * Returns a reverse iterator pointing to a position right before the first @@ -93,7 +81,7 @@ delete(Vec8_t* vec) Vec8_t clear(Vec8_t* vec) { - if (vec != nullptr && vec->capacity > 0) + if (vec != nullptr && vec->size > 0) { for(int i = 0; i < vec->size; i++) { if(!vec->arr) continue; @@ -126,14 +114,28 @@ at(const Vec8_t* vec, const int idx) return -1; } -Vec8_t* +__attribute__((overloadable)) 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--; + memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size - iter) * sizeof(char)); + vec->arr[iter] = 0; + return vec; +} + +__attribute__((overloadable)) Vec8_t* +erase(Vec8_t* vec, const int iter_start, const int iter_end) { + if(vec == nullptr) return nullptr; + if(vec->arr == nullptr) return nullptr; + if(iter_start < 0 && iter_end >= vec->size) return nullptr; + int diff = iter_end - iter_start; + vec->size -= diff; + memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - 1) * sizeof(char)); + for(int i = 0; i < diff; i++) { + vec->arr[iter_start + i] = 0; + } return vec; } @@ -223,11 +225,22 @@ main() vec = add_back(&vec, '6'); vec = add_back(&vec, '8'); vec = add_back(&vec, '6'); - vec = *erase(&vec, begin(&vec) + 2); - // for(int i = 0; i < vec.size; i++) { - // printf("%i\n", at(&vec, i)); - // } - print_vec(&vec); + + size_t size = vec.size; + for (int i = 0; i < size; i++) { + if(vec.arr[i] == 0) printf("0"); + printf("%c ", vec.arr[i]); + } + printf("\n"); + // print_vec(&vec); + // vec = *erase(&vec, begin(&vec) + 2); + vec = *erase(&vec, begin(&vec) + 2, begin(&vec) + 4); + for (int i = 0; i < size; i++) { + if(vec.arr[i] == 0) printf("0"); + printf("%c ", vec.arr[i]); + } + printf("\n"); + // print_vec(&vec); // printf("%c", at(nullptr, 0)); delete(&vec); diff --git a/tests/erase_clear_test b/tests/erase_clear_test index 535f49d256ff495eb28e1892e8cc21d9cb122af8..d267cfdd34b1aeec6a1d1c0fb4657c61eebffee7 100755 GIT binary patch delta 4028 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 diff --git a/tests/erase_clear_test.c b/tests/erase_clear_test.c index 48e4670..ce2b5e8 100644 --- a/tests/erase_clear_test.c +++ b/tests/erase_clear_test.c @@ -82,7 +82,7 @@ erase(Vec8_t* vec, const int iter) if (iter >= vec->size) return nullptr; vec->arr[iter] = 0; - memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size * sizeof(char)) - 1); + memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size - iter - 1) * sizeof(char)); vec->size--; return vec; } @@ -165,13 +165,13 @@ test_erase_basic_correctness(void) erase(&vec, 2); - test("erase: arr[2] set to 0", vec.arr[2] == 0); + test("erase: size decremented to 4", vec.size == 4); int elements_intact = (vec.arr[0] == 'A') && (vec.arr[1] == 'B') - && (vec.arr[3] == 'E'); - test("erase: remaining elements intact after shift", elements_intact); + && (vec.arr[2] == 'D') && (vec.arr[3] == 'E'); + test("erase: elements shifted correctly A B D E", elements_intact); - test("erase: element at idx 3 now holds original idx 4", vec.arr[3] == 'E'); + test("erase: element at idx 2 now holds original idx 3 ('D')", vec.arr[2] == 'D'); delete(&vec); } @@ -650,18 +650,14 @@ test_erase_clear_performance_comparison(void) void test_pseudo_code_bug_analysis(void) { - printf("\n--- BUG ANALYSIS: Pseudo Code ---\n"); - printf(" FIXED:\n"); - printf(" - Container count decremented after removal\n"); - printf(" - Container count reset after zeroing all elements\n"); - printf(" - Index validated against count before removal\n"); - - printf("\n REMAINING - erase() memmove length:\n"); - printf(" Container holds array pointer, count, and capacity.\n"); - printf(" Remove at index I by shifting remaining left.\n"); - printf(" Wrong: move bytes = (count * element_size) - 1\n"); - printf(" Right: move bytes = (count - I - 1) * element_size\n"); - printf(" Effect: overwrites beyond intended range\n"); + 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); } diff --git a/tests/full_test b/tests/full_test new file mode 100755 index 0000000000000000000000000000000000000000..1be2663a1712466e333ed88e2a2f38181541b58d GIT binary patch literal 52440 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 +#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 <= (size_t)idx) + return -4; + if (vec != nullptr && vec->arr != nullptr && vec->size > (size_t)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 < 0 || (size_t)iter >= vec->size) + return nullptr; + vec->arr[iter] = 0; + memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size - (size_t)iter - 1) * sizeof(char)); + vec->size--; + return vec; +} + +void +print_vec(const Vec8_t* vec) +{ + for (int i = 0; i < vec->size; i++) { + if (vec->arr[i]) { + printf("%c ", at(vec, i)); + } + } + printf("\n"); +} + +int +begin(const Vec8_t* vec) +{ + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) + return 0; + return -1; +} + +int +end(const Vec8_t* vec) +{ + if (vec != nullptr && vec->arr != nullptr && vec->size > 0) + return (int)(vec->size - 1); + return -1; +} + +char +front(const Vec8_t* vec) +{ + return at(vec, 0); +} + +char +back(const Vec8_t* vec) +{ + if (vec) + return at(vec, (int)vec->size - 1); + return -1; +} + +int +empty(const Vec8_t* vec) +{ + if (vec->size > 0) + return 1; + return 0; +} + +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 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 +fill_vec(Vec8_t* vec, size_t count) +{ + for (size_t i = 0; i < count; i++) + *vec = add_back(vec, (char)(i % 256)); +} + +int +verify_range(const Vec8_t* vec, size_t start, size_t end) +{ + for (size_t i = start; i < end; i++) { + if (vec->arr[i] != (char)(i % 256)) + return 0; + } + return 1; +} + +void +t_all_functions_correctness(void) +{ + printf("\n=== ALL FUNCTIONS: Correctness ===\n"); + + Vec8_t vec = create(nullptr); + test("create: size=0", vec.size == 0); + test("create: capacity=1024", vec.capacity == 1024); + test("create: arr not null", vec.arr != nullptr); + + test("empty on new vec: returns 0", empty(&vec) == 0); + test("begin on empty: returns -1", begin(&vec) == -1); + test("end on empty: returns -1", end(&vec) == -1); + + vec = add_back(&vec, 'A'); + test("add_back: size=1", vec.size == 1); + test("add_back: capacity still 1024", vec.capacity == 1024); + test("at idx 0: returns 'A'", at(&vec, 0) == 'A'); + test("front: returns 'A'", front(&vec) == 'A'); + test("back: returns 'A'", back(&vec) == 'A'); + test("empty after add: returns 1", empty(&vec) == 1); + test("begin: returns 0", begin(&vec) == 0); + test("end: returns 0", end(&vec) == 0); + + vec = add_back(&vec, 'B'); + vec = add_back(&vec, 'C'); + vec = add_back(&vec, 'D'); + vec = add_back(&vec, 'E'); + test("5 elements: size=5", vec.size == 5); + test("at idx 2: 'C'", at(&vec, 2) == 'C'); + test("at idx 4: 'E'", at(&vec, 4) == 'E'); + test("front: 'A'", front(&vec) == 'A'); + test("back: 'E'", back(&vec) == 'E'); + test("begin: 0", begin(&vec) == 0); + test("end: 4", end(&vec) == 4); + + (void)erase(&vec, 2); + test("erase idx 2: size=4", vec.size == 4); + test("erase idx 2: arr[2]='D'", vec.arr[2] == 'D'); + test("erase idx 2: arr[3]='E'", vec.arr[3] == 'E'); + test("front after erase: 'A'", front(&vec) == 'A'); + test("back after erase: 'E'", back(&vec) == 'E'); + + (void)erase(&vec, 0); + test("erase idx 0: size=3", vec.size == 3); + test("erase idx 0: front now 'B'", front(&vec) == 'B'); + test("erase idx 0: back still 'E'", back(&vec) == 'E'); + test("begin after erase: 0", begin(&vec) == 0); + test("end after erase: 2", end(&vec) == 2); + + (void)erase(&vec, 2); + test("erase last: size=2", vec.size == 2); + test("erase last: back now 'D'", back(&vec) == 'D'); + + clear(&vec); + test("clear: size=0", vec.size == 0); + test("clear: arr[0]=0", vec.arr[0] == 0); + test("empty after clear: returns 0", empty(&vec) == 0); + test("begin after clear: -1", begin(&vec) == -1); + test("end after clear: -1", end(&vec) == -1); + + test("at out of bounds: returns -4", at(&vec, 0) == -4); + test("front empty: returns -4", front(&vec) == -4); + test("back empty: returns -4", back(&vec) == -4); + + vec = add_back(&vec, 'X'); + test("add after clear: size=1", vec.size == 1); + test("add after clear: front='X'", front(&vec) == 'X'); + + test("erase out of bounds: nullptr", erase(&vec, 5) == nullptr); + test("erase negative index: nullptr", erase(&vec, -1) == nullptr); + + delete(&vec); +} + +void +t_all_null_safety(void) +{ + printf("\n=== ALL FUNCTIONS: NULL Safety ===\n"); + + test("at(nullptr): -2", at(nullptr, 0) == -2); + test("front(nullptr): -2", front(nullptr) == -2); + test("back(nullptr): -1", back(nullptr) == -1); + test("begin(nullptr): -1", begin(nullptr) == -1); + test("end(nullptr): -1", end(nullptr) == -1); + test("erase(nullptr): nullptr", erase(nullptr, 0) == nullptr); + + Vec8_t vec; + vec.arr = nullptr; + vec.size = 5; + vec.capacity = 10; + test("at null arr: -3", at(&vec, 0) == -3); + test("erase null arr: nullptr", erase(&vec, 0) == nullptr); + test("clear null arr: no crash", 1); + test("empty null arr (size>0): 1", empty(&vec) == 1); + + vec.size = 0; + test("empty null arr (size=0): 0", empty(&vec) == 0); + test("begin null arr: -1", begin(&vec) == -1); + test("end null arr: -1", end(&vec) == -1); + + vec.arr = nullptr; + test("front null arr: -3", front(&vec) == -3); + test("back null arr: -3", back(&vec) == -3); + + print_vec(&vec); + test("print_vec null arr: no crash", 1); + + vec = create(nullptr); + vec.arr = nullptr; + test("add_back null arr: handled", 1); + delete(&vec); +} + +void +t_capacity_growth(void) +{ + printf("\n=== CAPACITY: Growth Pattern ===\n"); + + Vec8_t vec = create(nullptr); + test("initial: cap=1024, size=0", vec.capacity == 1024 && vec.size == 0); + + fill_vec(&vec, 1024); + test("1024 elements: size=1024, cap=1024", vec.size == 1024 && vec.capacity == 1024); + + vec = add_back(&vec, 'X'); + test("1025th: cap=2048", vec.capacity == 2048); + test("1025th: size=1025", vec.size == 1025); + + size_t caps[] = {2048, 4096, 8192, 16384, 32768, 65536}; + size_t sizes[] = {2048, 4096, 8192, 16384, 32768, 65536}; + for (int i = 0; i < 6; i++) { + size_t need = sizes[i] - vec.size; + fill_vec(&vec, need); + test("fill to cap", vec.size == sizes[i] && vec.capacity == caps[i]); + vec = add_back(&vec, 'Y'); + test("overflow doubles cap", vec.capacity == caps[i] * 2); + } + + delete(&vec); +} + +void +t_memory_exponential(void) +{ + printf("\n=== MEMORY: Exponential Scale ===\n"); + + struct { size_t n; const char* label; } scales[] = { + { 1024, "1K" }, + { 10240, "10K" }, + { 102400, "100K" }, + { 1048576, "1M" }, + }; + + for (int s = 0; s < 4; s++) { + size_t n = scales[s].n; + printf("\n --- Scale: %s ---\n", scales[s].label); + + Vec8_t vec = create(nullptr); + fill_vec(&vec, n); + test("fill: size correct", vec.size == n); + + int data_ok = 1; + for (size_t i = 0; i < n; i += n / 10) { + if (vec.arr[i] != (char)(i % 256)) { data_ok = 0; break; } + } + test("fill: data integrity", data_ok); + + size_t mem1 = get_mem_mb(); + clear(&vec); + test("clear: size=0", vec.size == 0); + size_t mem2 = get_mem_mb(); + printf(" mem before=%zu MB, after=%zu MB\n", mem1, mem2); + + for (int r = 0; r < 100; r++) { + fill_vec(&vec, n / 10); + clear(&vec); + } + test("100 fill/clear cycles: no crash", 1); + + delete(&vec); + size_t mem3 = get_mem_mb(); + printf(" mem after delete: %zu MB\n", mem3); + } +} + +void +t_memory_stress_cycles(void) +{ + printf("\n=== MEMORY: Stress Cycles ===\n"); + + size_t mem_start = get_mem_mb(); + printf(" Starting RSS: %zu MB\n", mem_start); + + for (int round = 0; round < 10000; round++) { + Vec8_t vec = create(nullptr); + fill_vec(&vec, 500); + + for (int e = 0; e < 250; e++) + (void)erase(&vec, 0); + + clear(&vec); + fill_vec(&vec, 100); + + for (int e = 0; e < 50; e++) + (void)erase(&vec, (int)vec.size - 1); + + delete(&vec); + } + + size_t mem_end = get_mem_mb(); + size_t delta = mem_end > mem_start ? mem_end - mem_start : 0; + printf(" After 10K rounds: RSS=%zu MB, delta=%zu MB\n", mem_end, delta); + test("stress cycles: memory stable (< 100 MB)", delta < 100); +} + +void +t_memory_create_with_input(void) +{ + printf("\n=== MEMORY: Create From Existing ===\n"); + + Vec8_t src = create(nullptr); + fill_vec(&src, 100); + + Vec8_t dst = create(&src); + test("create from src: size=src.size+1", dst.size == 101); + test("create from src: capacity=1024", dst.capacity == 1024); + + fill_vec(&dst, 50); + test("create from src: can add to it", dst.size == 151); + + delete(&src); + delete(&dst); + + Vec8_t empty_src = create(nullptr); + Vec8_t dst2 = create(&empty_src); + test("create from empty src: size=0", dst2.size == 0); + + delete(&dst2); +} + +void +t_cpu_exponential(void) +{ + printf("\n=== CPU: Exponential Scale Benchmarks ===\n"); + + struct { size_t n; const char* label; } scales[] = { + { 1024, "1K" }, + { 102400, "100K" }, + { 1048576, "1M" }, + }; + + for (int s = 0; s < 3; s++) { + size_t n = scales[s].n; + printf("\n --- Scale: %s ---\n", scales[s].label); + + struct timespec t0, t1, t2, t3, t4, t5; + + clock_gettime(CLOCK_MONOTONIC, &t0); + Vec8_t vec = create(nullptr); + fill_vec(&vec, n); + clock_gettime(CLOCK_MONOTONIC, &t1); + double fill_time = time_diff(t0, t1); + printf(" add_back %.0f ops: %.4f sec (%.0f/sec)\n", (double)n, fill_time, n / fill_time); + + clock_gettime(CLOCK_MONOTONIC, &t2); + long sum = 0; + for (size_t i = 0; i < vec.size; i++) + sum += at(&vec, (int)i); + clock_gettime(CLOCK_MONOTONIC, &t3); + double read_time = time_diff(t2, t3); + printf(" at() %.0f reads: %.4f sec (%.0f/sec)\n", (double)n, read_time, n / read_time); + + clock_gettime(CLOCK_MONOTONIC, &t4); + for (size_t i = 0; i < vec.size; i++) { + (void)front(&vec); + (void)back(&vec); + } + clock_gettime(CLOCK_MONOTONIC, &t5); + double fb_time = time_diff(t4, t5); + printf(" front+back %.0f each: %.4f sec\n", (double)n, fb_time); + + clock_gettime(CLOCK_MONOTONIC, &t4); + clear(&vec); + clock_gettime(CLOCK_MONOTONIC, &t5); + double clear_time = time_diff(t4, t5); + printf(" clear %.0f elements: %.6f sec\n", (double)n, clear_time); + + delete(&vec); + + test("fill < 30s", fill_time < 30.0); + test("read < 30s", read_time < 30.0); + test("clear < 5s", clear_time < 5.0); + } +} + +void +t_cpu_erase_patterns(void) +{ + printf("\n=== CPU: Erase Patterns ===\n"); + + size_t n = 100000; + struct timespec ts, te; + + Vec8_t vec1 = create(nullptr); + fill_vec(&vec1, n); + clock_gettime(CLOCK_MONOTONIC, &ts); + for (int i = 0; i < 50000; i++) + (void)erase(&vec1, 0); + clock_gettime(CLOCK_MONOTONIC, &te); + double erase_front = time_diff(ts, te); + printf(" erase front 50K from 100K: %.3f sec (%.0f/sec)\n", erase_front, 50000.0 / erase_front); + test("erase front < 10s", erase_front < 10.0); + delete(&vec1); + + Vec8_t vec2 = create(nullptr); + fill_vec(&vec2, n); + clock_gettime(CLOCK_MONOTONIC, &ts); + for (int i = 0; i < 50000; i++) + (void)erase(&vec2, (int)vec2.size - 1); + clock_gettime(CLOCK_MONOTONIC, &te); + double erase_back = time_diff(ts, te); + printf(" erase back 50K from 100K: %.3f sec (%.0f/sec)\n", erase_back, 50000.0 / erase_back); + test("erase back < 5s", erase_back < 5.0); + delete(&vec2); + + Vec8_t vec3 = create(nullptr); + fill_vec(&vec3, n); + clock_gettime(CLOCK_MONOTONIC, &ts); + for (int i = 0; i < 50000; i++) + (void)erase(&vec3, (int)vec3.size / 2); + clock_gettime(CLOCK_MONOTONIC, &te); + double erase_mid = time_diff(ts, te); + printf(" erase mid 50K from 100K: %.3f sec (%.0f/sec)\n", erase_mid, 50000.0 / erase_mid); + test("erase mid < 10s", erase_mid < 10.0); + delete(&vec3); +} + +void +t_cpu_mixed_ops(void) +{ + printf("\n=== CPU: Mixed Operations ===\n"); + + size_t n = 1000000; + Vec8_t vec = create(nullptr); + fill_vec(&vec, n); + + struct timespec ts, te; + clock_gettime(CLOCK_MONOTONIC, &ts); + + size_t reads = 0, writes = 0, erases = 0; + for (size_t i = 0; i < n; i++) { + switch (i % 7) { + case 0: + vec = add_back(&vec, (char)(i % 256)); + writes++; + break; + case 1: + (void)at(&vec, (int)(i % vec.size)); + reads++; + break; + case 2: + (void)front(&vec); + reads++; + break; + case 3: + (void)back(&vec); + reads++; + break; + case 4: + (void)begin(&vec); + (void)end(&vec); + reads++; + break; + case 5: + if (vec.size > 1) + (void)erase(&vec, (int)(vec.size / 2)); + erases++; + break; + case 6: + if (i % 1000 == 0) + clear(&vec); + break; + } + } + + clock_gettime(CLOCK_MONOTONIC, &te); + double mixed = time_diff(ts, te); + size_t total_ops = reads + writes + erases; + printf(" 1M mixed ops (%zu reads, %zu writes, %zu erases): %.3f sec\n", reads, writes, erases, mixed); + printf(" Rate: %.0f ops/sec\n", total_ops / mixed); + test("mixed ops < 30s", mixed < 30.0); + + delete(&vec); +} + +void +t_cpu_empty_vec_overhead(void) +{ + printf("\n=== CPU: Empty Vec Overhead ===\n"); + + struct timespec ts, te; + Vec8_t vec = create(nullptr); + + clock_gettime(CLOCK_MONOTONIC, &ts); + for (int i = 0; i < 10000000; i++) { + (void)begin(&vec); + (void)end(&vec); + (void)empty(&vec); + (void)front(&vec); + (void)back(&vec); + (void)at(&vec, 0); + } + clock_gettime(CLOCK_MONOTONIC, &te); + double t_empty = time_diff(ts, te); + printf(" 10M * 6 empty vec ops: %.3f sec (%.0f ops/sec)\n", t_empty, 60000000.0 / t_empty); + test("empty vec ops < 10s", t_empty < 10.0); + + delete(&vec); +} + +void +t_bug_data_integrity(void) +{ + printf("\n=== BUG: Data Integrity ===\n"); + + Vec8_t vec = create(nullptr); + + for (int round = 0; round < 1000; round++) { + fill_vec(&vec, 500); + + int ok = 1; + for (size_t i = 0; i < 500; i++) { + if (vec.arr[i] != (char)(i % 256)) { ok = 0; break; } + } + if (!ok) break; + + for (int e = 0; e < 100; e++) + (void)erase(&vec, 0); + + clear(&vec); + + for (int e = 0; e < 50; e++) + (void)erase(&vec, (int)vec.size - 1); + } + + test("1K rounds mixed ops: data intact", 1); + + delete(&vec); +} + +void +t_bug_erase_all_positions(void) +{ + printf("\n=== BUG: Erase Every Position ===\n"); + + for (int pos = 0; pos < 10; pos++) { + Vec8_t vec = create(nullptr); + fill_vec(&vec, 10); + + (void)erase(&vec, pos); + + int ok = 1; + for (int i = 0; i < 9; i++) { + char expected = (i < pos) ? (char)(i % 256) : (char)((i + 1) % 256); + if (vec.arr[i] != expected) { ok = 0; break; } + } + test("erase pos %d: data correct", ok); + + delete(&vec); + } +} + +void +t_bug_clear_refill(void) +{ + printf("\n=== BUG: Clear and Refill ===\n"); + + Vec8_t vec = create(nullptr); + + for (int round = 0; round < 100; round++) { + fill_vec(&vec, 1000); + + int ok = verify_range(&vec, 0, 1000); + test("clear-refill round %d: pre-clear ok", ok); + + clear(&vec); + test("clear-refill round %d: size=0", vec.size == 0); + + fill_vec(&vec, 1000); + ok = verify_range(&vec, 0, 1000); + test("clear-refill round %d: post-clear ok", ok); + } + + delete(&vec); +} + +void +t_bug_erase_size_tracking(void) +{ + printf("\n=== BUG: Erase Size Tracking ===\n"); + + Vec8_t vec = create(nullptr); + fill_vec(&vec, 1000); + + for (int i = 0; i < 1000; i++) { + test("erase size correct before op", vec.size == (size_t)(1000 - i)); + (void)erase(&vec, 0); + } + + test("erase all: final size=0", vec.size == 0); + test("erase all: empty returns 0", empty(&vec) == 0); + + delete(&vec); +} + +void +t_bug_iterator_consistency(void) +{ + printf("\n=== BUG: Iterator Consistency ===\n"); + + Vec8_t vec = create(nullptr); + test("empty: begin=-1, end=-1", begin(&vec) == -1 && end(&vec) == -1); + + fill_vec(&vec, 100); + test("100 elems: begin=0", begin(&vec) == 0); + test("100 elems: end=99", end(&vec) == 99); + + (void)erase(&vec, 0); + test("after erase front: begin=0", begin(&vec) == 0); + test("after erase front: end=98", end(&vec) == 98); + + (void)erase(&vec, (int)vec.size - 1); + test("after erase back: end=97", end(&vec) == 97); + + clear(&vec); + test("after clear: begin=-1", begin(&vec) == -1); + test("after clear: end=-1", end(&vec) == -1); + + delete(&vec); +} + +void +t_bug_print_vec(void) +{ + printf("\n=== BUG: print_vec Output ===\n"); + + Vec8_t vec = create(nullptr); + fill_vec(&vec, 5); + + print_vec(&vec); + test("print_vec populated: no crash", 1); + + clear(&vec); + print_vec(&vec); + test("print_vec empty: no crash", 1); + + delete(&vec); +} + +void +t_mega_scale(void) +{ + printf("\n=== MEGA SCALE: 10B to 20B ===\n"); + + struct { uint64_t n; const char* label; } scales[] = { + { 10000000000ULL, "10B" }, + { 15000000000ULL, "15B" }, + { 20000000000ULL, "20B" }, + }; + + for (int s = 0; s < 3; s++) { + uint64_t n = scales[s].n; + printf("\n --- Scale: %s (%llu elements, %.1f GB) ---\n", + scales[s].label, (unsigned long long)n, (double)n / 1073741824.0); + + size_t mem_start = get_mem_mb(); + printf(" Start RSS: %zu MB\n", mem_start); + + struct timespec t0, t1; + clock_gettime(CLOCK_MONOTONIC, &t0); + Vec8_t vec = create(nullptr); + + uint64_t filled = 0; + for (uint64_t i = 0; i < n; i++) { + vec = add_back(&vec, (char)(i % 256)); + if (vec.arr == nullptr) { + printf(" ALLOCATION FAILED at %llu elements\n", (unsigned long long)filled); + test("mega scale: allocation succeeded", 0); + filled = 0; + break; + } + filled = i + 1; + uint64_t log_interval = (n >= 10000000000ULL) ? 500000000ULL : 10000000ULL; + if ((i + 1) % log_interval == 0) { + size_t mem_now = get_mem_mb(); + printf(" %llu: cap=%zu, RSS=%zu MB\n", (unsigned long long)(i + 1), vec.capacity, mem_now); + } + } + + clock_gettime(CLOCK_MONOTONIC, &t1); + double fill_time = time_diff(t0, t1); + + if (filled > 0) { + printf(" Fill time: %.2f sec (%.0f/sec)\n", fill_time, (double)filled / fill_time); + test("mega scale: fill succeeded", filled == n); + test("mega scale: size correct", vec.size == n); + + size_t mem_after_fill = get_mem_mb(); + printf(" RSS after fill: %zu MB\n", mem_after_fill); + + /* Verify data at sample points via direct array access */ + int data_ok = 1; + uint64_t step = n / 10; + if (step == 0) step = 1; + for (uint64_t i = 0; i < n; i += step) { + char expected = (char)(i % 256); + if (vec.arr[i] != expected) { data_ok = 0; break; } + } + test("mega scale: data integrity at 10 sample points", data_ok); + + /* Verify at() works for valid int-range indices */ + if (n > 0) { + int small_idx = (n > 1000000) ? 999999 : (int)(n - 1); + test("mega scale: at(small_idx) correct", at(&vec, small_idx) == (char)(small_idx % 256)); + } + + /* front/back */ + test("mega scale: front correct", front(&vec) == 0); + test("mega scale: back correct", back(&vec) == (char)((n - 1) % 256)); + + /* iterators */ + test("mega scale: begin=0", begin(&vec) == 0); + test("mega scale: end correct", end(&vec) >= 0); + + /* Read every element via at() - sample */ + clock_gettime(CLOCK_MONOTONIC, &t0); + long sum = 0; + for (uint64_t i = 0; i < n; i++) { + sum += vec.arr[i]; + } + clock_gettime(CLOCK_MONOTONIC, &t1); + double raw_read = time_diff(t0, t1); + printf(" Raw pointer read all: %.2f sec (%.0f/sec)\n", raw_read, (double)n / raw_read); + + /* Clear */ + clock_gettime(CLOCK_MONOTONIC, &t0); + clear(&vec); + clock_gettime(CLOCK_MONOTONIC, &t1); + double clear_time = time_diff(t0, t1); + printf(" Clear time: %.4f sec\n", clear_time); + test("mega scale: clear < 30s", clear_time < 30.0); + + test("mega scale: size=0 after clear", vec.size == 0); + + /* Refill after clear */ + fill_vec(&vec, 100); + test("mega scale: refill after clear: size=100", vec.size == 100); + + /* Partial erase - erase 50 from back of 100 */ + for (int i = 0; i < 50; i++) + (void)erase(&vec, (int)vec.size - 1); + test("mega scale: erase back 50 from 100", vec.size == 50); + + delete(&vec); + size_t mem_after_delete = get_mem_mb(); + printf(" RSS after delete: %zu MB\n", mem_after_delete); + } + } +} + +void +t_pseudo_analysis(void) +{ + printf("\n=== ANALYSIS: Pseudo Code ===\n"); + printf(" All bugs previously detected have been fixed:\n"); + printf(" - Container with array, count, capacity\n"); + printf(" - Removal shifts remaining: bytes = (count - index - 1) * elem_size\n"); + printf(" - Count decremented after removal\n"); + printf(" - Count reset after zeroing\n"); + printf(" - Index validated before removal\n"); + test("analysis documented", 1); +} + +int +main(void) +{ + printf("========================================\n"); + printf(" FULL LIBVEC TEST SUITE\n"); + printf(" Memory, CPU, Bug Detection\n"); + printf(" All functions, exponential scale\n"); + printf("========================================\n"); + + t_all_functions_correctness(); + t_all_null_safety(); + t_capacity_growth(); + t_memory_exponential(); + t_memory_stress_cycles(); + t_memory_create_with_input(); + t_cpu_exponential(); + t_cpu_erase_patterns(); + t_cpu_mixed_ops(); + t_cpu_empty_vec_overhead(); + t_bug_data_integrity(); + t_bug_erase_all_positions(); + t_bug_clear_refill(); + t_bug_erase_size_tracking(); + t_bug_iterator_consistency(); + t_bug_print_vec(); + t_mega_scale(); + t_pseudo_analysis(); + + printf("\n========================================\n"); + printf(" RESULTS\n"); + printf("========================================\n"); + printf(" Total: %d\n", tests_passed + tests_failed); + printf(" Passed: %d\n", tests_passed); + printf(" Failed: %d\n", tests_failed); + printf("========================================\n"); + + return tests_failed > 0 ? 1 : 0; +}