improve dynamic arrays
This commit is contained in:
+227
-2
@@ -1,9 +1,23 @@
|
||||
#include <criterion/criterion.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "cig.h"
|
||||
|
||||
static int int_cmp(const void *a, const void *b) {
|
||||
int ia = *(const int*)a;
|
||||
int ib = *(const int*)b;
|
||||
if (ia < ib) return -1;
|
||||
if (ia > ib) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool int_eq(const void *a, const void *b) {
|
||||
return *(const int*)a == *(const int*)b;
|
||||
}
|
||||
|
||||
static int reverse_cmp(const void *a, const void *b) {
|
||||
return -int_cmp(a, b);
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, append) {
|
||||
with_borrow(alloc) {
|
||||
int *numbers = make_arr(alloc, int);
|
||||
@@ -68,3 +82,214 @@ Test(dynamic_arrays, contains) {
|
||||
cr_assert_eq(arr_len(numbers), 100);
|
||||
}
|
||||
}
|
||||
Test(dynamic_arrays, insert_sorted_ascending) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
// Insert in random order
|
||||
arr_insert_sorted(arr, 5, int_cmp);
|
||||
arr_insert_sorted(arr, 2, int_cmp);
|
||||
arr_insert_sorted(arr, 8, int_cmp);
|
||||
arr_insert_sorted(arr, 1, int_cmp);
|
||||
arr_insert_sorted(arr, 9, int_cmp);
|
||||
arr_insert_sorted(arr, 3, int_cmp);
|
||||
|
||||
// Verify sorted order
|
||||
cr_assert_eq(arr_len(arr), 6);
|
||||
cr_assert_eq(arr[0], 1);
|
||||
cr_assert_eq(arr[1], 2);
|
||||
cr_assert_eq(arr[2], 3);
|
||||
cr_assert_eq(arr[3], 5);
|
||||
cr_assert_eq(arr[4], 8);
|
||||
cr_assert_eq(arr[5], 9);
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, insert_sorted_descending) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
// Insert in random order with reverse comparison
|
||||
arr_insert_sorted(arr, 5, reverse_cmp);
|
||||
arr_insert_sorted(arr, 2, reverse_cmp);
|
||||
arr_insert_sorted(arr, 8, reverse_cmp);
|
||||
arr_insert_sorted(arr, 1, reverse_cmp);
|
||||
|
||||
// Verify descending order
|
||||
cr_assert_eq(arr_len(arr), 4);
|
||||
cr_assert_eq(arr[0], 8);
|
||||
cr_assert_eq(arr[1], 5);
|
||||
cr_assert_eq(arr[2], 2);
|
||||
cr_assert_eq(arr[3], 1);
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, insert_sorted_duplicates) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
// Insert duplicates
|
||||
arr_insert_sorted(arr, 5, int_cmp);
|
||||
arr_insert_sorted(arr, 3, int_cmp);
|
||||
arr_insert_sorted(arr, 5, int_cmp);
|
||||
arr_insert_sorted(arr, 3, int_cmp);
|
||||
arr_insert_sorted(arr, 5, int_cmp);
|
||||
|
||||
// Verify all elements are present
|
||||
cr_assert_eq(arr_len(arr), 5);
|
||||
cr_assert_eq(arr[0], 3);
|
||||
cr_assert_eq(arr[1], 3);
|
||||
cr_assert_eq(arr[2], 5);
|
||||
cr_assert_eq(arr[3], 5);
|
||||
cr_assert_eq(arr[4], 5);
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_found) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
arr_append(arr, 10);
|
||||
arr_append(arr, 20);
|
||||
arr_append(arr, 30);
|
||||
|
||||
cr_assert(arr_contains(arr, &(int){10}));
|
||||
cr_assert(arr_contains(arr, &(int){20}));
|
||||
cr_assert(arr_contains(arr, &(int){30}));
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_not_found) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
arr_append(arr, 10);
|
||||
arr_append(arr, 20);
|
||||
arr_append(arr, 30);
|
||||
|
||||
cr_assert_not(arr_contains(arr, &(int){5}));
|
||||
cr_assert_not(arr_contains(arr, &(int){15}));
|
||||
cr_assert_not(arr_contains(arr, &(int){99}));
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_empty) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
cr_assert_not(arr_contains(arr, &(int){10}));
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, insert_sorted_single_element) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
arr_insert_sorted(arr, 42, int_cmp);
|
||||
|
||||
cr_assert_eq(arr_len(arr), 1);
|
||||
cr_assert_eq(arr[0], 42);
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, insert_sorted_already_sorted) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
// Insert in already sorted order
|
||||
arr_insert_sorted(arr, 1, int_cmp);
|
||||
arr_insert_sorted(arr, 2, int_cmp);
|
||||
arr_insert_sorted(arr, 3, int_cmp);
|
||||
arr_insert_sorted(arr, 4, int_cmp);
|
||||
|
||||
// Verify order maintained
|
||||
cr_assert_eq(arr_len(arr), 4);
|
||||
for (size_t i = 0; i < arr_len(arr); i++) {
|
||||
cr_assert_eq(arr[i], (int)(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, insert_sorted_reverse_order) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
// Insert in reverse order (worst case for bubble sort)
|
||||
arr_insert_sorted(arr, 5, int_cmp);
|
||||
arr_insert_sorted(arr, 4, int_cmp);
|
||||
arr_insert_sorted(arr, 3, int_cmp);
|
||||
arr_insert_sorted(arr, 2, int_cmp);
|
||||
arr_insert_sorted(arr, 1, int_cmp);
|
||||
|
||||
// Verify correct ascending order
|
||||
cr_assert_eq(arr_len(arr), 5);
|
||||
for (size_t i = 0; i < arr_len(arr); i++) {
|
||||
cr_assert_eq(arr[i], (int)(i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_cmp_found) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
arr_append(arr, 10);
|
||||
arr_append(arr, 20);
|
||||
arr_append(arr, 30);
|
||||
|
||||
cr_assert(arr_contains_cmp(arr, int_eq, &(int){10}));
|
||||
cr_assert(arr_contains_cmp(arr, int_eq, &(int){20}));
|
||||
cr_assert(arr_contains_cmp(arr, int_eq, &(int){30}));
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_cmp_not_found) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
arr_append(arr, 10);
|
||||
arr_append(arr, 20);
|
||||
arr_append(arr, 30);
|
||||
|
||||
cr_assert_not(arr_contains_cmp(arr, int_eq, &(int){5}));
|
||||
cr_assert_not(arr_contains_cmp(arr, int_eq, &(int){15}));
|
||||
cr_assert_not(arr_contains_cmp(arr, int_eq, &(int){99}));
|
||||
}
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_cmp_empty) {
|
||||
with_borrow(alloc) {
|
||||
int *arr = make_arr(alloc, int, .initial_capacity = 5);
|
||||
|
||||
cr_assert_not(arr_contains_cmp(arr, int_eq, &(int){10}));
|
||||
}
|
||||
}
|
||||
|
||||
// Test using arr_contains_cmp for a simple key-value map
|
||||
typedef struct {
|
||||
int key;
|
||||
const char *value;
|
||||
} kv_pair_t;
|
||||
|
||||
static bool kv_eq_by_key(const void *a, const void *b) {
|
||||
const kv_pair_t *pa = a;
|
||||
const kv_pair_t *pb = b;
|
||||
return pa->key == pb->key;
|
||||
}
|
||||
|
||||
Test(dynamic_arrays, contains_cmp_key_value_map) {
|
||||
with_borrow(alloc) {
|
||||
kv_pair_t *map = make_arr(alloc, kv_pair_t, .initial_capacity = 10);
|
||||
|
||||
// Add some key-value pairs
|
||||
arr_append(map, ((kv_pair_t){.key = 1, .value = "one"}));
|
||||
arr_append(map, ((kv_pair_t){.key = 5, .value = "five"}));
|
||||
arr_append(map, ((kv_pair_t){.key = 10, .value = "ten"}));
|
||||
|
||||
// Check if keys exist
|
||||
cr_assert(arr_contains_cmp(map, kv_eq_by_key, &(kv_pair_t){.key = 1}));
|
||||
cr_assert(arr_contains_cmp(map, kv_eq_by_key, &(kv_pair_t){.key = 5}));
|
||||
cr_assert(arr_contains_cmp(map, kv_eq_by_key, &(kv_pair_t){.key = 10}));
|
||||
|
||||
// Check for non-existent keys
|
||||
cr_assert_not(arr_contains_cmp(map, kv_eq_by_key, &(kv_pair_t){.key = 2}));
|
||||
cr_assert_not(arr_contains_cmp(map, kv_eq_by_key, &(kv_pair_t){.key = 99}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user