xref: /xnu-11215/iokit/Tests/TestContainers.cpp (revision a5e72196)
1 /*
2  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_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. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 #if DEBUG
29 #include "Tests.h"
30 
31 #include <libkern/c++/OSData.h>
32 #include <libkern/c++/OSString.h>
33 #include <libkern/c++/OSSymbol.h>
34 
35 static const char testC00[] = "The quick brown fox jumps over the lazy dog.  ";
36 static const char testC01[] = "The quick brown fox ";
37 static const char testC02[] = "jumps over the ";
38 static const char testC03[] = "lazy dog.  \n";
39 static const char testC04[] = "The ";
40 static const char testC05[] = "quick ";
41 static const char testC06[] = "brown ";
42 static const char testC07[] = "fox ";
43 static const char testC08[] = "jumps ";
44 static const char testC09[] = "over ";
45 static const char testC10[] = "the ";
46 static const char testC11[] = "lazy ";
47 static const char testC12[] = "dog.  \n";
48 static const char testC13[] = "Now is the time for all good "
49     "men to come to the aid of the party  \n";
50 static const char testC14[] = "Now is the time for ";
51 static const char testC15[] = "all good men to come ";
52 static const char testC16[] = "to the aid of the party  \n";
53 static const char testC17[] = "Now ";
54 static const char testC18[] = "is ";
55 static const char testC19[] = "the ";
56 static const char testC20[] = "time ";
57 static const char testC21[] = "for ";
58 static const char testC22[] = "all ";
59 static const char testC23[] = "good ";
60 static const char testC24[] = "men ";
61 static const char testC25[] = "to ";
62 static const char testC26[] = "come ";
63 static const char testC27[] = "to ";
64 static const char testC28[] = "the ";
65 static const char testC29[] = "aid ";
66 static const char testC30[] = "of ";
67 static const char testC31[] = "the ";
68 static const char testC32[] = "party.  \n";
69 static const char testC33[] = "Frank Burns eats worms.  \n";
70 static const char testC34[] = "Frank Burns ";
71 static const char testC35[] = "eats worms.  \n";
72 static const char testC36[] = "Frank ";
73 static const char testC37[] = "Burns ";
74 static const char testC38[] = "eats ";
75 static const char testC39[] = "worms.  \n";
76 static const char testC40[] = "Tired eyes?  Stiff neck?  Tight shoulders?  "
77     "Aching back?  The right moves can help "
78     "prevent these kinds of problem.  ";
79 static const char testC41[] = "Tired eyes?  Stiff neck?  ";
80 static const char testC42[] = "Tight shoulders?  Aching back?  ";
81 static const char testC43[] = "The right moves can help prevent ";
82 static const char testC44[] = "these kinds of problem.  ";
83 static const char testC45[] = "Tired ";
84 static const char testC46[] = "eyes?  ";
85 static const char testC47[] = "Stiff ";
86 static const char testC48[] = "neck?  ";
87 static const char testC49[] = "Tight ";
88 static const char testC50[] = "shoulders?  ";
89 static const char testC51[] = "Aching ";
90 static const char testC52[] = "back?  ";
91 static const char testC53[] = "The ";
92 static const char testC54[] = "right ";
93 static const char testC55[] = "moves ";
94 static const char testC56[] = "can ";
95 static const char testC57[] = "help ";
96 static const char testC58[] = "prevent ";
97 static const char testC59[] = "these ";
98 static const char testC60[] = "kinds ";
99 static const char testC61[] = "of ";
100 static const char testC62[] = "problem.  ";
101 
102 const char *strCache[] = {
103 	testC00, testC01, testC02, testC03, testC04, testC05, testC06, testC07,
104 	testC08, testC09, testC10, testC11, testC12, testC13, testC14, testC15,
105 	testC16, testC17, testC18, testC19, testC20, testC21, testC22, testC23,
106 	testC24, testC25, testC26, testC27, testC28, testC29, testC30, testC31,
107 	testC32, testC33, testC34, testC35, testC36, testC37, testC38, testC39,
108 	testC40, testC41, testC42, testC43, testC44, testC45, testC46, testC47,
109 	testC48, testC49, testC50, testC51, testC52, testC53, testC54, testC55,
110 	testC56, testC57, testC58, testC59, testC60, testC61, testC62,
111 };
112 const int numStrCache = ((int) (sizeof(strCache) / sizeof(strCache[0])));
113 
114 void
testData()115 testData()
116 {
117 #define DATA_SIZE_1      256
118 #define DATA_SIZE_2      512
119 #define DATA_SIZE_3     1024
120 #define DATA_SIZE_4     8192
121 
122 	OSData *test1, *test2, *test3;
123 	void *spaceCheck;
124 	unsigned int len;
125 	unsigned int i;
126 	bool res = true;
127 	unsigned short testData[DATA_SIZE_4 / sizeof(short)], *cp;
128 
129 	// very first test initialises the OSMetaClass cache.
130 	test1 = OSData::withCapacity(DATA_SIZE_1);
131 	TEST_ASSERT('d', "0a", test1);
132 	if (test1) {
133 		test1->release();
134 	}
135 
136 	for (i = 0; i < sizeof(testData) / sizeof(short); i++) {
137 		testData[i] = (unsigned short) i;
138 	}
139 
140 	// Check empty data allocation
141 	spaceCheck = checkPointSpace();
142 	test1 = OSData::withCapacity(DATA_SIZE_1);
143 	TEST_ASSERT('d', "1a", test1);
144 	if (test1) {
145 		TEST_ASSERT('d', "1b", !test1->getLength());
146 		TEST_ASSERT('d', "1c", test1->getCapacity() == DATA_SIZE_1);
147 		TEST_ASSERT('d', "1d", !test1->getBytesNoCopy());
148 		TEST_ASSERT('d', "1e", !test1->getBytesNoCopy(10, DATA_SIZE_1 - 10));
149 		TEST_ASSERT('d', "1f", test1->appendBytes(spaceCheck, 0));
150 		TEST_ASSERT('d', "1g", !test1->getLength());
151 		TEST_ASSERT('d', "1h", test1->getCapacity() == DATA_SIZE_1);
152 		TEST_ASSERT('d', "1i", !test1->getBytesNoCopy());
153 		test1->release();
154 	}
155 	res = res && checkSpace("(d)1", spaceCheck, 0);
156 
157 	// Check appending to empty data allocation
158 	spaceCheck = checkPointSpace();
159 	test1 = OSData::withCapacity(DATA_SIZE_1);
160 	TEST_ASSERT('d', "2a", test1);
161 	if (test1) {
162 		TEST_ASSERT('d', "2b", !test1->getLength());
163 		TEST_ASSERT('d', "2c", !test1->getBytesNoCopy());
164 		TEST_ASSERT('d', "2d", test1->appendBytes(testData, DATA_SIZE_1));
165 		TEST_ASSERT('d', "2e", test1->getLength() == DATA_SIZE_1);
166 		TEST_ASSERT('d', "2f", test1->getBytesNoCopy());
167 		cp = (unsigned short *) test1->getBytesNoCopy();
168 		for (i = 0; cp && i < (DATA_SIZE_1 / sizeof(short)); i++) {
169 			TEST_ASSERT('d', "2g", *cp++ == testData[i]);
170 			if (*cp != testData[i]) {
171 				break;
172 			}
173 		}
174 		TEST_ASSERT('d', "2h", test1->getBytesNoCopy(10, DATA_SIZE_1 - 10));
175 		cp = (unsigned short *) test1->getBytesNoCopy(10, DATA_SIZE_1 - 10);
176 		for (i = 5; cp && i < (DATA_SIZE_1 / sizeof(short)) - 5; i++) {
177 			TEST_ASSERT('d', "2i", *cp++ == testData[i]);
178 			if (*cp != testData[i]) {
179 				break;
180 			}
181 		}
182 		TEST_ASSERT('d', "2j", test1->isEqualTo(testData, DATA_SIZE_1));
183 		test1->release();
184 	}
185 	res = res && checkSpace("(d)2", spaceCheck, 0);
186 
187 	// Check data allocation from some constant data
188 	spaceCheck = checkPointSpace();
189 	test1 = OSData::withBytes(testData, sizeof(testData));
190 	TEST_ASSERT('d', "3a", test1);
191 	if (test1) {
192 		TEST_ASSERT('d', "3b", test1->getLength() == sizeof(testData));
193 		TEST_ASSERT('d', "3c", test1->getCapacity() == sizeof(testData));
194 		TEST_ASSERT('d', "3d", test1->getBytesNoCopy());
195 		TEST_ASSERT('d', "3e", test1->getBytesNoCopy(10, sizeof(testData) - 10));
196 		TEST_ASSERT('d', "3f", test1->appendBytes(spaceCheck, 0));
197 		TEST_ASSERT('d', "3g", test1->getLength() == sizeof(testData));
198 		TEST_ASSERT('d', "3h", test1->getCapacity() == sizeof(testData));
199 		TEST_ASSERT('d', "3i", test1->getBytesNoCopy());
200 		TEST_ASSERT('d', "3j", test1->getBytesNoCopy(10, sizeof(testData) - 10));
201 		TEST_ASSERT('d', "3k", !test1->appendBytes(testData, 10));
202 		test1->release();
203 	}
204 	res = res && checkSpace("(d)3", spaceCheck, 0);
205 
206 	// Check and continious addition of more data
207 	spaceCheck = checkPointSpace();
208 	test1 = OSData::withCapacity(DATA_SIZE_4);
209 	test2 = OSData::withBytesNoCopy(testData, DATA_SIZE_3);
210 	len = DATA_SIZE_3;
211 	TEST_ASSERT('d', "4a", (test1 && test2));
212 	if (test1 && test2) {
213 		TEST_ASSERT('d', "4b", !test1->getLength());
214 		for (i = 0; i < DATA_SIZE_4; i += DATA_SIZE_3) {
215 			TEST_ASSERT('d', "4c", test1->appendBytes(test2));
216 		}
217 		TEST_ASSERT('d', "4d", !test1->appendBytes(test2));
218 		for (i = 0; i < DATA_SIZE_4; i += DATA_SIZE_3) {
219 			TEST_ASSERT('d', "4e", test2->isEqualTo(
220 				    test1->getBytesNoCopy(i, DATA_SIZE_3),
221 				    DATA_SIZE_3));
222 
223 			test3 = OSData::withData(test1, i, DATA_SIZE_3);
224 			TEST_ASSERT('d', "4f", test3);
225 			if (test3) {
226 				TEST_ASSERT('d', "4g", test2->isEqualTo(test3));
227 				test3->release();
228 			}
229 
230 			test3 = OSData::withData(test1, i, len);
231 			TEST_ASSERT('d', "4i", test3);
232 			if (test3) {
233 				TEST_ASSERT('d', "4j", test2->isEqualTo(test3));
234 				test3->release();
235 			}
236 		}
237 		test1->release();
238 		test2->release();
239 	}
240 	res = res && checkSpace("(d)3", spaceCheck, 0);
241 
242 	if (res) {
243 		verPrintf(("testData: All OSData Tests passed\n"));
244 	} else {
245 		logPrintf(("testData: Some OSData Tests failed\n"));
246 	}
247 #undef DATA_SIZE_4
248 #undef DATA_SIZE_3
249 #undef DATA_SIZE_2
250 #undef DATA_SIZE_1
251 }
252 
253 void
testString()254 testString()
255 {
256 	OSString *test1, *test2;
257 	void *spaceCheck;
258 	int i;
259 	char c;
260 	bool res = true;
261 
262 	// very first test initialises the OSMetaClass cache.
263 	test1 = OSString::withCStringNoCopy(testC00);
264 	TEST_ASSERT('s', "0a", test1);
265 	if (test1) {
266 		test1->release();
267 	}
268 
269 	// Check c string allocation
270 	spaceCheck = checkPointSpace();
271 	test1 = OSString::withCString(testC00);
272 	TEST_ASSERT('s', "1a", test1);
273 	TEST_ASSERT('s', "1b", testC00 != test1->getCStringNoCopy());
274 	TEST_ASSERT('s', "1c", strcmp(testC00, test1->getCStringNoCopy()) == 0);
275 	TEST_ASSERT('s', "1d", strlen(testC00) == test1->getLength());
276 	TEST_ASSERT('s', "1e", test1->isEqualTo(testC00));
277 	TEST_ASSERT('s', "1f", !test1->isEqualTo(testC01));
278 	if (test1) {
279 		test1->release();
280 	}
281 	res = res && checkSpace("(s)1", spaceCheck, 0);
282 
283 	// Check c string no allocation
284 	spaceCheck = checkPointSpace();
285 	test1 = OSString::withCStringNoCopy(testC00);
286 	TEST_ASSERT('s', "2a", test1);
287 	TEST_ASSERT('s', "2b", testC00 == test1->getCStringNoCopy());
288 	if (test1) {
289 		test1->release();
290 	}
291 	res = res && checkSpace("(s)2", spaceCheck, 0);
292 
293 	// Check string from other string generation
294 	spaceCheck = checkPointSpace();
295 	test1 = OSString::withCStringNoCopy(testC00);
296 	TEST_ASSERT('s', "3a", test1);
297 	test2 = OSString::withString(test1);
298 	TEST_ASSERT('s', "3b", test2);
299 	TEST_ASSERT('s', "3c", test1 != test2);
300 	TEST_ASSERT('s', "3d", test1->isEqualTo(test2));
301 	if (test1) {
302 		test1->release();
303 	}
304 	if (test2) {
305 		test2->release();
306 	}
307 	res = res && checkSpace("(s)3", spaceCheck, 0);
308 
309 	// Check string comparison functionality no copy
310 	spaceCheck = checkPointSpace();
311 	test1 = OSString::withCStringNoCopy(testC00);
312 	test2 = OSString::withCStringNoCopy(testC01);
313 	TEST_ASSERT('s', "4a", test1 && test2);
314 	TEST_ASSERT('s', "4b", !test1->isEqualTo(test2));
315 	TEST_ASSERT('s', "4c", !test1->isEqualTo(testC01));
316 	TEST_ASSERT('s', "4d", test1->isEqualTo(testC00));
317 	if (test1) {
318 		test1->release();
319 	}
320 	if (test2) {
321 		test2->release();
322 	}
323 	res = res && checkSpace("(s)4", spaceCheck, 0);
324 
325 	// Check string comparison functionality with copy
326 	spaceCheck = checkPointSpace();
327 	test1 = OSString::withCString(testC00);
328 	test2 = OSString::withCString(testC01);
329 	TEST_ASSERT('s', "5a", test1 && test2);
330 	TEST_ASSERT('s', "5b", !test1->isEqualTo(test2));
331 	TEST_ASSERT('s', "5c", !test1->isEqualTo(testC01));
332 	TEST_ASSERT('s', "5d", test1->isEqualTo(testC00));
333 	if (test1) {
334 		test1->release();
335 	}
336 	if (test2) {
337 		test2->release();
338 	}
339 	res = res && checkSpace("(s)5", spaceCheck, 0);
340 
341 	// Check string inplace modifications
342 	spaceCheck = checkPointSpace();
343 	test1 = OSString::withCString(testC00);
344 	TEST_ASSERT('s', "6a", test1);
345 	for (i = 0; (c = test1->getChar(i)); i++) {
346 		if (c != testC00[i]) {
347 			verPrintf(("testString(s) test 6b failed\n")); res = false;
348 			break;
349 		}
350 	}
351 	TEST_ASSERT('s', "6c", !c);
352 	TEST_ASSERT('s', "6d", test1->setChar(' ', 0));
353 	TEST_ASSERT('s', "6e", !test1->isEqualTo(testC00));
354 	TEST_ASSERT('s', "6f", test1->setChar('T', 0));
355 	TEST_ASSERT('s', "6g", !test1->setChar(' ', sizeof(testC00)));
356 	TEST_ASSERT('s', "6h", test1->isEqualTo(testC00));
357 	if (test1) {
358 		test1->release();
359 	}
360 	res = res && checkSpace("(s)6", spaceCheck, 0);
361 
362 	// Check const string fail inplace modifications
363 	spaceCheck = checkPointSpace();
364 	test1 = OSString::withCStringNoCopy(testC00);
365 	TEST_ASSERT('s', "7a", test1);
366 	for (i = 0; (c = test1->getChar(i)); i++) {
367 		if (c != testC00[i]) {
368 			verPrintf(("testString(s) test 7b failed\n")); res = false;
369 			break;
370 		}
371 	}
372 	TEST_ASSERT('s', "7c", !c);
373 	TEST_ASSERT('s', "7d", !test1->setChar(' ', 0));
374 	TEST_ASSERT('s', "7e", test1->isEqualTo(testC00));
375 	TEST_ASSERT('s', "7f", !test1->setChar(' ', sizeof(testC00)));
376 	TEST_ASSERT('s', "7g", test1->isEqualTo(testC00));
377 	if (test1) {
378 		test1->release();
379 	}
380 	res = res && checkSpace("(s)7", spaceCheck, 0);
381 
382 	if (res) {
383 		verPrintf(("testString: All OSString Tests passed\n"));
384 	} else {
385 		logPrintf(("testString: Some OSString Tests failed\n"));
386 	}
387 }
388 
389 void
testSymbol()390 testSymbol()
391 {
392 	bool res = true;
393 	int i, j;
394 	int countDups;
395 	const OSSymbol *cache[numStrCache];
396 	void *spaceCheck;
397 
398 	// very first test initialises the OSMetaClass cache.
399 	cache[0] = IOSymbol::withCStringNoCopy(testC00);
400 	TEST_ASSERT('u', "0a", cache[0]);
401 	if (cache[0]) {
402 		cache[0]->release();
403 	}
404 
405 	spaceCheck = checkPointSpace();
406 
407 	// Setup the symbol cache, make sure it grows the symbol unique'ing
408 	// hash table.  Also determine that the symbol is created ok and that
409 	// it is indeed equal to the creating cString by strcmp.
410 	for (i = 0; i < numStrCache; i++) {
411 		cache[i] = OSSymbol::withCStringNoCopy(strCache[i]);
412 		if (!cache[i]) {
413 			verPrintf(("testSymbol(u) test 1a%d failed\n", i)); res = false;
414 		} else if (!cache[i]->isEqualTo(strCache[i])) {
415 			verPrintf(("testSymbol(u) test 1b%d failed\n", i)); res = false;
416 		}
417 	}
418 
419 	// The strCache does have some duplicates in it, mostly 'the'.  Make
420 	// sure that we wind them and that different cache entries really are
421 	// different by strcmp.  Fundamental to OSSymbol semantics.
422 	countDups = 0;
423 	for (i = 0; i < numStrCache; i++) {
424 		for (j = i + 1; j < numStrCache; j++) {
425 			if (cache[i] != cache[j] && cache[i]->isEqualTo(cache[j])) {
426 				verPrintf(("testSymbol(u) test 2a%d,%d failed\n", i, j));
427 				res = false;
428 			} else if (cache[i] == cache[j]) {
429 				if (cache[i]->getRetainCount() == 1) {
430 					verPrintf(("testSymbol(u) test 2b%d,%d failed\n", i, j));
431 					res = false;
432 				}
433 				countDups++;
434 			}
435 		}
436 	}
437 	TEST_ASSERT('u', "2c", countDups);
438 
439 	// Clear out the cache and check that the unique'ing hashtable has grown
440 	for (i = 0; i < numStrCache; i++) {
441 		if (cache[i]) {
442 			cache[i]->release();
443 			cache[i] = 0;
444 		}
445 	}
446 	// As of 1998-11-17 the hash growth is 364.
447 	res = res && checkSpace("(u)3", spaceCheck, 972);
448 	logSpace();
449 
450 	// Check for leaks by repeating the cacheing and freeing
451 	spaceCheck = checkPointSpace();
452 	for (i = 0; i < numStrCache; i++) {
453 		cache[i] = OSSymbol::withCString(strCache[i]);
454 	}
455 	for (i = 0; i < numStrCache; i++) {
456 		if (cache[i]) {
457 			cache[i]->release();
458 			cache[i] = 0;
459 		}
460 	}
461 	res = res && checkSpace("(u)4", spaceCheck, 0);
462 
463 	// Check that the OSString based symbol constructors work
464 	// and that they don't leak, and finally double check that while
465 	// the cache is active the symbol semantics still work.
466 	spaceCheck = checkPointSpace();
467 	for (i = 0; i < numStrCache; i++) {
468 		OSString *tmpStr;
469 
470 		tmpStr = (i & 1)
471 		    ? OSString::withCString(strCache[i])
472 		    : OSString::withCStringNoCopy(strCache[i]);
473 		if (tmpStr) {
474 			cache[i] = OSSymbol::withString(tmpStr);
475 			if (!cache[i]) {
476 				verPrintf(("testSymbol(u) test 5a%d failed\n", i));
477 				res = false;
478 			}
479 			tmpStr->release();
480 		}
481 	}
482 
483 	for (i = 0; i < numStrCache; i++) {
484 		if (cache[i]) {
485 			const OSSymbol *tmpSymb;
486 
487 			tmpSymb = OSSymbol::withCStringNoCopy(strCache[i]);
488 			if (cache[i] != tmpSymb) {
489 				verPrintf(("testSymbol(u) test 5b%d failed\n", i));
490 				res = false;
491 			}
492 			tmpSymb->release();
493 			cache[i]->release();
494 			cache[i] = 0;
495 		} else {
496 			verPrintf(("testSymbol(u) test 5c%d failed\n", i));
497 			res = false;
498 		}
499 	}
500 	res = res && checkSpace("(u)5", spaceCheck, 0);
501 
502 	if (res) {
503 		verPrintf(("testSymbol: All OSSymbol Tests passed\n"));
504 	} else {
505 		logPrintf(("testSymbol: Some OSSymbol Tests failed\n"));
506 	}
507 }
508 
509 #endif /* DEBUG */
510