removing AI and am going to start learning how to write my own unit tests

This commit is contained in:
Andrew Haynes
2026-05-05 13:23:19 -04:00
parent cbdcef91b9
commit b87efd2398
31 changed files with 27 additions and 3880 deletions
-12
View File
@@ -1,12 +0,0 @@
# AI Agent Rules
## AI Usage Policy (from src/main.c:46-55)
- Absolutely no AI is permitted when writing source code.
- AI is allowed to generate tests for code; however, test results and the AI cannot give code as to how to fix the source aside from pseudo code that has no clear relation to the source aside from a recreation of the problem in a different way entirely.
- Source code comments are for the author's short-term memory and do not affect AI behavior.
## Project Code Conventions
- **Formatting**: Follow `.clang-format` (Google-based style, tabs (width 8), Allman braces, short functions/if/loops can be single-line)
- **Linting**: Follow `.clang-tidy` (bugprone, concurrency, misc, modernize, performance, readability, portability checks; `lower_case` naming for variables and functions)
- **Build**: C23 standard, CMake 3.16+
- **Naming**: Variables and functions use `lower_case` (enforced by clang-tidy)
BIN
View File
Binary file not shown.
+27 -42
View File
@@ -7,12 +7,8 @@
/* /*
* All functions needed * All functions needed
* assign() Fills a vector with multiple values * assign() Fills a vector with multiple values stored
* 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 * 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() * 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 the last element of a vector rend()
* Returns a reverse iterator pointing to a position right before the first * Returns a reverse iterator pointing to a position right before the first
@@ -31,16 +27,6 @@
* String * String
*/ */
/* Absolutely no AI is permitted when writing code.
* AI is and can be used to generate tests for code; however, the test results
* and the AI can not give code as to how to fix the source aside from psuedo
* code that has no clear relation to the source aside from a recreation of the
* problem in a different way entirely
*
* Any code comments below are just used for my purposes with short term memory.
* It also serves as a way to remember what needs to be changed to be readable
* and not need comments in the first place.
*/
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -68,6 +54,26 @@ create(const Vec8_t* input)
return vec; return vec;
} }
Vec8_t*
shrink_to_fit(const Vec8_t* ptr) {
/* Create a new empty heap
* copy current ptr values
* realloc heap to current size
*
* */
}
char*
data(const Vec8_t* ptr) {
if(ptr == nullptr || ptr->arr == nullptr) return nullptr;
return &ptr->arr[0];
}
size_t
max_size(const Vec8_t* ptr) {
return ptr->capacity;
}
void void
delete(Vec8_t* vec) delete(Vec8_t* vec)
{ {
@@ -114,17 +120,6 @@ at(const Vec8_t* vec, const int idx)
return -1; return -1;
} }
// 1. Single erase (line 117-126):
// - size-- before memmove → wrong copy size
// - arr[iter] = 0 after memmove → zeros shifted element
// - Result: a b \0 e f g h i j (after erasing index 2 from a b c d e f g h i j)
// 2. Range erase (line 128-140):
// - Bounds check uses && (should be ||)
// - diff = iter_end - iter_start (off-by-one for inclusive range)
// - memmove uses iter_end not iter_end+1
// - Zeroing loop zeros wrong positions
// - Result: a b \0 \0 g h i j (size=8, should be 7)
__attribute__((overloadable)) Vec8_t* __attribute__((overloadable)) Vec8_t*
erase(Vec8_t* vec, const size_t iter) { erase(Vec8_t* vec, const size_t iter) {
if(vec == nullptr) return nullptr; if(vec == nullptr) return nullptr;
@@ -140,7 +135,7 @@ __attribute__((overloadable)) Vec8_t*
erase(Vec8_t* vec, const size_t iter_start, const size_t iter_end) { erase(Vec8_t* vec, const size_t iter_start, const size_t iter_end) {
if(vec == nullptr) return nullptr; if(vec == nullptr) return nullptr;
if(vec->arr == nullptr) return nullptr; if(vec->arr == nullptr) return nullptr;
if(iter_start < 0 || iter_end >= vec->size) return nullptr; if(iter_start < 0 || iter_end > vec->size) return nullptr;
if(iter_start >= iter_end) return nullptr; if(iter_start >= iter_end) return nullptr;
size_t diff = iter_end - iter_start; size_t diff = iter_end - iter_start;
memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - iter_end) * sizeof(char)); memmove(&vec->arr[iter_start], &vec->arr[iter_end], (vec->size - iter_end) * sizeof(char));
@@ -239,21 +234,11 @@ main()
vec = add_back(&vec, '6'); vec = add_back(&vec, '6');
size_t size = vec.size; size_t size = vec.size;
for (int i = 0; i < size; i++) { print_vec(&vec);
if(vec.arr[i] == 0) printf("0"); // vec = *erase(&vec, begin(&vec) + 2);
printf("%c ", vec.arr[i]); vec = *erase(&vec, begin(&vec) + 2, begin(&vec) + 4);
} print_vec(&vec);
printf("\n"); printf("%p", data(&vec));
// 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); delete(&vec);
return 0; return 0;
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
-187
View File
@@ -1,187 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(Vec8_t* input) {
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
if(input == nullptr) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != nullptr) free(vec->arr);
vec->arr = nullptr;
}
char at(Vec8_t* vec, 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;
}
int begin(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
return -1;
}
int end(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
return -1;
}
char front(Vec8_t* vec) {
return at(vec, 0);
}
char back(Vec8_t* vec) {
if (vec) return at(vec, (int)vec->size - 1);
return -1;
}
Vec8_t add_back(Vec8_t* vec, char val) {
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
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() {
struct timespec start, end_t;
Vec8_t vec;
printf("=== CPU Stress Tests ===\n\n");
// Test 1: Rapid fire inserts (tight loop)
printf("--- Test 1: Rapid Fire (100M tight loop) ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 100000000; i++) {
vec = add_back(&vec, (char)i);
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t1 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t1);
printf(" Rate: %.0f/sec\n", 100000000.0 / t1);
delete(&vec);
// Test 2: Read-heavy (iteration + at())
printf("\n--- Test 2: Read Every Element (100M at() calls) ---\n");
vec = create(nullptr);
for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i);
long sum = 0;
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < vec.size; i++) {
sum += at(&vec, (int)i);
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t2 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t2);
printf(" Sum: %ld\n", sum);
printf(" Rate: %.0f reads/sec\n", 100000000.0 / t2);
delete(&vec);
// Test 3: Mixed operations
printf("\n--- Test 3: Mixed Operations (50M each) ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 50000000; i++) {
vec = add_back(&vec, (char)i);
char f = front(&vec);
char b = back(&vec);
at(&vec, i / 2);
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t3 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t3);
printf(" Rate: %.0f ops/sec\n", 50000000.0 * 3 / t3);
delete(&vec);
// Test 4: Cache thrashing (random access)
printf("\n--- Test 4: Random Access (100M random at() calls) ---\n");
vec = create(nullptr);
for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i);
srand(12345);
clock_gettime(CLOCK_MONOTONIC, &start);
sum = 0;
for (int i = 0; i < 100000000; i++) {
int idx = rand() % (int)vec.size;
sum += at(&vec, idx);
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t4 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t4);
printf(" Sum: %ld\n", sum);
printf(" Rate: %.0f random reads/sec\n", 100000000.0 / t4);
delete(&vec);
// Test 5: Sequential scan (raw pointer access)
printf("\n--- Test 5: Sequential Scan (raw pointer, 500M bytes) ---\n");
vec = create(nullptr);
for (int i = 0; i < 500000000; i++) vec = add_back(&vec, (char)(i % 256));
sum = 0;
clock_gettime(CLOCK_MONOTONIC, &start);
char* ptr = vec.arr;
for (size_t i = 0; i < vec.size; i++) {
sum += ptr[i];
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t5 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t5);
printf(" Throughput: %.1f GB/sec\n", (vec.size / 1e9) / t5);
printf(" Sum: %ld\n", sum);
delete(&vec);
// Test 6: Create/delete cycles (memory allocation stress)
printf("\n--- Test 6: Create/Delete Cycles (1M vectors) ---\n");
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 1000000; i++) {
vec = create(nullptr);
for (int j = 0; j < 100; j++) vec = add_back(&vec, (char)j);
delete(&vec);
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t6 = time_diff(start, end_t);
printf(" Time: %.3f sec\n", t6);
printf(" Rate: %.0f create/delete cycles/sec\n", 1000000.0 / t6);
printf("\n=== CPU Stress Complete ===\n");
return 0;
}
Binary file not shown.
-107
View File
@@ -1,107 +0,0 @@
#include <mach/mach.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
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 = NULL, .size = 0, .capacity = CAPACITY };
if (input == NULL)
{
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (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 != NULL)
{
free(vec->arr);
vec->arr = NULL;
}
vec->size = 0;
vec->capacity = 0;
}
Vec8_t
add_back(Vec8_t* vec, const char val)
{
if (vec->size >= vec->capacity)
{
vec->capacity = 2 * vec->capacity;
char* new_arr =
reallocf(vec->arr, vec->capacity * sizeof(char));
if (new_arr == NULL)
{
return *vec;
}
vec->arr = new_arr;
}
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
vm_size_t
get_physical_mem()
{
struct task_basic_info info;
mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info,
&count);
return info.resident_size;
}
int
main()
{
printf("=== PROGRESSIVE TEST: 1K -> 10K -> 100K -> 1M -> 10M -> 100M -> 1B ===\n\n");
size_t targets[] = {1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
int num_tests = 7;
for (int t = 0; t < num_tests; t++) {
size_t target = targets[t];
printf("\n=== TEST %d: %zu elements ===\n", t+1, target);
Vec8_t vec = create(NULL);
size_t start_cap = vec.capacity;
for (size_t i = 0; i < target; i++) {
vec = add_back(&vec, 'x');
if (vec.arr == NULL) {
printf("CRASHED at %zu elements!\n", i);
return 1;
}
}
printf("SUCCESS: %zu elements, capacity %zu\n", vec.size, vec.capacity);
printf("Memory: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
delete(&vec);
}
printf("\n=== ALL TESTS PASSED ===\n");
printf("Final memory: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
return 0;
}
Binary file not shown.
-198
View File
@@ -1,198 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(const Vec8_t* input) {
Vec8_t vec = { .arr = NULL, .size = 0, .capacity = 4 };
if (input == NULL) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != NULL) {
free(vec->arr);
}
vec->arr = NULL;
}
Vec8_t add_back(Vec8_t* vec, const char val) {
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
if (nvec.arr == NULL) {
return *vec;
}
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
Vec8_t ret = { .arr = NULL, .capacity = 0, .size = 0 };
return ret;
}
void print_rusage(const char* label) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
printf("%s: %.2f MB maxRSS\n", label, ru.ru_maxrss / 1024.0);
}
void force_rusage_reset() {
struct rusage start;
getrusage(RUSAGE_SELF, &start);
}
int main() {
printf("=== MEMORY CRASH + LEAK TEST ===\n\n");
printf("Initial memory:\n");
print_rusage("before");
printf("\n=== TEST 1: PUSH UNTIL CRASH ===\n\n");
Vec8_t vec = create(NULL);
size_t crashed_at = 0;
for (size_t i = 0; ; i++) {
vec = add_back(&vec, (char)(i % 256));
if (vec.arr == NULL) {
crashed_at = i;
break;
}
if (i % 50000000 == 0 && i > 0) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
printf(" %zu elements: %.2f MB used\n", i, ru.ru_maxrss / 1024.0);
}
if (i >= 4000000000UL) {
crashed_at = i;
printf(" STOPPED at 4 billion\n");
break;
}
}
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
if (crashed_at > 0) {
printf("\nCRASHED at %zu elements\n", crashed_at);
} else {
printf("\nStopped at %zu elements\n", vec.size);
printf("capacity: %zu\n", vec.capacity);
}
printf("memory used: %.2f MB\n", ru.ru_maxrss / 1024.0);
delete(&vec);
printf("\nAfter delete:\n");
print_rusage("after delete");
printf("\n=== TEST 2: MULTIPLE VECTORS (LEAK CHECK) ===\n\n");
size_t num_vectors = 10000;
Vec8_t* vectors = calloc(num_vectors, sizeof(Vec8_t));
printf("Creating %zu vectors...\n", num_vectors);
print_rusage("before vectors");
for (size_t i = 0; i < num_vectors; i++) {
vectors[i] = create(NULL);
for (size_t j = 0; j < 10000; j++) {
vectors[i] = add_back(&vectors[i], (char)(j % 256));
}
}
print_rusage("with vectors");
printf("Each vector has %zu elements\n", vectors[0].size);
printf("\nFreeing vectors...\n");
for (size_t i = 0; i < num_vectors; i++) {
delete(&vectors[i]);
}
free(vectors);
print_rusage("after free");
printf("\n=== TEST 3: CREATE/DELETE CYCLES ===\n\n");
size_t cycles = 100000;
printf("Running %zu create/delete cycles...\n", cycles);
print_rusage("before cycles");
for (size_t c = 0; c < cycles; c++) {
Vec8_t v = create(NULL);
for (size_t i = 0; i < 1000; i++) {
v = add_back(&v, 'x');
}
delete(&v);
if (c % 10000 == 0) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
printf(" cycle %zu: %.2f MB\n", c, ru.ru_maxrss / 1024.0);
}
}
print_rusage("after cycles");
printf("\n=== TEST 4: REALLOC STRESS ===\n\n");
Vec8_t big = create(NULL);
printf("Single vec realloc stress...\n");
size_t prev_cap = 0;
for (size_t i = 0; i < 100000000; i++) {
big = add_back(&big, 'x');
if (big.capacity != prev_cap) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
printf(" cap %zu -> %.2f MB\n", big.capacity, ru.ru_maxrss / 1024.0);
prev_cap = big.capacity;
}
}
print_rusage("final big vec");
printf("size: %zu, capacity: %zu\n", big.size, big.capacity);
delete(&big);
printf("\nAfter cleanup:\n");
print_rusage("cleanup done");
printf("\n=== RESULT ===\n");
struct rusage final;
getrusage(RUSAGE_SELF, &final);
printf("Peak memory: %.2f MB\n", final.ru_maxrss / 1024.0);
return 0;
}
Binary file not shown.
-235
View File
@@ -1,235 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
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 = 4 };
if (input == nullptr) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
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) {
return vec->arr[idx];
}
return -1;
}
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;
}
Vec8_t add_back(Vec8_t* vec, const char val) {
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
if (nvec.arr == nullptr) {
printf("Malloc failed and returned nullptr: Returning old vector\n");
return *vec;
}
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
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++;
}
}
int main() {
printf("=== EDGE CASE BRUTAL TESTS ===\n\n");
Vec8_t vec;
char* ptr;
printf("--- Reallocation Behavior ---\n");
vec = create(nullptr);
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
ptr = vec.arr;
for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)('0' + (i % 10)));
test("after reallocation, vec.arr is new", ptr != vec.arr);
test("data preserved in new vec", vec.arr[0] == 'A' && vec.arr[9] == 'J');
test("vec must be reassigned: vec = add_back()", 1);
delete(&vec);
printf("\n--- Stack-Allocated Struct ---\n");
vec.arr = nullptr;
vec.size = 0;
vec.capacity = 0;
test("stack vec: add_back modifies nothing (capacity 0)", 1);
printf("\n--- Integer Overflow ---\n");
size_t doubled = 2 * (size_t)-1;
test("2 * SIZE_MAX overflows (demonstrates overflow)", 1);
printf("\n--- Signed/Unsigned Mixing ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'X');
test("at() with negative -1 returns error", at(&vec, -1) == -4);
test("at() with INT_MIN returns error", at(&vec, -2147483648) == -4);
delete(&vec);
printf("\n--- Huge Size Values ---\n");
vec.arr = calloc(4, 1);
vec.size = 1000000;
vec.capacity = 4;
test("at() works for valid idx despite bad size", at(&vec, 0) == 0);
free(vec.arr);
printf("\n--- Uninitialized Struct ---\n");
Vec8_t uninit;
printf(" Calling at() on uninitialized struct...\n");
printf(" This is undefined behavior - results unpredictable!\n");
test("uninitialized: expect garbage or crash (UB)", 1);
printf("\n--- Capacity Mismatch ---\n");
vec = create(nullptr);
vec.arr = realloc(vec.arr, 1000);
vec.capacity = 1000;
for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i);
test("manual realloc: capacity grows (add_back doesn't know)", 1);
delete(&vec);
printf("\n--- Memcpy Edge Cases ---\n");
vec = create(nullptr);
for (int i = 0; i < 5; i++) vec = add_back(&vec, (char)('A' + i));
test("empty memcpy edge case: works fine", vec.size == 5);
delete(&vec);
printf("\n--- Ignored Return Values ---\n");
vec = create(nullptr);
add_back(&vec, 'X');
test("add_back modifies in-place when capacity available", vec.size == 1);
test("data stored correctly", vec.arr[0] == 'X');
for (int i = 0; i < 3; i++) vec = add_back(&vec, (char)('A' + i));
char* old_ptr = vec.arr;
vec = add_back(&vec, 'Z');
test("reallocation triggered", old_ptr != vec.arr);
test("realloc: data preserved in new vec", vec.arr[4] == 'Z');
printf("\n--- Aliasing Issues ---\n");
Vec8_t v1 = create(nullptr);
Vec8_t v2 = create(nullptr);
for (int i = 0; i < 5; i++) v1 = add_back(&v1, (char)('A' + i));
for (int i = 0; i < 5; i++) v2 = add_back(&v2, (char)('1' + i));
test("v1 and v2 are separate", v1.arr != v2.arr);
test("v1 data correct", v1.arr[0] == 'A');
test("v2 data correct", v2.arr[0] == '1');
delete(&v1);
delete(&v2);
printf("\n--- Double Free ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'X');
delete(&vec);
delete(&vec);
test("double delete: no crash", 1);
printf("\n--- Malloc Failure Check ---\n");
printf(" add_back now checks if nvec.arr is nullptr\n");
printf(" If malloc fails, prints error and returns old vector\n");
test("malloc failure handled gracefully", 1);
printf("\n--- Use After Delete ---\n");
vec = create(nullptr);
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)i);
delete(&vec);
test("after delete: arr is null", vec.arr == nullptr);
test("after delete: size is still 10 (not cleared)", vec.size == 10);
test("after delete: accessing returns error", at(&vec, 0) == -3);
printf("\n--- Size/Capacity Edge ---\n");
vec.arr = malloc(100);
vec.size = 0;
vec.capacity = 100;
test("begin() returns -1 when size=0", begin(&vec) == -1);
test("end() returns -1 when size=0", end(&vec) == -1);
test("front() returns -4 when size=0", front(&vec) == -4);
test("back() returns -4 when size=0", back(&vec) == -4);
free(vec.arr);
printf("\n--- const Correctness ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'C');
const Vec8_t* const_vec = &vec;
test("const vec: at() works", at(const_vec, 0) == 'C');
test("const vec: front() works", front(const_vec) == 'C');
test("const vec: back() works", back(const_vec) == 'C');
test("const vec: begin() works", begin(const_vec) == 0);
test("const vec: end() works", end(const_vec) == 0);
delete(&vec);
printf("\n--- Iterator Safety ---\n");
vec = create(nullptr);
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
test("conceptual: iteration during add_back is unsafe (must reassign vec)", 1);
delete(&vec);
printf("\n=== Summary ===\n");
printf("Passed: %d\n", tests_passed);
printf("Failed: %d\n", tests_failed);
return tests_failed > 0 ? 1 : 0;
}
Binary file not shown.
-705
View File
@@ -1,705 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
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;
}
Binary file not shown.
-418
View File
@@ -1,418 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
#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;
}
BIN
View File
Binary file not shown.
-912
View File
@@ -1,912 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
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;
}
BIN
View File
Binary file not shown.
-108
View File
@@ -1,108 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mach/mach.h>
#include <sys/resource.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(const Vec8_t* input) {
Vec8_t vec = { .arr = NULL, .size = 0, .capacity = 4 };
if (input == NULL) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != NULL) {
free(vec->arr);
vec->arr = NULL;
}
vec->size = 0;
vec->capacity = 0;
}
Vec8_t add_back(Vec8_t* vec, const char val) {
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
if (nvec.arr == NULL) {
return *vec;
}
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
Vec8_t ret = { .arr = NULL, .capacity = 0, .size = 0 };
return ret;
}
vm_size_t get_physical_mem() {
struct task_basic_info info;
mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &count);
return info.resident_size;
}
int main() {
printf("=== PHYSICAL MEMORY LEAK TEST ===\n\n");
printf("Initial physical: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
printf("\n--- Creating large vector ---\n");
Vec8_t big = create(NULL);
printf("Adding elements...\n");
for (size_t i = 0; i < 100000000; i++) {
big = add_back(&big, 'x');
if (i % 10000000 == 0) {
printf(" %zu elements: %.2f MB\n", i+1, get_physical_mem() / 1024.0 / 1024.0);
}
}
printf(" Final: %zu elements, %.2f MB\n", big.size, get_physical_mem() / 1024.0 / 1024.0);
printf("\n--- BEFORE delete: %.2f MB ---\n", get_physical_mem() / 1024.0 / 1024.0);
delete(&big);
printf("--- AFTER delete: %.2f MB ---\n", get_physical_mem() / 1024.0 / 1024.0);
printf("\n--- Create 1000 vectors then delete ---\n");
printf("Before: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
for (int c = 0; c < 1000; c++) {
Vec8_t v = create(NULL);
for (int i = 0; i < 100000; i++) {
v = add_back(&v, 'x');
}
delete(&v);
}
printf("After cycles: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
printf("\n--- RESULT ---\n");
printf("Physical memory used: %.2f MB\n", get_physical_mem() / 1024.0 / 1024.0);
return 0;
}
Binary file not shown.
-95
View File
@@ -1,95 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct {
char* arr;
size_t size;
} Vec8_t;
Vec8_t create(size_t init_size) {
Vec8_t vec = { .arr = nullptr, .size = 0 };
if (init_size > 0) {
vec.arr = malloc(init_size * sizeof(char));
vec.size = init_size;
}
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != nullptr) free(vec->arr);
vec->arr = nullptr;
}
int main(int argc, char* argv[]) {
size_t count = 100000000; // 100M
int vec_count = 1;
if (argc > 1) count = atoll(argv[1]);
if (argc > 2) vec_count = atoi(argv[2]);
size_t total = count * (size_t)vec_count;
printf("=== Direct Allocation Memory Test ===\n");
printf("Elements per vector: %zu\n", count);
printf("Number of vectors: %d\n", vec_count);
printf("Total elements: %zu\n", total);
printf("Total memory: %.1f GB\n", (total * sizeof(char)) / (1024.0 * 1024.0 * 1024.0));
printf("\n");
struct timespec start, end;
Vec8_t* vecs = malloc(vec_count * sizeof(Vec8_t));
clock_gettime(CLOCK_MONOTONIC, &start);
printf("Allocating %d vectors of %zu elements each...\n", vec_count, count);
for (int v = 0; v < vec_count; v++) {
vecs[v] = create(count);
if (vecs[v].arr == nullptr) {
printf(" ERROR: Failed to allocate vector %d!\n", v);
return 1;
}
}
clock_gettime(CLOCK_MONOTONIC, &end);
double alloc_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("Allocation time: %.2f seconds\n", alloc_time);
printf("\nFilling vectors...\n");
clock_gettime(CLOCK_MONOTONIC, &start);
for (int v = 0; v < vec_count; v++) {
for (size_t i = 0; i < count; i++) {
vecs[v].arr[i] = (char)(i % 256);
}
}
clock_gettime(CLOCK_MONOTONIC, &end);
double fill_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("Fill time: %.2f seconds\n", fill_time);
printf("\nVerifying...\n");
int errors = 0;
for (int v = 0; v < vec_count; v++) {
if (vecs[v].size != count) errors++;
if (vecs[v].arr[0] != 0) errors++;
if (vecs[v].arr[count - 1] != (char)((count - 1) % 256)) errors++;
}
printf("Errors: %d\n", errors);
printf("\nFreeing...\n");
clock_gettime(CLOCK_MONOTONIC, &start);
for (int v = 0; v < vec_count; v++) {
delete(&vecs[v]);
}
clock_gettime(CLOCK_MONOTONIC, &end);
double free_time = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("Free time: %.2f seconds\n", free_time);
free(vecs);
printf("\n=== Complete ===\n");
printf("Total time: %.2f seconds\n", alloc_time + fill_time + free_time);
return errors > 0 ? 1 : 0;
}
BIN
View File
Binary file not shown.
-69
View File
@@ -1,69 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}
Binary file not shown.
-264
View File
@@ -1,264 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(Vec8_t* input) {
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
if(input == nullptr) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != nullptr) free(vec->arr);
vec->arr = nullptr;
}
char at(Vec8_t* vec, 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;
}
int begin(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
return -1;
}
int end(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
return -1;
}
char front(Vec8_t* vec) {
return at(vec, 0);
}
char back(Vec8_t* vec) {
if (vec) return at(vec, (int)vec->size - 1);
return -1;
}
Vec8_t add_back(Vec8_t* vec, char val) {
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
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++;
}
}
int main() {
printf("=== Reliability Tests ===\n\n");
Vec8_t vec;
// === Basic Initialization ===
printf("--- Initialization ---\n");
vec = create(nullptr);
test("create(nullptr) returns valid vec", vec.arr != nullptr);
test("create(nullptr) capacity = 4", vec.capacity == 4);
test("create(nullptr) size = 0", vec.size == 0);
delete(&vec);
// === Empty Vector Operations ===
printf("\n--- Empty Vector Operations ---\n");
vec = create(nullptr);
test("at() on empty returns error", at(&vec, 0) == -4);
test("at() on empty (neg idx) returns error", at(&vec, -1) == -4);
test("at() on empty (large idx) returns error", at(&vec, 100) == -4);
test("front() on empty returns error", front(&vec) == -4);
test("back() on empty returns error", back(&vec) == -4);
test("begin() on empty returns -1", begin(&vec) == -1);
test("end() on empty returns -1", end(&vec) == -1);
delete(&vec);
// === Single Element ===
printf("\n--- Single Element ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'X');
test("single element: size = 1", vec.size == 1);
test("single element: at(0) = 'X'", at(&vec, 0) == 'X');
test("single element: front() = 'X'", front(&vec) == 'X');
test("single element: back() = 'X'", back(&vec) == 'X');
test("single element: begin() = 0", begin(&vec) == 0);
test("single element: end() = 0", end(&vec) == 0);
delete(&vec);
// === Capacity Boundaries ===
printf("\n--- Capacity Boundaries ---\n");
vec = create(nullptr);
for (int i = 0; i < 4; i++) vec = add_back(&vec, (char)('A' + i));
test("at capacity (4): size = 4", vec.size == 4);
test("at capacity (4): capacity = 4", vec.capacity == 4);
vec = add_back(&vec, 'E');
test("at capacity (4): size = 5", vec.size == 5);
test("at capacity (4): capacity doubled = 8", vec.capacity == 8);
test("at capacity (4): arr[4] = 'E'", vec.arr[4] == 'E');
delete(&vec);
// === Data Integrity ===
printf("\n--- Data Integrity ---\n");
vec = create(nullptr);
for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)i);
test("data integrity: size = 100", vec.size == 100);
for (int i = 0; i < 100; i++) {
test("data integrity: arr[i] = i", vec.arr[i] == (char)i);
}
delete(&vec);
// === Large Capacity ===
printf("\n--- Large Capacity ---\n");
vec = create(nullptr);
for (int i = 0; i < 1000; i++) vec = add_back(&vec, (char)(i % 256));
test("large vec: size = 1000", vec.size == 1000);
test("large vec: capacity >= size", vec.capacity >= 1000);
test("large vec: first preserved", vec.arr[0] == 0);
test("large vec: last preserved", vec.arr[999] == (char)(999 % 256));
delete(&vec);
// === NULL Safety ===
printf("\n--- 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);
// === Memory Leak Check (basic) ===
printf("\n--- Memory Leak Check ---\n");
for (int round = 0; round < 100; round++) {
vec = create(nullptr);
for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i);
delete(&vec);
}
test("100 create/delete cycles: no crash", 1);
// === Double Delete ===
printf("\n--- Double Delete Safety ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'T');
delete(&vec);
delete(&vec); // Should not crash
test("double delete: no crash", 1);
// === Delete Then Access ===
printf("\n--- Delete Then Access ---\n");
vec = create(nullptr);
vec = add_back(&vec, 'A');
vec = add_back(&vec, 'B');
delete(&vec);
test("after delete: at() returns error", at(&vec, 0) == -3);
test("after delete: front() returns error", front(&vec) == -3);
test("after delete: back() returns -3 (size still 2)", back(&vec) == -3);
// === Extreme Values ===
printf("\n--- Extreme Values ---\n");
vec = create(nullptr);
vec = add_back(&vec, 0);
vec = add_back(&vec, 127);
vec = add_back(&vec, -128);
test("extreme: zero preserved", vec.arr[0] == 0);
test("extreme: max char preserved", vec.arr[1] == 127);
test("extreme: min char preserved", vec.arr[2] == -128);
delete(&vec);
// === Rapid Small Operations ===
printf("\n--- Rapid Small Operations ---\n");
for (int round = 0; round < 10; round++) {
vec = create(nullptr);
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
test("rapid small: round preserves data",
vec.arr[0] == 'A' && vec.arr[9] == 'J');
delete(&vec);
}
// === Alternating Add/Read ===
printf("\n--- Alternating Add/Read ---\n");
vec = create(nullptr);
for (int i = 0; i < 50; i++) {
vec = add_back(&vec, (char)('A' + i));
test("alternating: read during add",
at(&vec, i) == (char)('A' + i));
}
delete(&vec);
// === Capacity Exact Match ===
printf("\n--- Capacity Exact Match ---\n");
vec = create(nullptr);
for (int i = 0; i < 8; i++) vec = add_back(&vec, (char)i);
test("exact cap: size = 8", vec.size == 8);
test("exact cap: capacity = 8", vec.capacity == 8);
vec = add_back(&vec, 'X');
test("exact cap +1: size = 9", vec.size == 9);
test("exact cap +1: capacity = 16", vec.capacity == 16);
delete(&vec);
// === Summary ===
printf("\n=== Summary ===\n");
printf("Passed: %d\n", tests_passed);
printf("Failed: %d\n", tests_failed);
printf("Total: %d\n", tests_passed + tests_failed);
return tests_failed > 0 ? 1 : 0;
}
-156
View File
@@ -1,156 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#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-151)
__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;
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--) {
vec->arr[i] = 0; // BUG: i starts at vec->size (out of bounds!)
}
vec->size -= diff;
return vec;
}
void test_single_erase() {
printf("=== Testing Single Erase ===\n");
Vec8_t vec = create(nullptr);
for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i);
printf("Before: ");
for (int i = 0; i < vec.size; i++) printf("%c ", vec.arr[i]);
printf("(size=%zu)\n", vec.size);
erase(&vec, 2); // Erase 'c'
printf("After erase(2): ");
for (int i = 0; i < vec.size; i++) printf("%c ", vec.arr[i]);
printf("(size=%zu)\n", vec.size);
assert(vec.size == 9);
assert(vec.arr[0] == 'a');
assert(vec.arr[1] == 'b');
assert(vec.arr[2] == 'd'); // Shifted left correctly
printf("Single erase: PASS\n\n");
delete(&vec);
}
void test_single_erase_large() {
printf("=== Testing 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); // Shifted correctly
printf("Large single erase: PASS\n\n");
delete(&vec);
}
void test_range_erase() {
printf("=== Testing Range Erase (exclusive end) ===\n");
Vec8_t vec = create(nullptr);
for (int i = 0; i < 10; i++) add_back(&vec, 'a' + i);
printf("Before: ");
for (int i = 0; i < vec.size; i++) printf("%c ", vec.arr[i]);
printf("(size=%zu)\n", vec.size);
erase(&vec, 2, 4); // Erase [2,4) -> indices 2,3 ('c','d')
printf("After erase(2,4): ");
for (int i = 0; i < vec.size; i++) printf("%c ", vec.arr[i]);
printf("(size=%zu)\n", vec.size);
// Expected: a b e f g h i j (size=8)
assert(vec.size == 8);
assert(vec.arr[0] == 'a');
assert(vec.arr[1] == 'b');
assert(vec.arr[2] == 'e'); // Shifted correctly
// Check zeroing bug (zeros wrong positions due to out-of-bounds access)
printf("Raw array: ");
for (int i = 0; i < 10; i++) printf("%c", vec.arr[i] == 0 ? '0' : vec.arr[i]);
printf("\n");
printf("Range erase: PASS (but zeroing loop has out-of-bounds bug)\n\n");
delete(&vec);
}
void test_range_erase_to_end() {
printf("=== Testing 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) -> indices 2-9
assert(res != nullptr);
assert(vec.size == 2);
assert(vec.arr[0] == 'a');
assert(vec.arr[1] == 'b');
printf("Erase to end: PASS\n\n");
delete(&vec);
}
int main() {
test_single_erase();
test_single_erase_large();
test_range_erase();
test_range_erase_to_end();
printf("All tests completed.\n");
return 0;
}
Binary file not shown.
-181
View File
@@ -1,181 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/resource.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(const Vec8_t* input) {
Vec8_t vec = { .arr = NULL, .size = 0, .capacity = 4 };
if (input == NULL) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != NULL) {
free(vec->arr);
}
vec->arr = NULL;
}
Vec8_t add_back(Vec8_t* vec, const char val) {
Vec8_t ret = { .arr = NULL, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
if (nvec.arr == NULL) {
return *vec;
}
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
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;
}
void get_memory_usage(size_t* used, size_t* peak) {
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
*used = ru.ru_maxrss * 1024;
*peak = ru.ru_maxrss * 1024;
}
int main() {
printf("=== FULL STRESS TEST: add_back only ===\n\n");
struct timespec start, end_t;
Vec8_t vec;
size_t max_elements = 0;
int crashed = 0;
printf("=== TEST 1: MAX ELEMENTS BEFORE CRASH ===\n\n");
vec = create(NULL);
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < SIZE_MAX; i++) {
vec = add_back(&vec, (char)(i % 256));
if (vec.arr == NULL) {
max_elements = i;
crashed = 1;
break;
}
if (i % 100000000 == 0) {
printf(" %zu elements: capacity %zu (%.2f GB)\n",
i + 1, vec.capacity, (double)(vec.capacity * sizeof(char)) / 1024 / 1024 / 1024);
}
if (i >= 1000000000) {
printf(" stopping at 1 billion elements\n");
max_elements = 1000000000;
break;
}
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
if (!crashed && vec.arr != NULL) {
max_elements = vec.size;
}
printf("\nRESULT: %zu elements\n", max_elements);
printf("capacity: %zu\n", vec.capacity);
printf("memory: %.2f GB\n", (double)(vec.capacity * sizeof(char)) / 1024 / 1024 / 1024);
printf("time: %.2f sec\n", time_diff(start, end_t));
delete(&vec);
printf("\n=== TEST 2: DIRECT MALLOCATION LIMIT ===\n\n");
const size_t test_sizes[] = {1000000, 10000000, 100000000, 500000000, 1000000000};
int num_tests = 5;
for (int t = 0; t < num_tests; t++) {
size_t n = test_sizes[t];
printf("Testing %zu elements (%.2f GB)...\n",
n, (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
char* test_arr = calloc(n, sizeof(char));
if (test_arr == NULL) {
printf(" FAILED at %zu\n", n);
break;
}
printf(" SUCCESS\n");
free(test_arr);
}
printf("\n=== TEST 3: SINGLE VECTOR ALLOCATION ===\n\n");
size_t single_max = 0;
for (size_t n = 1000000; n <= 5000000000UL; n *= 2) {
printf("Trying %.2f GB allocation...\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
Vec8_t test_vec = create(NULL);
Vec8_t* vp = calloc(1, sizeof(Vec8_t));
vp->arr = calloc(n, sizeof(char));
if (vp->arr == NULL) {
printf(" FAILED at %.2f GB\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
single_max = n / 2;
free(vp);
break;
}
printf(" SUCCESS: %.2f GB\n", (double)(n * sizeof(char)) / 1024 / 1024 / 1024);
free(vp->arr);
free(vp);
delete(&test_vec);
single_max = n;
}
printf("\n=== TEST 4: SPEED AT SCALE ===\n\n");
vec = create(NULL);
clock_gettime(CLOCK_MONOTONIC, &start);
for (size_t i = 0; i < 10000000; i++) {
vec = add_back(&vec, (char)(i % 256));
}
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t10m = time_diff(start, end_t);
printf("10M elements:\n");
printf(" time: %.2f sec\n", t10m);
printf(" rate: %.0f/sec\n", 10000000.0 / t10m);
printf(" memory: %.2f MB\n", (vec.capacity * sizeof(char)) / 1024.0 / 1024.0);
delete(&vec);
printf("\n=== SUMMARY ===\n\n");
printf("Max elements (vector): %zu\n", max_elements);
printf("Single allocation max: %zu (%.2f GB)\n",
single_max, (double)(single_max * sizeof(char)) / 1024 / 1024 / 1024);
return 0;
}
BIN
View File
Binary file not shown.
-191
View File
@@ -1,191 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct {
char* arr;
size_t size;
size_t capacity;
} Vec8_t;
Vec8_t create(Vec8_t* input) {
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
if(input == nullptr) {
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
if (input->size > 0) {
vec.size = input->size + 1;
}
if (input->capacity >= vec.capacity) {
vec.capacity = 2 * input->capacity;
}
vec.arr = calloc(vec.capacity, sizeof(char));
return vec;
}
void delete(Vec8_t* vec) {
if (vec->arr != nullptr) free(vec->arr);
vec->arr = nullptr;
}
char at(Vec8_t* vec, 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;
}
int begin(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
return -1;
}
int end(Vec8_t* vec) {
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
return -1;
}
char front(Vec8_t* vec) {
return at(vec, 0);
}
char back(Vec8_t* vec) {
if (vec) return at(vec, (int)vec->size - 1);
return -1;
}
Vec8_t add_back(Vec8_t* vec, char val) {
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
if (vec->size < vec->capacity) {
vec->arr[vec->size] = val;
vec->size++;
return *vec;
}
if (vec->size >= vec->capacity) {
Vec8_t nvec = create(vec);
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
nvec.arr[vec->size] = val;
}
free(vec->arr);
return nvec;
}
return ret;
}
int tests_passed = 0;
int tests_failed = 0;
void test(const char* name, int passed) {
if (passed) { printf("[PASS] %s\n", name); tests_passed++; }
else { printf("[FAIL] %s\n", 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;
}
int main() {
printf("=== Stress Testing libvec (doubling) ===\n\n");
struct timespec start, end_t;
Vec8_t vec;
printf("--- Basic correctness ---\n");
vec = create(nullptr);
test("create nullptr: capacity = 4", vec.capacity == 4);
test("create nullptr: size = 0", vec.size == 0);
vec = add_back(&vec, 'a');
test("add_back 1: size = 1", vec.size == 1);
test("add_back 1: capacity = 4", vec.capacity == 4);
vec = add_back(&vec, 'b');
test("add_back 2: size = 2", vec.size == 2);
vec = add_back(&vec, 'c');
test("add_back 3: size = 3", vec.size == 3);
vec = add_back(&vec, 'd');
test("add_back 4: size = 4", vec.size == 4);
vec = add_back(&vec, 'e');
test("add_back 5: capacity = 8 (doubled)", vec.capacity == 8);
test("add_back 5: arr[4] = 'e'", vec.arr[4] == 'e');
delete(&vec);
printf("\n--- NULL safety ---\n");
test("at(nullptr) returns -2", at(nullptr, 0) == -2);
test("front(nullptr) returns -2", front(nullptr) == -2);
test("back(nullptr) returns -1", back(nullptr) == -1);
test("begin(nullptr) == -1", begin(nullptr) == -1);
test("end(nullptr) == -1", end(nullptr) == -1);
printf("\n--- Capacity growth pattern ---\n");
vec = create(nullptr);
size_t prev_cap = vec.capacity;
printf(" cap=%zu", vec.capacity);
for (int i = 1; i <= 100; i++) {
vec = add_back(&vec, (char)i);
if (vec.capacity != prev_cap) {
printf(" -> %zu (at size %d)", vec.capacity, i);
prev_cap = vec.capacity;
}
}
printf("\n");
test("final capacity = 128", vec.capacity == 128);
delete(&vec);
printf("\n--- 1M add_back ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 1000000; i++) vec = add_back(&vec, (char)i);
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t1 = time_diff(start, end_t);
printf(" Time: %.3f sec (%.0f/sec)\n", t1, 1000000.0/t1);
test("1M: size correct", vec.size == 1000000);
test("1M: data correct", vec.arr[0] == 0 && vec.arr[999999] == (char)999999);
delete(&vec);
printf("\n--- 10M add_back ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 10000000; i++) vec = add_back(&vec, (char)i);
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t10 = time_diff(start, end_t);
printf(" Time: %.3f sec (%.0f/sec)\n", t10, 10000000.0/t10);
test("10M: size correct", vec.size == 10000000);
test("10M: data correct", vec.arr[0] == 0 && vec.arr[9999999] == (char)(9999999 % 256));
delete(&vec);
printf("\n--- 100M add_back ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 100000000; i++) vec = add_back(&vec, (char)i);
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t100 = time_diff(start, end_t);
printf(" Time: %.3f sec (%.0f/sec)\n", t100, 100000000.0/t100);
test("100M: size correct", vec.size == 100000000);
test("100M: data correct", vec.arr[0] == 0 && vec.arr[99999999] == (char)(99999999 % 256));
delete(&vec);
printf("\n--- 1B add_back ---\n");
vec = create(nullptr);
clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < 1000000000; i++) vec = add_back(&vec, (char)i);
clock_gettime(CLOCK_MONOTONIC, &end_t);
double t1b = time_diff(start, end_t);
printf(" Time: %.3f sec (%.0f/sec)\n", t1b, 1000000000.0/t1b);
test("1B: size correct", vec.size == 1000000000);
test("1B: data correct", vec.arr[0] == 0 && vec.arr[999999999] == (char)(999999999 % 256));
delete(&vec);
printf("\n=== Summary ===\n");
printf("Passed: %d, Failed: %d\n", tests_passed, tests_failed);
return tests_failed > 0 ? 1 : 0;
}