gp: Test with binary content for certificate data
[Samba.git] / third_party / heimdal / lib / base / test_base.c
blobcc875d7f8b609098914c76c11b1015c62df4f42a
1 /*
2 * Copyright (c) 2010-2016 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Portions Copyright (c) 2010 Apple Inc. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
37 * This is a test of libheimbase functionality. If you make any changes
38 * to libheimbase or to this test you should run it under valgrind with
39 * the following options:
41 * -v --track-fds=yes --num-callers=30 --leak-check=full
43 * and make sure that there are no leaks that don't have
44 * __heim_string_constant() or heim_db_register() in their stack trace.
47 #include <err.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #ifndef WIN32
55 #include <sys/file.h>
56 #include <locale.h>
57 #endif
58 #ifdef HAVE_IO_H
59 #include <io.h>
60 #endif
61 #ifdef HAVE_UNISTD_H
62 #include <unistd.h>
63 #endif
64 #include <fcntl.h>
66 #include "baselocl.h"
67 #include "heimbase-atomics.h"
69 static void HEIM_CALLCONV
70 memory_free(heim_object_t obj)
74 static int
75 test_memory(void)
77 void *ptr;
79 ptr = heim_alloc(10, "memory", memory_free);
81 heim_retain(ptr);
82 heim_release(ptr);
84 heim_retain(ptr);
85 heim_release(ptr);
87 heim_release(ptr);
89 ptr = heim_alloc(10, "memory", NULL);
90 heim_release(ptr);
92 return 0;
95 static int
96 test_mutex(void)
98 HEIMDAL_MUTEX m = HEIMDAL_MUTEX_INITIALIZER;
100 HEIMDAL_MUTEX_lock(&m);
101 HEIMDAL_MUTEX_unlock(&m);
102 HEIMDAL_MUTEX_destroy(&m);
104 HEIMDAL_MUTEX_init(&m);
105 HEIMDAL_MUTEX_lock(&m);
106 HEIMDAL_MUTEX_unlock(&m);
107 HEIMDAL_MUTEX_destroy(&m);
109 return 0;
112 static int
113 test_rwlock(void)
115 HEIMDAL_RWLOCK l = HEIMDAL_RWLOCK_INITIALIZER;
117 HEIMDAL_RWLOCK_rdlock(&l);
118 HEIMDAL_RWLOCK_unlock(&l);
119 HEIMDAL_RWLOCK_wrlock(&l);
120 HEIMDAL_RWLOCK_unlock(&l);
121 if (HEIMDAL_RWLOCK_trywrlock(&l) != 0)
122 err(1, "HEIMDAL_RWLOCK_trywrlock() failed with lock not held");
123 HEIMDAL_RWLOCK_unlock(&l);
124 if (HEIMDAL_RWLOCK_tryrdlock(&l))
125 err(1, "HEIMDAL_RWLOCK_tryrdlock() failed with lock not held");
126 HEIMDAL_RWLOCK_unlock(&l);
127 HEIMDAL_RWLOCK_destroy(&l);
129 HEIMDAL_RWLOCK_init(&l);
130 HEIMDAL_RWLOCK_rdlock(&l);
131 HEIMDAL_RWLOCK_unlock(&l);
132 HEIMDAL_RWLOCK_wrlock(&l);
133 HEIMDAL_RWLOCK_unlock(&l);
134 if (HEIMDAL_RWLOCK_trywrlock(&l))
135 err(1, "HEIMDAL_RWLOCK_trywrlock() failed with lock not held");
136 HEIMDAL_RWLOCK_unlock(&l);
137 if (HEIMDAL_RWLOCK_tryrdlock(&l))
138 err(1, "HEIMDAL_RWLOCK_tryrdlock() failed with lock not held");
139 HEIMDAL_RWLOCK_unlock(&l);
140 HEIMDAL_RWLOCK_destroy(&l);
142 return 0;
145 static int
146 test_dict(void)
148 heim_dict_t dict;
149 heim_number_t a1 = heim_number_create(1);
150 heim_string_t a2 = heim_string_create("hejsan");
151 heim_number_t a3 = heim_number_create(3);
152 heim_string_t a4 = heim_string_create("foosan");
154 dict = heim_dict_create(10);
156 heim_dict_set_value(dict, a1, a2);
157 heim_dict_set_value(dict, a3, a4);
159 heim_dict_delete_key(dict, a3);
160 heim_dict_delete_key(dict, a1);
162 heim_release(a1);
163 heim_release(a2);
164 heim_release(a3);
165 heim_release(a4);
167 heim_release(dict);
169 return 0;
172 static int
173 test_auto_release(void)
175 heim_auto_release_t ar1, ar2;
176 heim_number_t n1;
177 heim_string_t s1;
179 ar1 = heim_auto_release_create();
181 s1 = heim_string_create("hejsan");
182 heim_auto_release(s1);
184 n1 = heim_number_create(1);
185 heim_auto_release(n1);
187 ar2 = heim_auto_release_create();
189 n1 = heim_number_create(1);
190 heim_auto_release(n1);
192 heim_release(ar2);
193 heim_release(ar1);
195 return 0;
198 static int
199 test_string(void)
201 heim_string_t s1, s2;
202 const char *string = "hejsan";
204 s1 = heim_string_create(string);
205 s2 = heim_string_create(string);
207 if (heim_cmp(s1, s2) != 0) {
208 printf("the same string is not the same\n");
209 exit(1);
212 heim_release(s1);
213 heim_release(s2);
215 return 0;
218 static int
219 test_error(void)
221 heim_error_t e;
222 heim_string_t s;
224 e = heim_error_create(10, "foo: %s", "bar");
225 heim_assert(heim_error_get_code(e) == 10, "error_code != 10");
227 s = heim_error_copy_string(e);
228 heim_assert(strcmp(heim_string_get_utf8(s), "foo: bar") == 0, "msg wrong");
230 heim_release(s);
231 heim_release(e);
233 return 0;
236 static int
237 test_json(void)
239 static char *j[] = {
240 "{ \"k1\" : \"s1\", \"k2\" : \"s2\" }",
241 "{ \"k1\" : [\"s1\", \"s2\", \"s3\"], \"k2\" : \"s3\" }",
242 "{ \"k1\" : {\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"}, \"k5\" : \"s4\" }",
243 ("[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, "
244 "null, true, false, 123456789, \"\"]"),
245 " -1"
247 char *s;
248 size_t i, k;
249 heim_object_t o, o2, o3;
250 heim_string_t k1 = heim_string_create("k1");
252 o = heim_json_create("\"string\"", 10, 0, NULL);
253 heim_assert(o != NULL, "string");
254 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
255 heim_assert(strcmp("string", heim_string_get_utf8(o)) == 0, "wrong string");
256 o2 = heim_json_copy_serialize(o, 0, NULL);
257 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
258 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
259 heim_release(o3);
260 heim_release(o2);
261 heim_release(o);
264 * Test string escaping:
266 * - C-like must-escapes
267 * - ASCII control character must-escapes
268 * - surrogate pairs
270 * We test round-tripping. First we parse, then we serialize, then parse,
271 * then compare the second parse to the first for equality.
273 * We do compare serialized forms in spite of their not being canonical.
274 * That means that some changes to serialization can cause failures here.
276 o = heim_json_create("\""
277 "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
278 "\x1e" /* ASCII control character w/o C-like escape */
279 "\\u00e1" /* &aacute; */
280 "\\u07ff"
281 "\\u0801"
282 "\\u8001"
283 "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
284 "\"", 10, 0, NULL);
285 heim_assert(o != NULL, "string");
286 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
287 heim_assert(strcmp(
288 "\b\f\n\r\t"
289 "\x1e"
290 "\xc3\xa1"
291 "\xdf\xbf"
292 "\xe0\xA0\x81"
293 "\xe8\x80\x81"
294 "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
295 o2 = heim_json_copy_serialize(o,
296 HEIM_JSON_F_STRICT |
297 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
298 heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001Eá߿ࠁ老\\uD834\\uDD1E\"",
299 heim_string_get_utf8(o2)) == 0,
300 "JSON encoding changed; please check that it is till valid");
301 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
302 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
303 heim_release(o3);
304 heim_release(o2);
305 heim_release(o);
307 o = heim_json_create("\""
308 "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
309 "\x1e" /* ASCII control character w/o C-like escape */
310 "\xc3\xa1"
311 "\xdf\xbf"
312 "\xe0\xa0\x81"
313 "\xE8\x80\x81"
314 "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
315 "\"", 10, 0, NULL);
316 heim_assert(o != NULL, "string");
317 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
318 heim_assert(strcmp(
319 "\b\f\n\r\t"
320 "\x1e"
321 "\xc3\xa1"
322 "\xdf\xbf"
323 "\xe0\xA0\x81"
324 "\xe8\x80\x81"
325 "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
326 o2 = heim_json_copy_serialize(o,
327 HEIM_JSON_F_STRICT |
328 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
329 heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001Eá߿ࠁ老\\uD834\\uDD1E\"",
330 heim_string_get_utf8(o2)) == 0,
331 "JSON encoding changed; please check that it is till valid");
332 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
333 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
334 heim_release(o3);
335 heim_release(o2);
336 heim_release(o);
339 * Test HEIM_JSON_F_ESCAPE_NON_ASCII.
341 * Also test that we get escaped non-ASCII because we're in a not-UTF-8
342 * locale, since we setlocale(LC_ALL, "C"), so we should escape non-ASCII
343 * by default.
345 o = heim_json_create("\""
346 "\\b\\f\\n\\r\\t" /* ASCII C-like escapes */
347 "\x1e" /* ASCII control character w/o C-like escape */
348 "\xc3\xa1"
349 "\xdf\xbf"
350 "\xe0\xa0\x81"
351 "\xE8\x80\x81"
352 "\\uD834\\udd1e" /* U+1D11E, as shown in RFC 7159 */
353 "\"", 10, 0, NULL);
354 heim_assert(o != NULL, "string");
355 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
356 heim_assert(strcmp(
357 "\b\f\n\r\t"
358 "\x1e"
359 "\xc3\xa1"
360 "\xdf\xbf"
361 "\xe0\xA0\x81"
362 "\xe8\x80\x81"
363 "\xf0\x9d\x84\x9e", heim_string_get_utf8(o)) == 0, "wrong string");
364 o2 = heim_json_copy_serialize(o,
365 HEIM_JSON_F_STRICT |
366 HEIM_JSON_F_ESCAPE_NON_ASCII, NULL);
367 heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001E\\u00E1\\u07FF\\u0801\\u8001"
368 "\\uD834\\uDD1E\"",
369 heim_string_get_utf8(o2)) == 0,
370 "JSON encoding changed; please check that it is till valid");
371 heim_release(o2);
372 o2 = heim_json_copy_serialize(o, HEIM_JSON_F_STRICT, NULL);
373 heim_assert(strcmp("\"\\b\\f\\n\\r\\t\\u001E\\u00E1\\u07FF\\u0801\\u8001"
374 "\\uD834\\uDD1E\"",
375 heim_string_get_utf8(o2)) == 0,
376 "JSON encoding changed; please check that it is till valid");
377 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
378 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
379 heim_release(o3);
380 heim_release(o2);
381 heim_release(o);
383 /* Test rejection of unescaped ASCII control characters */
384 o = heim_json_create("\"\b\\f\"", 10, HEIM_JSON_F_STRICT, NULL);
385 heim_assert(o == NULL, "strict parse accepted bad input");
386 o = heim_json_create("\"\b\x1e\"", 10, HEIM_JSON_F_STRICT, NULL);
387 heim_assert(o == NULL, "strict parse accepted bad input");
389 o = heim_json_create("\"\b\\f\"", 10, 0, NULL);
390 heim_assert(o != NULL, "string");
391 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
392 heim_assert(strcmp("\b\f", heim_string_get_utf8(o)) == 0, "wrong string");
393 o2 = heim_json_copy_serialize(o,
394 HEIM_JSON_F_STRICT |
395 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
396 heim_assert(strcmp("\"\\b\\f\"", heim_string_get_utf8(o2)) == 0,
397 "JSON encoding changed; please check that it is till valid");
398 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
399 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
400 heim_release(o3);
401 heim_release(o2);
402 heim_release(o);
404 /* Test bogus backslash escape */
405 o = heim_json_create("\""
406 "\\ "
407 "\"", 10, HEIM_JSON_F_STRICT, NULL);
408 heim_assert(o == NULL, "malformed string accepted");
409 o = heim_json_create("\""
410 "\\ "
411 "\"", 10, 0, NULL);
412 heim_assert(o != NULL, "malformed string rejected (not strict)");
413 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
414 heim_assert(strcmp(" ", heim_string_get_utf8(o)) == 0, "wrong string");
415 o2 = heim_json_copy_serialize(o,
416 HEIM_JSON_F_STRICT |
417 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
418 heim_assert(strcmp("\" \"", heim_string_get_utf8(o2)) == 0,
419 "JSON encoding changed; please check that it is till valid");
420 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
421 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
422 heim_release(o3);
423 heim_release(o2);
424 heim_release(o);
426 /* Test truncated surrogate encoding (bottom code unit) */
427 o = heim_json_create("\""
428 "\xE8\x80\x81"
429 "\\uD834\\udd"
430 "\"", 10, HEIM_JSON_F_STRICT, NULL);
431 heim_assert(o == NULL, "malformed string accepted");
432 o = heim_json_create("\""
433 "\xE8\x80\x81"
434 "\\uD834\\udd"
435 "\"", 10, 0, NULL);
436 heim_assert(o != NULL, "malformed string rejected (not strict)");
437 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
438 heim_assert(strcmp(
439 "\xe8\x80\x81"
440 "\\uD834\\udd", heim_string_get_utf8(o)) == 0, "wrong string");
441 o2 = heim_json_copy_serialize(o,
442 HEIM_JSON_F_STRICT |
443 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
444 heim_assert(strcmp("\"\\\\uD834\\\\udd\"",
445 heim_string_get_utf8(o2)) == 0,
446 "JSON encoding changed; please check that it is till valid");
447 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
448 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
449 heim_release(o3);
450 heim_release(o2);
451 heim_release(o);
453 /* Test truncated surrogate encodings (top code unit) */
454 o = heim_json_create("\""
455 "\xE8\x80\x81"
456 "\\uD83"
457 "\"", 10, HEIM_JSON_F_STRICT, NULL);
458 heim_assert(o == NULL, "malformed string accepted");
459 o = heim_json_create("\""
460 "\xE8\x80\x81"
461 "\\uD83"
462 "\"", 10, 0, NULL);
463 heim_assert(o != NULL, "malformed string rejected (not strict)");
464 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
465 heim_assert(strcmp(
466 "\xe8\x80\x81"
467 "\\uD83", heim_string_get_utf8(o)) == 0, "wrong string");
468 o2 = heim_json_copy_serialize(o,
469 HEIM_JSON_F_STRICT |
470 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
471 heim_assert(strcmp("\"\\\\uD83\"",
472 heim_string_get_utf8(o2)) == 0,
473 "JSON encoding changed; please check that it is till valid");
474 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
475 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
476 heim_release(o3);
477 heim_release(o2);
478 heim_release(o);
481 * Test handling of truncated UTF-8 multi-byte sequences.
483 o = heim_json_create("\""
484 "\xE8\x80"
485 "\"", 10, 0, NULL);
486 heim_assert(o != NULL, "malformed string rejected (not strict)");
487 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
488 heim_assert(strcmp("\xe8\x80",
489 heim_string_get_utf8(o)) == 0, "wrong string");
490 o2 = heim_json_copy_serialize(o,
491 HEIM_JSON_F_STRICT |
492 HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
493 heim_assert(o2 == NULL, "malformed string serialized");
494 o2 = heim_json_copy_serialize(o, HEIM_JSON_F_NO_ESCAPE_NON_ASCII, NULL);
495 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
496 heim_assert(o3 == NULL, "malformed string accepted (not strict)");
497 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
498 heim_assert(strcmp("\xe8\x80",
499 heim_string_get_utf8(o3)) == 0, "wrong string");
500 heim_release(o3);
501 heim_release(o2);
502 heim_release(o);
504 /* Test handling of unescaped / embedded newline */
505 o = heim_json_create("\"\n\"", 10, HEIM_JSON_F_STRICT, NULL);
506 heim_assert(o == NULL, "malformed string accepted (strict)");
507 o = heim_json_create("\"\n\"", 10, 0, NULL);
508 heim_assert(o != NULL, "malformed string rejected (not strict)");
509 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
510 heim_assert(strcmp("\n", heim_string_get_utf8(o)) == 0, "wrong string");
511 o2 = heim_json_copy_serialize(o, HEIM_JSON_F_STRICT, NULL);
512 heim_assert(o2 != NULL, "string not serialized");
513 o3 = heim_json_create(heim_string_get_utf8(o2), 10, HEIM_JSON_F_STRICT, NULL);
514 heim_assert(o3 != NULL, "string not accepted");
515 heim_assert(strcmp("\n", heim_string_get_utf8(o3)) == 0, "wrong string");
516 heim_release(o3);
517 heim_release(o2);
518 heim_release(o);
520 /* Test handling of embedded NULs (must decode as data, not string) */
521 o = heim_json_create("\"\\u0000\"", 10, HEIM_JSON_F_STRICT, NULL);
522 heim_assert(o != NULL, "string with NULs rejected");
523 heim_assert(heim_get_tid(o) == heim_data_get_type_id(), "data-tid");
524 heim_assert(heim_data_get_length(o) == 1, "wrong data length");
525 heim_assert(((const char *)heim_data_get_ptr(o))[0] == '\0',
526 "wrong data NUL");
527 o2 = heim_json_copy_serialize(o, 0, NULL);
528 heim_assert(o2 != NULL, "data not serialized");
529 heim_release(o2);
530 heim_release(o);
533 * Note that the trailing ']' is not part of the JSON text (which is just a
534 * string).
536 o = heim_json_create(" \"foo\\\"bar\" ]", 10, 0, NULL);
537 heim_assert(o != NULL, "string");
538 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
539 heim_assert(strcmp("foo\"bar", heim_string_get_utf8(o)) == 0, "wrong string");
540 o2 = heim_json_copy_serialize(o, 0, NULL);
541 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
542 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
543 heim_release(o3);
544 heim_release(o2);
545 heim_release(o);
547 o = heim_json_create(" { \"key\" : \"value\" }", 10, 0, NULL);
548 heim_assert(o != NULL, "dict");
549 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
550 o2 = heim_json_copy_serialize(o, 0, NULL);
551 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
552 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
553 heim_release(o3);
554 heim_release(o2);
555 heim_release(o);
558 * heim_json_eq() can't handle dicts with dicts as keys, so we don't check
559 * for round-tripping here
561 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
562 "{ \"k3\" : \"s4\" } : -1 }", 10, 0, NULL);
563 heim_assert(o != NULL, "dict");
564 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
565 heim_release(o);
567 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
568 "{ \"k3\" : \"s4\" } : -1 }", 10,
569 HEIM_JSON_F_STRICT_DICT, NULL);
570 heim_assert(o == NULL, "dict");
572 o = heim_json_create(" { \"k1\" : \"s1\", \"k2\" : \"s2\" }", 10, 0, NULL);
573 heim_assert(o != NULL, "dict");
574 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
575 o2 = heim_dict_copy_value(o, k1);
576 heim_assert(heim_get_tid(o2) == heim_string_get_type_id(), "string-tid");
577 heim_release(o2);
578 o2 = heim_json_copy_serialize(o, 0, NULL);
579 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
580 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
581 heim_release(o3);
582 heim_release(o2);
583 heim_release(o);
585 o = heim_json_create(" { \"k1\" : { \"k2\" : \"s2\" } }", 10, 0, NULL);
586 heim_assert(o != NULL, "dict");
587 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
588 o2 = heim_dict_copy_value(o, k1);
589 heim_assert(heim_get_tid(o2) == heim_dict_get_type_id(), "dict-tid");
590 heim_release(o2);
591 o2 = heim_json_copy_serialize(o, 0, NULL);
592 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
593 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
594 heim_release(o3);
595 heim_release(o2);
596 heim_release(o);
598 o = heim_json_create("{ \"k1\" : 1 }", 10, 0, NULL);
599 heim_assert(o != NULL, "array");
600 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
601 o2 = heim_dict_copy_value(o, k1);
602 heim_assert(heim_get_tid(o2) == heim_number_get_type_id(), "number-tid");
603 heim_release(o2);
604 o2 = heim_json_copy_serialize(o, 0, NULL);
605 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
606 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
607 heim_release(o3);
608 heim_release(o2);
609 heim_release(o);
611 o = heim_json_create("-10", 10, 0, NULL);
612 heim_assert(o != NULL, "number");
613 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
614 o2 = heim_json_copy_serialize(o, 0, NULL);
615 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
616 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
617 heim_release(o3);
618 heim_release(o2);
619 heim_release(o);
621 o = heim_json_create("99", 10, 0, NULL);
622 heim_assert(o != NULL, "number");
623 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
624 o2 = heim_json_copy_serialize(o, 0, NULL);
625 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
626 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
627 heim_release(o3);
628 heim_release(o2);
629 heim_release(o);
631 o = heim_json_create(" [ 1 ]", 10, 0, NULL);
632 heim_assert(o != NULL, "array");
633 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
634 o2 = heim_json_copy_serialize(o, 0, NULL);
635 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
636 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
637 heim_release(o3);
638 heim_release(o2);
639 heim_release(o);
641 o = heim_json_create(" [ -1 ]", 10, 0, NULL);
642 heim_assert(o != NULL, "array");
643 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
644 o2 = heim_json_copy_serialize(o, 0, NULL);
645 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
646 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
647 heim_release(o3);
648 heim_release(o2);
649 heim_release(o);
651 for (i = 0; i < (sizeof (j) / sizeof (j[0])); i++) {
652 o = heim_json_create(j[i], 10, 0, NULL);
653 if (o == NULL) {
654 fprintf(stderr, "Failed to parse this JSON: %s\n", j[i]);
655 return 1;
657 o2 = heim_json_copy_serialize(o, 0, NULL);
658 o3 = heim_json_create(heim_string_get_utf8(o2), 10, 0, NULL);
659 heim_assert(heim_json_eq(o, o3), "JSON text did not round-trip");
660 heim_release(o3);
661 heim_release(o2);
662 heim_release(o);
663 /* Simple fuzz test */
664 for (k = strlen(j[i]) - 1; k > 0; k--) {
665 o = heim_json_create_with_bytes(j[i], k, 10, 0, NULL);
666 if (o != NULL) {
667 fprintf(stderr, "Invalid JSON parsed: %.*s\n", (int)k, j[i]);
668 return EINVAL;
671 /* Again, but this time make it so valgrind can find invalid accesses */
672 for (k = strlen(j[i]) - 1; k > 0; k--) {
673 s = strndup(j[i], k);
674 if (s == NULL)
675 return ENOMEM;
676 o = heim_json_create(s, 10, 0, NULL);
677 free(s);
678 if (o != NULL) {
679 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
680 return EINVAL;
683 /* Again, but with no NUL termination */
684 for (k = strlen(j[i]) - 1; k > 0; k--) {
685 s = malloc(k);
686 if (s == NULL)
687 return ENOMEM;
688 memcpy(s, j[i], k);
689 o = heim_json_create_with_bytes(s, k, 10, 0, NULL);
690 free(s);
691 if (o != NULL) {
692 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
693 return EINVAL;
698 heim_release(k1);
700 return 0;
703 static int
704 test_path(void)
706 heim_dict_t dict = heim_dict_create(11);
707 heim_string_t p1 = heim_string_create("abc");
708 heim_string_t p2a = heim_string_create("def");
709 heim_string_t p2b = heim_string_create("DEF");
710 heim_number_t p3 = heim_number_create(0);
711 heim_string_t p4a = heim_string_create("ghi");
712 heim_string_t p4b = heim_string_create("GHI");
713 heim_array_t a = heim_array_create();
714 heim_number_t l1 = heim_number_create(42);
715 heim_number_t l2 = heim_number_create(813);
716 heim_number_t l3 = heim_number_create(1234);
717 heim_string_t k1 = heim_string_create("k1");
718 heim_string_t k2 = heim_string_create("k2");
719 heim_string_t k3 = heim_string_create("k3");
720 heim_string_t k2_1 = heim_string_create("k2-1");
721 heim_string_t k2_2 = heim_string_create("k2-2");
722 heim_string_t k2_3 = heim_string_create("k2-3");
723 heim_string_t k2_4 = heim_string_create("k2-4");
724 heim_string_t k2_5 = heim_string_create("k2-5");
725 heim_string_t k2_5_1 = heim_string_create("k2-5-1");
726 heim_object_t o;
727 heim_object_t neg_num;
728 int ret;
730 if (!dict || !p1 || !p2a || !p2b || !p4a || !p4b)
731 return ENOMEM;
733 ret = heim_path_create(dict, 11, a, NULL, p1, p2a, NULL);
734 heim_release(a);
735 if (ret)
736 return ret;
737 ret = heim_path_create(dict, 11, l3, NULL, p1, p2b, NULL);
738 if (ret)
739 return ret;
740 o = heim_path_get(dict, NULL, p1, p2b, NULL);
741 if (o != l3)
742 return 1;
743 ret = heim_path_create(dict, 11, NULL, NULL, p1, p2a, p3, NULL);
744 if (ret)
745 return ret;
746 ret = heim_path_create(dict, 11, l1, NULL, p1, p2a, p3, p4a, NULL);
747 if (ret)
748 return ret;
749 ret = heim_path_create(dict, 11, l2, NULL, p1, p2a, p3, p4b, NULL);
750 if (ret)
751 return ret;
753 o = heim_path_get(dict, NULL, p1, p2a, p3, p4a, NULL);
754 if (o != l1)
755 return 1;
756 o = heim_path_get(dict, NULL, p1, p2a, p3, p4b, NULL);
757 if (o != l2)
758 return 1;
760 heim_release(dict);
762 /* Test that JSON parsing works right by using heim_path_get() */
763 dict = heim_json_create("{\"k1\":1,"
764 "\"k2\":{\"k2-1\":21,"
765 "\"k2-2\":null,"
766 "\"k2-3\":true,"
767 "\"k2-4\":false,"
768 "\"k2-5\":[1,2,3,{\"k2-5-1\":-1},-2]},"
769 "\"k3\":[true,false,0,42]}", 10, 0, NULL);
770 heim_assert(dict != NULL, "dict");
771 o = heim_path_get(dict, NULL, k1, NULL);
772 if (heim_cmp(o, heim_number_create(1))) return 1;
773 o = heim_path_get(dict, NULL, k2, NULL);
774 if (heim_get_tid(o) != heim_dict_get_type_id()) return 1;
775 o = heim_path_get(dict, NULL, k2, k2_1, NULL);
776 if (heim_cmp(o, heim_number_create(21))) return 1;
777 o = heim_path_get(dict, NULL, k2, k2_2, NULL);
778 if (heim_cmp(o, heim_null_create())) return 1;
779 o = heim_path_get(dict, NULL, k2, k2_3, NULL);
780 if (heim_cmp(o, heim_bool_create(1))) return 1;
781 o = heim_path_get(dict, NULL, k2, k2_4, NULL);
782 if (heim_cmp(o, heim_bool_create(0))) return 1;
783 o = heim_path_get(dict, NULL, k2, k2_5, NULL);
784 if (heim_get_tid(o) != heim_array_get_type_id()) return 1;
785 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(0), NULL);
786 if (heim_cmp(o, heim_number_create(1))) return 1;
787 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(1), NULL);
788 if (heim_cmp(o, heim_number_create(2))) return 1;
789 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(3), k2_5_1, NULL);
790 if (heim_cmp(o, neg_num = heim_number_create(-1))) return 1;
791 heim_release(neg_num);
792 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(4), NULL);
793 if (heim_cmp(o, neg_num = heim_number_create(-2))) return 1;
794 heim_release(neg_num);
795 o = heim_path_get(dict, NULL, k3, heim_number_create(3), NULL);
796 if (heim_cmp(o, heim_number_create(42))) return 1;
798 heim_release(dict);
799 heim_release(p1);
800 heim_release(p2a);
801 heim_release(p2b);
802 heim_release(p4a);
803 heim_release(p4b);
804 heim_release(k1);
805 heim_release(k2);
806 heim_release(k3);
807 heim_release(k2_1);
808 heim_release(k2_2);
809 heim_release(k2_3);
810 heim_release(k2_4);
811 heim_release(k2_5);
812 heim_release(k2_5_1);
814 return 0;
817 typedef struct dict_db {
818 heim_dict_t dict;
819 int locked;
820 } *dict_db_t;
822 static int
823 dict_db_open(void *plug, const char *dbtype, const char *dbname,
824 heim_dict_t options, void **db, heim_error_t *error)
826 dict_db_t dictdb;
827 heim_dict_t contents = NULL;
829 if (error)
830 *error = NULL;
831 if (dbtype && *dbtype && strcmp(dbtype, "dictdb") != 0)
832 return EINVAL;
833 if (dbname && *dbname && strcmp(dbname, "MEMORY") != 0)
834 return EINVAL;
835 dictdb = heim_alloc(sizeof (*dictdb), "dict_db", NULL);
836 if (dictdb == NULL)
837 return ENOMEM;
839 if (contents != NULL)
840 dictdb->dict = contents;
841 else {
842 dictdb->dict = heim_dict_create(29);
843 if (dictdb->dict == NULL) {
844 heim_release(dictdb);
845 return ENOMEM;
849 *db = dictdb;
850 return 0;
853 static int
854 dict_db_close(void *db, heim_error_t *error)
856 dict_db_t dictdb = db;
858 if (error)
859 *error = NULL;
860 heim_release(dictdb->dict);
861 heim_release(dictdb);
862 return 0;
865 static int
866 dict_db_lock(void *db, int read_only, heim_error_t *error)
868 dict_db_t dictdb = db;
870 if (error)
871 *error = NULL;
872 if (dictdb->locked)
873 return EWOULDBLOCK;
874 dictdb->locked = 1;
875 return 0;
878 static int
879 dict_db_unlock(void *db, heim_error_t *error)
881 dict_db_t dictdb = db;
883 if (error)
884 *error = NULL;
885 dictdb->locked = 0;
886 return 0;
889 static heim_data_t
890 dict_db_copy_value(void *db, heim_string_t table, heim_data_t key,
891 heim_error_t *error)
893 dict_db_t dictdb = db;
895 if (error)
896 *error = NULL;
898 return heim_retain(heim_path_get(dictdb->dict, error, table, key, NULL));
901 static int
902 dict_db_set_value(void *db, heim_string_t table,
903 heim_data_t key, heim_data_t value, heim_error_t *error)
905 dict_db_t dictdb = db;
907 if (error)
908 *error = NULL;
910 if (table == NULL)
911 table = HSTR("");
913 return heim_path_create(dictdb->dict, 29, value, error, table, key, NULL);
916 static int
917 dict_db_del_key(void *db, heim_string_t table, heim_data_t key,
918 heim_error_t *error)
920 dict_db_t dictdb = db;
922 if (error)
923 *error = NULL;
925 if (table == NULL)
926 table = HSTR("");
928 heim_path_delete(dictdb->dict, error, table, key, NULL);
929 return 0;
932 struct dict_db_iter_ctx {
933 heim_db_iterator_f_t iter_f;
934 void *iter_ctx;
937 static void dict_db_iter_f(heim_object_t key, heim_object_t value, void *arg)
939 struct dict_db_iter_ctx *ctx = arg;
941 ctx->iter_f((heim_object_t)key, (heim_object_t)value, ctx->iter_ctx);
944 static void
945 dict_db_iter(void *db, heim_string_t table, void *iter_data,
946 heim_db_iterator_f_t iter_f, heim_error_t *error)
948 dict_db_t dictdb = db;
949 struct dict_db_iter_ctx ctx;
950 heim_dict_t table_dict;
952 if (error)
953 *error = NULL;
955 if (table == NULL)
956 table = HSTR("");
958 table_dict = heim_dict_copy_value(dictdb->dict, table);
959 if (table_dict == NULL)
960 return;
962 ctx.iter_ctx = iter_data;
963 ctx.iter_f = iter_f;
965 heim_dict_iterate_f(table_dict, &ctx, dict_db_iter_f);
966 heim_release(table_dict);
969 static void
970 test_db_iter(heim_data_t k, heim_data_t v, void *arg)
972 int *ret = arg;
973 const void *kptr, *vptr;
974 size_t klen, vlen;
976 heim_assert(heim_get_tid(k) == heim_data_get_type_id(), "...");
978 kptr = heim_data_get_ptr(k);
979 klen = heim_data_get_length(k);
980 vptr = heim_data_get_ptr(v);
981 vlen = heim_data_get_length(v);
983 if (klen == strlen("msg") && strncmp(kptr, "msg", strlen("msg")) == 0 &&
984 vlen == strlen("abc") && strncmp(vptr, "abc", strlen("abc")) == 0)
985 *ret &= ~(1);
986 else if (klen == strlen("msg2") &&
987 strncmp(kptr, "msg2", strlen("msg2")) == 0 &&
988 vlen == strlen("FooBar") &&
989 strncmp(vptr, "FooBar", strlen("FooBar")) == 0)
990 *ret &= ~(2);
991 else
992 *ret |= 4;
995 static struct heim_db_type dbt = {
996 1, dict_db_open, NULL, dict_db_close,
997 dict_db_lock, dict_db_unlock, NULL, NULL, NULL, NULL,
998 dict_db_copy_value, dict_db_set_value,
999 dict_db_del_key, dict_db_iter
1002 static int
1003 test_db(const char *dbtype, const char *dbname)
1005 heim_data_t k1, k2, v, v1, v2, v3;
1006 heim_db_t db;
1007 int ret;
1009 if (dbtype == NULL) {
1010 ret = heim_db_register("dictdb", NULL, &dbt);
1011 heim_assert(!ret, "...");
1012 db = heim_db_create("dictdb", "foo", NULL, NULL);
1013 heim_assert(!db, "...");
1014 db = heim_db_create("foobar", "MEMORY", NULL, NULL);
1015 heim_assert(!db, "...");
1016 db = heim_db_create("dictdb", "MEMORY", NULL, NULL);
1017 heim_assert(db, "...");
1018 } else {
1019 heim_dict_t options;
1021 options = heim_dict_create(11);
1022 if (options == NULL) return ENOMEM;
1023 if (heim_dict_set_value(options, HSTR("journal-filename"),
1024 HSTR("json-journal")))
1025 return ENOMEM;
1026 if (heim_dict_set_value(options, HSTR("create"), heim_null_create()))
1027 return ENOMEM;
1028 if (heim_dict_set_value(options, HSTR("truncate"), heim_null_create()))
1029 return ENOMEM;
1030 db = heim_db_create(dbtype, dbname, options, NULL);
1031 heim_assert(db, "...");
1032 heim_release(options);
1035 k1 = heim_data_create("msg", strlen("msg"));
1036 k2 = heim_data_create("msg2", strlen("msg2"));
1037 v1 = heim_data_create("Hello world!", strlen("Hello world!"));
1038 v2 = heim_data_create("FooBar", strlen("FooBar"));
1039 v3 = heim_data_create("abc", strlen("abc"));
1041 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
1042 heim_assert(!ret, "...");
1044 v = heim_db_copy_value(db, NULL, k1, NULL);
1045 heim_assert(v && !heim_cmp(v, v1), "...");
1046 heim_release(v);
1048 ret = heim_db_set_value(db, NULL, k2, v2, NULL);
1049 heim_assert(!ret, "...");
1051 v = heim_db_copy_value(db, NULL, k2, NULL);
1052 heim_assert(v && !heim_cmp(v, v2), "...");
1053 heim_release(v);
1055 ret = heim_db_set_value(db, NULL, k1, v3, NULL);
1056 heim_assert(!ret, "...");
1058 v = heim_db_copy_value(db, NULL, k1, NULL);
1059 heim_assert(v && !heim_cmp(v, v3), "...");
1060 heim_release(v);
1062 ret = 3;
1063 heim_db_iterate_f(db, NULL, &ret, test_db_iter, NULL);
1064 heim_assert(!ret, "...");
1066 ret = heim_db_begin(db, 0, NULL);
1067 heim_assert(!ret, "...");
1069 ret = heim_db_commit(db, NULL);
1070 heim_assert(!ret, "...");
1072 ret = heim_db_begin(db, 0, NULL);
1073 heim_assert(!ret, "...");
1075 ret = heim_db_rollback(db, NULL);
1076 heim_assert(!ret, "...");
1078 ret = heim_db_begin(db, 0, NULL);
1079 heim_assert(!ret, "...");
1081 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
1082 heim_assert(!ret, "...");
1084 v = heim_db_copy_value(db, NULL, k1, NULL);
1085 heim_assert(v && !heim_cmp(v, v1), "...");
1086 heim_release(v);
1088 ret = heim_db_rollback(db, NULL);
1089 heim_assert(!ret, "...");
1091 v = heim_db_copy_value(db, NULL, k1, NULL);
1092 heim_assert(v && !heim_cmp(v, v3), "...");
1093 heim_release(v);
1095 ret = heim_db_begin(db, 0, NULL);
1096 heim_assert(!ret, "...");
1098 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
1099 heim_assert(!ret, "...");
1101 v = heim_db_copy_value(db, NULL, k1, NULL);
1102 heim_assert(v && !heim_cmp(v, v1), "...");
1103 heim_release(v);
1105 ret = heim_db_commit(db, NULL);
1106 heim_assert(!ret, "...");
1108 v = heim_db_copy_value(db, NULL, k1, NULL);
1109 heim_assert(v && !heim_cmp(v, v1), "...");
1110 heim_release(v);
1112 ret = heim_db_begin(db, 0, NULL);
1113 heim_assert(!ret, "...");
1115 ret = heim_db_delete_key(db, NULL, k1, NULL);
1116 heim_assert(!ret, "...");
1118 v = heim_db_copy_value(db, NULL, k1, NULL);
1119 heim_assert(v == NULL, "...");
1120 heim_release(v);
1122 ret = heim_db_rollback(db, NULL);
1123 heim_assert(!ret, "...");
1125 v = heim_db_copy_value(db, NULL, k1, NULL);
1126 heim_assert(v && !heim_cmp(v, v1), "...");
1127 heim_release(v);
1129 if (dbtype != NULL) {
1130 heim_data_t k3 = heim_data_create("value-is-a-dict", strlen("value-is-a-dict"));
1131 heim_dict_t vdict = heim_dict_create(11);
1132 heim_db_t db2;
1134 heim_assert(k3 && vdict, "...");
1135 ret = heim_dict_set_value(vdict, HSTR("vdict-k1"), heim_number_create(11));
1136 heim_assert(!ret, "...");
1137 ret = heim_dict_set_value(vdict, HSTR("vdict-k2"), heim_null_create());
1138 heim_assert(!ret, "...");
1139 ret = heim_dict_set_value(vdict, HSTR("vdict-k3"), HSTR("a value"));
1140 heim_assert(!ret, "...");
1141 ret = heim_db_set_value(db, NULL, k3, (heim_data_t)vdict, NULL);
1142 heim_assert(!ret, "...");
1144 heim_release(vdict);
1146 db2 = heim_db_create(dbtype, dbname, NULL, NULL);
1147 heim_assert(db2, "...");
1149 vdict = (heim_dict_t)heim_db_copy_value(db2, NULL, k3, NULL);
1150 heim_release(db2);
1151 heim_release(k3);
1152 heim_assert(vdict, "...");
1153 heim_assert(heim_get_tid(vdict) == heim_dict_get_type_id(), "...");
1155 v = heim_dict_copy_value(vdict, HSTR("vdict-k1"));
1156 heim_assert(v && !heim_cmp(v, heim_number_create(11)), "...");
1157 heim_release(v);
1159 v = heim_dict_copy_value(vdict, HSTR("vdict-k2"));
1160 heim_assert(v && !heim_cmp(v, heim_null_create()), "...");
1161 heim_release(v);
1163 v = heim_dict_copy_value(vdict, HSTR("vdict-k3"));
1164 heim_assert(v && !heim_cmp(v, HSTR("a value")), "...");
1165 heim_release(v);
1167 heim_release(vdict);
1170 heim_release(db);
1171 heim_release(k1);
1172 heim_release(k2);
1173 heim_release(v1);
1174 heim_release(v2);
1175 heim_release(v3);
1177 return 0;
1180 struct test_array_iter_ctx {
1181 char buf[256];
1184 static void test_array_iter(heim_object_t elt, void *arg, int *stop)
1186 struct test_array_iter_ctx *iter_ctx = arg;
1188 strcat(iter_ctx->buf, heim_string_get_utf8((heim_string_t)elt));
1191 static int
1192 test_array()
1194 struct test_array_iter_ctx iter_ctx;
1195 heim_string_t s1 = heim_string_create("abc");
1196 heim_string_t s2 = heim_string_create("def");
1197 heim_string_t s3 = heim_string_create("ghi");
1198 heim_string_t s4 = heim_string_create("jkl");
1199 heim_string_t s5 = heim_string_create("mno");
1200 heim_string_t s6 = heim_string_create("pqr");
1201 heim_array_t a = heim_array_create();
1203 if (!s1 || !s2 || !s3 || !s4 || !s5 || !s6 || !a)
1204 return ENOMEM;
1206 heim_array_append_value(a, s4);
1207 heim_array_append_value(a, s5);
1208 heim_array_insert_value(a, 0, s3);
1209 heim_array_insert_value(a, 0, s2);
1210 heim_array_append_value(a, s6);
1211 heim_array_insert_value(a, 0, s1);
1213 iter_ctx.buf[0] = '\0';
1214 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1215 if (strcmp(iter_ctx.buf, "abcdefghijklmnopqr") != 0)
1216 return 1;
1218 iter_ctx.buf[0] = '\0';
1219 heim_array_delete_value(a, 2);
1220 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1221 if (strcmp(iter_ctx.buf, "abcdefjklmnopqr") != 0)
1222 return 1;
1224 iter_ctx.buf[0] = '\0';
1225 heim_array_delete_value(a, 2);
1226 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1227 if (strcmp(iter_ctx.buf, "abcdefmnopqr") != 0)
1228 return 1;
1230 iter_ctx.buf[0] = '\0';
1231 heim_array_delete_value(a, 0);
1232 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1233 if (strcmp(iter_ctx.buf, "defmnopqr") != 0)
1234 return 1;
1236 iter_ctx.buf[0] = '\0';
1237 heim_array_delete_value(a, 2);
1238 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1239 if (strcmp(iter_ctx.buf, "defmno") != 0)
1240 return 1;
1242 heim_array_insert_value(a, 0, s1);
1243 iter_ctx.buf[0] = '\0';
1244 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1245 if (strcmp(iter_ctx.buf, "abcdefmno") != 0)
1246 return 1;
1248 heim_array_insert_value(a, 0, s2);
1249 iter_ctx.buf[0] = '\0';
1250 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1251 if (strcmp(iter_ctx.buf, "defabcdefmno") != 0)
1252 return 1;
1254 heim_array_append_value(a, s3);
1255 iter_ctx.buf[0] = '\0';
1256 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1257 if (strcmp(iter_ctx.buf, "defabcdefmnoghi") != 0)
1258 return 1;
1260 heim_array_append_value(a, s6);
1261 iter_ctx.buf[0] = '\0';
1262 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
1263 if (strcmp(iter_ctx.buf, "defabcdefmnoghipqr") != 0)
1264 return 1;
1266 heim_release(s1);
1267 heim_release(s2);
1268 heim_release(s3);
1269 heim_release(s4);
1270 heim_release(s5);
1271 heim_release(s6);
1272 heim_release(a);
1274 return 0;
1277 /* This function tests only that heimbase-atomics.h compiles */
1278 static int
1279 test_atomics(void)
1281 heim_base_atomic(void *) tptr;
1282 heim_base_atomic(uint32_t) tu32;
1283 heim_base_atomic(uint64_t) tu64;
1285 heim_base_atomic_init(&tptr, NULL);
1286 heim_base_atomic_init(&tu32, 0);
1287 heim_base_atomic_init(&tu64, 0);
1289 if (heim_base_atomic_load(&tptr))
1290 return 1;
1291 if (heim_base_atomic_load(&tu32))
1292 return 1;
1293 if (heim_base_atomic_load(&tu64))
1294 return 1;
1296 heim_base_atomic_store(&tptr, &tptr);
1297 heim_base_atomic_store(&tu32, 1);
1298 heim_base_atomic_store(&tu64, 1);
1300 if (heim_base_atomic_load(&tptr) != &tptr)
1301 return 1;
1302 if (heim_base_atomic_load(&tu32) != 1)
1303 return 1;
1304 if (heim_base_atomic_load(&tu64) != 1)
1305 return 1;
1307 if (heim_base_atomic_inc_32(&tu32) != 2 ||
1308 heim_base_atomic_load(&tu32) != 2)
1309 return 1;
1310 if (heim_base_atomic_inc_64(&tu64) != 2 ||
1311 heim_base_atomic_load(&tu64) != 2)
1312 return 1;
1314 if (heim_base_atomic_dec_32(&tu32) != 1 ||
1315 heim_base_atomic_load(&tu32) != 1)
1316 return 1;
1317 if (heim_base_atomic_dec_64(&tu64) != 1 ||
1318 heim_base_atomic_load(&tu64) != 1)
1319 return 1;
1321 heim_base_exchange_pointer(&tptr, (void *)&tu32);
1322 if (heim_base_atomic_load(&tptr) != &tu32)
1323 return 1;
1324 heim_base_exchange_32(&tu32, 32);
1325 if (heim_base_atomic_load(&tu32) != 32)
1326 return 1;
1327 heim_base_exchange_64(&tu64, 64);
1328 if (heim_base_atomic_load(&tu64) != 64)
1329 return 1;
1331 if (heim_base_cas_pointer(&tptr, (void *)&tu32, (void *)&tu64) != &tu32)
1332 return 1;
1333 if (heim_base_cas_pointer(&tptr, (void *)&tu32, (void *)&tptr) != &tu64)
1334 return 1;
1335 if (heim_base_atomic_load(&tptr) != (void *)&tu64)
1336 return 1;
1338 if (heim_base_cas_32(&tu32, 32, 4) != 32)
1339 return 1;
1340 if (heim_base_cas_32(&tu32, 32, 4) != 4)
1341 return 1;
1342 if (heim_base_atomic_load(&tu32) != 4)
1343 return 1;
1345 if (heim_base_cas_64(&tu64, 64, 4) != 64)
1346 return 1;
1347 if (heim_base_cas_64(&tu64, 64, 4) != 4)
1348 return 1;
1349 if (heim_base_atomic_load(&tu64) != 4)
1350 return 1;
1352 return 0;
1356 main(int argc, char **argv)
1358 int res = 0;
1360 #ifndef WIN32
1361 setlocale(LC_ALL, "C");
1362 heim_assert(!heim_locale_is_utf8(), "setlocale(LC_ALL, \"C\") failed?");
1363 #endif
1365 res |= test_memory();
1366 res |= test_mutex();
1367 res |= test_rwlock();
1368 res |= test_dict();
1369 res |= test_auto_release();
1370 res |= test_string();
1371 res |= test_error();
1372 res |= test_json();
1373 res |= test_path();
1374 res |= test_db(NULL, NULL);
1375 res |= test_db("json", argc > 1 ? argv[1] : "test_db.json");
1376 res |= test_array();
1377 res |= test_atomics();
1379 return res ? 1 : 0;