#include #include #include #include #include #include #include "tap.h" #include "array.h" #include "util.h" typedef struct { char key[64]; int value; } Item; static int values[] = { 2, 3, 5, 7, 11 }; static const size_t len = LENGTH(values); static bool item_compare(Item *a, Item *b) { return strcmp(a->key, b->key) == 0 && a->value == b->value; } static void test_small_objects(void) { Array arr; array_init_sized(&arr, sizeof(int)); ok(array_length(&arr) == 0, "Initialization"); ok(!array_set(&arr, 0, NULL) && errno == EINVAL, "Set with invalid index"); ok(array_get(&arr, 0) == NULL && errno == EINVAL, "Get with invalid index"); ok(array_peek(&arr) == NULL && array_length(&arr) == 0, "Peek empty array"); ok(array_pop(&arr) == NULL && array_length(&arr) == 0, "Pop empty array"); for (size_t i = 0; i < len; i++) { int *v; ok(array_add(&arr, &values[i]) && array_length(&arr) == i+1, "Add integer: %zu = %d", i, values[i]); ok((v = array_get(&arr, i)) && *v == values[i], "Get integer: %zu = %d", i, *v); } for (size_t i = 0; i < len; i++) { ok(array_set(&arr, i, &values[len-i-1]) && array_length(&arr) == len, "Set array element: %zu = %d", i, values[len-i-1]); } for (size_t i = 0; i < len; i++) { int *v; ok((v = array_get(&arr, i)) && *v == values[len-i-1], "Get array element: %zu = %d", i, *v); } int *v; ok((v = array_peek(&arr)) && *v == values[0] && array_length(&arr) == len, "Peek populated array"); ok((v = array_pop(&arr)) && *v == values[0] && array_length(&arr) == len-1, "Pop populated array"); ok((v = array_peek(&arr)) && *v == values[1] && array_length(&arr) == len-1, "Peek after pop"); array_clear(&arr); ok(array_length(&arr) == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear"); for (size_t i = 0; i < len; i++) { ok(array_add(&arr, &values[i]) && array_length(&arr) == i+1, "Re-add integer: %zu = %d", i, values[i]); } int old, *tmp; ok((tmp = array_get(&arr, 0)) && (old = *tmp) && array_set(&arr, 0, NULL) && array_get(&arr, 0) == tmp && *tmp == 0 && array_set(&arr, 0, &old) && array_get(&arr, 0) == tmp && *tmp == old, "Set array element NULL"); ok(!array_set(&arr, array_length(&arr), &values[0]) && errno == EINVAL, "Get past end of array"); ok(!array_get(&arr, array_length(&arr)) && errno == EINVAL, "Get past end of array"); ok(!array_remove(&arr, array_length(&arr)) && errno == EINVAL, "Remove past end of array"); size_t len_before = array_length(&arr); ok(array_remove(&arr, 2) && array_length(&arr) == len_before-1 && (v = array_get(&arr, 0)) && *v == values[0] && (v = array_get(&arr, 1)) && *v == values[1] && (v = array_get(&arr, 2)) && *v == values[3] && (v = array_get(&arr, 3)) && *v == values[4], "Remove element 2"); len_before = array_length(&arr); ok(array_remove(&arr, 0) && array_length(&arr) == len_before-1 && (v = array_get(&arr, 0)) && *v == values[1] && (v = array_get(&arr, 1)) && *v == values[3] && (v = array_get(&arr, 2)) && *v == values[4], "Remove first element"); len_before = array_length(&arr); ok(array_remove(&arr, len_before-1) && array_length(&arr) == len_before-1 && (v = array_get(&arr, 0)) && *v == values[1] && (v = array_get(&arr, 1)) && *v == values[3], "Remove last element"); array_release(&arr); } static void test_large_objects(void) { Array arr; array_init_sized(&arr, sizeof(Item)); ok(array_length(&arr) == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Initialization"); Item items[len]; for (size_t i = 0; i < len; i++) { snprintf(items[i].key, sizeof items[i].key, "key: %zu", i); items[i].value = values[i]; Item *item; ok(array_add(&arr, &items[i]) && array_length(&arr) == i+1, "Add item: %zu = { '%s' = %d }", i, items[i].key, items[i].value); ok((item = array_get(&arr, i)) && item != &items[i] && item_compare(item, &items[i]), "Get item: %zu = { '%s' = %d }", i, item->key, item->value); } for (size_t i = 0; i < len; i++) { Item *item = &items[len-i-1]; ok(array_set(&arr, i, item) && array_length(&arr) == len, "Set array element: %zu = { '%s' = %d }", i, item->key, item->value); } for (size_t i = 0; i < len; i++) { Item *item; ok((item = array_get(&arr, i)) && item != &items[len-i-1] && item_compare(item, &items[len-i-1]), "Get item: %zu = { '%s' = %d }", i, item->key, item->value); } ok(!array_add_ptr(&arr, &items[0]) && errno == ENOTSUP && array_length(&arr) == len, "Adding pointer to non pointer array"); ok(!array_set_ptr(&arr, 0, &items[0]) && errno == ENOTSUP && item_compare(array_get(&arr, 0), &items[len-1]), "Setting pointer in non pointer array"); array_clear(&arr); ok(array_length(&arr) == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear"); array_release(&arr); } static void test_pointers(void) { Array arr; array_init_sized(&arr, 1); ok(array_length(&arr) == 0 && array_get_ptr(&arr, 0) == NULL && errno == ENOTSUP, "Initialization with size 1"); ok(!array_add_ptr(&arr, &arr) && errno == ENOTSUP && array_get_ptr(&arr, 0) == NULL, "Add pointer to non-pointer array"); errno = 0; char byte = '_', *ptr; ok(array_add(&arr, &byte) && (ptr = array_get(&arr, 0)) && *ptr == byte, "Add byte element"); ok(!array_get_ptr(&arr, 0) && errno == ENOTSUP, "Get pointer from non-pointer array"); array_release(&arr); array_init(&arr); ok(array_length(&arr) == 0 && array_get_ptr(&arr, 0) == NULL && errno == EINVAL, "Initialization"); Item *items[len]; for (size_t i = 0; i < len; i++) { items[i] = malloc(sizeof(Item)); snprintf(items[i]->key, sizeof(items[i]->key), "key: %zu", i); items[i]->value = values[i]; } for (size_t i = 0; i < len; i++) { Item *item; ok(array_add_ptr(&arr, items[i]) && array_length(&arr) == i+1, "Add item: %zu = %p", i, (void*)items[i]); ok((item = array_get_ptr(&arr, i)) && item == items[i], "Get item: %zu = %p", i, (void*)item); } for (size_t i = 0; i < len; i++) { Item *item = items[len-i-1]; ok(array_set_ptr(&arr, i, item) && array_length(&arr) == len, "Set item: %zu = %p", i, (void*)item); } for (size_t i = 0; i < len; i++) { Item *item; ok((item = array_get_ptr(&arr, i)) && item == items[len-i-1], "Get item: %zu = %p", i, (void*)item); } Item *tmp; ok((tmp = array_get_ptr(&arr, 0)) && array_set_ptr(&arr, 0, NULL) && array_get_ptr(&arr, 0) == NULL && array_set_ptr(&arr, 0, tmp) && array_get_ptr(&arr, 0) == tmp, "Set pointer NULL"); ok(!array_set_ptr(&arr, array_length(&arr), items[0]) && errno == EINVAL, "Set pointer past end of array"); ok(!array_get_ptr(&arr, array_length(&arr)) && errno == EINVAL, "Get pointer past end of array"); array_clear(&arr); ok(array_length(&arr) == 0 && array_get_ptr(&arr, 0) == NULL && errno == EINVAL, "Clear"); for (size_t i = 0; i < len; i++) { ok(array_add_ptr(&arr, items[i]) && array_length(&arr) == i+1, "Re-add item: %zu = %p", i, (void*)items[i]); } array_release_full(&arr); } int main(int argc, char *argv[]) { plan_no_plan(); test_small_objects(); test_large_objects(); test_pointers(); return exit_status(); }