Fix some typos.
[heimdal.git] / lib / base / test_base.c
blobd276f8fc71eb6fa8e7410c8c8255a1cf4e3ce999
1 /*
2 * Copyright (c) 2010 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 <errno.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sys/types.h>
52 #include <sys/stat.h>
53 #ifndef WIN32
54 #include <sys/file.h>
55 #endif
56 #ifdef HAVE_IO_H
57 #include <io.h>
58 #endif
59 #ifdef HAVE_UNISTD_H
60 #include <unistd.h>
61 #endif
62 #include <fcntl.h>
64 #include "baselocl.h"
66 static void
67 memory_free(heim_object_t obj)
71 static int
72 test_memory(void)
74 void *ptr;
76 ptr = heim_alloc(10, "memory", memory_free);
78 heim_retain(ptr);
79 heim_release(ptr);
81 heim_retain(ptr);
82 heim_release(ptr);
84 heim_release(ptr);
86 ptr = heim_alloc(10, "memory", NULL);
87 heim_release(ptr);
89 return 0;
92 static int
93 test_dict(void)
95 heim_dict_t dict;
96 heim_number_t a1 = heim_number_create(1);
97 heim_string_t a2 = heim_string_create("hejsan");
98 heim_number_t a3 = heim_number_create(3);
99 heim_string_t a4 = heim_string_create("foosan");
101 dict = heim_dict_create(10);
103 heim_dict_set_value(dict, a1, a2);
104 heim_dict_set_value(dict, a3, a4);
106 heim_dict_delete_key(dict, a3);
107 heim_dict_delete_key(dict, a1);
109 heim_release(a1);
110 heim_release(a2);
111 heim_release(a3);
112 heim_release(a4);
114 heim_release(dict);
116 return 0;
119 static int
120 test_auto_release(void)
122 heim_auto_release_t ar1, ar2;
123 heim_number_t n1;
124 heim_string_t s1;
126 ar1 = heim_auto_release_create();
128 s1 = heim_string_create("hejsan");
129 heim_auto_release(s1);
131 n1 = heim_number_create(1);
132 heim_auto_release(n1);
134 ar2 = heim_auto_release_create();
136 n1 = heim_number_create(1);
137 heim_auto_release(n1);
139 heim_release(ar2);
140 heim_release(ar1);
142 return 0;
145 static int
146 test_string(void)
148 heim_string_t s1, s2;
149 const char *string = "hejsan";
151 s1 = heim_string_create(string);
152 s2 = heim_string_create(string);
154 if (heim_cmp(s1, s2) != 0) {
155 printf("the same string is not the same\n");
156 exit(1);
159 heim_release(s1);
160 heim_release(s2);
162 return 0;
165 static int
166 test_error(void)
168 heim_error_t e;
169 heim_string_t s;
171 e = heim_error_create(10, "foo: %s", "bar");
172 heim_assert(heim_error_get_code(e) == 10, "error_code != 10");
174 s = heim_error_copy_string(e);
175 heim_assert(strcmp(heim_string_get_utf8(s), "foo: bar") == 0, "msg wrong");
177 heim_release(s);
178 heim_release(e);
180 return 0;
183 static int
184 test_json(void)
186 static char *j[] = {
187 "{ \"k1\" : \"s1\", \"k2\" : \"s2\" }",
188 "{ \"k1\" : [\"s1\", \"s2\", \"s3\"], \"k2\" : \"s3\" }",
189 "{ \"k1\" : {\"k2\":\"s1\",\"k3\":\"s2\",\"k4\":\"s3\"}, \"k5\" : \"s4\" }",
190 "[ \"v1\", \"v2\", [\"v3\",\"v4\",[\"v 5\",\" v 7 \"]], -123456789, "
191 "null, true, false, 123456789, \"\"]",
192 " -1"
194 char *s;
195 size_t i, k;
196 heim_object_t o, o2;
197 heim_string_t k1 = heim_string_create("k1");
199 o = heim_json_create("\"string\"", 10, 0, NULL);
200 heim_assert(o != NULL, "string");
201 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
202 heim_assert(strcmp("string", heim_string_get_utf8(o)) == 0, "wrong string");
203 heim_release(o);
205 o = heim_json_create(" \"foo\\\"bar\" ]", 10, 0, NULL);
206 heim_assert(o != NULL, "string");
207 heim_assert(heim_get_tid(o) == heim_string_get_type_id(), "string-tid");
208 heim_assert(strcmp("foo\"bar", heim_string_get_utf8(o)) == 0, "wrong string");
209 heim_release(o);
211 o = heim_json_create(" { \"key\" : \"value\" }", 10, 0, NULL);
212 heim_assert(o != NULL, "dict");
213 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
214 heim_release(o);
216 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
217 "{ \"k3\" : \"s4\" } : -1 }", 10, 0, NULL);
218 heim_assert(o != NULL, "dict");
219 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
220 heim_release(o);
222 o = heim_json_create("{ { \"k1\" : \"s1\", \"k2\" : \"s2\" } : \"s3\", "
223 "{ \"k3\" : \"s4\" } : -1 }", 10,
224 HEIM_JSON_F_STRICT_DICT, NULL);
225 heim_assert(o == NULL, "dict");
227 o = heim_json_create(" { \"k1\" : \"s1\", \"k2\" : \"s2\" }", 10, 0, NULL);
228 heim_assert(o != NULL, "dict");
229 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
230 o2 = heim_dict_copy_value(o, k1);
231 heim_assert(heim_get_tid(o2) == heim_string_get_type_id(), "string-tid");
232 heim_release(o2);
233 heim_release(o);
235 o = heim_json_create(" { \"k1\" : { \"k2\" : \"s2\" } }", 10, 0, NULL);
236 heim_assert(o != NULL, "dict");
237 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
238 o2 = heim_dict_copy_value(o, k1);
239 heim_assert(heim_get_tid(o2) == heim_dict_get_type_id(), "dict-tid");
240 heim_release(o2);
241 heim_release(o);
243 o = heim_json_create("{ \"k1\" : 1 }", 10, 0, NULL);
244 heim_assert(o != NULL, "array");
245 heim_assert(heim_get_tid(o) == heim_dict_get_type_id(), "dict-tid");
246 o2 = heim_dict_copy_value(o, k1);
247 heim_assert(heim_get_tid(o2) == heim_number_get_type_id(), "number-tid");
248 heim_release(o2);
249 heim_release(o);
251 o = heim_json_create("-10", 10, 0, NULL);
252 heim_assert(o != NULL, "number");
253 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
254 heim_release(o);
256 o = heim_json_create("99", 10, 0, NULL);
257 heim_assert(o != NULL, "number");
258 heim_assert(heim_get_tid(o) == heim_number_get_type_id(), "number-tid");
259 heim_release(o);
261 o = heim_json_create(" [ 1 ]", 10, 0, NULL);
262 heim_assert(o != NULL, "array");
263 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
264 heim_release(o);
266 o = heim_json_create(" [ -1 ]", 10, 0, NULL);
267 heim_assert(o != NULL, "array");
268 heim_assert(heim_get_tid(o) == heim_array_get_type_id(), "array-tid");
269 heim_release(o);
271 for (i = 0; i < (sizeof (j) / sizeof (j[0])); i++) {
272 o = heim_json_create(j[i], 10, 0, NULL);
273 if (o == NULL) {
274 fprintf(stderr, "Failed to parse this JSON: %s\n", j[i]);
275 return 1;
277 heim_release(o);
278 /* Simple fuzz test */
279 for (k = strlen(j[i]) - 1; k > 0; k--) {
280 o = heim_json_create_with_bytes(j[i], k, 10, 0, NULL);
281 if (o != NULL) {
282 fprintf(stderr, "Invalid JSON parsed: %.*s\n", (int)k, j[i]);
283 return EINVAL;
286 /* Again, but this time make it so valgrind can find invalid accesses */
287 for (k = strlen(j[i]) - 1; k > 0; k--) {
288 s = strndup(j[i], k);
289 if (s == NULL)
290 return ENOMEM;
291 o = heim_json_create(s, 10, 0, NULL);
292 free(s);
293 if (o != NULL) {
294 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
295 return EINVAL;
298 /* Again, but with no NUL termination */
299 for (k = strlen(j[i]) - 1; k > 0; k--) {
300 s = malloc(k);
301 if (s == NULL)
302 return ENOMEM;
303 memcpy(s, j[i], k);
304 o = heim_json_create_with_bytes(s, k, 10, 0, NULL);
305 free(s);
306 if (o != NULL) {
307 fprintf(stderr, "Invalid JSON parsed: %s\n", j[i]);
308 return EINVAL;
313 heim_release(k1);
315 return 0;
318 static int
319 test_path(void)
321 heim_dict_t dict = heim_dict_create(11);
322 heim_string_t p1 = heim_string_create("abc");
323 heim_string_t p2a = heim_string_create("def");
324 heim_string_t p2b = heim_string_create("DEF");
325 heim_number_t p3 = heim_number_create(0);
326 heim_string_t p4a = heim_string_create("ghi");
327 heim_string_t p4b = heim_string_create("GHI");
328 heim_array_t a = heim_array_create();
329 heim_number_t l1 = heim_number_create(42);
330 heim_number_t l2 = heim_number_create(813);
331 heim_number_t l3 = heim_number_create(1234);
332 heim_string_t k1 = heim_string_create("k1");
333 heim_string_t k2 = heim_string_create("k2");
334 heim_string_t k3 = heim_string_create("k3");
335 heim_string_t k2_1 = heim_string_create("k2-1");
336 heim_string_t k2_2 = heim_string_create("k2-2");
337 heim_string_t k2_3 = heim_string_create("k2-3");
338 heim_string_t k2_4 = heim_string_create("k2-4");
339 heim_string_t k2_5 = heim_string_create("k2-5");
340 heim_string_t k2_5_1 = heim_string_create("k2-5-1");
341 heim_object_t o;
342 heim_object_t neg_num;
343 int ret;
345 if (!dict || !p1 || !p2a || !p2b || !p4a || !p4b)
346 return ENOMEM;
348 ret = heim_path_create(dict, 11, a, NULL, p1, p2a, NULL);
349 heim_release(a);
350 if (ret)
351 return ret;
352 ret = heim_path_create(dict, 11, l3, NULL, p1, p2b, NULL);
353 if (ret)
354 return ret;
355 o = heim_path_get(dict, NULL, p1, p2b, NULL);
356 if (o != l3)
357 return 1;
358 ret = heim_path_create(dict, 11, NULL, NULL, p1, p2a, p3, NULL);
359 if (ret)
360 return ret;
361 ret = heim_path_create(dict, 11, l1, NULL, p1, p2a, p3, p4a, NULL);
362 if (ret)
363 return ret;
364 ret = heim_path_create(dict, 11, l2, NULL, p1, p2a, p3, p4b, NULL);
365 if (ret)
366 return ret;
368 o = heim_path_get(dict, NULL, p1, p2a, p3, p4a, NULL);
369 if (o != l1)
370 return 1;
371 o = heim_path_get(dict, NULL, p1, p2a, p3, p4b, NULL);
372 if (o != l2)
373 return 1;
375 heim_release(dict);
377 /* Test that JSON parsing works right by using heim_path_get() */
378 dict = heim_json_create("{\"k1\":1,"
379 "\"k2\":{\"k2-1\":21,"
380 "\"k2-2\":null,"
381 "\"k2-3\":true,"
382 "\"k2-4\":false,"
383 "\"k2-5\":[1,2,3,{\"k2-5-1\":-1},-2]},"
384 "\"k3\":[true,false,0,42]}", 10, 0, NULL);
385 heim_assert(dict != NULL, "dict");
386 o = heim_path_get(dict, NULL, k1, NULL);
387 if (heim_cmp(o, heim_number_create(1))) return 1;
388 o = heim_path_get(dict, NULL, k2, NULL);
389 if (heim_get_tid(o) != heim_dict_get_type_id()) return 1;
390 o = heim_path_get(dict, NULL, k2, k2_1, NULL);
391 if (heim_cmp(o, heim_number_create(21))) return 1;
392 o = heim_path_get(dict, NULL, k2, k2_2, NULL);
393 if (heim_cmp(o, heim_null_create())) return 1;
394 o = heim_path_get(dict, NULL, k2, k2_3, NULL);
395 if (heim_cmp(o, heim_bool_create(1))) return 1;
396 o = heim_path_get(dict, NULL, k2, k2_4, NULL);
397 if (heim_cmp(o, heim_bool_create(0))) return 1;
398 o = heim_path_get(dict, NULL, k2, k2_5, NULL);
399 if (heim_get_tid(o) != heim_array_get_type_id()) return 1;
400 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(0), NULL);
401 if (heim_cmp(o, heim_number_create(1))) return 1;
402 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(1), NULL);
403 if (heim_cmp(o, heim_number_create(2))) return 1;
404 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(3), k2_5_1, NULL);
405 if (heim_cmp(o, neg_num = heim_number_create(-1))) return 1;
406 heim_release(neg_num);
407 o = heim_path_get(dict, NULL, k2, k2_5, heim_number_create(4), NULL);
408 if (heim_cmp(o, neg_num = heim_number_create(-2))) return 1;
409 heim_release(neg_num);
410 o = heim_path_get(dict, NULL, k3, heim_number_create(3), NULL);
411 if (heim_cmp(o, heim_number_create(42))) return 1;
413 heim_release(dict);
414 heim_release(p1);
415 heim_release(p2a);
416 heim_release(p2b);
417 heim_release(p4a);
418 heim_release(p4b);
419 heim_release(k1);
420 heim_release(k2);
421 heim_release(k3);
422 heim_release(k2_1);
423 heim_release(k2_2);
424 heim_release(k2_3);
425 heim_release(k2_4);
426 heim_release(k2_5);
427 heim_release(k2_5_1);
429 return 0;
432 typedef struct dict_db {
433 heim_dict_t dict;
434 int locked;
435 } *dict_db_t;
437 static int
438 dict_db_open(void *plug, const char *dbtype, const char *dbname,
439 heim_dict_t options, void **db, heim_error_t *error)
441 dict_db_t dictdb;
442 heim_dict_t contents = NULL;
444 if (error)
445 *error = NULL;
446 if (dbtype && *dbtype && strcmp(dbtype, "dictdb"))
447 return EINVAL;
448 if (dbname && *dbname && strcmp(dbname, "MEMORY") != 0)
449 return EINVAL;
450 dictdb = heim_alloc(sizeof (*dictdb), "dict_db", NULL);
451 if (dictdb == NULL)
452 return ENOMEM;
454 if (contents != NULL)
455 dictdb->dict = contents;
456 else {
457 dictdb->dict = heim_dict_create(29);
458 if (dictdb->dict == NULL) {
459 heim_release(dictdb);
460 return ENOMEM;
464 *db = dictdb;
465 return 0;
468 static int
469 dict_db_close(void *db, heim_error_t *error)
471 dict_db_t dictdb = db;
473 if (error)
474 *error = NULL;
475 heim_release(dictdb->dict);
476 heim_release(dictdb);
477 return 0;
480 static int
481 dict_db_lock(void *db, int read_only, heim_error_t *error)
483 dict_db_t dictdb = db;
485 if (error)
486 *error = NULL;
487 if (dictdb->locked)
488 return EWOULDBLOCK;
489 dictdb->locked = 1;
490 return 0;
493 static int
494 dict_db_unlock(void *db, heim_error_t *error)
496 dict_db_t dictdb = db;
498 if (error)
499 *error = NULL;
500 dictdb->locked = 0;
501 return 0;
504 static heim_data_t
505 dict_db_copy_value(void *db, heim_string_t table, heim_data_t key,
506 heim_error_t *error)
508 dict_db_t dictdb = db;
510 if (error)
511 *error = NULL;
513 return heim_retain(heim_path_get(dictdb->dict, error, table, key, NULL));
516 static int
517 dict_db_set_value(void *db, heim_string_t table,
518 heim_data_t key, heim_data_t value, heim_error_t *error)
520 dict_db_t dictdb = db;
522 if (error)
523 *error = NULL;
525 if (table == NULL)
526 table = HSTR("");
528 return heim_path_create(dictdb->dict, 29, value, error, table, key, NULL);
531 static int
532 dict_db_del_key(void *db, heim_string_t table, heim_data_t key,
533 heim_error_t *error)
535 dict_db_t dictdb = db;
537 if (error)
538 *error = NULL;
540 if (table == NULL)
541 table = HSTR("");
543 heim_path_delete(dictdb->dict, error, table, key, NULL);
544 return 0;
547 struct dict_db_iter_ctx {
548 heim_db_iterator_f_t iter_f;
549 void *iter_ctx;
552 static void dict_db_iter_f(heim_object_t key, heim_object_t value, void *arg)
554 struct dict_db_iter_ctx *ctx = arg;
556 ctx->iter_f((heim_object_t)key, (heim_object_t)value, ctx->iter_ctx);
559 static void
560 dict_db_iter(void *db, heim_string_t table, void *iter_data,
561 heim_db_iterator_f_t iter_f, heim_error_t *error)
563 dict_db_t dictdb = db;
564 struct dict_db_iter_ctx ctx;
565 heim_dict_t table_dict;
567 if (error)
568 *error = NULL;
570 if (table == NULL)
571 table = HSTR("");
573 table_dict = heim_dict_copy_value(dictdb->dict, table);
574 if (table_dict == NULL)
575 return;
577 ctx.iter_ctx = iter_data;
578 ctx.iter_f = iter_f;
580 heim_dict_iterate_f(table_dict, &ctx, dict_db_iter_f);
581 heim_release(table_dict);
584 static void
585 test_db_iter(heim_data_t k, heim_data_t v, void *arg)
587 int *ret = arg;
588 const void *kptr, *vptr;
589 size_t klen, vlen;
591 heim_assert(heim_get_tid(k) == heim_data_get_type_id(), "...");
593 kptr = heim_data_get_ptr(k);
594 klen = heim_data_get_length(k);
595 vptr = heim_data_get_ptr(v);
596 vlen = heim_data_get_length(v);
598 if (klen == strlen("msg") && !strncmp(kptr, "msg", strlen("msg")) &&
599 vlen == strlen("abc") && !strncmp(vptr, "abc", strlen("abc")))
600 *ret &= ~(1);
601 else if (klen == strlen("msg2") &&
602 !strncmp(kptr, "msg2", strlen("msg2")) &&
603 vlen == strlen("FooBar") && !strncmp(vptr, "FooBar", strlen("FooBar")))
604 *ret &= ~(2);
605 else
606 *ret |= 4;
609 static struct heim_db_type dbt = {
610 1, dict_db_open, NULL, dict_db_close,
611 dict_db_lock, dict_db_unlock, NULL, NULL, NULL, NULL,
612 dict_db_copy_value, dict_db_set_value,
613 dict_db_del_key, dict_db_iter
616 static int
617 test_db(const char *dbtype, const char *dbname)
619 heim_data_t k1, k2, v, v1, v2, v3;
620 heim_db_t db;
621 int ret;
623 if (dbtype == NULL) {
624 ret = heim_db_register("dictdb", NULL, &dbt);
625 heim_assert(!ret, "...");
626 db = heim_db_create("dictdb", "foo", NULL, NULL);
627 heim_assert(!db, "...");
628 db = heim_db_create("foobar", "MEMORY", NULL, NULL);
629 heim_assert(!db, "...");
630 db = heim_db_create("dictdb", "MEMORY", NULL, NULL);
631 heim_assert(db, "...");
632 } else {
633 heim_dict_t options;
635 options = heim_dict_create(11);
636 if (options == NULL) return ENOMEM;
637 if (heim_dict_set_value(options, HSTR("journal-filename"),
638 HSTR("json-journal")))
639 return ENOMEM;
640 if (heim_dict_set_value(options, HSTR("create"), heim_null_create()))
641 return ENOMEM;
642 if (heim_dict_set_value(options, HSTR("truncate"), heim_null_create()))
643 return ENOMEM;
644 db = heim_db_create(dbtype, dbname, options, NULL);
645 heim_assert(db, "...");
646 heim_release(options);
649 k1 = heim_data_create("msg", strlen("msg"));
650 k2 = heim_data_create("msg2", strlen("msg2"));
651 v1 = heim_data_create("Hello world!", strlen("Hello world!"));
652 v2 = heim_data_create("FooBar", strlen("FooBar"));
653 v3 = heim_data_create("abc", strlen("abc"));
655 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
656 heim_assert(!ret, "...");
658 v = heim_db_copy_value(db, NULL, k1, NULL);
659 heim_assert(v && !heim_cmp(v, v1), "...");
660 heim_release(v);
662 ret = heim_db_set_value(db, NULL, k2, v2, NULL);
663 heim_assert(!ret, "...");
665 v = heim_db_copy_value(db, NULL, k2, NULL);
666 heim_assert(v && !heim_cmp(v, v2), "...");
667 heim_release(v);
669 ret = heim_db_set_value(db, NULL, k1, v3, NULL);
670 heim_assert(!ret, "...");
672 v = heim_db_copy_value(db, NULL, k1, NULL);
673 heim_assert(v && !heim_cmp(v, v3), "...");
674 heim_release(v);
676 ret = 3;
677 heim_db_iterate_f(db, NULL, &ret, test_db_iter, NULL);
678 heim_assert(!ret, "...");
680 ret = heim_db_begin(db, 0, NULL);
681 heim_assert(!ret, "...");
683 ret = heim_db_commit(db, NULL);
684 heim_assert(!ret, "...");
686 ret = heim_db_begin(db, 0, NULL);
687 heim_assert(!ret, "...");
689 ret = heim_db_rollback(db, NULL);
690 heim_assert(!ret, "...");
692 ret = heim_db_begin(db, 0, NULL);
693 heim_assert(!ret, "...");
695 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
696 heim_assert(!ret, "...");
698 v = heim_db_copy_value(db, NULL, k1, NULL);
699 heim_assert(v && !heim_cmp(v, v1), "...");
700 heim_release(v);
702 ret = heim_db_rollback(db, NULL);
703 heim_assert(!ret, "...");
705 v = heim_db_copy_value(db, NULL, k1, NULL);
706 heim_assert(v && !heim_cmp(v, v3), "...");
707 heim_release(v);
709 ret = heim_db_begin(db, 0, NULL);
710 heim_assert(!ret, "...");
712 ret = heim_db_set_value(db, NULL, k1, v1, NULL);
713 heim_assert(!ret, "...");
715 v = heim_db_copy_value(db, NULL, k1, NULL);
716 heim_assert(v && !heim_cmp(v, v1), "...");
717 heim_release(v);
719 ret = heim_db_commit(db, NULL);
720 heim_assert(!ret, "...");
722 v = heim_db_copy_value(db, NULL, k1, NULL);
723 heim_assert(v && !heim_cmp(v, v1), "...");
724 heim_release(v);
726 ret = heim_db_begin(db, 0, NULL);
727 heim_assert(!ret, "...");
729 ret = heim_db_delete_key(db, NULL, k1, NULL);
730 heim_assert(!ret, "...");
732 v = heim_db_copy_value(db, NULL, k1, NULL);
733 heim_assert(v == NULL, "...");
734 heim_release(v);
736 ret = heim_db_rollback(db, NULL);
737 heim_assert(!ret, "...");
739 v = heim_db_copy_value(db, NULL, k1, NULL);
740 heim_assert(v && !heim_cmp(v, v1), "...");
741 heim_release(v);
743 if (dbtype != NULL) {
744 heim_data_t k3 = heim_data_create("value-is-a-dict", strlen("value-is-a-dict"));
745 heim_dict_t vdict = heim_dict_create(11);
746 heim_db_t db2;
748 heim_assert(k3 && vdict, "...");
749 ret = heim_dict_set_value(vdict, HSTR("vdict-k1"), heim_number_create(11));
750 heim_assert(!ret, "...");
751 ret = heim_dict_set_value(vdict, HSTR("vdict-k2"), heim_null_create());
752 heim_assert(!ret, "...");
753 ret = heim_dict_set_value(vdict, HSTR("vdict-k3"), HSTR("a value"));
754 heim_assert(!ret, "...");
755 ret = heim_db_set_value(db, NULL, k3, (heim_data_t)vdict, NULL);
756 heim_assert(!ret, "...");
758 heim_release(vdict);
760 db2 = heim_db_create(dbtype, dbname, NULL, NULL);
761 heim_assert(db2, "...");
763 vdict = (heim_dict_t)heim_db_copy_value(db2, NULL, k3, NULL);
764 heim_release(db2);
765 heim_release(k3);
766 heim_assert(vdict, "...");
767 heim_assert(heim_get_tid(vdict) == heim_dict_get_type_id(), "...");
769 v = heim_dict_copy_value(vdict, HSTR("vdict-k1"));
770 heim_assert(v && !heim_cmp(v, heim_number_create(11)), "...");
771 heim_release(v);
773 v = heim_dict_copy_value(vdict, HSTR("vdict-k2"));
774 heim_assert(v && !heim_cmp(v, heim_null_create()), "...");
775 heim_release(v);
777 v = heim_dict_copy_value(vdict, HSTR("vdict-k3"));
778 heim_assert(v && !heim_cmp(v, HSTR("a value")), "...");
779 heim_release(v);
781 heim_release(vdict);
784 heim_release(db);
785 heim_release(k1);
786 heim_release(k2);
787 heim_release(v1);
788 heim_release(v2);
789 heim_release(v3);
791 return 0;
794 struct test_array_iter_ctx {
795 char buf[256];
798 static void test_array_iter(heim_object_t elt, void *arg, int *stop)
800 struct test_array_iter_ctx *iter_ctx = arg;
802 strcat(iter_ctx->buf, heim_string_get_utf8((heim_string_t)elt));
805 static int
806 test_array()
808 struct test_array_iter_ctx iter_ctx;
809 heim_string_t s1 = heim_string_create("abc");
810 heim_string_t s2 = heim_string_create("def");
811 heim_string_t s3 = heim_string_create("ghi");
812 heim_string_t s4 = heim_string_create("jkl");
813 heim_string_t s5 = heim_string_create("mno");
814 heim_string_t s6 = heim_string_create("pqr");
815 heim_array_t a = heim_array_create();
817 if (!s1 || !s2 || !s3 || !s4 || !s5 || !s6 || !a)
818 return ENOMEM;
820 heim_array_append_value(a, s4);
821 heim_array_append_value(a, s5);
822 heim_array_insert_value(a, 0, s3);
823 heim_array_insert_value(a, 0, s2);
824 heim_array_append_value(a, s6);
825 heim_array_insert_value(a, 0, s1);
827 iter_ctx.buf[0] = '\0';
828 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
829 if (strcmp(iter_ctx.buf, "abcdefghijklmnopqr") != 0)
830 return 1;
832 iter_ctx.buf[0] = '\0';
833 heim_array_delete_value(a, 2);
834 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
835 if (strcmp(iter_ctx.buf, "abcdefjklmnopqr") != 0)
836 return 1;
838 iter_ctx.buf[0] = '\0';
839 heim_array_delete_value(a, 2);
840 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
841 if (strcmp(iter_ctx.buf, "abcdefmnopqr") != 0)
842 return 1;
844 iter_ctx.buf[0] = '\0';
845 heim_array_delete_value(a, 0);
846 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
847 if (strcmp(iter_ctx.buf, "defmnopqr") != 0)
848 return 1;
850 iter_ctx.buf[0] = '\0';
851 heim_array_delete_value(a, 2);
852 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
853 if (strcmp(iter_ctx.buf, "defmno") != 0)
854 return 1;
856 heim_array_insert_value(a, 0, s1);
857 iter_ctx.buf[0] = '\0';
858 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
859 if (strcmp(iter_ctx.buf, "abcdefmno") != 0)
860 return 1;
862 heim_array_insert_value(a, 0, s2);
863 iter_ctx.buf[0] = '\0';
864 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
865 if (strcmp(iter_ctx.buf, "defabcdefmno") != 0)
866 return 1;
868 heim_array_append_value(a, s3);
869 iter_ctx.buf[0] = '\0';
870 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
871 if (strcmp(iter_ctx.buf, "defabcdefmnoghi") != 0)
872 return 1;
874 heim_array_append_value(a, s6);
875 iter_ctx.buf[0] = '\0';
876 heim_array_iterate_f(a, &iter_ctx, test_array_iter);
877 if (strcmp(iter_ctx.buf, "defabcdefmnoghipqr") != 0)
878 return 1;
880 heim_release(s1);
881 heim_release(s2);
882 heim_release(s3);
883 heim_release(s4);
884 heim_release(s5);
885 heim_release(s6);
886 heim_release(a);
888 return 0;
892 main(int argc, char **argv)
894 int res = 0;
896 res |= test_memory();
897 res |= test_dict();
898 res |= test_auto_release();
899 res |= test_string();
900 res |= test_error();
901 res |= test_json();
902 res |= test_path();
903 res |= test_db(NULL, NULL);
904 res |= test_db("json", argc > 1 ? argv[1] : "test_db.json");
905 res |= test_array();
907 return res ? 1 : 0;