3d96fa564614cd0b4b987943c48dffb5a9c55f02
[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(41);
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_from_c, darray_foreach, darray_foreach_reverse);
75         {
76                 long   *i;
77                 size_t  j;
78                 
79                 darray_from_c(arr, lotsOfNumbers);
80                 ok1(darray_size(arr) == ARRAY_SIZE(lotsOfNumbers));
81                 ok1(darray_alloc(arr) >= darray_size(arr));
82                 ok1(memcmp(arr.item, lotsOfNumbers, sizeof(lotsOfNumbers)) == 0);
83                 
84                 j = 0;
85                 darray_foreach(i, arr) {
86                         if (i - arr.item != j)
87                                 break;
88                         if (*i != (long)lotsOfNumbers[j])
89                                 break;
90                         j++;
91                 };
92                 ok1(j == ARRAY_SIZE(lotsOfNumbers));
93                 
94                 j = 0;
95                 darray_foreach_reverse(i, arr) {
96                         if (i - arr.item != darray_size(arr)-j-1)
97                                 break;
98                         if (*i != (long)lotsOfNumbers[darray_size(arr)-j-1])
99                                 break;
100                         j++;
101                 };
102                 ok1(j == ARRAY_SIZE(lotsOfNumbers));
103         }
104         reset(arr);
105         
106         testing(darray_append_string);
107         {
108                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
109                         darray_append_string(str, lotsOfStrings[i]);
110                 ok1(str.size == amalgams.stringsSize);
111                 ok1(str.alloc > str.size);
112                 ok1(str.item[str.size] == 0);
113                 ok1(!strcmp(str.item, amalgams.stringsF));
114         }
115         reset(str);
116         
117         testing(darray_prepend_string);
118         {
119                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
120                         darray_prepend_string(str, lotsOfStrings[i]);
121                 ok1(str.size == amalgams.stringsSize);
122                 ok1(str.alloc > str.size);
123                 ok1(str.item[str.size] == 0);
124                 ok1(!strcmp(str.item, amalgams.stringsB));
125         }
126         reset(str);
127         
128         testing(darray_from_string);
129         {
130                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++) {
131                         darray_from_string(str, lotsOfStrings[i]);
132                         if (str.size != strlen(lotsOfStrings[i]))
133                                 break;
134                         if (str.alloc < strlen(lotsOfStrings[i])+1)
135                                 break;
136                         if (strcmp(str.item, lotsOfStrings[i]))
137                                 break;
138                 }
139                 ok1(i == ARRAY_SIZE(lotsOfStrings));
140         }
141         reset(str);
142         
143         testing(darray_resize0);
144         {
145                 size_t prevSize=0, size;
146                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++, prevSize=size) {
147                         size = lotsOfNumbers[i] & 0xFFFF;
148                         darray_resize0(arr, size);
149                         if (darray_size(arr) != size)
150                                 break;
151                         if (darray_alloc(arr) < size)
152                                 break;
153                         if (size>prevSize) {
154                                 if (!isZeros(arr.item+prevSize, (size-prevSize)*sizeof(*arr.item)))
155                                         break;
156                         }
157                         //fill the darray with lotsOfNumbers garbage
158                         memtile(arr.item, darray_size(arr)*sizeof(*arr.item), lotsOfNumbers, sizeof(lotsOfNumbers));
159                 }
160                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
161         }
162         reset(arr);
163         
164         testing(darray_realloc);
165         {
166                 size_t s,a;
167                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++) {
168                         arr.size = (s = lotsOfNumbers[i] >> 16);
169                                 //give size a nonsense value to make sure darray_realloc doesn't care about it
170                         a = amalgams.stringsSize/sizeof(*arr.item)+2;
171                         darray_realloc(arr, a = lotsOfNumbers[i] % ((amalgams.stringsSize/sizeof(*arr.item))+1));
172                         if (a*sizeof(*arr.item) > amalgams.stringsSize)
173                                 break;
174                         if (darray_alloc(arr) != a)
175                                 break;
176                         if (darray_size(arr) != s)
177                                 break;
178                         memtile(arr.item, a*sizeof(*arr.item), amalgams.stringsF, a*sizeof(*arr.item));
179                         if (memcmp(arr.item, amalgams.stringsF, a*sizeof(*arr.item)))
180                                 break;
181                 }
182                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
183         }
184         reset(arr);
185         
186         testing(darray_growalloc);
187         {
188                 size_t prevA, s, a;
189                 for (i=0; i < ARRAY_SIZE(lotsOfNumbers); i++) {
190                         arr.size = (s = lotsOfNumbers[i] >> 16);
191                                 //give size a nonsense value to make sure darray_growalloc doesn't care about it
192                         a = amalgams.stringsSize/sizeof(*arr.item)+2;
193                         prevA = darray_alloc(arr);
194                         darray_growalloc(arr, a = lotsOfNumbers[i] % ((amalgams.stringsSize/sizeof(*arr.item))+1));
195                         if (a*sizeof(*arr.item) > amalgams.stringsSize)
196                                 break;
197                         if (darray_alloc(arr) < a)
198                                 break;
199                         if (darray_alloc(arr) < prevA)
200                                 break;
201                         if (darray_size(arr) != s)
202                                 break;
203                         
204                         memtile(arr.item, a*sizeof(*arr.item), amalgams.stringsF, a*sizeof(*arr.item));
205                         if (memcmp(arr.item, amalgams.stringsF, a*sizeof(*arr.item)))
206                                 break;
207                         
208                         //clear the darray every now and then
209                         if (!(lotsOfNumbers[i] & 15)) {
210                                 reset(arr);
211                         }
212                 }
213                 ok1(i == ARRAY_SIZE(lotsOfNumbers));
214         }
215         reset(arr);
216         
217         testing(darray_make_room);
218         {
219                 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++) {
220                         char *dest = darray_make_room(str, strlen(lotsOfStrings[i]));
221                         if (str.alloc < str.size+strlen(lotsOfStrings[i]))
222                                 break;
223                         if (dest != str.item+str.size)
224                                 break;
225                         
226                         memcpy(dest, lotsOfStrings[i], strlen(lotsOfStrings[i]));
227                         str.size += strlen(lotsOfStrings[i]);
228                 }
229                 ok1(i == ARRAY_SIZE(lotsOfStrings));
230                 ok1(str.size == amalgams.stringsSize);
231                 
232                 darray_append(str, 0);
233                 ok1(!strcmp(str.item, amalgams.stringsF));
234         }
235         reset(str);
236         
237         testing(darray_appends, darray_prepends, darray_pop_check);
238         {
239                 darray(const char*) arr = darray_new();
240                 const char *n[9] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight"};
241
242 #if HAVE_TYPEOF         
243                 darray_appends(arr, n[5], n[6], n[7], n[8]);
244 #else
245                 darray_appends_t(arr, const char *, n[5], n[6], n[7], n[8]);
246 #endif
247                 ok1(darray_size(arr)==4 && darray_alloc(arr)>=4);
248
249 #if HAVE_TYPEOF         
250                 darray_prepends(arr, n[0], n[1], n[2], n[3], n[4]);
251 #else
252                 darray_prepends_t(arr, const char *, n[0], n[1], n[2], n[3], n[4]);
253 #endif
254
255                 ok1(darray_size(arr)==9 && darray_alloc(arr)>=9);
256                 
257                 ok1(arr.item[0]==n[0] &&
258                     arr.item[1]==n[1] &&
259                     arr.item[2]==n[2] &&
260                     arr.item[3]==n[3] &&
261                     arr.item[4]==n[4] &&
262                     arr.item[5]==n[5] &&
263                     arr.item[6]==n[6] &&
264                     arr.item[7]==n[7] &&
265                     arr.item[8]==n[8]);
266                 
267                 ok1(darray_pop_check(arr)==n[8] &&
268                     darray_pop_check(arr)==n[7] &&
269                     darray_pop_check(arr)==n[6] &&
270                     darray_pop_check(arr)==n[5] &&
271                     darray_pop_check(arr)==n[4] &&
272                     darray_pop_check(arr)==n[3] &&
273                     darray_pop_check(arr)==n[2] &&
274                     darray_pop_check(arr)==n[1] &&
275                     darray_pop_check(arr)==n[0]);
276                 
277                 ok1(darray_size(arr)==0);
278                 
279                 ok1(darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL);
280                 
281                 darray_free(arr);
282         }
283         
284         trace("Freeing amalgams (internal)");
285         freeAmalgams();
286         
287         return exit_status();
288 }
289
290 static void generateAmalgams(void) {
291         size_t i;
292         size_t lotsOfStringsLen = 0;
293         const char *src;
294         char *p;
295         
296         for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
297                 lotsOfStringsLen += strlen(lotsOfStrings[i]);
298         amalgams.stringsSize = lotsOfStringsLen;
299         
300         amalgams.stringsF = malloc(lotsOfStringsLen+1);
301         amalgams.stringsB = malloc(lotsOfStringsLen+1);
302         
303         for (i=0,p=amalgams.stringsF; i < ARRAY_SIZE(lotsOfStrings); i++) {
304                 size_t len = strlen(src=lotsOfStrings[i]);
305                 memcpy(p, src, len);
306                 p += len;
307         }
308         *p = 0;
309         ok1(p-amalgams.stringsF == (long)lotsOfStringsLen);
310         ok1(strlen(amalgams.stringsF) == lotsOfStringsLen);
311         
312         for (i = ARRAY_SIZE(lotsOfStrings), p = amalgams.stringsB; i--;) {
313                 size_t len = strlen(src=lotsOfStrings[i]);
314                 memcpy(p, src, len);
315                 p += len;
316         }
317         *p = 0;
318         ok1(p-amalgams.stringsB == (long)lotsOfStringsLen);
319         ok1(strlen(amalgams.stringsB) == lotsOfStringsLen);
320 }
321
322 static void freeAmalgams(void) {
323         free(amalgams.stringsF);
324         free(amalgams.stringsB);
325 }
326
327 static int isZeros(void *ptr, size_t size) {
328         unsigned char *pc = ptr;
329         size_t *pl;
330         if (size>8) {
331                 //test one byte at a time until we have an aligned size_t pointer
332                 while ((size_t)pc & (sizeof(size_t)-1))
333                         if (*pc++)
334                                 return 0;
335                 pl = (size_t*)pc;
336                 size -= pc-(unsigned char*)ptr;
337                 while (size >= sizeof(size_t)) {
338                         size -= sizeof(size_t);
339                         if (*pl++)
340                                 return 0;
341                 }
342                 pc = (unsigned char*)pl;
343         }
344         while (size--)
345                 if (*pc++)
346                         return 0;
347         return 1;
348 }
349
350 static void memtile(void *dest, size_t destWidth, const void *src, size_t srcWidth) {
351         char *d = dest;
352         while (destWidth > srcWidth) {
353                 destWidth -= srcWidth;
354                 memcpy(d, src, srcWidth);
355                 d += srcWidth;
356         }
357         memcpy(d, src, destWidth);
358 }