1 #include <ccan/tap/tap.h>
2 #include <ccan/darray/darray.h>
5 #include "lotsOfNumbers.h"
6 #include "lotsOfStrings.h"
8 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*(arr)))
11 char *stringsF, *stringsB;
12 //items of lotsOfStrings glued together
13 size_t stringsSize; //total strlen of all strings combined
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);
23 #define testing(...) printf("Testing %s...\n", #__VA_ARGS__)
24 #define trace(...) do {printf(__VA_ARGS__); puts("");} while(0)
26 #define testing(...) do {} while(0)
27 #define trace(...) do {} while(0)
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)
38 trace("Generating amalgams (internal)");
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)));
55 testing(darray_prepend, darray_pop);
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)));
63 for (i = ARRAY_SIZE(lotsOfNumbers); i;) {
64 if (darray_pop(arr) != (long)lotsOfNumbers[--i]) {
70 ok1(darray_size(arr) == 0);
74 testing(darray_from_c, darray_foreach, darray_foreach_reverse);
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);
85 darray_foreach(i, arr) {
86 if (i - arr.item != j)
88 if (*i != (long)lotsOfNumbers[j])
92 ok1(j == ARRAY_SIZE(lotsOfNumbers));
95 darray_foreach_reverse(i, arr) {
96 if (i - arr.item != darray_size(arr)-j-1)
98 if (*i != (long)lotsOfNumbers[darray_size(arr)-j-1])
102 ok1(j == ARRAY_SIZE(lotsOfNumbers));
106 testing(darray_append_string);
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));
117 testing(darray_prepend_string);
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));
128 testing(darray_from_string);
130 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++) {
131 darray_from_string(str, lotsOfStrings[i]);
132 if (str.size != strlen(lotsOfStrings[i]))
134 if (str.alloc < strlen(lotsOfStrings[i])+1)
136 if (strcmp(str.item, lotsOfStrings[i]))
139 ok1(i == ARRAY_SIZE(lotsOfStrings));
143 testing(darray_resize0);
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)
151 if (darray_alloc(arr) < size)
154 if (!isZeros(arr.item+prevSize, (size-prevSize)*sizeof(*arr.item)))
157 //fill the darray with lotsOfNumbers garbage
158 memtile(arr.item, darray_size(arr)*sizeof(*arr.item), lotsOfNumbers, sizeof(lotsOfNumbers));
160 ok1(i == ARRAY_SIZE(lotsOfNumbers));
164 testing(darray_realloc);
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)
174 if (darray_alloc(arr) != a)
176 if (darray_size(arr) != s)
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)))
182 ok1(i == ARRAY_SIZE(lotsOfNumbers));
186 testing(darray_growalloc);
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)
197 if (darray_alloc(arr) < a)
199 if (darray_alloc(arr) < prevA)
201 if (darray_size(arr) != s)
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)))
208 //clear the darray every now and then
209 if (!(lotsOfNumbers[i] & 15)) {
213 ok1(i == ARRAY_SIZE(lotsOfNumbers));
217 testing(darray_make_room);
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]))
223 if (dest != str.item+str.size)
226 memcpy(dest, lotsOfStrings[i], strlen(lotsOfStrings[i]));
227 str.size += strlen(lotsOfStrings[i]);
229 ok1(i == ARRAY_SIZE(lotsOfStrings));
230 ok1(str.size == amalgams.stringsSize);
232 darray_append(str, 0);
233 ok1(!strcmp(str.item, amalgams.stringsF));
237 testing(darray_appends, darray_prepends, darray_pop_check);
239 darray(const char*) arr = darray_new();
240 const char *n[9] = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight"};
242 darray_appends(arr, n[5], n[6], n[7], n[8]);
243 ok1(darray_size(arr)==4 && darray_alloc(arr)>=4);
245 darray_prepends(arr, n[0], n[1], n[2], n[3], n[4]);
246 ok1(darray_size(arr)==9 && darray_alloc(arr)>=9);
248 ok1(arr.item[0]==n[0] &&
258 ok1(darray_pop_check(arr)==n[8] &&
259 darray_pop_check(arr)==n[7] &&
260 darray_pop_check(arr)==n[6] &&
261 darray_pop_check(arr)==n[5] &&
262 darray_pop_check(arr)==n[4] &&
263 darray_pop_check(arr)==n[3] &&
264 darray_pop_check(arr)==n[2] &&
265 darray_pop_check(arr)==n[1] &&
266 darray_pop_check(arr)==n[0]);
268 ok1(darray_size(arr)==0);
270 ok1(darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL && darray_pop_check(arr)==NULL);
275 trace("Freeing amalgams (internal)");
278 return exit_status();
281 static void generateAmalgams(void) {
283 size_t lotsOfStringsLen = 0;
287 for (i=0; i < ARRAY_SIZE(lotsOfStrings); i++)
288 lotsOfStringsLen += strlen(lotsOfStrings[i]);
289 amalgams.stringsSize = lotsOfStringsLen;
291 amalgams.stringsF = malloc(lotsOfStringsLen+1);
292 amalgams.stringsB = malloc(lotsOfStringsLen+1);
294 for (i=0,p=amalgams.stringsF; i < ARRAY_SIZE(lotsOfStrings); i++) {
295 size_t len = strlen(src=lotsOfStrings[i]);
300 ok1(p-amalgams.stringsF == (long)lotsOfStringsLen);
301 ok1(strlen(amalgams.stringsF) == lotsOfStringsLen);
303 for (i = ARRAY_SIZE(lotsOfStrings), p = amalgams.stringsB; i--;) {
304 size_t len = strlen(src=lotsOfStrings[i]);
309 ok1(p-amalgams.stringsB == (long)lotsOfStringsLen);
310 ok1(strlen(amalgams.stringsB) == lotsOfStringsLen);
313 static void freeAmalgams(void) {
314 free(amalgams.stringsF);
315 free(amalgams.stringsB);
318 static int isZeros(void *ptr, size_t size) {
319 unsigned char *pc = ptr;
322 //test one byte at a time until we have an aligned size_t pointer
323 while ((size_t)pc & (sizeof(size_t)-1))
327 size -= pc-(unsigned char*)ptr;
328 while (size >= sizeof(size_t)) {
329 size -= sizeof(size_t);
333 pc = (unsigned char*)pl;
341 static void memtile(void *dest, size_t destWidth, const void *src, size_t srcWidth) {
343 while (destWidth > srcWidth) {
344 destWidth -= srcWidth;
345 memcpy(d, src, srcWidth);
348 memcpy(d, src, destWidth);