Tue, 06 Aug 2019 16:26:46 +0200
removes cumbersome array accessor macros
1 /*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3 *
4 * Copyright 2019 Mike Becker, Olaf Wintermann All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
29 #include "array_tests.h"
30 #include <ucx/utils.h>
32 UCX_TEST(test_ucx_array_free) {
33 UcxArray array = ucx_array_new(16, sizeof(int));
35 UCX_TEST_BEGIN
36 ucx_array_free(&array);
37 UCX_TEST_ASSERT(array.data == NULL, "data pointer not NULL after free");
38 UCX_TEST_ASSERT(array.size == 0, "size not zero after free");
39 UCX_TEST_ASSERT(array.capacity == 0, "capacity not zero after free");
40 UCX_TEST_ASSERT(array.allocator == ucx_default_allocator(),
41 "allocator corrupted during free");
42 UCX_TEST_END
43 }
45 UCX_TEST(test_ucx_array_new) {
46 UcxArray array = ucx_array_new(16, 47);
48 UCX_TEST_BEGIN
49 UCX_TEST_ASSERT(array.data, "no memory allocated");
50 UCX_TEST_ASSERT(array.size == 0, "size not initially zero");
51 UCX_TEST_ASSERT(array.capacity == 16, "capacity not as requested");
52 UCX_TEST_ASSERT(array.elemsize == 47, "element size not as requested");
53 UCX_TEST_ASSERT(array.allocator == ucx_default_allocator(),
54 "array not using the default allocator");
55 UCX_TEST_END
56 ucx_array_free(&array);
57 }
59 UCX_TEST(test_ucx_array_append) {
60 UcxArray array = ucx_array_new(16, sizeof(int));
61 int *elements;
63 int x = 42;
64 ucx_array_append(&array, &x);
65 UCX_TEST_BEGIN
67 elements = array.data;
68 UCX_TEST_ASSERT(elements[0] == 42, "failed");
70 x = 13;
71 ucx_array_append(&array, &x);
73 elements = array.data;
74 UCX_TEST_ASSERT(array.size == 2, "incorrect size after append");
75 UCX_TEST_ASSERT(elements[1] == 13, "failed");
76 UCX_TEST_ASSERT(elements[0] == 42,
77 "append corrupted previously inserted data");
79 ucx_array_append(&array, NULL);
81 elements = array.data;
82 UCX_TEST_ASSERT(array.size == 3, "incorrect size after NULL append");
83 UCX_TEST_ASSERT(elements[2] == 0, "element is not zeroed");
84 UCX_TEST_ASSERT(elements[0] == 42,
85 "NULL append corrupted previously inserted data");
86 UCX_TEST_ASSERT(elements[1] == 13,
87 "NULL append corrupted previously inserted data");
89 UCX_TEST_END
91 ucx_array_free(&array);
92 }
94 UCX_TEST(test_ucx_array_prepend) {
95 int *elems;
96 UcxArray array = ucx_array_new(16, sizeof(int));
98 int x = 42;
99 ucx_array_prepend(&array, &x);
100 UCX_TEST_BEGIN
102 elems = array.data;
103 UCX_TEST_ASSERT(elems[0] == 42, "failed");
105 x = 13;
106 ucx_array_prepend(&array, &x);
108 elems = array.data;
109 UCX_TEST_ASSERT(array.size == 2, "incorrect size after prepend");
110 UCX_TEST_ASSERT(elems[0] == 13, "failed");
111 UCX_TEST_ASSERT(elems[1] == 42,
112 "prepend corrupted previously inserted data");
114 ucx_array_prepend(&array, NULL);
116 elems = array.data;
117 UCX_TEST_ASSERT(array.size == 3, "incorrect size after NULL prepend");
118 UCX_TEST_ASSERT(elems[0] == 0, "element is not zeroed");
119 UCX_TEST_ASSERT(elems[1] == 13,
120 "NULL prepend corrupted previously inserted data");
121 UCX_TEST_ASSERT(elems[2] == 42,
122 "NULL prepend corrupted previously inserted data");
124 UCX_TEST_END
126 ucx_array_free(&array);
127 }
129 UCX_TEST(test_ucx_array_set) {
130 int *elems;
131 UcxArray array = ucx_array_new(16, sizeof(int));
134 int x = 42;
136 UCX_TEST_BEGIN
138 ucx_array_set(&array, 7, &x);
140 elems = array.data;
141 UCX_TEST_ASSERT(elems[7] == 42, "failed");
142 UCX_TEST_ASSERT(array.size >= 8, "array not resized on set");
143 UCX_TEST_ASSERT(array.capacity == 16, "capacity changed unnecessarily");
145 x = 13;
146 ucx_array_set(&array, 27, &x);
148 elems = array.data;
149 UCX_TEST_ASSERT(elems[27] == 13, "failed");
150 UCX_TEST_ASSERT(array.size == 28, "array not resized on set");
151 UCX_TEST_ASSERT(array.capacity == 28, "capacity not grown");
153 ucx_array_set(&array, 7, NULL);
155 elems = array.data;
156 UCX_TEST_ASSERT(elems[7] == 0, "not zeroed on NULL set");
158 UCX_TEST_END
160 ucx_array_free(&array);
161 }
163 UCX_TEST(test_ucx_array_equals) {
164 UcxArray a1 = ucx_array_new(16, sizeof(int));
165 UcxArray a2 = ucx_array_new(16, sizeof(int));
166 UcxArray a3 = ucx_array_new(16, sizeof(long int));
167 UcxArray a4 = ucx_array_new(16, sizeof(int));
169 int *intelems;
170 long int *longintelems;
172 a1.size = 5;
173 intelems = a1.data;
174 intelems[0] = 47;
175 intelems[1] = 11;
176 intelems[2] = 0;
177 intelems[3] = 8;
178 intelems[4] = 15;
179 a2.size = 5;
180 intelems = a2.data;
181 intelems[0] = 47;
182 intelems[1] = 11;
183 intelems[2] = 0;
184 intelems[3] = 8;
185 intelems[4] = 15;
186 a3.size = 5;
187 longintelems = a3.data;
188 longintelems[0] = 47;
189 longintelems[1] = 11;
190 longintelems[2] = 0;
191 longintelems[3] = 8;
192 longintelems[4] = 15;
193 a4.size = 5;
194 intelems = a4.data;
195 intelems[0] = 47;
196 intelems[1] = 11;
197 intelems[2] = -6;
198 intelems[3] = 8;
199 intelems[4] = 15;
201 UCX_TEST_BEGIN
203 UCX_TEST_ASSERT(ucx_array_equals(a1, a2, ucx_cmp_int, NULL), "failed");
204 UCX_TEST_ASSERT(!ucx_array_equals(a1, a4, ucx_cmp_int, NULL), "failed");
205 UCX_TEST_ASSERT(!ucx_array_equals(a4, a1, ucx_cmp_int, NULL), "failed");
206 UCX_TEST_ASSERT(!ucx_array_equals(a1, a3, ucx_cmp_int, NULL),
207 "comparing arrays of different element size shall fail");
208 UCX_TEST_ASSERT(!ucx_array_equals(a3, a1, ucx_cmp_int, NULL),
209 "comparing arrays of different element size shall fail");
211 UCX_TEST_ASSERT(ucx_array_equals(a1, a2, NULL, NULL),
212 "compare using memcmp() failed");
213 UCX_TEST_ASSERT(!ucx_array_equals(a1, a4, NULL, NULL),
214 "compare using memcmp() failed");
216 UCX_TEST_END
217 ucx_array_free(&a1);
218 ucx_array_free(&a2);
219 ucx_array_free(&a3);
220 ucx_array_free(&a4);
221 }
223 UCX_TEST(test_ucx_array_concat) {
224 UcxArray a1 = ucx_array_new(16, sizeof(int));
225 UcxArray a2 = ucx_array_new(16, sizeof(int));
226 int *elems;
228 a1.size = 2;
229 elems = a1.data;
230 elems[0] = 47;
231 elems[1] = 11;
232 a2.size = 3;
233 elems = a2.data;
234 elems[0] = 0;
235 elems[1] = 8;
236 elems[2] = 15;
238 UCX_TEST_BEGIN
240 UCX_TEST_ASSERT(!ucx_array_concat(&a1, &a2), "failed");
241 UCX_TEST_ASSERT(a1.size == 5, "failed");
242 elems = a1.data;
243 UCX_TEST_ASSERT(elems[0] == 47, "failed");
244 UCX_TEST_ASSERT(elems[1] == 11, "failed");
245 UCX_TEST_ASSERT(elems[2] == 0, "failed");
246 UCX_TEST_ASSERT(elems[3] == 8, "failed");
247 UCX_TEST_ASSERT(elems[4] == 15, "failed");
249 a1.elemsize *= 2;
250 UCX_TEST_ASSERT(ucx_array_concat(&a1, &a2),
251 "arrays of different element size must not be concatenated");
252 UCX_TEST_ASSERT(a1.size == 5,
253 "arrays of different element size must not be concatenated");
255 UCX_TEST_END
256 ucx_array_free(&a1);
257 ucx_array_free(&a2);
258 }
260 UCX_TEST(test_ucx_array_find) {
261 UcxArray array = ucx_array_new(16, sizeof(int));
262 int *elems;
264 array.size = 5;
265 elems = array.data;
266 elems[0] = 47;
267 elems[1] = 11;
268 elems[2] = 0;
269 elems[3] = 8;
270 elems[4] = 15;
272 int x = 8;
273 int y = 90;
275 UCX_TEST_BEGIN
277 UCX_TEST_ASSERT(ucx_array_find(array,(void*)&x,ucx_cmp_int,NULL) == 3,
278 "doesn't find element");
279 UCX_TEST_ASSERT(ucx_array_find(array,(void*)&y,ucx_cmp_int,NULL) == 5,
280 "finds non-existing element");
282 UCX_TEST_ASSERT(ucx_array_find(array,(void*)&x,NULL,NULL) == 3,
283 "failed using memcmp()");
284 UCX_TEST_ASSERT(ucx_array_find(array,(void*)&y,NULL,NULL) == 5,
285 "failed using memcmp()");
287 UCX_TEST_END
288 ucx_array_free(&array);
289 }
291 UCX_TEST(test_ucx_array_contains) {
292 UcxArray array = ucx_array_new(16, sizeof(int));
293 int *elems;
295 array.size = 5;
296 elems = array.data;
297 elems[0] = 47;
298 elems[1] = 11;
299 elems[2] = 0;
300 elems[3] = 8;
301 elems[4] = 15;
303 int x = 8;
304 int y = 90;
306 UCX_TEST_BEGIN
308 UCX_TEST_ASSERT(ucx_array_contains(array,(void*)&x,ucx_cmp_int,NULL),
309 "false negative");
310 UCX_TEST_ASSERT(!ucx_array_contains(array,(void*)&y,ucx_cmp_int,NULL),
311 "false positive");
313 UCX_TEST_ASSERT(ucx_array_contains(array,(void*)&x,NULL,NULL),
314 "false negative using memcmp()");
315 UCX_TEST_ASSERT(!ucx_array_contains(array,(void*)&y,NULL,NULL),
316 "false positive using memcmp()");
318 UCX_TEST_END
319 ucx_array_free(&array);
320 }
322 UCX_TEST(test_ucx_array_remove) {
323 UcxArray array = ucx_array_new(16, sizeof(int));
324 int *elems;
326 array.size = 5;
327 elems = array.data;
328 elems[0] = 47;
329 elems[1] = 11;
330 elems[2] = 0;
331 elems[3] = 8;
332 elems[4] = 15;
334 UCX_TEST_BEGIN
336 ucx_array_remove(&array, 2);
337 elems = array.data;
338 UCX_TEST_ASSERT(
339 elems[0] == 47 &&
340 elems[1] == 11 &&
341 elems[2] == 8 &&
342 elems[3] == 15,
343 "wrong contents after remove");
344 UCX_TEST_ASSERT(array.size == 4, "wrong size after remove");
346 ucx_array_remove_fast(&array, 1);
347 elems = array.data;
348 UCX_TEST_ASSERT(
349 elems[0] == 47 &&
350 elems[1] == 15 &&
351 elems[2] == 8,
352 "wrong contents after fast remove");
353 UCX_TEST_ASSERT(array.size == 3, "wrong size after fast remove");
355 UCX_TEST_END
356 ucx_array_free(&array);
357 }
359 UCX_TEST(test_ucx_array_clone) {
360 UcxArray array = ucx_array_new(16, sizeof(int));
361 int *elems;
363 array.size = 5;
364 elems = array.data;
365 elems[0] = 47;
366 elems[1] = 11;
367 elems[2] = 0;
368 elems[3] = 8;
369 elems[4] = 15;
371 UcxArray copy = ucx_array_clone(array);
372 UCX_TEST_BEGIN
374 UCX_TEST_ASSERT(array.data != copy.data, "no true copy");
375 UCX_TEST_ASSERT(array.size == copy.size, "size mismatch");
376 UCX_TEST_ASSERT(array.capacity == copy.capacity, "capacity mismatch");
377 UCX_TEST_ASSERT(array.elemsize == copy.elemsize, "element size mismatch");
378 UCX_TEST_ASSERT(array.allocator == copy.allocator, "allocator mismatch");
379 UCX_TEST_ASSERT(ucx_array_equals(array, copy, ucx_cmp_int, NULL), "failed");
381 UCX_TEST_END
383 ucx_array_free(&array);
384 ucx_array_free(©);
385 }
387 static int ucx_cmp_int_reverse(const void* x, const void* y, void* data) {
388 return -ucx_cmp_int(x,y,data);
389 }
391 UCX_TEST(test_ucx_array_sort) {
392 int *elems;
394 UcxArray array = ucx_array_new(16, sizeof(int));
395 array.size = 5;
396 elems = array.data;
397 elems[0] = 47;
398 elems[1] = 11;
399 elems[2] = 0;
400 elems[3] = 8;
401 elems[4] = 15;
403 UcxArray expected = ucx_array_new(16, sizeof(int));
404 expected.size = 5;
405 elems = expected.data;
406 elems[0] = 0;
407 elems[1] = 8;
408 elems[2] = 11;
409 elems[3] = 15;
410 elems[4] = 47;
412 UcxArray expectedrev = ucx_array_new(16, sizeof(int));
413 expectedrev.size = 5;
414 elems = expectedrev.data;
415 elems[0] = 47;
416 elems[1] = 15;
417 elems[2] = 11;
418 elems[3] = 8;
419 elems[4] = 0;
422 UCX_TEST_BEGIN
423 void* original_ptr = array.data;
424 ucx_array_sort(array, ucx_cmp_int, NULL);
425 UCX_TEST_ASSERT(ucx_array_equals(array, expected, NULL, NULL), "failed");
426 UCX_TEST_ASSERT(array.size == 5, "size corrupted");
427 UCX_TEST_ASSERT(array.data == original_ptr, "shall not reallocate");
429 ucx_array_sort(array, ucx_cmp_int_reverse, NULL);
430 UCX_TEST_ASSERT(ucx_array_equals(array, expectedrev, NULL, NULL), "failed");
432 ucx_array_reserve(&array, 32);
433 ucx_array_reserve(&expected, 32);
434 array.size = expected.size = 32;
435 for (size_t i = 0 ; i < 32 ; i++) {
436 ((int*)array.data)[i]= ((i%2==0)?-1:1) * ((int) i);
437 ((int*)expected.data)[i] = (-30+2*i) - (i > 15 ? 1 : 0);
438 }
440 /* dummy third argument to trigger a possible fallback for qsort_s */
441 ucx_array_sort(array, ucx_cmp_int, array.data);
442 UCX_TEST_ASSERT(ucx_array_equals(array, expected, NULL, NULL),
443 "failed for bigger arrays");
444 UCX_TEST_END
446 ucx_array_free(&expected);
447 ucx_array_free(&array);
448 }
450 UCX_TEST(test_ucx_array_autogrow) {
451 int *elems;
452 UcxArray array = ucx_array_new(4, sizeof(int));
453 array.size = 3;
454 elems = array.data;
455 elems[0] = 47;
456 elems[1] = 11;
457 int x = 5;
459 UCX_TEST_BEGIN
461 void* oldptr = array.data;
463 ucx_array_append(&array, &x);
464 UCX_TEST_ASSERT(array.capacity == 4 && array.data == oldptr,
465 "array should not grow too early");
466 ucx_array_append(&array, &x);
467 elems = array.data;
468 UCX_TEST_ASSERT(array.capacity == 8, "array did not grow");
469 UCX_TEST_ASSERT(array.size == 5, "incorrect size after grow");
470 UCX_TEST_ASSERT(elems[3] == 5 && elems[4] == 5, "corrupt data");
472 UCX_TEST_END
473 ucx_array_free(&array);
474 }
476 UCX_TEST(test_ucx_array_shrink) {
477 UcxArray array = ucx_array_new(16, sizeof(int));
478 array.size = 4;
480 UCX_TEST_BEGIN
481 UCX_TEST_ASSERT(!ucx_array_shrink(&array), "failed");
482 UCX_TEST_ASSERT(array.capacity == 4, "incorrect capacity after shrink");
483 UCX_TEST_END
484 ucx_array_free(&array);
485 }
487 UCX_TEST(test_ucx_array_resize) {
488 UcxArray array = ucx_array_new(16, sizeof(int));
489 array.size = 8;
491 UCX_TEST_BEGIN
493 UCX_TEST_ASSERT(!ucx_array_resize(&array, 32), "failed");
494 UCX_TEST_ASSERT(array.capacity == 32, "incorrect capacity after resize");
495 UCX_TEST_ASSERT(array.size == 8, "incorrect size after resize");
497 UCX_TEST_ASSERT(!ucx_array_resize(&array, 4), "failed");
498 UCX_TEST_ASSERT(array.capacity == 4, "incorrect capacity after resize");
499 UCX_TEST_ASSERT(array.size == 4, "incorrect size after resize");
501 UCX_TEST_END
502 ucx_array_free(&array);
503 }
505 UCX_TEST(test_ucx_array_reserve) {
506 UcxArray array = ucx_array_new(16, sizeof(int));
508 UCX_TEST_BEGIN
510 UCX_TEST_ASSERT(!ucx_array_reserve(&array, 4), "failed");
511 UCX_TEST_ASSERT(array.capacity == 16, "reserve shall not shrink");
513 UCX_TEST_ASSERT(!ucx_array_resize(&array, 32), "failed");
514 UCX_TEST_ASSERT(array.capacity == 32, "incorrect capacity after reserve");
516 UCX_TEST_END
517 ucx_array_free(&array);
518 }