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