vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
array-test.c
(6863B)
1 #include <stdlib.h>
2 #include <stddef.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include "tap.h"
8 #include "array.h"
9 #include "util.h"
10
11 typedef struct {
12 char key[64];
13 int value;
14 } Item;
15
16 static int values[] = { 2, 3, 5, 7, 11 };
17 static const size_t len = LENGTH(values);
18
19 static bool item_compare(Item *a, Item *b) {
20 return strcmp(a->key, b->key) == 0 && a->value == b->value;
21 }
22
23 static void test_small_objects(void) {
24 Array arr;
25 array_init_sized(&arr, sizeof(int));
26 ok(arr.len == 0, "Initialization");
27 ok(!array_set(&arr, 0, NULL) && errno == EINVAL, "Set with invalid index");
28 ok(array_get(&arr, 0) == NULL && errno == EINVAL, "Get with invalid index");
29 ok(array_peek(&arr) == NULL && arr.len == 0, "Peek empty array");
30 ok(array_pop(&arr) == NULL && arr.len == 0, "Pop empty array");
31
32 for (size_t i = 0; i < len; i++) {
33 int *v;
34 ok(array_add(&arr, &values[i]) && arr.len == i+1,
35 "Add integer: %zu = %d", i, values[i]);
36 ok((v = array_get(&arr, i)) && *v == values[i],
37 "Get integer: %zu = %d", i, *v);
38 }
39
40 for (size_t i = 0; i < len; i++) {
41 ok(array_set(&arr, i, &values[len-i-1]) && arr.len == len,
42 "Set array element: %zu = %d", i, values[len-i-1]);
43 }
44
45 for (size_t i = 0; i < len; i++) {
46 int *v;
47 ok((v = array_get(&arr, i)) && *v == values[len-i-1],
48 "Get array element: %zu = %d", i, *v);
49 }
50
51 int *v;
52 ok((v = array_peek(&arr)) && *v == values[0] && arr.len == len, "Peek populated array");
53 ok((v = array_pop(&arr)) && *v == values[0] && arr.len == len-1, "Pop populated array");
54 ok((v = array_peek(&arr)) && *v == values[1] && arr.len == len-1, "Peek after pop");
55
56 array_clear(&arr);
57 ok(arr.len == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear");
58
59 for (size_t i = 0; i < len; i++) {
60 ok(array_add(&arr, &values[i]) && arr.len == i+1,
61 "Re-add integer: %zu = %d", i, values[i]);
62 }
63
64 int old, *tmp;
65 ok((tmp = array_get(&arr, 0)) && (old = *tmp) && array_set(&arr, 0, NULL) &&
66 array_get(&arr, 0) == tmp && *tmp == 0 && array_set(&arr, 0, &old) &&
67 array_get(&arr, 0) == tmp && *tmp == old, "Set array element NULL");
68 ok(!array_set(&arr, arr.len, &values[0]) && errno == EINVAL, "Get past end of array");
69 ok(!array_get(&arr, arr.len) && errno == EINVAL, "Get past end of array");
70
71 ok(!array_remove(&arr, arr.len) && errno == EINVAL, "Remove past end of array");
72
73 size_t len_before = arr.len;
74 ok(array_remove(&arr, 2) && arr.len == len_before-1 &&
75 (v = array_get(&arr, 0)) && *v == values[0] &&
76 (v = array_get(&arr, 1)) && *v == values[1] &&
77 (v = array_get(&arr, 2)) && *v == values[3] &&
78 (v = array_get(&arr, 3)) && *v == values[4],
79 "Remove element 2");
80
81 len_before = arr.len;
82 ok(array_remove(&arr, 0) && arr.len == len_before-1 &&
83 (v = array_get(&arr, 0)) && *v == values[1] &&
84 (v = array_get(&arr, 1)) && *v == values[3] &&
85 (v = array_get(&arr, 2)) && *v == values[4],
86 "Remove first element");
87
88 len_before = arr.len;
89 ok(array_remove(&arr, len_before-1) && arr.len == len_before-1 &&
90 (v = array_get(&arr, 0)) && *v == values[1] &&
91 (v = array_get(&arr, 1)) && *v == values[3],
92 "Remove last element");
93
94 array_release(&arr);
95 }
96
97 static void test_large_objects(void) {
98 Array arr;
99 array_init_sized(&arr, sizeof(Item));
100 ok(arr.len == 0 && array_get(&arr, 0) == NULL && errno == EINVAL,
101 "Initialization");
102
103 Item items[len];
104
105 for (size_t i = 0; i < len; i++) {
106 snprintf(items[i].key, sizeof items[i].key, "key: %zu", i);
107 items[i].value = values[i];
108 Item *item;
109 ok(array_add(&arr, &items[i]) && arr.len == i+1,
110 "Add item: %zu = { '%s' = %d }", i, items[i].key, items[i].value);
111 ok((item = array_get(&arr, i)) && item != &items[i] && item_compare(item, &items[i]),
112 "Get item: %zu = { '%s' = %d }", i, item->key, item->value);
113 }
114
115 for (size_t i = 0; i < len; i++) {
116 Item *item = &items[len-i-1];
117 ok(array_set(&arr, i, item) && arr.len == len,
118 "Set array element: %zu = { '%s' = %d }", i, item->key, item->value);
119 }
120
121 for (size_t i = 0; i < len; i++) {
122 Item *item;
123 ok((item = array_get(&arr, i)) && item != &items[len-i-1] && item_compare(item, &items[len-i-1]),
124 "Get item: %zu = { '%s' = %d }", i, item->key, item->value);
125 }
126
127 ok(!array_add_ptr(&arr, &items[0]) && errno == ENOTSUP && arr.len == len,
128 "Adding pointer to non pointer array");
129 ok(!array_set_ptr(&arr, 0, &items[0]) && errno == ENOTSUP && item_compare(array_get(&arr, 0), &items[len-1]),
130 "Setting pointer in non pointer array");
131
132 array_clear(&arr);
133 ok(arr.len == 0 && array_get(&arr, 0) == NULL && errno == EINVAL, "Clear");
134
135 array_release(&arr);
136 }
137
138 static void test_pointers(void) {
139
140 Array arr;
141
142 array_init_sized(&arr, 1);
143 ok(arr.len == 0 && array_get_ptr(&arr, 0) == NULL && errno == ENOTSUP,
144 "Initialization with size 1");
145
146 ok(!array_add_ptr(&arr, &arr) && errno == ENOTSUP && array_get_ptr(&arr, 0) == NULL,
147 "Add pointer to non-pointer array");
148
149 errno = 0;
150 char byte = '_', *ptr;
151 ok(array_add(&arr, &byte) && (ptr = array_get(&arr, 0)) && *ptr == byte,
152 "Add byte element");
153 ok(!array_get_ptr(&arr, 0) && errno == ENOTSUP, "Get pointer from non-pointer array");
154 array_release(&arr);
155
156 array_init(&arr);
157 ok(arr.len == 0 && array_get_ptr(&arr, 0) == NULL && errno == EINVAL,
158 "Initialization");
159
160 Item *items[len];
161
162 for (size_t i = 0; i < len; i++) {
163 items[i] = malloc(sizeof(Item));
164 snprintf(items[i]->key, sizeof(items[i]->key), "key: %zu", i);
165 items[i]->value = values[i];
166 }
167
168 for (size_t i = 0; i < len; i++) {
169 Item *item;
170 ok(array_add_ptr(&arr, items[i]) && arr.len == i+1,
171 "Add item: %zu = %p", i, (void*)items[i]);
172 ok((item = array_get_ptr(&arr, i)) && item == items[i],
173 "Get item: %zu = %p", i, (void*)item);
174 }
175
176 for (size_t i = 0; i < len; i++) {
177 Item *item = items[len-i-1];
178 ok(array_set_ptr(&arr, i, item) && arr.len == len,
179 "Set item: %zu = %p", i, (void*)item);
180 }
181
182 for (size_t i = 0; i < len; i++) {
183 Item *item;
184 ok((item = array_get_ptr(&arr, i)) && item == items[len-i-1],
185 "Get item: %zu = %p", i, (void*)item);
186 }
187
188 Item *tmp;
189 ok((tmp = array_get_ptr(&arr, 0)) && array_set_ptr(&arr, 0, NULL) &&
190 array_get_ptr(&arr, 0) == NULL && array_set_ptr(&arr, 0, tmp) &&
191 array_get_ptr(&arr, 0) == tmp, "Set pointer NULL");
192 ok(!array_set_ptr(&arr, arr.len, items[0]) && errno == EINVAL, "Set pointer past end of array");
193 ok(!array_get_ptr(&arr, arr.len) && errno == EINVAL, "Get pointer past end of array");
194
195 array_clear(&arr);
196 ok(arr.len == 0 && array_get_ptr(&arr, 0) == NULL && errno == EINVAL, "Clear");
197
198 for (size_t i = 0; i < len; i++) {
199 ok(array_add_ptr(&arr, items[i]) && arr.len == i+1,
200 "Re-add item: %zu = %p", i, (void*)items[i]);
201 }
202 array_release_full(&arr);
203 }
204
205 int main(int argc, char *argv[]) {
206 plan_no_plan();
207
208 test_small_objects();
209 test_large_objects();
210 test_pointers();
211
212 return exit_status();
213 }