From cbdcef91b9e7789356e553a745161eb2b687a8eb Mon Sep 17 00:00:00 2001 From: Andrew Haynes Date: Tue, 5 May 2026 10:34:35 -0400 Subject: [PATCH] erase() should really now set proper values to 0 after move --- src/main.c | 11 +- tests/erase_stress_test | Bin 0 -> 35072 bytes tests/erase_stress_test.c | 418 ++++++++++++++++++++++++++++++++++++++ tests/quick_test | Bin 0 -> 33736 bytes tests/quick_test.c | 69 +++++++ 5 files changed, 493 insertions(+), 5 deletions(-) create mode 100755 tests/erase_stress_test create mode 100644 tests/erase_stress_test.c create mode 100755 tests/quick_test create mode 100644 tests/quick_test.c diff --git a/src/main.c b/src/main.c index 11b4a48..7e84fe9 100644 --- a/src/main.c +++ b/src/main.c @@ -126,7 +126,7 @@ at(const Vec8_t* vec, const int idx) // - Result: a b \0 \0 g h i j (size=8, should be 7) __attribute__((overloadable)) Vec8_t* -erase(Vec8_t* vec, const int iter) { +erase(Vec8_t* vec, const size_t iter) { if(vec == nullptr) return nullptr; if(vec->arr == nullptr) return nullptr; if(iter >= vec->size) return nullptr; @@ -137,13 +137,14 @@ erase(Vec8_t* vec, const int iter) { } __attribute__((overloadable)) Vec8_t* -erase(Vec8_t* vec, const int iter_start, const int iter_end) { +erase(Vec8_t* vec, const size_t iter_start, const size_t 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; + if(iter_start < 0 || iter_end >= vec->size) return nullptr; + if(iter_start >= iter_end) return nullptr; + size_t diff = iter_end - iter_start; memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - iter_end) * sizeof(char)); - for(size_t i = vec->size; i > iter_end; i--) { + for(size_t i = vec->size - diff; i < vec->size; i++) { vec->arr[i] = 0; } vec->size -= diff; diff --git a/tests/erase_stress_test b/tests/erase_stress_test new file mode 100755 index 0000000000000000000000000000000000000000..1d1b3d04dd5ea725c076a00eb8c775ac6b317536 GIT binary patch literal 35072 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 literal 0 HcmV?d00001 diff --git a/tests/erase_stress_test.c b/tests/erase_stress_test.c new file mode 100644 index 0000000..e84d283 --- /dev/null +++ b/tests/erase_stress_test.c @@ -0,0 +1,418 @@ +#include +#include +#include +#include +#include + +#define CAPACITY 1024 +#define nullptr ((void*)0) + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +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 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; +} + +// Exact copy of src/main.c single erase (lines 128-137) +__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; + memmove(&vec->arr[iter], &vec->arr[iter + 1], (vec->size - iter - 1) * sizeof(char)); + vec->arr[vec->size - 1] = 0; + vec->size--; + return vec; +} + +// Exact copy of src/main.c range erase (lines 139-152) +__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; + if(iter_start >= iter_end) return nullptr; + size_t diff = iter_end - iter_start; + memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - iter_end) * sizeof(char)); + for(size_t i = vec->size - 1; i > iter_end; i--) { + vec->arr[i] = 0; + } + vec->size -= diff; + return vec; +} + +void print_vec(const Vec8_t* vec) { + for (int i = 0; i < vec->size; i++) printf("%c ", vec->arr[i]); + printf("(size=%zu)\n", vec->size); +} + +// Test 1: Basic single erase +void test_single_erase_basic() { + printf("Test: Single erase basic\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i); + + erase(&vec, 2); // Erase 'c' + + assert(vec.size == 9); + assert(vec.arr[0] == 'a'); + assert(vec.arr[1] == 'b'); + assert(vec.arr[2] == 'd'); // Shifted correctly + assert(vec.arr[8] == 'j'); // Last element correct + printf("PASS\n\n"); + delete(&vec); +} + +// Test 2: Single erase at boundaries +void test_single_erase_boundaries() { + printf("Test: Single erase at boundaries\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 5; i++) add_back(&vec, 'a' + i); + + // Erase first element + erase(&vec, 0); + assert(vec.size == 4); + assert(vec.arr[0] == 'b'); + printf("Erase first: PASS\n"); + + // Reset + delete(&vec); + vec = create(nullptr); + for (int i = 0; i < 5; i++) add_back(&vec, 'a' + i); + + // Erase last element + erase(&vec, 4); + assert(vec.size == 4); + assert(vec.arr[3] == 'd'); + printf("Erase last: PASS\n"); + + delete(&vec); + printf("\n"); +} + +// Test 3: Single erase invalid inputs +void test_single_erase_invalid() { + printf("Test: Single erase invalid inputs\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 5; i++) add_back(&vec, 'a' + i); + + // Erase with negative index + assert(erase(&vec, -1) == nullptr); + + // Erase with out-of-bounds index + assert(erase(&vec, 10) == nullptr); + assert(erase(&vec, 5) == nullptr); + + // Erase on null vector + assert(erase(nullptr, 0) == nullptr); + + // Erase on vector with null arr + Vec8_t vec2 = { .arr = nullptr, .size = 0, .capacity = 0 }; + assert(erase(&vec2, 0) == nullptr); + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 4: Range erase basic +void test_range_erase_basic() { + printf("Test: Range erase basic\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i); + + erase(&vec, 2, 4); // Erase [2,4) -> 'c','d' + + printf("After erase(2,4): "); + print_vec(&vec); + + assert(vec.size == 8); + assert(vec.arr[0] == 'a'); + assert(vec.arr[1] == 'b'); + assert(vec.arr[2] == 'e'); // Shifted correctly + assert(vec.arr[7] == 'j'); // Last element correct + + // Check that valid data is not zeroed incorrectly + for (int i = 0; i < vec.size; i++) { + assert(vec.arr[i] != 0); // Valid positions should not be zero + } + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 5: Range erase - verify zeroing works correctly now +void test_range_erase_zeroing_fixed() { + printf("Test: Range erase zeroing verification\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i); + + erase(&vec, 2, 4); + + printf("After erase(2,4): "); + print_vec(&vec); + + // Verify valid data is not zeroed + for (int i = 0; i < vec.size; i++) { + assert(vec.arr[i] != 0); // Valid positions should not be zero + } + + // Verify that positions beyond new size are zeroed + // (The zeroing loop should zero from vec.size-1 down to iter_end) + printf("Zeroing verification: "); + int all_valid = 1; + for (int i = 0; i < vec.size; i++) { + if (vec.arr[i] == 0) { + printf("BUG: arr[%d] is zero but should be valid! ", i); + all_valid = 0; + } + } + if (all_valid) printf("PASS"); + + printf("\n\n"); + delete(&vec); +} + +// Test 6: Range erase to end +void test_range_erase_to_end() { + printf("Test: Range erase to end\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i); + + Vec8_t* res = erase(&vec, 2, 10); // Erase [2,10) + assert(res != nullptr); + assert(vec.size == 2); + assert(vec.arr[0] == 'a'); + assert(vec.arr[1] == 'b'); + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 7: Range erase invalid inputs +void test_range_erase_invalid() { + printf("Test: Range erase invalid inputs\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 5; i++) add_back(&vec, 'a' + i); + + // Invalid start + assert(erase(&vec, -1, 3) == nullptr); + + // Invalid end (>= size now, not just >) + assert(erase(&vec, 0, 5) == nullptr); // 5 >= size (5) + + // Start >= end now returns nullptr + assert(erase(&vec, 3, 2) == nullptr); // start >= end + assert(erase(&vec, 2, 2) == nullptr); // start == end + + // Null vector + assert(erase(nullptr, 0, 1) == nullptr); + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 8: Large vector single erase +void test_large_single_erase() { + printf("Test: Large vector single erase (100k elements)\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 100000; i++) add_back(&vec, (char)(i % 256)); + + erase(&vec, 0); // Erase front + assert(vec.size == 99999); + assert(vec.arr[0] == 1); + + erase(&vec, 50000); // Erase middle + assert(vec.size == 99998); + assert(vec.arr[50000] == 2); // After erasing index 1 (value 1), index 50000 is now value 2 + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 9: Large vector range erase +void test_large_range_erase() { + printf("Test: Large vector range erase (100k elements, erase 10k)\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 100000; i++) add_back(&vec, (char)(i % 256)); + + erase(&vec, 10000, 20000); // Erase 10k elements + assert(vec.size == 90000); + assert(vec.arr[10000] == (char)(20000 % 256)); // First element after erased range + + printf("PASS\n\n"); + delete(&vec); +} + +// Test 10: Repeated single erasures +void test_repeated_single_erase() { + printf("Test: Repeated single erasures until empty\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 100; i++) add_back(&vec, 'a' + (i % 26)); + + size_t initial_size = vec.size; + for (int i = 0; i < initial_size; i++) { + erase(&vec, 0); // Always erase first element + } + + assert(vec.size == 0); + printf("PASS\n\n"); + delete(&vec); +} + +// Test 11: Stress - random erasures +void test_random_erasures() { + printf("Test: Random erasures (1000 rounds)\n"); + srand((unsigned int)time(NULL)); + + for (int round = 0; round < 1000; round++) { + Vec8_t vec = create(nullptr); + int num_elements = rand() % 1000 + 10; + for (int i = 0; i < num_elements; i++) add_back(&vec, (char)(rand() % 256)); + + int num_erasures = rand() % 50; + for (int j = 0; j < num_erasures && vec.size > 0; j++) { + int idx = rand() % vec.size; + erase(&vec, idx); + } + + // Verify integrity + for (int i = 0; i < vec.size; i++) { + // Just check that we can access without crashing + char val = vec.arr[i]; + (void)val; + } + + delete(&vec); + } + + printf("PASS\n\n"); +} + +// Test 12: Stress - random range erasures +void test_random_range_erasures() { + printf("Test: Random range erasures (1000 rounds)\n"); + srand((unsigned int)time(NULL)); + + for (int round = 0; round < 1000; round++) { + Vec8_t vec = create(nullptr); + int num_elements = rand() % 1000 + 10; + for (int i = 0; i < num_elements; i++) add_back(&vec, (char)(rand() % 256)); + + int num_erasures = rand() % 20; + for (int j = 0; j < num_erasures && vec.size > 1; j++) { + int start = rand() % (vec.size - 1); + int end = start + rand() % (vec.size - start) + 1; + if (end > vec.size) end = vec.size; + erase(&vec, start, end); + } + + // Verify integrity + for (int i = 0; i < vec.size; i++) { + char val = vec.arr[i]; + (void)val; + } + + delete(&vec); + } + + printf("PASS\n\n"); +} + +// Test 13: Erase all elements one by one +void test_erase_all_single() { + printf("Test: Erase all elements one by one\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 1000; i++) add_back(&vec, 'a' + (i % 26)); + + while (vec.size > 0) { + erase(&vec, 0); + } + + assert(vec.size == 0); + printf("PASS\n\n"); + delete(&vec); +} + +// Test 14: Erase all elements with range erase +void test_erase_all_range() { + printf("Test: Erase all elements with range erase\n"); + Vec8_t vec = create(nullptr); + for (int i = 0; i < 1000; i++) add_back(&vec, 'a' + (i % 26)); + + erase(&vec, 0, vec.size); + + assert(vec.size == 0); + printf("PASS\n\n"); + delete(&vec); +} + +// Test 15: Memory stress - large vector, erase in middle repeatedly +void test_memory_stress() { + printf("Test: Memory stress - large vector, repeated middle erasure\n"); + Vec8_t vec = create(nullptr); + + // Add 1 million elements + for (int i = 0; i < 1000000; i++) { + add_back(&vec, (char)(i % 256)); + } + + printf(" Created vector with %zu elements\n", vec.size); + + // Erase from middle repeatedly + for (int i = 0; i < 10000; i++) { + if (vec.size == 0) break; + int idx = vec.size / 2; + erase(&vec, idx); + } + + printf(" After 10k middle erasures, size = %zu\n", vec.size); + + delete(&vec); + printf("PASS\n\n"); +} + + int main() { + printf("=== ERASE STRESS TEST SUITE ===\n\n"); + + test_single_erase_basic(); + test_single_erase_boundaries(); + test_single_erase_invalid(); + test_range_erase_basic(); + test_range_erase_zeroing_fixed(); + test_range_erase_to_end(); + test_range_erase_invalid(); + test_large_single_erase(); + test_large_range_erase(); + test_repeated_single_erase(); + test_random_erasures(); + test_random_range_erasures(); + test_erase_all_single(); + test_erase_all_range(); + test_memory_stress(); + + printf("=== ALL TESTS COMPLETED ===\n"); + return 0; +} diff --git a/tests/quick_test b/tests/quick_test new file mode 100755 index 0000000000000000000000000000000000000000..200cb5f09768bd77e447cc0723896e47adff2120 GIT binary patch literal 33736 zcmeI5VQgDh701uBo5oJ6G$mzWDbd{8Wr%t-ax41OI#7m|J--& zI8F;f6CaSymF~OuoO|!N|MPp-NxnGuH#h(K&vir=p?FX?pboDgI!iWsM0cWgpeohb zvbX(6`=NvEU0L+vm9AA5$N4QLDs{NM>+s59y*{|oN5(FLJ70N*QZeU5jC*b=jrS_F zbG*BG5enO!SD~z-c%hGuQqkCGPqg4FjrX?Sjkn#*V7oY;&%^^mU6cw%hN8;?OXK+} z+;|@|^V#;A{;e9si^fL6L&wZuX*}D+>oMbO7nfqK>{n`Z=qur&UKJkdi)ef0`*_a8 z>oP&uE{$P^bi?oUMO3BQS`N3UJqHgw?!MiiIaFwMDQP)puKcd5QI$FtS*CXTcsAzh z5?sk`Eu47Og|d8ZAKQ1}(e}1|t}5cUzv8^X=JE^k5_n9HYcJ7*Si$;u-4vP!j6DUr zA2ze$cj@~Y5sn7Uq8&zCiQ0);T=M6*SZDD#_g}<%U#Syz6{?NO=d5uwI?{MN+|$^5 z@^~+7E}KwUN4V=#tyeo9`RTdJgkAH|*RJe<&qlRSiS7cVyL4Zt>-%8MC*jrk>2aa} z^5ZxY<;Gze-nR*r$K3Pq7}BwpwLs6~C!;ZE@V?gjpex+tF1!~F$6t)QZG*9y7njYb zJih%5a(6|t`?e)FPFI)4tklvTN@TpgnT(gR*UKpjW>dcUK!U8xyKO7J+vg8v1AfY; z%Y)gZMHdlzBlmq}s21JuTXdLx8E;U}(f%?@1j;C@=fY2jQBU!OMvI@(p8ZzkWQRo$ zv%iBmAm0w;d#kt{XKAc8g&f^ny%uuyrj}q&dy(h-CuaY+iRO}CwKzep#!JY5Ki09& zhkc9vZS0?aa@J=pKBW0>iqEAmuYq-d&p5e!IL5+K;SziM^J(Jf0+ke*Dkmh%S`SqKr z=1Z7gm|I30l32@n@PV45cpz~ax#k*aPHS!iU&O2Mxa^bOCl@n~@wtj{rU{=boau@g zoWHDI`$ix!jJ1Vzh@D29zachjO|R#3g!NcgSo5nuB7`;9*9WsL6hCwZbqM-&ynh4| zM_J2Oqh+hB537r{U9j zYi_Ogj=bJ2MlbgL({1$P_Y5?~4=s)D#aZ&`v$P%Wy4r)ESDw0Sy1%xlUs2Sra{I`4 zbuquBTAjYgh+{h=-BG96rh7s*1)||o&hC3ojW$$JOJB?xaYq9?wmsN@DHZJ}hMiE% z>20>V?H=2)`|M+Oza6%pvfY(UShqJ4YqoX4&R{_wHwubd4}ARhTM#W*{@aU7P(PO+ z{JU%&qEzch+Hce^&yk)G5CTF#2nYcoAOwVf5D)@FKnMr{As_^VfDjM@LO=)z0U;m+ zgn$qb0zyCt2mv7=1cZPP5CTF#2nYcoAOwVf5D)@FKnMr{As_^VfDjM@Lg4?CKy{qI zgN1M6#`!x}-12v-P~!S24N-m{}Gifl&nr%0N&W!hic>AOhv)yX!6^6TZVapW8T=E5DV z-+bWcJD>f*>F>YR6?rq$cX`b_SFa9u4tAC0p1t_&sk6WP$z;d5ZQuK_<6ob8=79S9 z%fD{x|Kl_CNZK+IyR;tP4+M Y7QXwLcYkbG{qPU!$oU +#include +#include + +#define CAPACITY 1024 +#define nullptr ((void*)0) + +typedef struct { + char* arr; + size_t size; + size_t capacity; +} Vec8_t; + +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; +} + +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; +} + +// Your current implementation +__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; + if(iter_start >= iter_end) return nullptr; + size_t diff = iter_end - iter_start; + memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - iter_end) * sizeof(char)); + for(size_t i = vec->size - 1; i > iter_end; i--) { + vec->arr[i] = 0; + } + vec->size -= diff; + return vec; +} + +int main() { + Vec8_t vec = create(nullptr); + for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i); + + printf("Before erase: "); + for (int i = 0; i < 10; i++) printf("%c ", vec.arr[i]); + printf("(size=%zu)\n", vec.size); + + erase(&vec, 2, 4); + + printf("After erase(2,4): "); + for (int i = 0; i < 10; i++) printf("%c ", vec.arr[i] == 0 ? '0' : vec.arr[i]); + printf("(size=%zu)\n", vec.size); + + printf("\nExpected: a b e f g h i j (size=8)\n"); + printf("Got: "); + for (int i = 0; i < vec.size; i++) printf("%c ", vec.arr[i] == 0 ? '0' : vec.arr[i]); + printf("(size=%zu)\n", vec.size); + + return 0; +}