]> git.ozlabs.org Git - ccan/blob - ccan/darray/test/run.c
darray: Add darray_insert() to insert a value at a specified index
[ccan] / ccan / darray / test / run.c
1 #include <ccan/tap/tap.h>
2 #include <ccan/darray/darray.h>
3 #include <stdio.h>
4
5 #include "lotsOfNumbers.h"
6 #include "lotsOfStrings.h"
7
8 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
9
10 struct {
11         char *stringsF, *stringsB;
12                 //items of lotsOfStrings glued together
13         size_t stringsSize; //total strlen of all strings combined
14 } amalgams;
15
16 static void generateAmalgams(void);
17 static void freeAmalgams(void);
18 static int isZeros(void *ptr, size_t size);
19 static void memtile(void *dest, size_t destWidth, const void *src, size_t srcWidth);
20
21
22 #if 0
23 #define testing(...) printf("Testing %s...\n", #__VA_ARGS__)
24 #define trace(...) do {printf(__VA_ARGS__); puts("");} while(0)
25 #else
26 #define testing(...) do {} while(0)
27 #define trace(...) do {} while(0)
28 #endif
29
30 #include "testLits.h"
31
32 int main(void) {
33         darray(long) arr = darray_new();
34         darray_char str = darray_new();
35         #define reset(arr) do {darray_free(arr); darray_init(arr);} while(0)
36         size_t i;
37         
38         trace("Generating amalgams (internal)");
39         generateAmalgams();
40         
41         plan_tests(47);
42         
43         testLits();
44         
45         testing(darray_push);
46         {
47                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++)
48                         darray_push(arr, lotsOfNumbers[i]);
49                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers));
50                 ok1(darray_alloc(arr) >= darray_size(arr));
51                 ok1(!memcmp(arr.item, lotsOfNumbers, sizeof(lotsOfNumbers)));
52         }
53         reset(arr);
54         
55         testing(darray_prepend, darray_pop);
56         {
57                 for (i = ARRAY_SIZE(lotsOfNumbers); i;)
58                         darray_prepend(arr, lotsOfNumbers[--i]);
59                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers));
60                 ok1(darray_alloc(arr) >= darray_size(arr));
61                 ok1(!memcmp(arr.item, lotsOfNumbers, sizeof(lotsOfNumbers)));
62                 
63                 for (i = ARRAY_SIZE(lotsOfNumbers); i;) {
64                         if (darray_pop(arr) != (long)lotsOfNumbers[--i]) {
65                                 i++;
66                                 break;
67                         }
68                 }
69                 ok1(i==0);
70                 ok1(darray_size(arr) == 0);
71         }
72         reset(arr);
73
74         testing(darray_insert);
75         {
76                 size_t middle_i;
77
78                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++)
79                         darray_insert(arr, i, lotsOfNumbers[i]);
80                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers));
81                 ok1(darray_alloc(arr) >= darray_size(arr));
82                 ok1(!memcmp(arr.item, lotsOfNumbers, sizeof(lotsOfNumbers)));
83
84                 middle_i = ARRAY_SIZE(lotsOfNumbers) / 2;
85                 darray_insert(arr, middle_i, 42);
86                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers) + 1);
87                 ok1(arr.item[middle_i] == 42);
88                 ok1(arr.item[middle_i + 1] == lotsOfNumbers[middle_i]);
89         }
90         reset(arr);
91
92         testing(darray_from_c, darray_foreach, darray_foreach_reverse);
93         {
94                 long   *i;
95                 size_t  j;
96                 
97                 darray_from_c(arr, lotsOfNumbers);
98                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers));
99                 ok1(darray_alloc(arr) >= darray_size(arr));
100                 ok1(memcmp(arr.item, lotsOfNumbers, sizeof(lotsOfNumbers)) == 0);
101                 
102                 j = 0;
103                 darray_foreach(i, arr) {
104                         if (i - arr.item != j)
105                                 break;
106                         if (*i != (long)lotsOfNumbers[j])
107                                 break;
108                         j++;
109                 };
110                 ok1(j == ARRAY_SIZE(lotsOfNumbers));
111                 
112                 j = 0;
113                 darray_foreach_reverse(i, arr) {
114                         if (i - arr.item != darray_size(arr)-j-1)
115                                 break;
116                         if (*i != (long)lotsOfNumbers[darray_size(arr)-j-1])
117                                 break;
118                         j++;
119                 };
120                 ok1(j == ARRAY_SIZE(lotsOfNumbers));
121         }
122         reset(arr);
123         
124         testing(darray_append_string);
125         {
126                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
127                         darray_append_string(str, lotsOfStrings[i]);
128                 ok1(str.size == amalgams.stringsSize);
129                 ok1(str.alloc > str.size);
130                 ok1(str.item[str.size] == 0);
131                 ok1(!strcmp(str.item, amalgams.stringsF));
132         }
133         reset(str);
134         
135         testing(darray_prepend_string);
136         {
137                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
138                         darray_prepend_string(str, lotsOfStrings[i]);
139                 ok1(str.size == amalgams.stringsSize);
140                 ok1(str.alloc > str.size);
141                 ok1(str.item[str.size] == 0);
142                 ok1(!strcmp(str.item, amalgams.stringsB));
143         }
144         reset(str);
145         
146         testing(darray_from_string);
147         {
148                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++) {
149                         darray_from_string(str, lotsOfStrings[i]);
150                         if (str.size != strlen(lotsOfStrings[i]))
151                                 break;
152                         if (str.alloc < strlen(lotsOfStrings[i])+1)
153                                 break;
154                         if (strcmp(str.item, lotsOfStrings[i]))
155                                 break;
156                 }
157                 ok1(i == ARRAY_SIZE(lotsOfStrings));
158         }
159         reset(str);
160         
161         testing(darray_resize0);
162         {
163                 size_t prevSize=0, size;
164                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++, prevSize=size) {
165                         size = lotsOfNumbers[i] & 0xFFFF;
166                         darray_resize0(arr, size);
167                         if (darray_size(arr) != size)
168                                 break;
169                         if (darray_alloc(arr) < size)
170                                 break;
171                         if (size>prevSize) {
172                                 if (!isZeros(arr.item+prevSize, (size-prevSize)*sizeof(*arr.item)))
173                                         break;
174                         }
175                         //fill the darray with lotsOfNumbers garbage
176                         memtile(arr.item, darray_size(arr)*sizeof(*arr.item), lotsOfNumbers, sizeof(lotsOfNumbers));
177                 }
178                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
179         }
180         reset(arr);
181         
182         testing(darray_realloc);
183         {
184                 size_t s,a;
185                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++) {
186                         arr.size = (s = lotsOfNumbers[i] >> 16);
187                                 //give size a nonsense value to make sure darray_realloc doesn't care about it
188                         a = amalgams.stringsSize/sizeof(*arr.item)+2;
189                         darray_realloc(arr, a = lotsOfNumbers[i] % ((amalgams.stringsSize/sizeof(*arr.item))+1));
190                         if (a*sizeof(*arr.item) > amalgams.stringsSize)
191                                 break;
192                         if (darray_alloc(arr) != a)
193                                 break;
194                         if (darray_size(arr) != s)
195                                 break;
196                         memtile(arr.item, a*sizeof(*arr.item), amalgams.stringsF, a*sizeof(*arr.item));
197                         if (memcmp(arr.item, amalgams.stringsF, a*sizeof(*arr.item)))
198                                 break;
199                 }
200                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
201         }
202         reset(arr);
203         
204         testing(darray_growalloc);
205         {
206                 size_t prevA, s, a;
207                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++) {
208                         arr.size = (s = lotsOfNumbers[i] >> 16);
209                                 //give size a nonsense value to make sure darray_growalloc doesn't care about it
210                         a = amalgams.stringsSize/sizeof(*arr.item)+2;
211                         prevA = darray_alloc(arr);
212                         darray_growalloc(arr, a = lotsOfNumbers[i] % ((amalgams.stringsSize/sizeof(*arr.item))+1));
213                         if (a*sizeof(*arr.item) > amalgams.stringsSize)
214                                 break;
215                         if (darray_alloc(arr) < a)
216                                 break;
217                         if (darray_alloc(arr) < prevA)
218                                 break;
219                         if (darray_size(arr) != s)
220                                 break;
221                         
222                         memtile(arr.item, a*sizeof(*arr.item), amalgams.stringsF, a*sizeof(*arr.item));
223                         if (memcmp(arr.item, amalgams.stringsF, a*sizeof(*arr.item)))
224                                 break;
225                         
226                         //clear the darray every now and then
227                         if (!(lotsOfNumbers[i] & 15)) {
228                                 reset(arr);
229                         }
230                 }
231                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
232         }
233         reset(arr);
234         
235         testing(darray_make_room);
236         {
237                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++) {
238                         char *dest = darray_make_room(str, strlen(lotsOfStrings[i]));
239                         if (str.alloc < str.size+strlen(lotsOfStrings[i]))
240                                 break;
241                         if (dest != str.item+str.size)
242                                 break;
243                         
244                         memcpy(dest, lotsOfStrings[i], strlen(lotsOfStrings[i]));
245                         str.size += strlen(lotsOfStrings[i]);
246                 }
247                 ok1(i == ARRAY_SIZE(lotsOfStrings));
248                 ok1(str.size == amalgams.stringsSize);
249                 
250                 darray_append(str, 0);
251                 ok1(!strcmp(str.item, amalgams.stringsF));
252         }
253         reset(str);
254         
255         testing(darray_appends, darray_prepends, darray_pop_check);
256         {
257                 darray(const char*) arr = darray_new();
258                 const char *n[9] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight"};
259
260 #if HAVE_TYPEOF         
261                 darray_appends(arr, n[5], n[6], n[7], n[8]);
262 #else
263                 darray_appends_t(arr, const char *, n[5], n[6], n[7], n[8]);
264 #endif
265                 ok1(darray_size(arr)==4 && darray_alloc(arr)>=4);
266
267 #if HAVE_TYPEOF         
268                 darray_prepends(arr, n[0], n[1], n[2], n[3], n[4]);
269 #else
270                 darray_prepends_t(arr, const char *, n[0], n[1], n[2], n[3], n[4]);
271 #endif
272
273                 ok1(darray_size(arr)==9 && darray_alloc(arr)>=9);
274                 
275                 ok1(arr.item[0]==n[0] &&
276                     arr.item[1]==n[1] &&
277                     arr.item[2]==n[2] &&
278                     arr.item[3]==n[3] &&
279                     arr.item[4]==n[4] &&
280                     arr.item[5]==n[5] &&
281                     arr.item[6]==n[6] &&
282                     arr.item[7]==n[7] &&
283                     arr.item[8]==n[8]);
284                 
285                 ok1(darray_pop_check(arr)==n[8] &&
286                     darray_pop_check(arr)==n[7] &&
287                     darray_pop_check(arr)==n[6] &&
288                     darray_pop_check(arr)==n[5] &&
289                     darray_pop_check(arr)==n[4] &&
290                     darray_pop_check(arr)==n[3] &&
291                     darray_pop_check(arr)==n[2] &&
292                     darray_pop_check(arr)==n[1] &&
293                     darray_pop_check(arr)==n[0]);
294                 
295                 ok1(darray_size(arr)==0);
296                 
297                 ok1(darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL);
298                 
299                 darray_free(arr);
300         }
301         
302         trace("Freeing amalgams (internal)");
303         freeAmalgams();
304         
305         return exit_status();
306 }
307
308 static void generateAmalgams(void) {
309         size_t i;
310         size_t lotsOfStringsLen = 0;
311         const char *src;
312         char *p;
313         
314         for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
315                 lotsOfStringsLen += strlen(lotsOfStrings[i]);
316         amalgams.stringsSize = lotsOfStringsLen;
317         
318         amalgams.stringsF = malloc(lotsOfStringsLen+1);
319         amalgams.stringsB = malloc(lotsOfStringsLen+1);
320         
321         for (i=0,p=amalgams.stringsF; i < ARRAY_SIZE(lotsOfStrings); i++) {
322                 size_t len = strlen(src=lotsOfStrings[i]);
323                 memcpy(p, src, len);
324                 p += len;
325         }
326         *p = 0;
327         ok1(p-amalgams.stringsF == (long)lotsOfStringsLen);
328         ok1(strlen(amalgams.stringsF) == lotsOfStringsLen);
329         
330         for (i = ARRAY_SIZE(lotsOfStrings), p = amalgams.stringsB; i--;) {
331                 size_t len = strlen(src=lotsOfStrings[i]);
332                 memcpy(p, src, len);
333                 p += len;
334         }
335         *p = 0;
336         ok1(p-amalgams.stringsB == (long)lotsOfStringsLen);
337         ok1(strlen(amalgams.stringsB) == lotsOfStringsLen);
338 }
339
340 static void freeAmalgams(void) {
341         free(amalgams.stringsF);
342         free(amalgams.stringsB);
343 }
344
345 static int isZeros(void *ptr, size_t size) {
346         unsigned char *pc = ptr;
347         size_t *pl;
348         if (size>8) {
349                 //test one byte at a time until we have an aligned size_t pointer
350                 while ((size_t)pc & (sizeof(size_t)-1))
351                         if (*pc++)
352                                 return 0;
353                 pl = (size_t*)pc;
354                 size -= pc-(unsigned char*)ptr;
355                 while (size >= sizeof(size_t)) {
356                         size -= sizeof(size_t);
357                         if (*pl++)
358                                 return 0;
359                 }
360                 pc = (unsigned char*)pl;
361         }
362         while (size--)
363                 if (*pc++)
364                         return 0;
365         return 1;
366 }
367
368 static void memtile(void *dest, size_t destWidth, const void *src, size_t srcWidth) {
369         char *d = dest;
370         while (destWidth > srcWidth) {
371                 destWidth -= srcWidth;
372                 memcpy(d, src, srcWidth);
373                 d += srcWidth;
374         }
375         memcpy(d, src, destWidth);
376 }