Windows: update default timestamping service
[heimdal.git] / lib / base / test_base.c
blob250708df2ef4bc2b6133187cc0a0f0a156fafae2
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 #endif
57 #ifdef HAVE_IO_H
58 #include <io.h>
59 #endif
60 #ifdef HAVE_UNISTD_H
61 #include <unistd.h>
62 #endif
63 #include <fcntl.h>
65 #include "baselocl.h"
67 static void
68 memory_free(heim_object_t obj)
72 static int
73 test_memory(void)
75 void *ptr;
77 ptr = heim_alloc(10, "memory", memory_free);
79 heim_retain(ptr);
80 heim_release(ptr);
82 heim_retain(ptr);
83 heim_release(ptr);
85 heim_release(ptr);
87 ptr = heim_alloc(10, "memory", NULL);
88 heim_release(ptr);
90 return 0;
93 static int
94 test_mutex(void)
96 HEIMDAL_MUTEX m = HEIMDAL_MUTEX_INITIALIZER;
98 HEIMDAL_MUTEX_lock(&m);
99 HEIMDAL_MUTEX_unlock(&m);
100 HEIMDAL_MUTEX_destroy(&m);
102 HEIMDAL_MUTEX_init(&m);
103 HEIMDAL_MUTEX_lock(&m);
104 HEIMDAL_MUTEX_unlock(&m);
105 HEIMDAL_MUTEX_destroy(&m);
107 return 0;
110 static int
111 test_rwlock(void)
113 HEIMDAL_RWLOCK l = HEIMDAL_RWLOCK_INITIALIZER;
115 HEIMDAL_RWLOCK_rdlock(&l);
116 HEIMDAL_RWLOCK_unlock(&l);
117 HEIMDAL_RWLOCK_wrlock(&l);
118 HEIMDAL_RWLOCK_unlock(&l);
119 if (HEIMDAL_RWLOCK_trywrlock(&l) != 0)
120 err(1, "HEIMDAL_RWLOCK_trywrlock() failed with lock not held");
121 HEIMDAL_RWLOCK_unlock(&l);
122 if (HEIMDAL_RWLOCK_tryrdlock(&l))
123 err(1, "HEIMDAL_RWLOCK_tryrdlock() failed with lock not held");
124 HEIMDAL_RWLOCK_unlock(&l);
125 HEIMDAL_RWLOCK_destroy(&l);
127 HEIMDAL_RWLOCK_init(&l);
128 HEIMDAL_RWLOCK_rdlock(&l);
129 HEIMDAL_RWLOCK_unlock(&l);
130 HEIMDAL_RWLOCK_wrlock(&l);
131 HEIMDAL_RWLOCK_unlock(&l);
132 if (HEIMDAL_RWLOCK_trywrlock(&l))
133 err(1, "HEIMDAL_RWLOCK_trywrlock() failed with lock not held");
134 HEIMDAL_RWLOCK_unlock(&l);
135 if (HEIMDAL_RWLOCK_tryrdlock(&l))
136 err(1, "HEIMDAL_RWLOCK_tryrdlock() failed with lock not held");
137 HEIMDAL_RWLOCK_unlock(&l);
138 HEIMDAL_RWLOCK_destroy(&l);
140 return 0;
143 static int
144 test_dict(void)
146 heim_dict_t dict;
147 heim_number_t a1 = heim_number_create(1);
148 heim_string_t a2 = heim_string_create("hejsan");
149 heim_number_t a3 = heim_number_create(3);
150 heim_string_t a4 = heim_string_create("foosan");
152 dict = heim_dict_create(10);
154 heim_dict_set_value(dict, a1, a2);
155 heim_dict_set_value(dict, a3, a4);
157 heim_dict_delete_key(dict, a3);
158 heim_dict_delete_key(dict, a1);
160 heim_release(a1);
161 heim_release(a2);
162 heim_release(a3);
163 heim_release(a4);
165 heim_release(dict);
167 return 0;
170 static int
171 test_auto_release(void)
173 heim_auto_release_t ar1, ar2;
174 heim_number_t n1;
175 heim_string_t s1;
177 ar1 = heim_auto_release_create();
179 s1 = heim_string_create("hejsan");
180 heim_auto_release(s1);
182 n1 = heim_number_create(1);
183 heim_auto_release(n1);
185 ar2 = heim_auto_release_create();
187 n1 = heim_number_create(1);
188 heim_auto_release(n1);
190 heim_release(ar2);
191 heim_release(ar1);
193 return 0;
196 static int
197 test_string(void)
199 heim_string_t s1, s2;
200 const char *string = "hejsan";
202 s1 = heim_string_create(string);
203 s2 = heim_string_create(string);
205 if (heim_cmp(s1, s2) != 0) {
206 printf("the same string is not the same\n");
207 exit(1);
210 heim_release(s1);
211 heim_release(s2);
213 return 0;
216 static int
217 test_error(void)
219 heim_error_t e;
220 heim_string_t s;
222 e = heim_error_create(10, "foo: %s", "bar");
223 heim_assert(heim_error_get_code(e) == 10, "error_code != 10");
225 s = heim_error_copy_string(e);
226 heim_assert(strcmp(heim_string_get_utf8(s), "foo: bar") == 0, "msg wrong");
228 heim_release(s);
229 heim_release(e);
231 return 0;
234 static int
235 test_json(void)
237 static char *j[] = {
238 "{ \"k1\" : \"s1\", \"k2\" : \"s2\" }",
239 "{ \"k1\" : [\"s1\", \"s2\", \"s3\"], \"k2\" : \"s3\" }",
240 "{ \"k1\" : {\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"}, \"k5\" : \"s4\" }",
241 "[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, "
242 "null, true, false, 123456789, \"\"]",
243 " -1"
245 char *s;
246 size_t i, k;
247 heim_object_t o, o2;
248 heim_string_t k1 = heim_string_create("k1");
250 o = heim_json_create("\"string\"", 10, 0, NULL);
251 heim_assert(o != NULL, "string");
252 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
253 heim_assert(strcmp("string", heim_string_get_utf8(o)) == 0, "wrong string");
254 heim_release(o);
256 o = heim_json_create(" \"foo\\\"bar\" ]", 10, 0, NULL);
257 heim_assert(o != NULL, "string");
258 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
259 heim_assert(strcmp("foo\"bar", heim_string_get_utf8(o)) == 0, "wrong string");
260 heim_release(o);
262 o = heim_json_create(" { \"key\" : \"value\" }", 10, 0, NULL);
263 heim_assert(o != NULL, "dict");
264 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
265 heim_release(o);
267 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
268 "{ \"k3\" : \"s4\" } : -1 }", 10, 0, NULL);
269 heim_assert(o != NULL, "dict");
270 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
271 heim_release(o);
273 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
274 "{ \"k3\" : \"s4\" } : -1 }", 10,
275 HEIM_JSON_F_STRICT_DICT, NULL);
276 heim_assert(o == NULL, "dict");
278 o = heim_json_create(" { \"k1\" : \"s1\", \"k2\" : \"s2\" }", 10, 0, NULL);
279 heim_assert(o != NULL, "dict");
280 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
281 o2 = heim_dict_copy_value(o, k1);
282 heim_assert(heim_get_tid(o2) == heim_string_get_type_id(), "string-tid");
283 heim_release(o2);
284 heim_release(o);
286 o = heim_json_create(" { \"k1\" : { \"k2\" : \"s2\" } }", 10, 0, NULL);
287 heim_assert(o != NULL, "dict");
288 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
289 o2 = heim_dict_copy_value(o, k1);
290 heim_assert(heim_get_tid(o2) == heim_dict_get_type_id(), "dict-tid");
291 heim_release(o2);
292 heim_release(o);
294 o = heim_json_create("{ \"k1\" : 1 }", 10, 0, NULL);
295 heim_assert(o != NULL, "array");
296 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
297 o2 = heim_dict_copy_value(o, k1);
298 heim_assert(heim_get_tid(o2) == heim_number_get_type_id(), "number-tid");
299 heim_release(o2);
300 heim_release(o);
302 o = heim_json_create("-10", 10, 0, NULL);
303 heim_assert(o != NULL, "number");
304 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
305 heim_release(o);
307 o = heim_json_create("99", 10, 0, NULL);
308 heim_assert(o != NULL, "number");
309 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
310 heim_release(o);
312 o = heim_json_create(" [ 1 ]", 10, 0, NULL);
313 heim_assert(o != NULL, "array");
314 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
315 heim_release(o);
317 o = heim_json_create(" [ -1 ]", 10, 0, NULL);
318 heim_assert(o != NULL, "array");
319 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
320 heim_release(o);
322 for (i = 0; i < (sizeof (j) / sizeof (j[0])); i++) {
323 o = heim_json_create(j[i], 10, 0, NULL);
324 if (o == NULL) {
325 fprintf(stderr, "Failed to parse this JSON: %s\n", j[i]);
326 return 1;
328 heim_release(o);
329 /* Simple fuzz test */
330 for (k = strlen(j[i]) - 1; k > 0; k--) {
331 o = heim_json_create_with_bytes(j[i], k, 10, 0, NULL);
332 if (o != NULL) {
333 fprintf(stderr, "Invalid JSON parsed: %.*s\n", (int)k, j[i]);
334 return EINVAL;
337 /* Again, but this time make it so valgrind can find invalid accesses */
338 for (k = strlen(j[i]) - 1; k > 0; k--) {
339 s = strndup(j[i], k);
340 if (s == NULL)
341 return ENOMEM;
342 o = heim_json_create(s, 10, 0, NULL);
343 free(s);
344 if (o != NULL) {
345 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
346 return EINVAL;
349 /* Again, but with no NUL termination */
350 for (k = strlen(j[i]) - 1; k > 0; k--) {
351 s = malloc(k);
352 if (s == NULL)
353 return ENOMEM;
354 memcpy(s, j[i], k);
355 o = heim_json_create_with_bytes(s, k, 10, 0, NULL);
356 free(s);
357 if (o != NULL) {
358 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
359 return EINVAL;
364 heim_release(k1);
366 return 0;
369 static int
370 test_path(void)
372 heim_dict_t dict = heim_dict_create(11);
373 heim_string_t p1 = heim_string_create("abc");
374 heim_string_t p2a = heim_string_create("def");
375 heim_string_t p2b = heim_string_create("DEF");
376 heim_number_t p3 = heim_number_create(0);
377 heim_string_t p4a = heim_string_create("ghi");
378 heim_string_t p4b = heim_string_create("GHI");
379 heim_array_t a = heim_array_create();
380 heim_number_t l1 = heim_number_create(42);
381 heim_number_t l2 = heim_number_create(813);
382 heim_number_t l3 = heim_number_create(1234);
383 heim_string_t k1 = heim_string_create("k1");
384 heim_string_t k2 = heim_string_create("k2");
385 heim_string_t k3 = heim_string_create("k3");
386 heim_string_t k2_1 = heim_string_create("k2-1");
387 heim_string_t k2_2 = heim_string_create("k2-2");
388 heim_string_t k2_3 = heim_string_create("k2-3");
389 heim_string_t k2_4 = heim_string_create("k2-4");
390 heim_string_t k2_5 = heim_string_create("k2-5");
391 heim_string_t k2_5_1 = heim_string_create("k2-5-1");
392 heim_object_t o;
393 heim_object_t neg_num;
394 int ret;
396 if (!dict || !p1 || !p2a || !p2b || !p4a || !p4b)
397 return ENOMEM;
399 ret = heim_path_create(dict, 11, a, NULL, p1, p2a, NULL);
400 heim_release(a);
401 if (ret)
402 return ret;
403 ret = heim_path_create(dict, 11, l3, NULL, p1, p2b, NULL);
404 if (ret)
405 return ret;
406 o = heim_path_get(dict, NULL, p1, p2b, NULL);
407 if (o != l3)
408 return 1;
409 ret = heim_path_create(dict, 11, NULL, NULL, p1, p2a, p3, NULL);
410 if (ret)
411 return ret;
412 ret = heim_path_create(dict, 11, l1, NULL, p1, p2a, p3, p4a, NULL);
413 if (ret)
414 return ret;
415 ret = heim_path_create(dict, 11, l2, NULL, p1, p2a, p3, p4b, NULL);
416 if (ret)
417 return ret;
419 o = heim_path_get(dict, NULL, p1, p2a, p3, p4a, NULL);
420 if (o != l1)
421 return 1;
422 o = heim_path_get(dict, NULL, p1, p2a, p3, p4b, NULL);
423 if (o != l2)
424 return 1;
426 heim_release(dict);
428 /* Test that JSON parsing works right by using heim_path_get() */
429 dict = heim_json_create("{\"k1\":1,"
430 "\"k2\":{\"k2-1\":21,"
431 "\"k2-2\":null,"
432 "\"k2-3\":true,"
433 "\"k2-4\":false,"
434 "\"k2-5\":[1,2,3,{\"k2-5-1\":-1},-2]},"
435 "\"k3\":[true,false,0,42]}", 10, 0, NULL);
436 heim_assert(dict != NULL, "dict");
437 o = heim_path_get(dict, NULL, k1, NULL);
438 if (heim_cmp(o, heim_number_create(1))) return 1;
439 o = heim_path_get(dict, NULL, k2, NULL);
440 if (heim_get_tid(o) != heim_dict_get_type_id()) return 1;
441 o = heim_path_get(dict, NULL, k2, k2_1, NULL);
442 if (heim_cmp(o, heim_number_create(21))) return 1;
443 o = heim_path_get(dict, NULL, k2, k2_2, NULL);
444 if (heim_cmp(o, heim_null_create())) return 1;
445 o = heim_path_get(dict, NULL, k2, k2_3, NULL);
446 if (heim_cmp(o, heim_bool_create(1))) return 1;
447 o = heim_path_get(dict, NULL, k2, k2_4, NULL);
448 if (heim_cmp(o, heim_bool_create(0))) return 1;
449 o = heim_path_get(dict, NULL, k2, k2_5, NULL);
450 if (heim_get_tid(o) != heim_array_get_type_id()) return 1;
451 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(0), NULL);
452 if (heim_cmp(o, heim_number_create(1))) return 1;
453 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(1), NULL);
454 if (heim_cmp(o, heim_number_create(2))) return 1;
455 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(3), k2_5_1, NULL);
456 if (heim_cmp(o, neg_num = heim_number_create(-1))) return 1;
457 heim_release(neg_num);
458 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(4), NULL);
459 if (heim_cmp(o, neg_num = heim_number_create(-2))) return 1;
460 heim_release(neg_num);
461 o = heim_path_get(dict, NULL, k3, heim_number_create(3), NULL);
462 if (heim_cmp(o, heim_number_create(42))) return 1;
464 heim_release(dict);
465 heim_release(p1);
466 heim_release(p2a);
467 heim_release(p2b);
468 heim_release(p4a);
469 heim_release(p4b);
470 heim_release(k1);
471 heim_release(k2);
472 heim_release(k3);
473 heim_release(k2_1);
474 heim_release(k2_2);
475 heim_release(k2_3);
476 heim_release(k2_4);
477 heim_release(k2_5);
478 heim_release(k2_5_1);
480 return 0;
483 typedef struct dict_db {
484 heim_dict_t dict;
485 int locked;
486 } *dict_db_t;
488 static int
489 dict_db_open(void *plug, const char *dbtype, const char *dbname,
490 heim_dict_t options, void **db, heim_error_t *error)
492 dict_db_t dictdb;
493 heim_dict_t contents = NULL;
495 if (error)
496 *error = NULL;
497 if (dbtype && *dbtype && strcmp(dbtype, "dictdb"))
498 return EINVAL;
499 if (dbname && *dbname && strcmp(dbname, "MEMORY") != 0)
500 return EINVAL;
501 dictdb = heim_alloc(sizeof (*dictdb), "dict_db", NULL);
502 if (dictdb == NULL)
503 return ENOMEM;
505 if (contents != NULL)
506 dictdb->dict = contents;
507 else {
508 dictdb->dict = heim_dict_create(29);
509 if (dictdb->dict == NULL) {
510 heim_release(dictdb);
511 return ENOMEM;
515 *db = dictdb;
516 return 0;
519 static int
520 dict_db_close(void *db, heim_error_t *error)
522 dict_db_t dictdb = db;
524 if (error)
525 *error = NULL;
526 heim_release(dictdb->dict);
527 heim_release(dictdb);
528 return 0;
531 static int
532 dict_db_lock(void *db, int read_only, heim_error_t *error)
534 dict_db_t dictdb = db;
536 if (error)
537 *error = NULL;
538 if (dictdb->locked)
539 return EWOULDBLOCK;
540 dictdb->locked = 1;
541 return 0;
544 static int
545 dict_db_unlock(void *db, heim_error_t *error)
547 dict_db_t dictdb = db;
549 if (error)
550 *error = NULL;
551 dictdb->locked = 0;
552 return 0;
555 static heim_data_t
556 dict_db_copy_value(void *db, heim_string_t table, heim_data_t key,
557 heim_error_t *error)
559 dict_db_t dictdb = db;
561 if (error)
562 *error = NULL;
564 return heim_retain(heim_path_get(dictdb->dict, error, table, key, NULL));
567 static int
568 dict_db_set_value(void *db, heim_string_t table,
569 heim_data_t key, heim_data_t value, heim_error_t *error)
571 dict_db_t dictdb = db;
573 if (error)
574 *error = NULL;
576 if (table == NULL)
577 table = HSTR("");
579 return heim_path_create(dictdb->dict, 29, value, error, table, key, NULL);
582 static int
583 dict_db_del_key(void *db, heim_string_t table, heim_data_t key,
584 heim_error_t *error)
586 dict_db_t dictdb = db;
588 if (error)
589 *error = NULL;
591 if (table == NULL)
592 table = HSTR("");
594 heim_path_delete(dictdb->dict, error, table, key, NULL);
595 return 0;
598 struct dict_db_iter_ctx {
599 heim_db_iterator_f_t iter_f;
600 void *iter_ctx;
603 static void dict_db_iter_f(heim_object_t key, heim_object_t value, void *arg)
605 struct dict_db_iter_ctx *ctx = arg;
607 ctx->iter_f((heim_object_t)key, (heim_object_t)value, ctx->iter_ctx);
610 static void
611 dict_db_iter(void *db, heim_string_t table, void *iter_data,
612 heim_db_iterator_f_t iter_f, heim_error_t *error)
614 dict_db_t dictdb = db;
615 struct dict_db_iter_ctx ctx;
616 heim_dict_t table_dict;
618 if (error)
619 *error = NULL;
621 if (table == NULL)
622 table = HSTR("");
624 table_dict = heim_dict_copy_value(dictdb->dict, table);
625 if (table_dict == NULL)
626 return;
628 ctx.iter_ctx = iter_data;
629 ctx.iter_f = iter_f;
631 heim_dict_iterate_f(table_dict, &ctx, dict_db_iter_f);
632 heim_release(table_dict);
635 static void
636 test_db_iter(heim_data_t k, heim_data_t v, void *arg)
638 int *ret = arg;
639 const void *kptr, *vptr;
640 size_t klen, vlen;
642 heim_assert(heim_get_tid(k) == heim_data_get_type_id(), "...");
644 kptr = heim_data_get_ptr(k);
645 klen = heim_data_get_length(k);
646 vptr = heim_data_get_ptr(v);
647 vlen = heim_data_get_length(v);
649 if (klen == strlen("msg") && !strncmp(kptr, "msg", strlen("msg")) &&
650 vlen == strlen("abc") && !strncmp(vptr, "abc", strlen("abc")))
651 *ret &= ~(1);
652 else if (klen == strlen("msg2") &&
653 !strncmp(kptr, "msg2", strlen("msg2")) &&
654 vlen == strlen("FooBar") && !strncmp(vptr, "FooBar", strlen("FooBar")))
655 *ret &= ~(2);
656 else
657 *ret |= 4;
660 static struct heim_db_type dbt = {
661 1, dict_db_open, NULL, dict_db_close,
662 dict_db_lock, dict_db_unlock, NULL, NULL, NULL, NULL,
663 dict_db_copy_value, dict_db_set_value,
664 dict_db_del_key, dict_db_iter
667 static int
668 test_db(const char *dbtype, const char *dbname)
670 heim_data_t k1, k2, v, v1, v2, v3;
671 heim_db_t db;
672 int ret;
674 if (dbtype == NULL) {
675 ret = heim_db_register("dictdb", NULL, &dbt);
676 heim_assert(!ret, "...");
677 db = heim_db_create("dictdb", "foo", NULL, NULL);
678 heim_assert(!db, "...");
679 db = heim_db_create("foobar", "MEMORY", NULL, NULL);
680 heim_assert(!db, "...");
681 db = heim_db_create("dictdb", "MEMORY", NULL, NULL);
682 heim_assert(db, "...");
683 } else {
684 heim_dict_t options;
686 options = heim_dict_create(11);
687 if (options == NULL) return ENOMEM;
688 if (heim_dict_set_value(options, HSTR("journal-filename"),
689 HSTR("json-journal")))
690 return ENOMEM;
691 if (heim_dict_set_value(options, HSTR("create"), heim_null_create()))
692 return ENOMEM;
693 if (heim_dict_set_value(options, HSTR("truncate"), heim_null_create()))
694 return ENOMEM;
695 db = heim_db_create(dbtype, dbname, options, NULL);
696 heim_assert(db, "...");
697 heim_release(options);
700 k1 = heim_data_create("msg", strlen("msg"));
701 k2 = heim_data_create("msg2", strlen("msg2"));
702 v1 = heim_data_create("Hello world!", strlen("Hello world!"));
703 v2 = heim_data_create("FooBar", strlen("FooBar"));
704 v3 = heim_data_create("abc", strlen("abc"));
706 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
707 heim_assert(!ret, "...");
709 v = heim_db_copy_value(db, NULL, k1, NULL);
710 heim_assert(v && !heim_cmp(v, v1), "...");
711 heim_release(v);
713 ret = heim_db_set_value(db, NULL, k2, v2, NULL);
714 heim_assert(!ret, "...");
716 v = heim_db_copy_value(db, NULL, k2, NULL);
717 heim_assert(v && !heim_cmp(v, v2), "...");
718 heim_release(v);
720 ret = heim_db_set_value(db, NULL, k1, v3, NULL);
721 heim_assert(!ret, "...");
723 v = heim_db_copy_value(db, NULL, k1, NULL);
724 heim_assert(v && !heim_cmp(v, v3), "...");
725 heim_release(v);
727 ret = 3;
728 heim_db_iterate_f(db, NULL, &ret, test_db_iter, NULL);
729 heim_assert(!ret, "...");
731 ret = heim_db_begin(db, 0, NULL);
732 heim_assert(!ret, "...");
734 ret = heim_db_commit(db, NULL);
735 heim_assert(!ret, "...");
737 ret = heim_db_begin(db, 0, NULL);
738 heim_assert(!ret, "...");
740 ret = heim_db_rollback(db, NULL);
741 heim_assert(!ret, "...");
743 ret = heim_db_begin(db, 0, NULL);
744 heim_assert(!ret, "...");
746 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
747 heim_assert(!ret, "...");
749 v = heim_db_copy_value(db, NULL, k1, NULL);
750 heim_assert(v && !heim_cmp(v, v1), "...");
751 heim_release(v);
753 ret = heim_db_rollback(db, NULL);
754 heim_assert(!ret, "...");
756 v = heim_db_copy_value(db, NULL, k1, NULL);
757 heim_assert(v && !heim_cmp(v, v3), "...");
758 heim_release(v);
760 ret = heim_db_begin(db, 0, NULL);
761 heim_assert(!ret, "...");
763 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
764 heim_assert(!ret, "...");
766 v = heim_db_copy_value(db, NULL, k1, NULL);
767 heim_assert(v && !heim_cmp(v, v1), "...");
768 heim_release(v);
770 ret = heim_db_commit(db, NULL);
771 heim_assert(!ret, "...");
773 v = heim_db_copy_value(db, NULL, k1, NULL);
774 heim_assert(v && !heim_cmp(v, v1), "...");
775 heim_release(v);
777 ret = heim_db_begin(db, 0, NULL);
778 heim_assert(!ret, "...");
780 ret = heim_db_delete_key(db, NULL, k1, NULL);
781 heim_assert(!ret, "...");
783 v = heim_db_copy_value(db, NULL, k1, NULL);
784 heim_assert(v == NULL, "...");
785 heim_release(v);
787 ret = heim_db_rollback(db, NULL);
788 heim_assert(!ret, "...");
790 v = heim_db_copy_value(db, NULL, k1, NULL);
791 heim_assert(v && !heim_cmp(v, v1), "...");
792 heim_release(v);
794 if (dbtype != NULL) {
795 heim_data_t k3 = heim_data_create("value-is-a-dict", strlen("value-is-a-dict"));
796 heim_dict_t vdict = heim_dict_create(11);
797 heim_db_t db2;
799 heim_assert(k3 && vdict, "...");
800 ret = heim_dict_set_value(vdict, HSTR("vdict-k1"), heim_number_create(11));
801 heim_assert(!ret, "...");
802 ret = heim_dict_set_value(vdict, HSTR("vdict-k2"), heim_null_create());
803 heim_assert(!ret, "...");
804 ret = heim_dict_set_value(vdict, HSTR("vdict-k3"), HSTR("a value"));
805 heim_assert(!ret, "...");
806 ret = heim_db_set_value(db, NULL, k3, (heim_data_t)vdict, NULL);
807 heim_assert(!ret, "...");
809 heim_release(vdict);
811 db2 = heim_db_create(dbtype, dbname, NULL, NULL);
812 heim_assert(db2, "...");
814 vdict = (heim_dict_t)heim_db_copy_value(db2, NULL, k3, NULL);
815 heim_release(db2);
816 heim_release(k3);
817 heim_assert(vdict, "...");
818 heim_assert(heim_get_tid(vdict) == heim_dict_get_type_id(), "...");
820 v = heim_dict_copy_value(vdict, HSTR("vdict-k1"));
821 heim_assert(v && !heim_cmp(v, heim_number_create(11)), "...");
822 heim_release(v);
824 v = heim_dict_copy_value(vdict, HSTR("vdict-k2"));
825 heim_assert(v && !heim_cmp(v, heim_null_create()), "...");
826 heim_release(v);
828 v = heim_dict_copy_value(vdict, HSTR("vdict-k3"));
829 heim_assert(v && !heim_cmp(v, HSTR("a value")), "...");
830 heim_release(v);
832 heim_release(vdict);
835 heim_release(db);
836 heim_release(k1);
837 heim_release(k2);
838 heim_release(v1);
839 heim_release(v2);
840 heim_release(v3);
842 return 0;
845 struct test_array_iter_ctx {
846 char buf[256];
849 static void test_array_iter(heim_object_t elt, void *arg, int *stop)
851 struct test_array_iter_ctx *iter_ctx = arg;
853 strcat(iter_ctx->buf, heim_string_get_utf8((heim_string_t)elt));
856 static int
857 test_array()
859 struct test_array_iter_ctx iter_ctx;
860 heim_string_t s1 = heim_string_create("abc");
861 heim_string_t s2 = heim_string_create("def");
862 heim_string_t s3 = heim_string_create("ghi");
863 heim_string_t s4 = heim_string_create("jkl");
864 heim_string_t s5 = heim_string_create("mno");
865 heim_string_t s6 = heim_string_create("pqr");
866 heim_array_t a = heim_array_create();
868 if (!s1 || !s2 || !s3 || !s4 || !s5 || !s6 || !a)
869 return ENOMEM;
871 heim_array_append_value(a, s4);
872 heim_array_append_value(a, s5);
873 heim_array_insert_value(a, 0, s3);
874 heim_array_insert_value(a, 0, s2);
875 heim_array_append_value(a, s6);
876 heim_array_insert_value(a, 0, s1);
878 iter_ctx.buf[0] = '\0';
879 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
880 if (strcmp(iter_ctx.buf, "abcdefghijklmnopqr") != 0)
881 return 1;
883 iter_ctx.buf[0] = '\0';
884 heim_array_delete_value(a, 2);
885 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
886 if (strcmp(iter_ctx.buf, "abcdefjklmnopqr") != 0)
887 return 1;
889 iter_ctx.buf[0] = '\0';
890 heim_array_delete_value(a, 2);
891 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
892 if (strcmp(iter_ctx.buf, "abcdefmnopqr") != 0)
893 return 1;
895 iter_ctx.buf[0] = '\0';
896 heim_array_delete_value(a, 0);
897 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
898 if (strcmp(iter_ctx.buf, "defmnopqr") != 0)
899 return 1;
901 iter_ctx.buf[0] = '\0';
902 heim_array_delete_value(a, 2);
903 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
904 if (strcmp(iter_ctx.buf, "defmno") != 0)
905 return 1;
907 heim_array_insert_value(a, 0, s1);
908 iter_ctx.buf[0] = '\0';
909 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
910 if (strcmp(iter_ctx.buf, "abcdefmno") != 0)
911 return 1;
913 heim_array_insert_value(a, 0, s2);
914 iter_ctx.buf[0] = '\0';
915 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
916 if (strcmp(iter_ctx.buf, "defabcdefmno") != 0)
917 return 1;
919 heim_array_append_value(a, s3);
920 iter_ctx.buf[0] = '\0';
921 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
922 if (strcmp(iter_ctx.buf, "defabcdefmnoghi") != 0)
923 return 1;
925 heim_array_append_value(a, s6);
926 iter_ctx.buf[0] = '\0';
927 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
928 if (strcmp(iter_ctx.buf, "defabcdefmnoghipqr") != 0)
929 return 1;
931 heim_release(s1);
932 heim_release(s2);
933 heim_release(s3);
934 heim_release(s4);
935 heim_release(s5);
936 heim_release(s6);
937 heim_release(a);
939 return 0;
943 main(int argc, char **argv)
945 int res = 0;
947 res |= test_memory();
948 res |= test_mutex();
949 res |= test_rwlock();
950 res |= test_dict();
951 res |= test_auto_release();
952 res |= test_string();
953 res |= test_error();
954 res |= test_json();
955 res |= test_path();
956 res |= test_db(NULL, NULL);
957 res |= test_db("json", argc > 1 ? argv[1] : "test_db.json");
958 res |= test_array();
960 return res ? 1 : 0;