erase() function iter fixess
This commit is contained in:
+597
-110
@@ -2,7 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
typedef struct {
|
||||
char* arr;
|
||||
@@ -12,37 +12,90 @@ typedef struct {
|
||||
|
||||
#define CAPACITY 1024
|
||||
|
||||
Vec8_t create(const Vec8_t* input) {
|
||||
Vec8_t
|
||||
create(const Vec8_t* input)
|
||||
{
|
||||
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = CAPACITY };
|
||||
if (input != nullptr && input->size > 0) {
|
||||
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) {
|
||||
void
|
||||
delete(Vec8_t* vec)
|
||||
{
|
||||
if (vec->arr != nullptr)
|
||||
{
|
||||
free(vec->arr);
|
||||
}
|
||||
vec->arr = nullptr;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 add_back(Vec8_t* vec, const char val) {
|
||||
if (vec->size >= vec->capacity) {
|
||||
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 * sizeof(char)) - 1);
|
||||
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) {
|
||||
if (nvec == NULL)
|
||||
{
|
||||
return *vec;
|
||||
}
|
||||
vec->arr = nvec;
|
||||
@@ -52,171 +105,605 @@ Vec8_t add_back(Vec8_t* vec, const char val) {
|
||||
return *vec;
|
||||
}
|
||||
|
||||
Vec8_t* erase(Vec8_t* vec, const int iter) {
|
||||
if(vec == nullptr) return nullptr;
|
||||
if(vec->arr == nullptr) return nullptr;
|
||||
vec->arr[iter] = 0;
|
||||
memmove(&vec[iter], &vec[iter + 1], (vec->size * sizeof(char)) -1);
|
||||
return vec;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
int
|
||||
empty(const Vec8_t* vec)
|
||||
{
|
||||
if (vec->size > 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return *vec;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tests_passed = 0;
|
||||
int tests_failed = 0;
|
||||
int test_num = 0;
|
||||
|
||||
void test(const char* name, int passed) {
|
||||
void
|
||||
test(const char* name, int passed)
|
||||
{
|
||||
test_num++;
|
||||
if (passed) {
|
||||
if (passed)
|
||||
{
|
||||
printf("[PASS] #%d: %s\n", test_num, name);
|
||||
tests_passed++;
|
||||
} else {
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("=== ERASE & CLEAR FUNCTION TESTS ===\n\n");
|
||||
size_t
|
||||
get_mem_mb(void)
|
||||
{
|
||||
struct rusage ru;
|
||||
getrusage(RUSAGE_SELF, &ru);
|
||||
return (size_t)(ru.ru_maxrss / 1024);
|
||||
}
|
||||
|
||||
Vec8_t vec;
|
||||
struct timespec start, end_t;
|
||||
void
|
||||
test_erase_basic_correctness(void)
|
||||
{
|
||||
printf("\n--- ERASE: Basic Correctness ---\n");
|
||||
|
||||
printf("--- ERASE: Basic Correctness ---\n");
|
||||
vec = create(nullptr);
|
||||
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);
|
||||
test("erase setup: 5 elements", vec.size == 5);
|
||||
|
||||
erase(&vec, 2);
|
||||
test("erase: size unchanged (intentional)", vec.size == 5);
|
||||
test("erase: element at idx 2 set to 0", vec.arr[2] == 0);
|
||||
|
||||
test("erase: arr[2] set to 0", vec.arr[2] == 0);
|
||||
|
||||
int elements_intact = (vec.arr[0] == 'A') && (vec.arr[1] == 'B')
|
||||
&& (vec.arr[3] == 'E');
|
||||
test("erase: remaining elements intact after shift", elements_intact);
|
||||
|
||||
test("erase: element at idx 3 now holds original idx 4", vec.arr[3] == 'E');
|
||||
|
||||
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);
|
||||
|
||||
vec = create(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);
|
||||
}
|
||||
|
||||
printf("\n--- ERASE: Return Value ---\n");
|
||||
vec = create(nullptr);
|
||||
void
|
||||
test_erase_bounds_violation(void)
|
||||
{
|
||||
printf("\n--- ERASE: Bounds Violation ---\n");
|
||||
|
||||
Vec8_t vec = create(nullptr);
|
||||
vec = add_back(&vec, 'A');
|
||||
Vec8_t* result = erase(&vec, 0);
|
||||
test("erase returns non-null for valid vec", result != nullptr);
|
||||
test("erase returns vec pointer", result == &vec);
|
||||
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);
|
||||
}
|
||||
|
||||
printf("\n--- ERASE: Memmove Bug Analysis ---\n");
|
||||
printf(" BUG IN ERASE (src/main.c:137):\n");
|
||||
printf(" Current: memmove(&vec[iter], &vec[iter + 1], ...)\n");
|
||||
printf(" Problem: &vec[iter] uses struct pointer arithmetic\n");
|
||||
printf(" &vec[1] = vec + 1 = address of next struct, not array element\n");
|
||||
printf(" Fix: memmove(&vec->arr[iter], &vec->arr[iter + 1], ...)\n");
|
||||
printf(" Also: length calculation is wrong\n");
|
||||
printf(" Current: (vec->size * sizeof(char)) - 1\n");
|
||||
printf(" Fix: (vec->size - iter - 1) * sizeof(char)\n");
|
||||
test("memmove bug documented", 1);
|
||||
|
||||
void
|
||||
test_clear_basic_correctness(void)
|
||||
{
|
||||
printf("\n--- CLEAR: Basic Correctness ---\n");
|
||||
vec = create(nullptr);
|
||||
|
||||
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: returns vec", cleared.arr == vec.arr);
|
||||
|
||||
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: size unchanged (intentional)", vec.size == 3);
|
||||
delete(&vec);
|
||||
test("clear: returns vec", cleared.arr == vec.arr);
|
||||
|
||||
printf("\n--- CLEAR: NULL Safety ---\n");
|
||||
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;
|
||||
cleared = clear(&vec);
|
||||
test("clear: null arr no crash", 1);
|
||||
|
||||
printf("\n--- CLEAR: Empty Vector ---\n");
|
||||
vec = create(nullptr);
|
||||
cleared = clear(&vec);
|
||||
test("clear: empty vec size=0", vec.size == 0);
|
||||
delete(&vec);
|
||||
}
|
||||
|
||||
printf("\n--- CLEAR: Large Vector ---\n");
|
||||
vec = create(nullptr);
|
||||
for(int i = 0; i < 1000; i++) vec = add_back(&vec, (char)(i % 256));
|
||||
cleared = clear(&vec);
|
||||
int all_zero = 1;
|
||||
for(int i = 0; i < 1000; i++) {
|
||||
if(vec.arr[i] != 0) { all_zero = 0; break; }
|
||||
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);
|
||||
}
|
||||
test("clear: 1000 elements all zero", all_zero);
|
||||
test("clear: size still 1000 after clear", vec.size == 1000);
|
||||
delete(&vec);
|
||||
|
||||
printf("\n--- MEMORY: Clear Stress ---\n");
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
for(int round = 0; round < 1000; round++) {
|
||||
vec = create(nullptr);
|
||||
for(int i = 0; i < 100; i++) vec = add_back(&vec, (char)i);
|
||||
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(" 1000 rounds of clear: %.3f sec\n", clear_time);
|
||||
test("clear stress: no crash", 1);
|
||||
|
||||
printf("\n--- CPU: Clear Performance ---\n");
|
||||
vec = create(nullptr);
|
||||
for(int i = 0; i < 100000; i++) vec = add_back(&vec, (char)(i % 256));
|
||||
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||
clear(&vec);
|
||||
clock_gettime(CLOCK_MONOTONIC, &end_t);
|
||||
double cpu_clear = time_diff(start, end_t);
|
||||
printf(" clear 100K elements: %.3f sec\n", cpu_clear);
|
||||
delete(&vec);
|
||||
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);
|
||||
|
||||
printf("\n--- PSEUDO CODE: Fix for erase memmove bug ---\n");
|
||||
printf(" Problem recreation (independent of source):\n");
|
||||
printf(" struct Container { char* data; size_t len; size_t cap; };\n");
|
||||
printf(" void remove_at(Container* c, int idx) {\n");
|
||||
printf(" c->data[idx] = 0;\n");
|
||||
printf(" // Bug: memmove(&c[idx], &c[idx+1], ...)\n");
|
||||
printf(" // This moves from/to wrong addresses\n");
|
||||
printf(" // Fix: memmove(&c->data[idx], &c->data[idx+1], (c->len - idx - 1) * sizeof(char))\n");
|
||||
printf(" }\n");
|
||||
test("pseudo code fix provided", 1);
|
||||
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: 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");
|
||||
|
||||
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);
|
||||
printf("\nBugs Found:\n");
|
||||
printf("1. erase() memmove uses &vec[iter] instead of &vec->arr[iter]\n");
|
||||
printf("2. erase() memmove length calculation is wrong\n");
|
||||
|
||||
return tests_failed > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user