1/* $Id: t_ppath.c,v 1.1 2011/08/25 19:09:46 dyoung Exp $ */
2
3/* Copyright (c) 2010 David Young.  All rights reserved. */
4
5#include <sys/cdefs.h>
6__RCSID("$Id: t_ppath.c,v 1.1 2011/08/25 19:09:46 dyoung Exp $");
7
8#include <assert.h>
9#include <atf-c.h>
10#include <errno.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include <ppath/ppath.h>
15#include "personnel.h"
16
17void test_ppath_extant_inc(void);
18void test_ppath_extant_dec(void);
19void test_ppath_component_extant_inc(void);
20void test_ppath_component_extant_dec(void);
21
22__strong_alias(ppath_extant_inc, test_ppath_extant_inc);
23__strong_alias(ppath_extant_dec, test_ppath_extant_dec);
24__strong_alias(ppath_component_extant_inc, test_ppath_component_extant_inc);
25__strong_alias(ppath_component_extant_dec, test_ppath_component_extant_dec);
26
27static uint64_t nppath = 0, nppath_component = 0;
28
29static bool
30dictionary_equals(prop_dictionary_t ld, prop_dictionary_t rd)
31{
32	bool eq;
33	char *lt, *rt;
34
35	lt = prop_dictionary_externalize(ld);
36	rt = prop_dictionary_externalize(rd);
37
38	assert(lt != NULL && rt != NULL);
39
40	eq = (strcmp(lt, rt) == 0);
41
42	free(lt);
43	free(rt);
44
45	return eq;
46}
47
48static void
49assert_no_ppath_extant(void)
50{
51	ATF_CHECK_EQ(nppath, 0);
52}
53
54static void
55assert_no_ppath_component_extant(void)
56{
57	ATF_CHECK_EQ(nppath_component, 0);
58}
59
60void
61test_ppath_extant_inc(void)
62{
63	if (++nppath == 0)
64		atf_tc_fail("count of extant paths overflowed");
65}
66
67void
68test_ppath_extant_dec(void)
69{
70	if (nppath-- == 0)
71		atf_tc_fail("count of extant path underflowed");
72}
73
74void
75test_ppath_component_extant_inc(void)
76{
77	if (++nppath_component == 0)
78		atf_tc_fail("count of extant path components overflowed");
79}
80
81void
82test_ppath_component_extant_dec(void)
83{
84	if (nppath_component-- == 0)
85		atf_tc_fail("count of extant path components underflowed");
86}
87
88ATF_TC(push_until_full);
89
90ATF_TC_HEAD(push_until_full, tc)
91{
92	atf_tc_set_md_var(tc, "descr", "check ppath_push() returns error "
93	    "after ppath_t reaches maximum length");
94}
95
96ATF_TC_BODY(push_until_full, tc)
97{
98	ppath_t *p, *rp;
99	ppath_component_t *pc;
100	int i;
101
102	assert_no_ppath_extant();
103	assert_no_ppath_component_extant();
104
105	if ((p = ppath_create()) == NULL)
106		atf_tc_fail("ppath_create failed");
107
108	if ((pc = ppath_idx(0)) == NULL)
109		atf_tc_fail("ppath_idx failed");
110
111	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
112		rp = ppath_push(p, pc);
113		ATF_CHECK_EQ(rp, p);
114	}
115
116	rp = ppath_push(p, pc);
117	ATF_CHECK_EQ(rp, NULL);
118
119	rp = ppath_push(p, pc);
120	ATF_CHECK_EQ(rp, NULL);
121
122	ppath_component_release(pc);
123	ppath_release(p);
124
125	assert_no_ppath_extant();
126	assert_no_ppath_component_extant();
127}
128
129ATF_TC(pop_until_empty);
130ATF_TC_HEAD(pop_until_empty, tc)
131{
132	atf_tc_set_md_var(tc, "descr", "check ppath_pop() returns error "
133	    "after ppath_t is empty");
134}
135
136ATF_TC_BODY(pop_until_empty, tc)
137{
138	ppath_t *p, *rp;
139	ppath_component_t *pc, *rpc;
140	int i;
141
142	assert_no_ppath_extant();
143	assert_no_ppath_component_extant();
144
145	if ((p = ppath_create()) == NULL)
146		atf_tc_fail("ppath_create failed");
147
148	if ((pc = ppath_idx(0)) == NULL)
149		atf_tc_fail("ppath_idx failed");
150
151	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
152		rp = ppath_push(p, pc);
153		ATF_CHECK_EQ(rp, p);
154	}
155
156	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
157		rp = ppath_pop(p, &rpc);
158		ATF_CHECK_EQ(rp, p);
159		ATF_CHECK_EQ(rpc, pc);
160		ppath_component_release(rpc);
161	}
162
163	rp = ppath_pop(p, &rpc);
164	ATF_CHECK_EQ(rp, NULL);
165	rp = ppath_pop(p, &rpc);
166	ATF_CHECK_EQ(rp, NULL);
167
168	ppath_component_release(pc);
169	ppath_release(p);
170
171	assert_no_ppath_extant();
172	assert_no_ppath_component_extant();
173}
174
175ATF_TC(length);
176
177ATF_TC_HEAD(length, tc)
178{
179	atf_tc_set_md_var(tc, "descr", "check that ppath_push() "
180	    "and ppath_pop() affect ppath_length() correctly");
181}
182
183ATF_TC_BODY(length, tc)
184{
185	ppath_t *p, *rp;
186	ppath_component_t *pc;
187	unsigned int i, len;
188
189	assert_no_ppath_extant();
190	assert_no_ppath_component_extant();
191
192	if ((p = ppath_create()) == NULL)
193		atf_tc_fail("ppath_create failed");
194
195	if ((pc = ppath_idx(0)) == NULL)
196		atf_tc_fail("ppath_idx failed");
197
198	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
199		len = ppath_length(p);
200		ATF_CHECK_EQ(len, i);
201		rp = ppath_push(p, pc);
202		ATF_CHECK_EQ(rp, p);
203	}
204
205	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
206		len = ppath_length(p);
207		ATF_CHECK_EQ(len, PPATH_MAX_COMPONENTS - i);
208		rp = ppath_pop(p, NULL);
209		ATF_CHECK_EQ(rp, p);
210	}
211	ppath_component_release(pc);
212	ppath_release(p);
213
214	assert_no_ppath_extant();
215	assert_no_ppath_component_extant();
216}
217
218ATF_TC(component_at);
219
220ATF_TC_HEAD(component_at, tc)
221{
222	atf_tc_set_md_var(tc, "descr", "check that ppath_component_at() "
223	    "returns the expected component");
224}
225
226ATF_TC_BODY(component_at, tc)
227{
228	ppath_t *p, *rp;
229	ppath_component_t *pc;
230	unsigned int i;
231
232	assert_no_ppath_extant();
233	assert_no_ppath_component_extant();
234
235	if ((p = ppath_create()) == NULL)
236		atf_tc_fail("ppath_create failed");
237
238	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
239		if ((pc = ppath_idx(i)) == NULL)
240			atf_tc_fail("ppath_idx failed");
241		rp = ppath_push(p, pc);
242		ppath_component_release(pc);
243		ATF_CHECK_EQ(rp, p);
244	}
245
246	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
247		pc = ppath_component_at(p, i);
248		ATF_CHECK_EQ(ppath_component_idx(pc), (int)i);
249		ppath_component_release(pc);
250	}
251	ppath_release(p);
252
253	assert_no_ppath_extant();
254	assert_no_ppath_component_extant();
255}
256
257ATF_TC(get_idx_key);
258
259ATF_TC_HEAD(get_idx_key, tc)
260{
261	atf_tc_set_md_var(tc, "descr", "check that ppath_component_idx() "
262	    "and ppath_component_key() return -1 and NULL, respectively, if "
263	    "the component is a key or an index, respectively.");
264}
265
266ATF_TC_BODY(get_idx_key, tc)
267{
268	ppath_component_t *idx, *key;
269
270	assert_no_ppath_extant();
271	assert_no_ppath_component_extant();
272
273	if ((idx = ppath_idx(0)) == NULL)
274		atf_tc_fail("ppath_idx failed");
275	if ((key = ppath_key("key")) == NULL)
276		atf_tc_fail("ppath_idx failed");
277
278	ATF_CHECK_EQ(ppath_component_key(idx), NULL);
279	ATF_CHECK_EQ(ppath_component_idx(key), -1);
280
281	ppath_component_release(idx);
282	ppath_component_release(key);
283
284	assert_no_ppath_extant();
285	assert_no_ppath_component_extant();
286}
287
288ATF_TC(ppath_copy);
289
290ATF_TC_HEAD(ppath_copy, tc)
291{
292	atf_tc_set_md_var(tc, "descr", "check that ppath_copy() "
293	    "creates an exact replica of a path, and that no "
294	    "resources are leaked.");
295}
296
297ATF_TC_BODY(ppath_copy, tc)
298{
299	ppath_component_t *pc, *cpc;
300	ppath_t *p, *cp, *rp;
301	unsigned int i;
302
303	assert_no_ppath_extant();
304	assert_no_ppath_component_extant();
305
306	if ((p = ppath_create()) == NULL)
307		atf_tc_fail("ppath_create failed");
308
309	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
310		if ((pc = ppath_idx(i)) == NULL)
311			atf_tc_fail("ppath_idx failed");
312		rp = ppath_push(p, pc);
313		ppath_component_release(pc);
314		ATF_CHECK_EQ(rp, p);
315	}
316
317	if ((cp = ppath_copy(p)) == NULL)
318		atf_tc_fail("ppath_copy failed");
319
320	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
321		pc = ppath_component_at(p, i);
322		cpc = ppath_component_at(cp, i);
323		ATF_CHECK_EQ(pc, cpc);
324		ppath_component_release(pc);
325		ppath_component_release(cpc);
326	}
327
328	ppath_release(cp);
329	ppath_release(p);
330
331	assert_no_ppath_extant();
332	assert_no_ppath_component_extant();
333}
334
335ATF_TC(replace);
336
337ATF_TC_HEAD(replace, tc)
338{
339	atf_tc_set_md_var(tc, "descr", "check that ppath_replace_idx() "
340	    "and ppath_replace_key() produce the paths we expect without "
341	    "leaking resources.");
342}
343
344ATF_TC_BODY(replace, tc)
345{
346	ppath_component_t *pc;
347	ppath_t *p, *cp, *rp;
348	unsigned int i;
349
350	assert_no_ppath_extant();
351	assert_no_ppath_component_extant();
352
353	if ((p = ppath_create()) == NULL)
354		atf_tc_fail("ppath_create failed");
355
356	/* index replacement fails on an empty path */
357	rp = ppath_replace_idx(p, 0);
358	ATF_CHECK_EQ(rp, NULL);
359
360	/* key replacement fails on an empty path */
361	rp = ppath_replace_key(p, "key");
362	ATF_CHECK_EQ(rp, NULL);
363
364	for (i = 0; i < PPATH_MAX_COMPONENTS; i++) {
365		if ((pc = ppath_idx(i)) == NULL)
366			atf_tc_fail("ppath_idx failed");
367		rp = ppath_push(p, pc);
368		ppath_component_release(pc);
369		ATF_CHECK_EQ(rp, p);
370	}
371
372	if ((cp = ppath_copy(p)) == NULL)
373		atf_tc_fail("ppath_copy failed");
374
375	rp = ppath_pop(cp, NULL);
376	ATF_CHECK_EQ(rp, cp);
377	rp = ppath_push_key(cp, "key");
378	ATF_CHECK_EQ(rp, cp);
379
380	ppath_replace_idx(p, 0);
381
382	if ((pc = ppath_component_at(p, PPATH_MAX_COMPONENTS - 1)) == NULL)
383		atf_tc_fail("ppath_idx failed");
384	ATF_CHECK_EQ(ppath_component_idx(pc), 0);
385	ppath_component_release(pc);
386
387	for (i = 0; i < PPATH_MAX_COMPONENTS - 1; i++) {
388		if ((pc = ppath_component_at(p, i)) == NULL)
389			atf_tc_fail("ppath_idx failed");
390		ATF_CHECK_EQ(ppath_component_idx(pc), (int)i);
391		ppath_component_release(pc);
392	}
393
394	for (i = 0; i < PPATH_MAX_COMPONENTS - 1; i++) {
395		if ((pc = ppath_component_at(cp, i)) == NULL)
396			atf_tc_fail("ppath_idx failed");
397		ATF_CHECK_EQ(ppath_component_idx(pc), (int)i);
398		ppath_component_release(pc);
399	}
400
401	if ((pc = ppath_component_at(cp, PPATH_MAX_COMPONENTS - 1)) == NULL)
402		atf_tc_fail("ppath_idx failed");
403	if (ppath_component_key(pc) == NULL ||
404	    strcmp(ppath_component_key(pc), "key") != 0)
405		atf_tc_fail("last path component expected to be \"key\"");
406	ppath_component_release(pc);
407	ppath_release(p);
408	ppath_release(cp);
409
410	assert_no_ppath_extant();
411	assert_no_ppath_component_extant();
412}
413
414ATF_TC(copyset_object_twice_success);
415
416ATF_TC_HEAD(copyset_object_twice_success, tc)
417{
418	atf_tc_set_md_var(tc, "descr",
419	    "check that after back-to-back ppath_copyset_object() calls, "
420	    "changing the \"u.s. citizen\" property and the first property "
421	    "in \"children\" in the \"John Doe\" record in the "
422	    "\"personnel\" property list, the properties are changed "
423	    "in the new dictionary and unchanged in the old dictionary");
424}
425
426ATF_TC_BODY(copyset_object_twice_success, tc)
427{
428	const char *s;
429	char *oext, *next;
430	int rc;
431	bool v = false;
432	prop_dictionary_t d, od;
433	prop_object_t nd = NULL, ond;
434	prop_object_t r, or;
435	ppath_t *p, *p2, *p3;
436
437	assert_no_ppath_extant();
438	assert_no_ppath_component_extant();
439
440	if ((d = prop_dictionary_internalize(personnel)) == NULL)
441		atf_tc_fail("prop_dictionary_internalize failed");
442	od = prop_dictionary_copy(d);
443
444	if (!dictionary_equals(od, d)) {
445		oext = prop_dictionary_externalize(od);
446		next = prop_dictionary_externalize(d);
447		atf_tc_fail("dictionaries are unequal from the outset, argh! "
448		    "original\n%s\nnew\n%s", oext, next);
449		free(oext);
450		free(next);
451	}
452
453	if ((p = ppath_create()) == NULL || (p2 = ppath_create()) == NULL ||
454	    (p3 = ppath_create()) == NULL)
455		atf_tc_fail("ppath_create failed");
456
457	if (ppath_push_key(p, "John Doe") == NULL)
458		atf_tc_fail("ppath_push_key failed");
459	if (ppath_push_key(p, "u.s. citizen") == NULL)
460		atf_tc_fail("ppath_push_key failed");
461
462	if (ppath_push_key(p2, "John Doe") == NULL)
463		atf_tc_fail("ppath_push_key failed");
464	if (ppath_push_key(p2, "children") == NULL)
465		atf_tc_fail("ppath_push_key failed");
466	if (ppath_push_idx(p2, 0) == NULL)
467		atf_tc_fail("ppath_push_idx failed");
468
469	if (ppath_push_key(p3, "John Doe") == NULL)
470		atf_tc_fail("ppath_push_key failed");
471
472	v = false;
473	rc = ppath_get_bool(d, p, &v);
474	ATF_CHECK_EQ(rc, 0);
475	ATF_CHECK_EQ(v, true);
476
477	s = "";
478	rc = ppath_get_string(d, p2, &s);
479	ATF_CHECK_EQ(rc, 0);
480	ATF_CHECK_STREQ(s, "Jane Doe");
481
482	rc = ppath_copyset_bool(d, &nd, p, false);
483	ATF_CHECK_EQ(rc, 0);
484
485	rc = ppath_get_object(nd, p3, &r);
486	ATF_CHECK_EQ(rc, 0);
487
488	ond = nd;
489
490	rc = ppath_copyset_string(d, &nd, p2, "Martha Doe");
491	ATF_CHECK_EQ(rc, 0);
492
493	ATF_CHECK_EQ(nd, ond);
494
495	rc = ppath_get_object(nd, p3, &or);
496	ATF_CHECK_EQ(rc, 0);
497
498	ATF_CHECK_EQ(r, or);
499
500	v = true;
501	rc = ppath_get_bool(nd, p, &v);
502	ATF_CHECK_EQ(rc, 0);
503	ATF_CHECK_EQ(v, false);
504
505	s = "";
506	rc = ppath_get_string(nd, p2, &s);
507	ATF_CHECK_EQ(rc, 0);
508	ATF_CHECK_STREQ(s, "Martha Doe");
509
510	if (!dictionary_equals(od, d)) {
511		oext = prop_dictionary_externalize(od);
512		next = prop_dictionary_externalize(d);
513		atf_tc_fail("copydel modified original dictionary, "
514		    "original\n%s\nnew\n%s", oext, next);
515		free(oext);
516		free(next);
517	}
518
519	if (dictionary_equals(od, nd)) {
520		oext = prop_dictionary_externalize(od);
521		next = prop_dictionary_externalize(nd);
522		atf_tc_fail("copydel made no change to the new "
523		    "dictionary, original\n%s\nnew\n%s", oext, next);
524		free(oext);
525		free(next);
526	}
527
528	rc = ppath_set_bool(od, p, false);
529	ATF_CHECK_EQ(rc, 0);
530
531	rc = ppath_set_string(od, p2, "Martha Doe");
532	ATF_CHECK_EQ(rc, 0);
533
534	if (!dictionary_equals(od, nd)) {
535		oext = prop_dictionary_externalize(od);
536		next = prop_dictionary_externalize(nd);
537		atf_tc_fail("copydel made an out-of-bounds change to the new "
538		    "dictionary, original\n%s\nnew\n%s", oext, next);
539		free(oext);
540		free(next);
541	}
542
543	ppath_release(p);
544	ppath_release(p2);
545	ppath_release(p3);
546	prop_object_release(d);
547	prop_object_release(od);
548	prop_object_release(nd);
549	assert_no_ppath_extant();
550	assert_no_ppath_component_extant();
551}
552
553ATF_TC(copydel_object_twice_success);
554
555ATF_TC_HEAD(copydel_object_twice_success, tc)
556{
557	atf_tc_set_md_var(tc, "descr",
558	    "check that after back-to-back ppath_copydel_object() calls, "
559	    "removing the \"u.s. citizen\" property and the first property "
560	    "in \"children\" from the \"John Doe\" record in the "
561	    "\"personnel\" property list, the properties are missing "
562	    "from the new dictionary and unchanged in the old dictionary");
563}
564
565ATF_TC_BODY(copydel_object_twice_success, tc)
566{
567	const char *s;
568	char *oext, *next;
569	int rc;
570	bool v = false;
571	prop_dictionary_t d, od;
572	prop_object_t nd = NULL, ond;
573	prop_object_t r, or;
574	ppath_t *p, *p2, *p3;
575
576	assert_no_ppath_extant();
577	assert_no_ppath_component_extant();
578
579	if ((d = prop_dictionary_internalize(personnel)) == NULL)
580		atf_tc_fail("prop_dictionary_internalize failed");
581	od = prop_dictionary_copy(d);
582
583	if (!dictionary_equals(od, d)) {
584		oext = prop_dictionary_externalize(od);
585		next = prop_dictionary_externalize(d);
586		atf_tc_fail("dictionaries are unequal from the outset, argh! "
587		    "original\n%s\nnew\n%s", oext, next);
588		free(oext);
589		free(next);
590	}
591
592	if ((p = ppath_create()) == NULL || (p2 = ppath_create()) == NULL ||
593	    (p3 = ppath_create()) == NULL)
594		atf_tc_fail("ppath_create failed");
595
596	if (ppath_push_key(p, "John Doe") == NULL)
597		atf_tc_fail("ppath_push_key failed");
598	if (ppath_push_key(p, "u.s. citizen") == NULL)
599		atf_tc_fail("ppath_push_key failed");
600
601	if (ppath_push_key(p2, "John Doe") == NULL)
602		atf_tc_fail("ppath_push_key failed");
603	if (ppath_push_key(p2, "children") == NULL)
604		atf_tc_fail("ppath_push_key failed");
605	if (ppath_push_idx(p2, 0) == NULL)
606		atf_tc_fail("ppath_push_idx failed");
607
608	if (ppath_push_key(p3, "John Doe") == NULL)
609		atf_tc_fail("ppath_push_key failed");
610
611	v = false;
612	rc = ppath_get_bool(d, p, &v);
613	ATF_CHECK_EQ(rc, 0);
614	ATF_CHECK_EQ(v, true);
615
616	s = "";
617	rc = ppath_get_string(d, p2, &s);
618	ATF_CHECK_EQ(rc, 0);
619	ATF_CHECK_STREQ(s, "Jane Doe");
620
621	rc = ppath_copydel_bool(d, &nd, p);
622	ATF_CHECK_EQ(rc, 0);
623
624	ond = nd;
625
626	rc = ppath_get_object(nd, p3, &r);
627	ATF_CHECK_EQ(rc, 0);
628
629	rc = ppath_copydel_string(d, &nd, p2);
630	ATF_CHECK_EQ(rc, 0);
631
632	ATF_CHECK_EQ(nd, ond);
633
634	rc = ppath_get_object(nd, p3, &or);
635	ATF_CHECK_EQ(rc, 0);
636
637	ATF_CHECK_EQ(r, or);
638
639	v = true;
640	rc = ppath_get_bool(nd, p, &v);
641	ATF_CHECK_EQ(rc, ENOENT);
642	ATF_CHECK_EQ(v, true);
643
644	if (!dictionary_equals(od, d)) {
645		oext = prop_dictionary_externalize(od);
646		next = prop_dictionary_externalize(d);
647		atf_tc_fail("copydel modified original dictionary, "
648		    "original\n%s\nnew\n%s", oext, next);
649		free(oext);
650		free(next);
651	}
652
653	if (dictionary_equals(od, nd)) {
654		oext = prop_dictionary_externalize(od);
655		next = prop_dictionary_externalize(nd);
656		atf_tc_fail("copydel made no change to the new "
657		    "dictionary, original\n%s\nnew\n%s", oext, next);
658		free(oext);
659		free(next);
660	}
661
662	rc = ppath_delete_bool(od, p);
663	ATF_CHECK_EQ(rc, 0);
664
665	rc = ppath_delete_string(od, p2);
666	ATF_CHECK_EQ(rc, 0);
667
668	if (!dictionary_equals(od, nd)) {
669		oext = prop_dictionary_externalize(od);
670		next = prop_dictionary_externalize(nd);
671		atf_tc_fail("copydel made an out-of-bounds change to the new "
672		    "dictionary, original\n%s\nnew\n%s", oext, next);
673		free(oext);
674		free(next);
675	}
676
677	ppath_release(p);
678	ppath_release(p2);
679	ppath_release(p3);
680	prop_object_release(d);
681	prop_object_release(od);
682	prop_object_release(nd);
683	assert_no_ppath_extant();
684	assert_no_ppath_component_extant();
685}
686
687ATF_TC(copydel_bool_success);
688
689ATF_TC_HEAD(copydel_bool_success, tc)
690{
691	atf_tc_set_md_var(tc, "descr", "check ppath_copydel_bool() deletes "
692	    "the \"u.s. citizen\" property in the \"John Doe\" record in the "
693	    "\"personnel\" property list and verifies the value is missing "
694	    "from the new dictionary and unchanged in the old dictionary");
695}
696
697ATF_TC_BODY(copydel_bool_success, tc)
698{
699	char *oext, *next;
700	int rc;
701	bool v = false;
702	prop_dictionary_t d, od;
703	prop_object_t nd = NULL;
704	ppath_t *p;
705
706	assert_no_ppath_extant();
707	assert_no_ppath_component_extant();
708
709	if ((d = prop_dictionary_internalize(personnel)) == NULL)
710		atf_tc_fail("prop_dictionary_internalize failed");
711	od = prop_dictionary_copy(d);
712
713	if (!dictionary_equals(od, d)) {
714		oext = prop_dictionary_externalize(od);
715		next = prop_dictionary_externalize(d);
716		atf_tc_fail("dictionaries are unequal from the outset, argh! "
717		    "original\n%s\nnew\n%s", oext, next);
718		free(oext);
719		free(next);
720	}
721
722	if ((p = ppath_create()) == NULL)
723		atf_tc_fail("ppath_create failed");
724
725	if (ppath_push_key(p, "John Doe") == NULL)
726		atf_tc_fail("ppath_push_key failed");
727	if (ppath_push_key(p, "u.s. citizen") == NULL)
728		atf_tc_fail("ppath_push_key failed");
729
730	v = false;
731	rc = ppath_get_bool(d, p, &v);
732	ATF_CHECK_EQ(rc, 0);
733	ATF_CHECK_EQ(v, true);
734
735	rc = ppath_copydel_bool(d, &nd, p);
736	ATF_CHECK_EQ(rc, 0);
737
738	v = true;
739	rc = ppath_get_bool(nd, p, &v);
740	ATF_CHECK_EQ(rc, ENOENT);
741	ATF_CHECK_EQ(v, true);
742
743	if (!dictionary_equals(od, d)) {
744		oext = prop_dictionary_externalize(od);
745		next = prop_dictionary_externalize(d);
746		atf_tc_fail("copydel modified original dictionary, "
747		    "original\n%s\nnew\n%s", oext, next);
748		free(oext);
749		free(next);
750	}
751
752	if (dictionary_equals(od, nd)) {
753		oext = prop_dictionary_externalize(od);
754		next = prop_dictionary_externalize(nd);
755		atf_tc_fail("copydel made no change to the new "
756		    "dictionary, original\n%s\nnew\n%s", oext, next);
757		free(oext);
758		free(next);
759	}
760
761	rc = ppath_delete_bool(od, p);
762	ATF_CHECK_EQ(rc, 0);
763
764	if (!dictionary_equals(od, nd)) {
765		oext = prop_dictionary_externalize(od);
766		next = prop_dictionary_externalize(nd);
767		atf_tc_fail("copydel made an out-of-bounds change to the new "
768		    "dictionary, original\n%s\nnew\n%s", oext, next);
769		free(oext);
770		free(next);
771	}
772
773	ppath_release(p);
774	prop_object_release(d);
775	prop_object_release(od);
776	prop_object_release(nd);
777	assert_no_ppath_extant();
778	assert_no_ppath_component_extant();
779}
780
781ATF_TC(copyset_bool_success);
782
783ATF_TC_HEAD(copyset_bool_success, tc)
784{
785	atf_tc_set_md_var(tc, "descr", "check ppath_copyset_bool() sets "
786	    "the \"u.s. citizen\" property in the \"John Doe\" record in the "
787	    "\"personnel\" property list to false and verifies the new value "
788	    "in the new dictionary and that the old dictionary is unchanged");
789}
790
791ATF_TC_BODY(copyset_bool_success, tc)
792{
793	char *oext, *next;
794	int rc;
795	bool v = false;
796	prop_dictionary_t d, od;
797	prop_object_t nd = NULL;
798	ppath_t *p;
799
800	assert_no_ppath_extant();
801	assert_no_ppath_component_extant();
802
803	if ((d = prop_dictionary_internalize(personnel)) == NULL)
804		atf_tc_fail("prop_dictionary_internalize failed");
805	od = prop_dictionary_copy(d);
806
807	if (!dictionary_equals(od, d)) {
808		oext = prop_dictionary_externalize(od);
809		next = prop_dictionary_externalize(d);
810		atf_tc_fail("dictionaries are unequal from the outset, argh! "
811		    "original\n%s\nnew\n%s", oext, next);
812		free(oext);
813		free(next);
814	}
815
816	if ((p = ppath_create()) == NULL)
817		atf_tc_fail("ppath_create failed");
818
819	if (ppath_push_key(p, "John Doe") == NULL)
820		atf_tc_fail("ppath_push_key failed");
821	if (ppath_push_key(p, "u.s. citizen") == NULL)
822		atf_tc_fail("ppath_push_key failed");
823
824	v = false;
825	rc = ppath_get_bool(d, p, &v);
826	ATF_CHECK_EQ(rc, 0);
827	ATF_CHECK_EQ(v, true);
828
829	rc = ppath_copyset_bool(d, &nd, p, false);
830	ATF_CHECK_EQ(rc, 0);
831
832	v = true;
833	rc = ppath_get_bool(nd, p, &v);
834	ATF_CHECK_EQ(rc, 0);
835	ATF_CHECK_EQ(v, false);
836
837	if (!dictionary_equals(od, d)) {
838		oext = prop_dictionary_externalize(od);
839		next = prop_dictionary_externalize(d);
840		atf_tc_fail("copyset modified original dictionary, "
841		    "original\n%s\nnew\n%s", oext, next);
842		free(oext);
843		free(next);
844	}
845
846	if (dictionary_equals(od, nd)) {
847		oext = prop_dictionary_externalize(od);
848		next = prop_dictionary_externalize(nd);
849		atf_tc_fail("copyset made no change to the new "
850		    "dictionary, original\n%s\nnew\n%s", oext, next);
851		free(oext);
852		free(next);
853	}
854
855	rc = ppath_set_bool(nd, p, true);
856	ATF_CHECK_EQ(rc, 0);
857
858	if (!dictionary_equals(od, nd)) {
859		oext = prop_dictionary_externalize(od);
860		next = prop_dictionary_externalize(nd);
861		atf_tc_fail("copyset made an out-of-bounds change to the new "
862		    "dictionary, original\n%s\nnew\n%s", oext, next);
863		free(oext);
864		free(next);
865	}
866
867	ppath_release(p);
868	prop_object_release(d);
869	prop_object_release(od);
870	prop_object_release(nd);
871	assert_no_ppath_extant();
872	assert_no_ppath_component_extant();
873}
874
875ATF_TC(set_bool_eftype);
876
877ATF_TC_HEAD(set_bool_eftype, tc)
878{
879	atf_tc_set_md_var(tc, "descr", "check ppath_set_bool() does not "
880	    "overwrite with a bool "
881	    "the \"job title\" property in the \"John Doe\" record in "
882	    "the "
883	    "\"personnel\" property list");
884}
885
886ATF_TC_BODY(set_bool_eftype, tc)
887{
888	int rc;
889	bool v = false;
890	prop_dictionary_t d;
891	ppath_t *p;
892
893	assert_no_ppath_extant();
894	assert_no_ppath_component_extant();
895
896	if ((d = prop_dictionary_internalize(personnel)) == NULL)
897		atf_tc_fail("prop_dictionary_internalize failed");
898
899	if ((p = ppath_create()) == NULL)
900		atf_tc_fail("ppath_create failed");
901
902	if (ppath_push_key(p, "John Doe") == NULL)
903		atf_tc_fail("ppath_push_key failed");
904	if (ppath_push_key(p, "job title") == NULL)
905		atf_tc_fail("ppath_push_key failed");
906
907	v = false;
908	rc = ppath_get_bool(d, p, &v);
909	ATF_CHECK_EQ(rc, EFTYPE);
910	ATF_CHECK_EQ(v, false);
911
912	rc = ppath_set_bool(d, p, false);
913	ATF_CHECK_EQ(rc, EFTYPE);
914
915	v = true;
916	rc = ppath_get_bool(d, p, &v);
917	ATF_CHECK_EQ(rc, EFTYPE);
918	ATF_CHECK_EQ(v, true);
919
920	ppath_release(p);
921	prop_object_release(d);
922	assert_no_ppath_extant();
923	assert_no_ppath_component_extant();
924}
925
926ATF_TC(set_bool_enoent);
927
928ATF_TC_HEAD(set_bool_enoent, tc)
929{
930	atf_tc_set_md_var(tc, "descr", "check ppath_set_bool() does not create "
931	    "the \"russian citizen\" property in the \"John Doe\" record in "
932	    "the "
933	    "\"personnel\" property list");
934}
935
936ATF_TC_BODY(set_bool_enoent, tc)
937{
938	int rc;
939	bool v = false;
940	prop_dictionary_t d;
941	ppath_t *p;
942
943	assert_no_ppath_extant();
944	assert_no_ppath_component_extant();
945
946	if ((d = prop_dictionary_internalize(personnel)) == NULL)
947		atf_tc_fail("prop_dictionary_internalize failed");
948
949	if ((p = ppath_create()) == NULL)
950		atf_tc_fail("ppath_create failed");
951
952	if (ppath_push_key(p, "John Doe") == NULL)
953		atf_tc_fail("ppath_push_key failed");
954	if (ppath_push_key(p, "russian citizen") == NULL)
955		atf_tc_fail("ppath_push_key failed");
956
957	v = false;
958	rc = ppath_get_bool(d, p, &v);
959	ATF_CHECK_EQ(rc, ENOENT);
960	ATF_CHECK_EQ(v, false);
961
962	rc = ppath_set_bool(d, p, false);
963	ATF_CHECK_EQ(rc, ENOENT);
964
965	v = true;
966	rc = ppath_get_bool(d, p, &v);
967	ATF_CHECK_EQ(rc, ENOENT);
968	ATF_CHECK_EQ(v, true);
969
970	ppath_release(p);
971	prop_object_release(d);
972	assert_no_ppath_extant();
973	assert_no_ppath_component_extant();
974}
975
976ATF_TC(create_bool_eexist);
977
978ATF_TC_HEAD(create_bool_eexist, tc)
979{
980	atf_tc_set_md_var(tc, "descr", "check ppath_create_bool() returns "
981	    "EEXIST because the \"u.s. citizen\" property in the "
982	    "\"John Doe\" record in the \"personnel\" property list "
983	    "already exists");
984}
985
986ATF_TC_BODY(create_bool_eexist, tc)
987{
988	int rc;
989	bool v = false;
990	prop_dictionary_t d;
991	ppath_t *p;
992
993	assert_no_ppath_extant();
994	assert_no_ppath_component_extant();
995
996	if ((d = prop_dictionary_internalize(personnel)) == NULL)
997		atf_tc_fail("prop_dictionary_internalize failed");
998
999	if ((p = ppath_create()) == NULL)
1000		atf_tc_fail("ppath_create failed");
1001
1002	if (ppath_push_key(p, "John Doe") == NULL)
1003		atf_tc_fail("ppath_push_key failed");
1004	if (ppath_push_key(p, "u.s. citizen") == NULL)
1005		atf_tc_fail("ppath_push_key failed");
1006
1007	v = false;
1008	rc = ppath_get_bool(d, p, &v);
1009	ATF_CHECK_EQ(rc, 0);
1010	ATF_CHECK_EQ(v, true);
1011
1012	rc = ppath_create_bool(d, p, false);
1013	ATF_CHECK_EQ(rc, EEXIST);
1014
1015	v = false;
1016	rc = ppath_get_bool(d, p, &v);
1017	ATF_CHECK_EQ(rc, 0);
1018	ATF_CHECK_EQ(v, true);
1019
1020	ppath_release(p);
1021	prop_object_release(d);
1022	assert_no_ppath_extant();
1023	assert_no_ppath_component_extant();
1024}
1025
1026ATF_TC(create_bool_success);
1027
1028ATF_TC_HEAD(create_bool_success, tc)
1029{
1030	atf_tc_set_md_var(tc, "descr", "check ppath_create_bool() creates "
1031	    "the \"russian citizen\" property in the \"John Doe\" record in "
1032	    "the \"personnel\" property list and sets it to false");
1033}
1034
1035ATF_TC_BODY(create_bool_success, tc)
1036{
1037	int rc;
1038	bool v = false;
1039	prop_dictionary_t d;
1040	ppath_t *p;
1041
1042	assert_no_ppath_extant();
1043	assert_no_ppath_component_extant();
1044
1045	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1046		atf_tc_fail("prop_dictionary_internalize failed");
1047
1048	if ((p = ppath_create()) == NULL)
1049		atf_tc_fail("ppath_create failed");
1050
1051	if (ppath_push_key(p, "John Doe") == NULL)
1052		atf_tc_fail("ppath_push_key failed");
1053	if (ppath_push_key(p, "russian citizen") == NULL)
1054		atf_tc_fail("ppath_push_key failed");
1055
1056	v = false;
1057	rc = ppath_get_bool(d, p, &v);
1058	ATF_CHECK_EQ(rc, ENOENT);
1059	ATF_CHECK_EQ(v, false);
1060
1061	rc = ppath_create_bool(d, p, false);
1062	ATF_CHECK_EQ(rc, 0);
1063
1064	v = true;
1065	rc = ppath_get_bool(d, p, &v);
1066	ATF_CHECK_EQ(rc, 0);
1067	ATF_CHECK_EQ(v, false);
1068
1069	ppath_release(p);
1070	prop_object_release(d);
1071	assert_no_ppath_extant();
1072	assert_no_ppath_component_extant();
1073}
1074
1075ATF_TC(set_bool_success);
1076
1077ATF_TC_HEAD(set_bool_success, tc)
1078{
1079	atf_tc_set_md_var(tc, "descr", "check ppath_set_bool() sets "
1080	    "the \"u.s. citizen\" property in the \"John Doe\" record in the "
1081	    "\"personnel\" property list to false and verifies the new value");
1082}
1083
1084ATF_TC_BODY(set_bool_success, tc)
1085{
1086	int rc;
1087	bool v = false;
1088	prop_dictionary_t d;
1089	ppath_t *p;
1090
1091	assert_no_ppath_extant();
1092	assert_no_ppath_component_extant();
1093
1094	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1095		atf_tc_fail("prop_dictionary_internalize failed");
1096
1097	if ((p = ppath_create()) == NULL)
1098		atf_tc_fail("ppath_create failed");
1099
1100	if (ppath_push_key(p, "John Doe") == NULL)
1101		atf_tc_fail("ppath_push_key failed");
1102	if (ppath_push_key(p, "u.s. citizen") == NULL)
1103		atf_tc_fail("ppath_push_key failed");
1104
1105	v = false;
1106	rc = ppath_get_bool(d, p, &v);
1107	ATF_CHECK_EQ(rc, 0);
1108	ATF_CHECK_EQ(v, true);
1109
1110	rc = ppath_set_bool(d, p, v);
1111	ATF_CHECK_EQ(rc, 0);
1112
1113	v = true;
1114	rc = ppath_get_bool(d, p, &v);
1115	ATF_CHECK_EQ(rc, 0);
1116	ATF_CHECK_EQ(v, true);
1117
1118	ppath_release(p);
1119	prop_object_release(d);
1120	assert_no_ppath_extant();
1121	assert_no_ppath_component_extant();
1122}
1123
1124ATF_TC(get_bool_success);
1125
1126ATF_TC_HEAD(get_bool_success, tc)
1127{
1128	atf_tc_set_md_var(tc, "descr", "check ppath_get_bool() fetches "
1129	    "the \"u.s. citizen\" property from the \"John Doe\" record in the "
1130	    "\"personnel\" property list, and compares it with the expected "
1131	    "value, true");
1132}
1133
1134ATF_TC_BODY(get_bool_success, tc)
1135{
1136	int rc;
1137	bool v = false;
1138	prop_dictionary_t d;
1139	ppath_t *p;
1140
1141	assert_no_ppath_extant();
1142	assert_no_ppath_component_extant();
1143
1144	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1145		atf_tc_fail("prop_dictionary_internalize failed");
1146
1147	if ((p = ppath_create()) == NULL)
1148		atf_tc_fail("ppath_create failed");
1149
1150	if (ppath_push_key(p, "John Doe") == NULL)
1151		atf_tc_fail("ppath_push_key failed");
1152	if (ppath_push_key(p, "u.s. citizen") == NULL)
1153		atf_tc_fail("ppath_push_key failed");
1154
1155	rc = ppath_get_bool(d, p, &v);
1156	ATF_CHECK_EQ(rc, 0);
1157	ATF_CHECK_EQ(v, true);
1158
1159	ppath_release(p);
1160	prop_object_release(d);
1161	assert_no_ppath_extant();
1162	assert_no_ppath_component_extant();
1163}
1164
1165ATF_TC(delete_bool_success);
1166
1167ATF_TC_HEAD(delete_bool_success, tc)
1168{
1169	atf_tc_set_md_var(tc, "descr", "check ppath_delete_bool() succeeds "
1170	    "for the path (\"John Doe\", \"u.s. citizen\") in the "
1171	    "\"personnel\" property list");
1172}
1173
1174ATF_TC_BODY(delete_bool_success, tc)
1175{
1176	int rc;
1177	prop_dictionary_t d;
1178	ppath_t *p;
1179
1180	assert_no_ppath_extant();
1181	assert_no_ppath_component_extant();
1182
1183	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1184		atf_tc_fail("prop_dictionary_internalize failed");
1185
1186	if ((p = ppath_create()) == NULL)
1187		atf_tc_fail("ppath_create failed");
1188
1189	if (ppath_push_key(p, "John Doe") == NULL)
1190		atf_tc_fail("ppath_push_key failed");
1191	if (ppath_push_key(p, "u.s. citizen") == NULL)
1192		atf_tc_fail("ppath_push_key failed");
1193
1194	rc = ppath_delete_bool(d, p);
1195	ATF_CHECK_EQ(rc, 0);
1196
1197	rc = ppath_get_bool(d, p, NULL);
1198	ATF_CHECK_EQ(rc, ENOENT);
1199
1200	ppath_release(p);
1201	prop_object_release(d);
1202	assert_no_ppath_extant();
1203	assert_no_ppath_component_extant();
1204}
1205
1206ATF_TC(delete_bool_eftype);
1207
1208ATF_TC_HEAD(delete_bool_eftype, tc)
1209{
1210	atf_tc_set_md_var(tc, "descr", "check ppath_delete_bool() returns "
1211	    "EFTYPE for the path (\"John Doe\", \"job title\") in the "
1212	    "\"personnel\" property list and does not delete the path");
1213}
1214
1215ATF_TC_BODY(delete_bool_eftype, tc)
1216{
1217	int rc;
1218	prop_dictionary_t d;
1219	ppath_t *p;
1220
1221	assert_no_ppath_extant();
1222	assert_no_ppath_component_extant();
1223
1224	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1225		atf_tc_fail("prop_dictionary_internalize failed");
1226
1227	if ((p = ppath_create()) == NULL)
1228		atf_tc_fail("ppath_create failed");
1229
1230	if (ppath_push_key(p, "John Doe") == NULL)
1231		atf_tc_fail("ppath_push_key failed");
1232	if (ppath_push_key(p, "job title") == NULL)
1233		atf_tc_fail("ppath_push_key failed");
1234
1235	rc = ppath_delete_bool(d, p);
1236	ATF_CHECK_EQ(rc, EFTYPE);
1237
1238	rc = ppath_get_object(d, p, NULL);
1239	ATF_CHECK_EQ(rc, 0);
1240
1241	ppath_release(p);
1242	prop_object_release(d);
1243	assert_no_ppath_extant();
1244	assert_no_ppath_component_extant();
1245}
1246
1247ATF_TC(delete_bool_enoent);
1248
1249ATF_TC_HEAD(delete_bool_enoent, tc)
1250{
1251	atf_tc_set_md_var(tc, "descr", "check ppath_delete_bool() returns "
1252	    "ENOENT for the path (\"John Doe\", \"citizen\") in the "
1253	    "\"personnel\" property list");
1254}
1255
1256ATF_TC_BODY(delete_bool_enoent, tc)
1257{
1258	int rc;
1259	prop_dictionary_t d;
1260	ppath_t *p;
1261
1262	assert_no_ppath_extant();
1263	assert_no_ppath_component_extant();
1264
1265	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1266		atf_tc_fail("prop_dictionary_internalize failed");
1267
1268	if ((p = ppath_create()) == NULL)
1269		atf_tc_fail("ppath_create failed");
1270
1271	if (ppath_push_key(p, "John Doe") == NULL)
1272		atf_tc_fail("ppath_push_key failed");
1273	if (ppath_push_key(p, "citizen") == NULL)
1274		atf_tc_fail("ppath_push_key failed");
1275
1276	rc = ppath_delete_bool(d, p);
1277	ATF_CHECK_EQ(rc, ENOENT);
1278
1279	ppath_release(p);
1280	prop_object_release(d);
1281	assert_no_ppath_extant();
1282	assert_no_ppath_component_extant();
1283}
1284
1285ATF_TC(get_bool_enoent);
1286
1287ATF_TC_HEAD(get_bool_enoent, tc)
1288{
1289	atf_tc_set_md_var(tc, "descr", "check ppath_get_bool() returns "
1290	    "ENOENT for the path (\"John Doe\", \"citizen\") in the "
1291	    "\"personnel\" property list, and the bool * argument is "
1292	    "unchanged");
1293}
1294
1295ATF_TC_BODY(get_bool_enoent, tc)
1296{
1297	int rc;
1298	bool v;
1299	prop_dictionary_t d;
1300	ppath_t *p;
1301
1302	assert_no_ppath_extant();
1303	assert_no_ppath_component_extant();
1304
1305	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1306		atf_tc_fail("prop_dictionary_internalize failed");
1307
1308	if ((p = ppath_create()) == NULL)
1309		atf_tc_fail("ppath_create failed");
1310
1311	if (ppath_push_key(p, "John Doe") == NULL)
1312		atf_tc_fail("ppath_push_key failed");
1313	if (ppath_push_key(p, "citizen") == NULL)
1314		atf_tc_fail("ppath_push_key failed");
1315
1316	v = true;
1317	rc = ppath_get_bool(d, p, &v);
1318	ATF_CHECK_EQ(rc, ENOENT);
1319	ATF_CHECK_EQ(v, true);
1320
1321	v = false;
1322	rc = ppath_get_bool(d, p, &v);
1323	ATF_CHECK_EQ(rc, ENOENT);
1324	ATF_CHECK_EQ(v, false);
1325
1326	ppath_release(p);
1327	prop_object_release(d);
1328	assert_no_ppath_extant();
1329	assert_no_ppath_component_extant();
1330}
1331
1332ATF_TC(get_bool_eftype);
1333
1334ATF_TC_HEAD(get_bool_eftype, tc)
1335{
1336	atf_tc_set_md_var(tc, "descr", "check ppath_get_bool() returns "
1337	    "EFTYPE for the path (\"John Doe\", \"job title\") in the "
1338	    "\"personnel\" property list, and the bool * argument is "
1339	    "unchanged");
1340}
1341
1342ATF_TC_BODY(get_bool_eftype, tc)
1343{
1344	int rc;
1345	bool v;
1346	prop_dictionary_t d;
1347	ppath_t *p;
1348
1349	assert_no_ppath_extant();
1350	assert_no_ppath_component_extant();
1351
1352	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1353		atf_tc_fail("prop_dictionary_internalize failed");
1354
1355	if ((p = ppath_create()) == NULL)
1356		atf_tc_fail("ppath_create failed");
1357
1358	if (ppath_push_key(p, "John Doe") == NULL)
1359		atf_tc_fail("ppath_push_key failed");
1360	if (ppath_push_key(p, "job title") == NULL)
1361		atf_tc_fail("ppath_push_key failed");
1362
1363	v = true;
1364	rc = ppath_get_bool(d, p, &v);
1365	ATF_CHECK_EQ(rc, EFTYPE);
1366	ATF_CHECK_EQ(v, true);
1367
1368	v = false;
1369	rc = ppath_get_bool(d, p, &v);
1370	ATF_CHECK_EQ(rc, EFTYPE);
1371	ATF_CHECK_EQ(v, false);
1372
1373	ppath_release(p);
1374	prop_object_release(d);
1375	assert_no_ppath_extant();
1376	assert_no_ppath_component_extant();
1377}
1378
1379ATF_TC(get_string_eftype);
1380
1381ATF_TC_HEAD(get_string_eftype, tc)
1382{
1383	atf_tc_set_md_var(tc, "descr", "check ppath_get_string() returns "
1384	    "EFTYPE for the path (\"John Doe\", \"u.s. citizen\") in the "
1385	    "\"personnel\" property list, and the const char ** argument is "
1386	    "unchanged");
1387}
1388
1389ATF_TC_BODY(get_string_eftype, tc)
1390{
1391	int rc;
1392	const char *v;
1393	prop_dictionary_t d;
1394	ppath_t *p;
1395
1396	assert_no_ppath_extant();
1397	assert_no_ppath_component_extant();
1398
1399	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1400		atf_tc_fail("prop_dictionary_internalize failed");
1401
1402	if ((p = ppath_create()) == NULL)
1403		atf_tc_fail("ppath_create failed");
1404
1405	if (ppath_push_key(p, "John Doe") == NULL)
1406		atf_tc_fail("ppath_push_key failed");
1407	if (ppath_push_key(p, "u.s. citizen") == NULL)
1408		atf_tc_fail("ppath_push_key failed");
1409
1410	v = NULL;
1411	rc = ppath_get_string(d, p, &v);
1412	ATF_CHECK_EQ(rc, EFTYPE);
1413	ATF_CHECK_EQ(v, NULL);
1414
1415	v = "xyz";
1416	rc = ppath_get_string(d, p, &v);
1417	ATF_CHECK_EQ(rc, EFTYPE);
1418	ATF_CHECK_STREQ(v, "xyz");
1419
1420	ppath_release(p);
1421	prop_object_release(d);
1422	assert_no_ppath_extant();
1423	assert_no_ppath_component_extant();
1424}
1425
1426ATF_TC(get_string_enoent);
1427
1428ATF_TC_HEAD(get_string_enoent, tc)
1429{
1430	atf_tc_set_md_var(tc, "descr", "check ppath_get_string() returns "
1431	    "ENOENT for the path (\"John Doe\", \"title\") in the "
1432	    "\"personnel\" property list, and the const char ** argument is "
1433	    "unchanged");
1434}
1435
1436ATF_TC_BODY(get_string_enoent, tc)
1437{
1438	int rc;
1439	const char *v;
1440	prop_dictionary_t d;
1441	ppath_t *p;
1442
1443	assert_no_ppath_extant();
1444	assert_no_ppath_component_extant();
1445
1446	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1447		atf_tc_fail("prop_dictionary_internalize failed");
1448
1449	if ((p = ppath_create()) == NULL)
1450		atf_tc_fail("ppath_create failed");
1451
1452	if (ppath_push_key(p, "John Doe") == NULL)
1453		atf_tc_fail("ppath_push_key failed");
1454	if (ppath_push_key(p, "title") == NULL)
1455		atf_tc_fail("ppath_push_key failed");
1456
1457	v = NULL;
1458	rc = ppath_get_string(d, p, &v);
1459	ATF_CHECK_EQ(rc, ENOENT);
1460	ATF_CHECK_EQ(v, NULL);
1461
1462	v = "xyz";
1463	rc = ppath_get_string(d, p, &v);
1464	ATF_CHECK_EQ(rc, ENOENT);
1465	ATF_CHECK_STREQ(v, "xyz");
1466
1467	ppath_release(p);
1468	prop_object_release(d);
1469	assert_no_ppath_extant();
1470	assert_no_ppath_component_extant();
1471}
1472
1473ATF_TC(get_string_success);
1474
1475ATF_TC_HEAD(get_string_success, tc)
1476{
1477	atf_tc_set_md_var(tc, "descr", "check ppath_get_string() fetches "
1478	    "the \"job title\" property from the \"John Doe\" record in the "
1479	    "\"personnel\" property list and compares it with the expected "
1480	    "value, \"computer programmer\"");
1481}
1482
1483ATF_TC_BODY(get_string_success, tc)
1484{
1485	int rc;
1486	const char *v = NULL;;
1487	prop_dictionary_t d;
1488	ppath_t *p;
1489
1490	assert_no_ppath_extant();
1491	assert_no_ppath_component_extant();
1492
1493	if ((d = prop_dictionary_internalize(personnel)) == NULL)
1494		atf_tc_fail("prop_dictionary_internalize failed");
1495
1496	if ((p = ppath_create()) == NULL)
1497		atf_tc_fail("ppath_create failed");
1498
1499	if (ppath_push_key(p, "John Doe") == NULL)
1500		atf_tc_fail("ppath_push_key failed");
1501	if (ppath_push_key(p, "job title") == NULL)
1502		atf_tc_fail("ppath_push_key failed");
1503
1504	rc = ppath_get_string(d, p, &v);
1505	ATF_CHECK_EQ(rc, 0);
1506	ATF_CHECK_STREQ(v, "computer programmer");
1507
1508	ppath_release(p);
1509	prop_object_release(d);
1510	assert_no_ppath_extant();
1511	assert_no_ppath_component_extant();
1512}
1513
1514ATF_TP_ADD_TCS(tp)
1515{
1516
1517	ATF_TP_ADD_TC(tp, push_until_full);
1518	ATF_TP_ADD_TC(tp, pop_until_empty);
1519	ATF_TP_ADD_TC(tp, length);
1520	ATF_TP_ADD_TC(tp, component_at);
1521	ATF_TP_ADD_TC(tp, get_idx_key);
1522	ATF_TP_ADD_TC(tp, ppath_copy);
1523	ATF_TP_ADD_TC(tp, replace);
1524
1525	ATF_TP_ADD_TC(tp, delete_bool_eftype);
1526	ATF_TP_ADD_TC(tp, delete_bool_enoent);
1527	ATF_TP_ADD_TC(tp, delete_bool_success);
1528
1529	ATF_TP_ADD_TC(tp, get_bool_eftype);
1530	ATF_TP_ADD_TC(tp, get_bool_enoent);
1531	ATF_TP_ADD_TC(tp, get_bool_success);
1532
1533	ATF_TP_ADD_TC(tp, copydel_bool_success);
1534	ATF_TP_ADD_TC(tp, copydel_object_twice_success);
1535	ATF_TP_ADD_TC(tp, copyset_object_twice_success);
1536	ATF_TP_ADD_TC(tp, copyset_bool_success);
1537	ATF_TP_ADD_TC(tp, create_bool_eexist);
1538	ATF_TP_ADD_TC(tp, create_bool_success);
1539	ATF_TP_ADD_TC(tp, set_bool_enoent);
1540	ATF_TP_ADD_TC(tp, set_bool_eftype);
1541	ATF_TP_ADD_TC(tp, set_bool_success);
1542
1543	ATF_TP_ADD_TC(tp, get_string_eftype);
1544	ATF_TP_ADD_TC(tp, get_string_enoent);
1545	ATF_TP_ADD_TC(tp, get_string_success);
1546
1547	return atf_no_error();
1548}
1549