1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24/*
25
26to build:
27
28cc -g -framework IOKit -framework CoreFoundation IOCFSerializeTest.c -o IOCFSerializeTest
29
30cc -g IOCFSerializeTest.c -framework CoreFoundation /local/build/IOKit/IOKit.build/objects-optimized/IOCFSerialize.o \
31 /local/build/IOKit/IOKit.build/objects-optimized/IOCFUnserialize.tab.o -o IOCFSerializeTest
32
33to run:
34
35./IOCFSerializeTest
36find /System/Library/Extensions -name Info.plist  | xargs -n 1 ./IOCFSerializeTest
37
38*/
39
40#include <IOKit/IOCFSerialize.h>
41#include <IOKit/IOCFUnserialize.h>
42#include <CoreFoundation/CFPropertyList.h>
43
44#include <ctype.h>
45#include <stdlib.h>
46#include <stdio.h>
47#include <string.h>
48
49#include <sys/types.h>
50#include <sys/stat.h>
51#include <sys/fcntl.h>
52#include <errno.h>
53
54char *testBuffer =
55
56" <?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
57" <!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\"> \n"
58" <plist version=\"1.0\"> \n"
59" <!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> \n"
60" <plist version=\"0.9\"> \n"
61" <!-- this is a comment --> \n"
62" <!-- this is a comment with embedded XML statements \n"
63" <key>ignore me</key>	<true/> \n"
64" --> \n"
65
66" <dict> \n"
67
68" <key>key true</key>	<true/> \n"
69" <key>key false</key>	<false/> \n"
70
71" <key>key d0</key>	<data> </data> \n"
72" <key>key d1</key>	<data>AQ==</data> \n"
73" <key>key d2</key>	<data>ASM=</data> \n"
74" <key>key d3</key>	<data>ASNF</data> \n"
75" <key>key d4</key>	<data ID=\"1\">ASNFZw==</data> \n"
76
77" <key>key i0</key>	<integer></integer> \n"
78" <key>key i1</key>	<integer>123456789</integer> \n"
79" <key>key i2</key>	<integer>-123456789</integer> \n"
80" <key>key i3</key>	<integer size=\"32\" ID=\"2\">0x12345678</integer> \n"
81
82" <key>key s0</key>	<string></string> \n"
83" <key>key s1</key>	<string>string 1</string> \n"
84" <key>key s2</key>	<string ID=\"3\">string 2</string> \n"
85" <key>key mr �</key>	<string>mac roman copyright �</string> \n"
86" <key>key uft8 \xc2\xa9</key>	<string>utf-8 copyright \xc2\xa9</string> \n"
87" <key>key &lt;&amp;&gt;</key>	<string>&lt;&amp;&gt;</string> \n"
88
89" <key>key D0</key>	<dict ID=\"4\"> \n"
90"                        </dict> \n"
91
92" <key>key a0</key>	<array> \n"
93"                        </array> \n"
94
95" <key>key a1</key>	<array ID=\"5\"> \n"
96"                            <string>array string 1</string> \n"
97"                            <string>array string 2</string> \n"
98"                        </array> \n"
99
100" <key>key r1</key>	<ref IDREF=\"1\"/> \n"
101" <key>key r2</key>	<ref IDREF=\"2\"/> \n"
102" <key>key r3</key>	<ref IDREF=\"3\"/> \n"
103" <key>key r4</key>	<ref IDREF=\"4\"/> \n"
104" <key>key r5</key>	<ref IDREF=\"5\"/> \n"
105
106" <key>key e1</key>	<array/> \n"
107" <key>key e2</key>	<dict/> \n"
108" <key>key e4</key>	<integer/> \n"
109" <key>key e5</key>	<string/> \n"
110" <key>key e6</key>	<data/> \n"
111
112// CFPropertyListCreateXMLData() can't handle sets
113#if 0
114" <key>key S0</key>	<set> \n"
115"                        </set> \n"
116" <key>key S1</key>	<set ID=\"6\"> \n"
117"                             <string>set string 1</string> \n"
118"                             <string>set string 2</string> \n"
119"                         </set> \n"
120" <key>key r6</key>	<ref IDREF=\"6\"/> \n"
121" <key>key e3</key>	<set/> \n"
122#endif
123" </dict> \n"
124" </plist> \n"
125;
126
127
128int
129main(int argc, char **argv)
130{
131	CFTypeRef	properties0, properties1, properties2, properties3, properties4, properties5;
132	CFDataRef	data1, data2, data3, data4;
133	CFStringRef  	errorString;
134	int i, j;
135	int fd = 0;
136	char * bufPtr;
137	struct stat sb;
138	size_t size;
139	int usingFile = 0;
140
141	if (argc == 2) {
142
143		if (stat(argv[1], &sb)) exit(1);
144		size = (size_t)sb.st_size;
145
146		printf("checking file %s, file size %ld\n", argv[1], size);
147
148		bufPtr = (char *)malloc(size);
149		if (!bufPtr) exit(1);
150
151		fd = open(argv[1], O_RDONLY | O_NDELAY, 0);
152		if (fd <= 0) exit(1);
153
154		if ((read(fd, bufPtr, size) != size) || errno) exit(1);
155
156		testBuffer = bufPtr;
157
158		usingFile = 1;
159
160	} else {
161
162		printf("running self check testing...\n");
163
164		// random error injection testing, this is painfully slow
165#if 1
166		char * randomBuffer = (char *)strdup(testBuffer);
167		int randomBufferSize = strlen(randomBuffer);
168
169		for (i=0; i < randomBufferSize; i++) {
170
171			for (j=0; j < 256; j++) {
172
173				randomBuffer[i] = (char)j;
174
175//				printf("testBuffer[%d] = %c, randomBuffer[%d] = %c\n", i, testBuffer[i], i, randomBuffer[i]);
176
177				properties0 = IOCFUnserialize(randomBuffer, kCFAllocatorDefault, 0, &errorString);
178				if (properties0) {
179					CFRelease(properties0);
180					if (errorString) {
181						printf("random testing failed - errorString is set\n");
182						printf("testBuffer[%d] = %c, randomBuffer[%d] = %c\n", i, testBuffer[i], i, randomBuffer[i]);
183						exit(1);
184					}
185				} else {
186					if (errorString) {
187						CFRelease(errorString);
188					} else {
189						printf("random testing failed - errorString is null\n");
190						printf("testBuffer[%d] = %c, randomBuffer[%d] = %c\n", i, testBuffer[i], i, randomBuffer[i]);
191						exit(1);
192					}
193				}
194			}
195			randomBuffer[i] = testBuffer[i];
196		}
197		if (!usingFile) printf("random syntax error testing successful\n");
198#endif
199	}
200
201
202	// unserialize test buffer and then re-serialize it
203
204
205	properties1 = IOCFUnserialize(testBuffer, kCFAllocatorDefault, 0, &errorString);
206	if (!properties1) {
207		CFIndex bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errorString),
208		       kCFStringEncodingUTF8) + sizeof('\0');
209		char *buffer = malloc(bufSize);
210		if (!buffer || !CFStringGetCString(errorString, buffer, bufSize,
211						   kCFStringEncodingUTF8)) {
212			exit(1);
213		}
214
215		printf("prop1 error: %s\n", buffer);
216		CFRelease(errorString);
217		exit(1);
218	}
219
220	data1 = IOCFSerialize(properties1, kNilOptions);
221	if (!data1) {
222		printf("serialize on prop1 failed\n");
223		exit(1);
224	}
225
226
227	// unserialize again, using the previous re-serialization compare resulting objects
228
229
230	properties2 = IOCFUnserialize((char *)CFDataGetBytePtr(data1), kCFAllocatorDefault, 0, &errorString);
231	if (!properties2) {
232		CFIndex bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errorString),
233		       kCFStringEncodingUTF8) + sizeof('\0');
234		char *buffer = malloc(bufSize);
235		if (!buffer || !CFStringGetCString(errorString, buffer, bufSize, kCFStringEncodingUTF8)) {
236			exit(1);
237		}
238
239		printf("prop2 error: %s\n", buffer);
240		CFRelease(errorString);
241		exit(1);
242	}
243
244	if (CFEqual(properties1, properties2)) {
245		if (!usingFile) printf("test successful, prop1 == prop2\n");
246	} else {
247		printf("test failed, prop1 == prop2\n");
248//		printf("%s\n", testBuffer);
249//		printf("%s\n", (char *)CFDataGetBytePtr(data1));
250		exit(1);
251	}
252
253	data2 = IOCFSerialize(properties2, kNilOptions);
254	if (!data2) {
255		printf("serialize on prop2 failed\n");
256		exit(1);
257	}
258
259	// unserialize again, using the previous re-serialization compare resulting objects
260
261	properties3 = IOCFUnserialize((char *)CFDataGetBytePtr(data2), kCFAllocatorDefault, 0, &errorString);
262	if (!properties3) {
263		CFIndex bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errorString),
264		       kCFStringEncodingUTF8) + sizeof('\0');
265		char *buffer = malloc(bufSize);
266		if (!buffer || !CFStringGetCString(errorString, buffer, bufSize, kCFStringEncodingUTF8)) {
267		    exit(1);
268		}
269
270		printf("prop3 error: %s\n", buffer);
271		CFRelease(errorString);
272		exit(1);
273	}
274
275	if (CFEqual(properties2, properties3)) {
276		if (!usingFile) printf("test successful, prop2 == prop3\n");
277	} else {
278		printf("test failed, prop2 == prop3\n");
279//		printf("%s\n", (char *)CFDataGetBytePtr(data1));
280//		printf("%s\n", (char *)CFDataGetBytePtr(data2));
281		exit(1);
282	}
283
284	// re-serialize using CF serializer, unserialize again and compare resulting objects
285
286	data3 = CFPropertyListCreateXMLData(NULL, properties3);
287	if (!data3) {
288		printf("serialize on prop3 failed\n");
289		exit(1);
290	}
291
292	properties4 = IOCFUnserialize((char *)CFDataGetBytePtr(data3), kCFAllocatorDefault, 0, &errorString);
293	if (!properties4) {
294		CFIndex bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errorString),
295		       kCFStringEncodingUTF8) + sizeof('\0');
296		char *buffer = malloc(bufSize);
297		if (!buffer || !CFStringGetCString(errorString, buffer, bufSize, kCFStringEncodingUTF8)) {
298		    exit(1);
299		}
300
301		printf("prop4 error: %s\n", buffer);
302//		printf("%s\n", (char *)CFDataGetBytePtr(data3));
303		CFRelease(errorString);
304		exit(1);
305	}
306
307	if (CFEqual(properties3, properties4)) {
308		if (!usingFile) printf("test successful, prop3 == prop4\n");
309	} else {
310		printf("test failed, prop3 == prop4\n");
311//		printf("%s\n", (char *)CFDataGetBytePtr(data2));
312//		printf("%s\n", (char *)CFDataGetBytePtr(data3));
313		exit(1);
314	}
315
316	// unserialize test buffer using CF and compare objects
317
318	if (usingFile) {
319
320		data4 = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, testBuffer, size, kCFAllocatorNull);
321		if (!data4) {
322			printf("serialize on prop 4 failed\n");
323			exit(1);
324		}
325
326		properties5 = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, data4, kCFPropertyListImmutable, &errorString);
327		if (!properties5) {
328			CFIndex bufSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(errorString),
329			       kCFStringEncodingUTF8) + sizeof('\0');
330			char *buffer = malloc(bufSize);
331			if (!buffer || !CFStringGetCString(errorString, buffer, bufSize, kCFStringEncodingUTF8)) {
332			    exit(1);
333			}
334
335			printf("prop5 error: %s\n", buffer);
336			CFRelease(errorString);
337			exit(1);
338		}
339
340		if (CFEqual(properties1, properties5)) {
341			if (!usingFile) printf("test successful, prop1 == prop5\n");
342		} else {
343			printf("test failed, prop3 == prop4\n");
344			exit(1);
345		}
346	}
347
348	CFRelease(data1);
349	CFRelease(data2);
350	CFRelease(data3);
351	CFRelease(properties1);
352	CFRelease(properties2);
353	CFRelease(properties3);
354	CFRelease(properties4);
355	if (usingFile) {
356		CFRelease(data4);
357		CFRelease(properties5);
358	}
359	return 0;
360}
361