summaryrefslogtreecommitdiffstats
path: root/test/xml_behavior_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/xml_behavior_test.c')
-rw-r--r--test/xml_behavior_test.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/test/xml_behavior_test.c b/test/xml_behavior_test.c
new file mode 100644
index 0000000..94d8a7f
--- /dev/null
+++ b/test/xml_behavior_test.c
@@ -0,0 +1,167 @@
1/*
2 * xml_behavior_test.c
3 *
4 * Tests XML parser behavior for correctness and specification compliance:
5 *
6 * 1) A <plist> element must contain exactly one root value node.
7 * Any additional value nodes after the first root object must
8 * cause parsing to fail.
9 *
10 * 2) Dictionaries of the form:
11 * <dict>
12 * <key>CF$UID</key>
13 * <integer>...</integer>
14 * </dict>
15 * must be converted to PLIST_UID nodes during XML parsing,
16 * including when they appear nested inside other containers.
17 *
18 * These tests ensure proper root handling and UID node conversion
19 * when parsing XML property lists.
20 */
21
22#include <stdio.h>
23#include <string.h>
24#include <stdint.h>
25#include <inttypes.h>
26
27#include "plist/plist.h"
28
29static int test_nested_cfuid_converts_to_uid(void)
30{
31 const char *xml =
32 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
33 "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
34 "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
35 "<plist version=\"1.0\">"
36 " <dict>"
37 " <key>obj</key>"
38 " <dict>"
39 " <key>CF$UID</key>"
40 " <integer>7</integer>"
41 " </dict>"
42 " </dict>"
43 "</plist>";
44
45 plist_t root = NULL;
46 plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root);
47 if (err != PLIST_ERR_SUCCESS || !root) {
48 fprintf(stderr, "nested CF$UID: plist_from_xml failed (err=%d)\n", err);
49 plist_free(root);
50 return 0;
51 }
52
53 if (plist_get_node_type(root) != PLIST_DICT) {
54 fprintf(stderr, "nested CF$UID: root is not dict\n");
55 plist_free(root);
56 return 0;
57 }
58
59 plist_t obj = plist_dict_get_item(root, "obj");
60 if (!obj) {
61 fprintf(stderr, "nested CF$UID: missing key 'obj'\n");
62 plist_free(root);
63 return 0;
64 }
65
66 if (plist_get_node_type(obj) != PLIST_UID) {
67 fprintf(stderr, "nested CF$UID: expected PLIST_UID, got %d\n",
68 plist_get_node_type(obj));
69 plist_free(root);
70 return 0;
71 }
72
73 uint64_t uid = 0;
74 plist_get_uid_val(obj, &uid);
75 if (uid != 7) {
76 fprintf(stderr, "nested CF$UID: expected uid=7, got %" PRIu64 "\n", uid);
77 plist_free(root);
78 return 0;
79 }
80
81 plist_free(root);
82 return 1;
83}
84
85static int test_extra_root_value_is_rejected(void)
86{
87 /* Two root values inside <plist> must be rejected */
88 const char *xml =
89 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
90 "<plist version=\"1.0\">"
91 " <string>one</string>"
92 " <string>two</string>"
93 "</plist>";
94
95 plist_t root = NULL;
96 plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root);
97
98 /* Must fail, and root must be NULL (consistent with other parsers) */
99 if (err == PLIST_ERR_SUCCESS || root != NULL) {
100 fprintf(stderr, "extra root value: expected failure, got err=%d root=%p\n",
101 err, (void*)root);
102 plist_free(root);
103 return 0;
104 }
105 return 1;
106}
107
108static int test_scalar_then_extra_node_is_rejected(void)
109{
110 /* Scalar root followed by another node must be rejected */
111 const char *xml =
112 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
113 "<plist version=\"1.0\">"
114 " <true/>"
115 " <dict><key>A</key><string>x</string></dict>"
116 "</plist>";
117
118 plist_t root = NULL;
119 plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root);
120
121 if (err == PLIST_ERR_SUCCESS || root != NULL) {
122 fprintf(stderr, "scalar then extra node: expected failure, got err=%d root=%p\n",
123 err, (void*)root);
124 plist_free(root);
125 return 0;
126 }
127 return 1;
128}
129
130static int test_scalar_with_comment_is_ok(void)
131{
132 /* Comment after the single root value is not an extra value node */
133 const char *xml =
134 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
135 "<plist version=\"1.0\">"
136 " <string>ok</string>"
137 " <!-- trailing comment -->"
138 "</plist>";
139
140 plist_t root = NULL;
141 plist_err_t err = plist_from_xml(xml, (uint32_t)strlen(xml), &root);
142 if (err != PLIST_ERR_SUCCESS || !root) {
143 fprintf(stderr, "scalar + comment: expected success, got err=%d\n", err);
144 plist_free(root);
145 return 0;
146 }
147 if (plist_get_node_type(root) != PLIST_STRING) {
148 fprintf(stderr, "scalar + comment: expected root string, got %d\n",
149 plist_get_node_type(root));
150 plist_free(root);
151 return 0;
152 }
153 plist_free(root);
154 return 1;
155}
156
157int main(void)
158{
159 int ok = 1;
160
161 ok &= test_nested_cfuid_converts_to_uid();
162 ok &= test_extra_root_value_is_rejected();
163 ok &= test_scalar_then_extra_node_is_rejected();
164 ok &= test_scalar_with_comment_is_ok();
165
166 return ok ? 0 : 1;
167}