removed push_front because I realized how much I dont need it I also made safer checks and used more tests
This commit is contained in:
+4
-18
@@ -146,11 +146,6 @@ back(const Vec8_t* vec)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a Vector
|
|
||||||
* if below capacity
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* */
|
|
||||||
Vec8_t
|
Vec8_t
|
||||||
add_back(Vec8_t* vec, const char val)
|
add_back(Vec8_t* vec, const char val)
|
||||||
{
|
{
|
||||||
@@ -165,6 +160,10 @@ add_back(Vec8_t* vec, const char val)
|
|||||||
if (vec->size >= vec->capacity)
|
if (vec->size >= vec->capacity)
|
||||||
{
|
{
|
||||||
Vec8_t nvec = create(vec);
|
Vec8_t nvec = create(vec);
|
||||||
|
if(nvec.arr == nullptr) {
|
||||||
|
printf("Malloc failed and returned nullptr: Returning old vector");
|
||||||
|
return *vec;
|
||||||
|
}
|
||||||
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
|
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
|
||||||
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size))
|
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size))
|
||||||
{
|
{
|
||||||
@@ -176,18 +175,6 @@ add_back(Vec8_t* vec, const char val)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vec8_t
|
|
||||||
// add_front(Vec8_t* vec, char val)
|
|
||||||
// {
|
|
||||||
// Vec8_t nvec = create(vec->size + 1);
|
|
||||||
// memcpy(&nvec.arr[1], &vec->arr[0], vec->size * sizeof(char));
|
|
||||||
// if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size))
|
|
||||||
// {
|
|
||||||
// nvec.arr[0] = val;
|
|
||||||
// }
|
|
||||||
// return nvec;
|
|
||||||
// }
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@@ -196,7 +183,6 @@ main()
|
|||||||
vec = add_back(&vec, '4');
|
vec = add_back(&vec, '4');
|
||||||
vec = add_back(&vec, '5');
|
vec = add_back(&vec, '5');
|
||||||
vec = add_back(&vec, '6');
|
vec = add_back(&vec, '6');
|
||||||
vec = add_back(&vec, '7');
|
|
||||||
print_vec(&vec);
|
print_vec(&vec);
|
||||||
// vec = add_back(&vec, '6');
|
// vec = add_back(&vec, '6');
|
||||||
// vec = add_front(&vec, 'c');
|
// vec = add_front(&vec, 'c');
|
||||||
|
|||||||
Binary file not shown.
+52
-134
@@ -10,9 +10,9 @@ typedef struct {
|
|||||||
size_t capacity;
|
size_t capacity;
|
||||||
} Vec8_t;
|
} Vec8_t;
|
||||||
|
|
||||||
Vec8_t create(Vec8_t* input) {
|
Vec8_t create(const Vec8_t* input) {
|
||||||
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
|
Vec8_t vec = { .arr = nullptr, .size = 0, .capacity = 4 };
|
||||||
if(input == nullptr) {
|
if (input == nullptr) {
|
||||||
vec.arr = calloc(vec.capacity, sizeof(char));
|
vec.arr = calloc(vec.capacity, sizeof(char));
|
||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ void delete(Vec8_t* vec) {
|
|||||||
vec->arr = nullptr;
|
vec->arr = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char at(Vec8_t* vec, int idx) {
|
char at(const Vec8_t* vec, const int idx) {
|
||||||
if (vec == nullptr) return -2;
|
if (vec == nullptr) return -2;
|
||||||
if (vec->arr == nullptr) return -3;
|
if (vec->arr == nullptr) return -3;
|
||||||
if (vec->size <= idx) return -4;
|
if (vec->size <= idx) return -4;
|
||||||
@@ -41,26 +41,26 @@ char at(Vec8_t* vec, int idx) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int begin(Vec8_t* vec) {
|
int begin(const Vec8_t* vec) {
|
||||||
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
|
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int end(Vec8_t* vec) {
|
int end(const Vec8_t* vec) {
|
||||||
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
|
if (vec != nullptr && vec->arr != nullptr && vec->size > 0) return (int)(vec->size - 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char front(Vec8_t* vec) {
|
char front(const Vec8_t* vec) {
|
||||||
return at(vec, 0);
|
return at(vec, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char back(Vec8_t* vec) {
|
char back(const Vec8_t* vec) {
|
||||||
if (vec) return at(vec, (int)vec->size - 1);
|
if (vec) return at(vec, (int)vec->size - 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vec8_t add_back(Vec8_t* vec, char val) {
|
Vec8_t add_back(Vec8_t* vec, const char val) {
|
||||||
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
|
Vec8_t ret = { .arr = nullptr, .capacity = 0, .size = 0 };
|
||||||
if (vec->size < vec->capacity) {
|
if (vec->size < vec->capacity) {
|
||||||
vec->arr[vec->size] = val;
|
vec->arr[vec->size] = val;
|
||||||
@@ -69,6 +69,10 @@ Vec8_t add_back(Vec8_t* vec, char val) {
|
|||||||
}
|
}
|
||||||
if (vec->size >= vec->capacity) {
|
if (vec->size >= vec->capacity) {
|
||||||
Vec8_t nvec = create(vec);
|
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));
|
memcpy(&nvec.arr[0], &vec->arr[0], vec->size * sizeof(char));
|
||||||
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
|
if (nvec.arr && (nvec.size > 0 || nvec.size > vec->size)) {
|
||||||
nvec.arr[vec->size] = val;
|
nvec.arr[vec->size] = val;
|
||||||
@@ -100,218 +104,132 @@ int main() {
|
|||||||
Vec8_t vec;
|
Vec8_t vec;
|
||||||
char* ptr;
|
char* ptr;
|
||||||
|
|
||||||
// === Test 1: Use after reallocation (expected behavior) ===
|
|
||||||
printf("--- Reallocation Behavior ---\n");
|
printf("--- Reallocation Behavior ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
|
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
|
||||||
ptr = vec.arr; // save pointer (will be freed on next realloc)
|
ptr = vec.arr;
|
||||||
|
|
||||||
for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)('0' + (i % 10)));
|
for (int i = 0; i < 100; i++) vec = add_back(&vec, (char)('0' + (i % 10)));
|
||||||
|
|
||||||
// Pointer changes after reallocation - this is expected
|
|
||||||
test("after reallocation, vec.arr is new", ptr != vec.arr);
|
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("data preserved in new vec", vec.arr[0] == 'A' && vec.arr[9] == 'J');
|
||||||
test("vec must be reassigned: vec = add_back()", 1);
|
test("vec must be reassigned: vec = add_back()", 1);
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
|
|
||||||
// === Test 2: Stack-allocated struct (not created via create) ===
|
|
||||||
printf("\n--- Stack-Allocated Struct ---\n");
|
printf("\n--- Stack-Allocated Struct ---\n");
|
||||||
|
vec.arr = nullptr;
|
||||||
Vec8_t stack_vec;
|
|
||||||
stack_vec.arr = nullptr;
|
|
||||||
stack_vec.size = 0;
|
|
||||||
stack_vec.capacity = 0;
|
|
||||||
|
|
||||||
// This will fail because capacity starts at 0, not 4
|
|
||||||
// and there's no way to use add_back properly
|
|
||||||
// BUG: User can't easily use functions without calling create()
|
|
||||||
test("stack vec: add_back modifies nothing (capacity 0)", 1); // informational
|
|
||||||
|
|
||||||
// === Test 3: Integer overflow potential ===
|
|
||||||
printf("\n--- Integer Overflow ---\n");
|
|
||||||
|
|
||||||
// If someone passes SIZE_MAX or near-max to create
|
|
||||||
// The doubling could overflow
|
|
||||||
vec = create(nullptr);
|
|
||||||
vec.capacity = (size_t)-1; // max size_t
|
|
||||||
vec.size = 0;
|
vec.size = 0;
|
||||||
vec.arr = calloc(1, 1); // tiny allocation
|
vec.capacity = 0;
|
||||||
|
test("stack vec: add_back modifies nothing (capacity 0)", 1);
|
||||||
|
|
||||||
// BUG: 2 * capacity overflows to 0
|
printf("\n--- Integer Overflow ---\n");
|
||||||
size_t doubled = 2 * vec.capacity;
|
size_t doubled = 2 * (size_t)-1;
|
||||||
test("2 * SIZE_MAX overflows (demonstrates overflow)", 1); // informational
|
test("2 * SIZE_MAX overflows (demonstrates overflow)", 1);
|
||||||
|
|
||||||
free(vec.arr);
|
|
||||||
|
|
||||||
// === Test 4: Negative index with signed int ===
|
|
||||||
printf("\n--- Signed/Unsigned Mixing ---\n");
|
printf("\n--- Signed/Unsigned Mixing ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
vec = add_back(&vec, 'X');
|
vec = add_back(&vec, 'X');
|
||||||
|
test("at() with negative -1 returns error", at(&vec, -1) == -4);
|
||||||
int neg_idx = -1;
|
test("at() with INT_MIN returns error", at(&vec, -2147483648) == -4);
|
||||||
// BUG: -1 as unsigned is huge, causing out-of-bounds access
|
|
||||||
char result = at(&vec, neg_idx);
|
|
||||||
test("at() with negative -1 returns error", result == -4);
|
|
||||||
|
|
||||||
neg_idx = -2147483648;
|
|
||||||
result = at(&vec, neg_idx);
|
|
||||||
test("at() with INT_MIN returns error", result == -4);
|
|
||||||
|
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
|
|
||||||
// === Test 5: Size very large ===
|
|
||||||
printf("\n--- Huge Size Values ---\n");
|
printf("\n--- Huge Size Values ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
|
||||||
vec.size = 1000000; // manually corrupt size (bad user code)
|
|
||||||
vec.capacity = 4;
|
|
||||||
vec.arr = calloc(4, 1);
|
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);
|
||||||
|
|
||||||
// BUG: size > capacity, add_back will try to create with size+1 = 1000001
|
|
||||||
// which allocates based on old logic
|
|
||||||
result = at(&vec, 0);
|
|
||||||
// Should still work for valid indices within actual capacity
|
|
||||||
test("at() works for valid idx despite bad size", result == 0);
|
|
||||||
|
|
||||||
delete(&vec);
|
|
||||||
|
|
||||||
// === Test 6: Uninitialized struct ===
|
|
||||||
printf("\n--- Uninitialized Struct ---\n");
|
printf("\n--- Uninitialized Struct ---\n");
|
||||||
|
|
||||||
Vec8_t uninit;
|
Vec8_t uninit;
|
||||||
// BUG: arr, size, capacity contain garbage
|
|
||||||
// Any function call is undefined behavior
|
|
||||||
printf(" Calling at() on uninitialized struct...\n");
|
printf(" Calling at() on uninitialized struct...\n");
|
||||||
printf(" This is undefined behavior - results unpredictable!\n");
|
printf(" This is undefined behavior - results unpredictable!\n");
|
||||||
test("uninitialized: expect garbage or crash (UB)", 1); // informational
|
test("uninitialized: expect garbage or crash (UB)", 1);
|
||||||
|
|
||||||
// === Test 7: Capacity not matching allocation ===
|
|
||||||
printf("\n--- Capacity Mismatch ---\n");
|
printf("\n--- Capacity Mismatch ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
vec.arr = realloc(vec.arr, 1000); // manually grow
|
vec.arr = realloc(vec.arr, 1000);
|
||||||
vec.capacity = 1000; // but don't tell anyone
|
vec.capacity = 1000;
|
||||||
|
|
||||||
for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i);
|
for (int i = 0; i < 50; i++) vec = add_back(&vec, (char)i);
|
||||||
test("manual realloc: capacity grows (add_back doesn't know)", 1); // informational
|
test("manual realloc: capacity grows (add_back doesn't know)", 1);
|
||||||
|
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
|
|
||||||
// === Test 8: memcpy with null ===
|
|
||||||
printf("\n--- Memcpy Edge Cases ---\n");
|
printf("\n--- Memcpy Edge Cases ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
vec.size = 0;
|
|
||||||
// BUG: memcpy(&vec.arr[0], &vec.arr[0], 0) - this is actually fine (no-op)
|
|
||||||
for (int i = 0; i < 5; i++) vec = add_back(&vec, (char)('A' + i));
|
for (int i = 0; i < 5; i++) vec = add_back(&vec, (char)('A' + i));
|
||||||
test("empty memcpy edge case: works fine", vec.size == 5);
|
test("empty memcpy edge case: works fine", vec.size == 5);
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
|
|
||||||
// === Test 9: Return value ignored ===
|
|
||||||
printf("\n--- Ignored Return Values ---\n");
|
printf("\n--- Ignored Return Values ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
add_back(&vec, 'X'); // Modifies in-place when capacity available
|
add_back(&vec, 'X');
|
||||||
test("add_back modifies in-place when capacity available", vec.size == 1);
|
test("add_back modifies in-place when capacity available", vec.size == 1);
|
||||||
test("data stored correctly", vec.arr[0] == 'X');
|
test("data stored correctly", vec.arr[0] == 'X');
|
||||||
|
|
||||||
// Fill to capacity (4): size goes 1->4
|
|
||||||
for (int i = 0; i < 3; i++) vec = add_back(&vec, (char)('A' + i));
|
for (int i = 0; i < 3; i++) vec = add_back(&vec, (char)('A' + i));
|
||||||
// Now size=4, cap=4
|
|
||||||
|
|
||||||
// Add more: this triggers reallocation (size >= capacity)
|
|
||||||
char* old_ptr = vec.arr;
|
char* old_ptr = vec.arr;
|
||||||
vec = add_back(&vec, 'Z'); // reallocates! size becomes 5, cap becomes 8
|
vec = add_back(&vec, 'Z');
|
||||||
test("reallocation triggered", old_ptr != vec.arr);
|
test("reallocation triggered", old_ptr != vec.arr);
|
||||||
test("realloc: data preserved in new vec", vec.arr[4] == 'Z');
|
test("realloc: data preserved in new vec", vec.arr[4] == 'Z');
|
||||||
delete(&vec);
|
|
||||||
|
|
||||||
// === Test 10: Multiple vectors, aliasing ===
|
|
||||||
printf("\n--- Aliasing Issues ---\n");
|
printf("\n--- Aliasing Issues ---\n");
|
||||||
|
|
||||||
Vec8_t v1 = create(nullptr);
|
Vec8_t v1 = create(nullptr);
|
||||||
Vec8_t v2 = 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++) v1 = add_back(&v1, (char)('A' + i));
|
||||||
for (int i = 0; i < 5; i++) v2 = add_back(&v2, (char)('1' + 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 and v2 are separate", v1.arr != v2.arr);
|
||||||
test("v1 data correct", v1.arr[0] == 'A');
|
test("v1 data correct", v1.arr[0] == 'A');
|
||||||
test("v2 data correct", v2.arr[0] == '1');
|
test("v2 data correct", v2.arr[0] == '1');
|
||||||
|
|
||||||
delete(&v1);
|
delete(&v1);
|
||||||
delete(&v2);
|
delete(&v2);
|
||||||
|
|
||||||
// === Test 11: Freeing already-freed memory ===
|
|
||||||
printf("\n--- Double Free ---\n");
|
printf("\n--- Double Free ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
vec = add_back(&vec, 'X');
|
vec = add_back(&vec, 'X');
|
||||||
char* data = vec.arr;
|
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
free(data); // BUG: double free!
|
delete(&vec);
|
||||||
printf(" Double free detected (would crash with sanitizers)\n");
|
test("double delete: no crash", 1);
|
||||||
test("double free: undefined behavior", 1); // informational
|
|
||||||
|
|
||||||
// === Test 12: Realloc failure ===
|
printf("\n--- Malloc Failure Check ---\n");
|
||||||
printf("\n--- Realloc Failure ---\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);
|
||||||
|
|
||||||
// Hard to test without mocking, but conceptually:
|
|
||||||
// If malloc/calloc fails, the library doesn't check
|
|
||||||
// BUG: nvec.arr could be NULL, then memcpy with NULL crashes
|
|
||||||
printf(" If realloc fails: nvec.arr is NULL, memcpy crashes\n");
|
|
||||||
test("no malloc failure check in create()", 1); // informational
|
|
||||||
|
|
||||||
// === Test 13: Reading freed memory ===
|
|
||||||
printf("\n--- Use After Delete ---\n");
|
printf("\n--- Use After Delete ---\n");
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)i);
|
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)i);
|
||||||
delete(&vec);
|
delete(&vec);
|
||||||
|
|
||||||
// BUG: vec.arr is nullptr, vec.size is still 10
|
|
||||||
// User might expect size to be 0 after delete
|
|
||||||
test("after delete: arr is null", vec.arr == nullptr);
|
test("after delete: arr is null", vec.arr == nullptr);
|
||||||
test("after delete: size is still 10 (not cleared)", vec.size == 10);
|
test("after delete: size is still 10 (not cleared)", vec.size == 10);
|
||||||
test("after delete: accessing returns error", at(&vec, 0) == -3);
|
test("after delete: accessing returns error", at(&vec, 0) == -3);
|
||||||
|
|
||||||
// === Test 14: Size 0 with capacity 0 ===
|
|
||||||
printf("\n--- Size/Capacity Edge ---\n");
|
printf("\n--- Size/Capacity Edge ---\n");
|
||||||
|
|
||||||
vec.arr = malloc(100);
|
vec.arr = malloc(100);
|
||||||
vec.size = 0;
|
vec.size = 0;
|
||||||
vec.capacity = 100;
|
vec.capacity = 100;
|
||||||
|
|
||||||
// BUG: begin() checks size > 0, so returns -1 even though we have capacity
|
|
||||||
test("begin() returns -1 when size=0", begin(&vec) == -1);
|
test("begin() returns -1 when size=0", begin(&vec) == -1);
|
||||||
test("end() returns -1 when size=0", end(&vec) == -1);
|
test("end() returns -1 when size=0", end(&vec) == -1);
|
||||||
test("front() returns -4 when size=0", front(&vec) == -4);
|
test("front() returns -4 when size=0", front(&vec) == -4);
|
||||||
test("back() returns -4 when size=0", back(&vec) == -4);
|
test("back() returns -4 when size=0", back(&vec) == -4);
|
||||||
|
|
||||||
free(vec.arr);
|
free(vec.arr);
|
||||||
|
|
||||||
// === Test 15: Concurrent modification (conceptual) ===
|
printf("\n--- const Correctness ---\n");
|
||||||
printf("\n--- Iterator Invalidation Concept ---\n");
|
|
||||||
|
|
||||||
vec = create(nullptr);
|
vec = create(nullptr);
|
||||||
for (int i = 0; i < 10; i++) vec = add_back(&vec, (char)('A' + i));
|
vec = add_back(&vec, 'C');
|
||||||
|
const Vec8_t* const_vec = &vec;
|
||||||
// If user iterates while adding:
|
test("const vec: at() works", at(const_vec, 0) == 'C');
|
||||||
// for (int i = 0; i < 1000; i++) {
|
test("const vec: front() works", front(const_vec) == 'C');
|
||||||
// if (i == 10) vec = add_back(&vec, 'Z'); // reallocation!
|
test("const vec: back() works", back(const_vec) == 'C');
|
||||||
// use vec.arr[i]; // BUG: pointer invalid after realloc
|
test("const vec: begin() works", begin(const_vec) == 0);
|
||||||
// }
|
test("const vec: end() works", end(const_vec) == 0);
|
||||||
printf(" Iteration + reallocation invalidates pointers\n");
|
delete(&vec);
|
||||||
test("conceptual: iteration during add_back is unsafe", 1);
|
|
||||||
|
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);
|
delete(&vec);
|
||||||
|
|
||||||
// === Summary ===
|
|
||||||
printf("\n=== Summary ===\n");
|
printf("\n=== Summary ===\n");
|
||||||
printf("Passed: %d\n", tests_passed);
|
printf("Passed: %d\n", tests_passed);
|
||||||
printf("Failed: %d\n", tests_failed);
|
printf("Failed: %d\n", tests_failed);
|
||||||
printf("Note: 'informational' tests always pass, real bugs above\n");
|
|
||||||
|
|
||||||
return 0;
|
return tests_failed > 0 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user