xref: /xnu-11215/iokit/Tests/TestContainers.cpp (revision 76e12aa3)
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 {
116 #define DATA_SIZE_1	 256
117 #define DATA_SIZE_2	 512
118 #define DATA_SIZE_3	1024
119 #define DATA_SIZE_4	8192
120 
121     OSData *test1, *test2, *test3;
122     void *spaceCheck;
123     unsigned int len;
124     unsigned int i;
125     bool res = true;
126     unsigned short testData[DATA_SIZE_4/sizeof(short)], *cp;
127 
128     // very first test initialises the OSMetaClass cache.
129     test1 = OSData::withCapacity(DATA_SIZE_1);
130     TEST_ASSERT('d', "0a", test1);
131     if (test1)
132         test1->release();
133 
134     for (i = 0; i < sizeof(testData)/sizeof(short); i++)
135         testData[i] = (unsigned short) i;
136 
137     // Check empty data allocation
138     spaceCheck = checkPointSpace();
139     test1 = OSData::withCapacity(DATA_SIZE_1);
140     TEST_ASSERT('d', "1a", test1);
141     if (test1) {
142         TEST_ASSERT('d', "1b", !test1->getLength());
143         TEST_ASSERT('d', "1c", test1->getCapacity() == DATA_SIZE_1);
144         TEST_ASSERT('d', "1d", !test1->getBytesNoCopy());
145         TEST_ASSERT('d', "1e", !test1->getBytesNoCopy(10, DATA_SIZE_1 - 10));
146         TEST_ASSERT('d', "1f", test1->appendBytes(spaceCheck, 0));
147         TEST_ASSERT('d', "1g", !test1->getLength());
148         TEST_ASSERT('d', "1h", test1->getCapacity() == DATA_SIZE_1);
149         TEST_ASSERT('d', "1i", !test1->getBytesNoCopy());
150         test1->release();
151     }
152     res = res && checkSpace("(d)1", spaceCheck, 0);
153 
154     // Check appending to empty data allocation
155     spaceCheck = checkPointSpace();
156     test1 = OSData::withCapacity(DATA_SIZE_1);
157     TEST_ASSERT('d', "2a", test1);
158     if (test1) {
159         TEST_ASSERT('d', "2b", !test1->getLength());
160         TEST_ASSERT('d', "2c", !test1->getBytesNoCopy());
161         TEST_ASSERT('d', "2d", test1->appendBytes(testData, DATA_SIZE_1));
162         TEST_ASSERT('d', "2e", test1->getLength() == DATA_SIZE_1);
163         TEST_ASSERT('d', "2f", test1->getBytesNoCopy());
164         cp = (unsigned short *) test1->getBytesNoCopy();
165         for (i = 0; cp && i < (DATA_SIZE_1/sizeof(short)); i++) {
166             TEST_ASSERT('d', "2g", *cp++ == testData[i]);
167             if (*cp != testData[i])
168                 break;
169         }
170         TEST_ASSERT('d', "2h", test1->getBytesNoCopy(10, DATA_SIZE_1-10));
171         cp = (unsigned short *) test1->getBytesNoCopy(10, DATA_SIZE_1 - 10);
172         for (i = 5; cp && i < (DATA_SIZE_1/sizeof(short)) - 5; i++) {
173             TEST_ASSERT('d', "2i", *cp++ == testData[i]);
174             if (*cp != testData[i])
175                 break;
176         }
177         TEST_ASSERT('d', "2j", test1->isEqualTo(testData, DATA_SIZE_1));
178         test1->release();
179     }
180     res = res && checkSpace("(d)2", spaceCheck, 0);
181 
182     // Check data allocation from some constant data
183     spaceCheck = checkPointSpace();
184     test1 = OSData::withBytes(testData, sizeof(testData));
185     TEST_ASSERT('d', "3a", test1);
186     if (test1) {
187         TEST_ASSERT('d', "3b", test1->getLength() == sizeof(testData));
188         TEST_ASSERT('d', "3c", test1->getCapacity() == sizeof(testData));
189         TEST_ASSERT('d', "3d", test1->getBytesNoCopy());
190         TEST_ASSERT('d', "3e", test1->getBytesNoCopy(10, sizeof(testData)-10));
191         TEST_ASSERT('d', "3f", test1->appendBytes(spaceCheck, 0));
192         TEST_ASSERT('d', "3g", test1->getLength() == sizeof(testData));
193         TEST_ASSERT('d', "3h", test1->getCapacity() == sizeof(testData));
194         TEST_ASSERT('d', "3i", test1->getBytesNoCopy());
195         TEST_ASSERT('d', "3j", test1->getBytesNoCopy(10, sizeof(testData)-10));
196         TEST_ASSERT('d', "3k", !test1->appendBytes(testData, 10));
197         test1->release();
198     }
199     res = res && checkSpace("(d)3", spaceCheck, 0);
200 
201     // Check and continious addition of more data
202     spaceCheck = checkPointSpace();
203     test1 = OSData::withCapacity(DATA_SIZE_4);
204     test2 = OSData::withBytesNoCopy(testData, DATA_SIZE_3);
205     len = DATA_SIZE_3;
206     TEST_ASSERT('d', "4a", (test1 && test2));
207     if (test1 && test2) {
208         TEST_ASSERT('d', "4b", !test1->getLength());
209         for (i = 0; i < DATA_SIZE_4; i += DATA_SIZE_3)
210             TEST_ASSERT('d', "4c", test1->appendBytes(test2));
211         TEST_ASSERT('d', "4d", !test1->appendBytes(test2));
212         for (i = 0; i < DATA_SIZE_4; i += DATA_SIZE_3) {
213 
214             TEST_ASSERT('d', "4e", test2->isEqualTo(
215                                         test1->getBytesNoCopy(i, DATA_SIZE_3),
216                                         DATA_SIZE_3));
217 
218             test3 = OSData::withData(test1, i, DATA_SIZE_3);
219             TEST_ASSERT('d', "4f", test3);
220             if (test3) {
221                 TEST_ASSERT('d', "4g", test2->isEqualTo(test3));
222                 test3->release();
223             }
224 
225             test3 = OSData::withData(test1, i, len);
226             TEST_ASSERT('d', "4i", test3);
227             if (test3) {
228                 TEST_ASSERT('d', "4j", test2->isEqualTo(test3));
229                 test3->release();
230             }
231         }
232         test1->release();
233         test2->release();
234     }
235     res = res && checkSpace("(d)3", spaceCheck, 0);
236 
237     if (res)
238         verPrintf(("testData: All OSData Tests passed\n"));
239     else
240         logPrintf(("testData: Some OSData Tests failed\n"));
241 #undef DATA_SIZE_4
242 #undef DATA_SIZE_3
243 #undef DATA_SIZE_2
244 #undef DATA_SIZE_1
245 }
246 
247 void testString()
248 {
249     OSString *test1, *test2;
250     void *spaceCheck;
251     int i;
252     char c;
253     bool res = true;
254 
255     // very first test initialises the OSMetaClass cache.
256     test1 = OSString::withCStringNoCopy(testC00);
257     TEST_ASSERT('s', "0a", test1);
258     if (test1)
259         test1->release();
260 
261     // Check c string allocation
262     spaceCheck = checkPointSpace();
263     test1 = OSString::withCString(testC00);
264     TEST_ASSERT('s', "1a", test1);
265     TEST_ASSERT('s', "1b", testC00 != test1->getCStringNoCopy());
266     TEST_ASSERT('s', "1c", strcmp(testC00, test1->getCStringNoCopy()) == 0);
267     TEST_ASSERT('s', "1d", strlen(testC00) == test1->getLength());
268     TEST_ASSERT('s', "1e", test1->isEqualTo(testC00));
269     TEST_ASSERT('s', "1f", !test1->isEqualTo(testC01));
270     if (test1) test1->release();
271     res = res && checkSpace("(s)1", spaceCheck, 0);
272 
273     // Check c string no allocation
274     spaceCheck = checkPointSpace();
275     test1 = OSString::withCStringNoCopy(testC00);
276     TEST_ASSERT('s', "2a", test1);
277     TEST_ASSERT('s', "2b", testC00 == test1->getCStringNoCopy());
278     if (test1) test1->release();
279     res = res && checkSpace("(s)2", spaceCheck, 0);
280 
281     // Check string from other string generation
282     spaceCheck = checkPointSpace();
283     test1 = OSString::withCStringNoCopy(testC00);
284     TEST_ASSERT('s', "3a", test1);
285     test2 = OSString::withString(test1);
286     TEST_ASSERT('s', "3b", test2);
287     TEST_ASSERT('s', "3c", test1 != test2);
288     TEST_ASSERT('s', "3d", test1->isEqualTo(test2));
289     if (test1) test1->release();
290     if (test2) test2->release();
291     res = res && checkSpace("(s)3", spaceCheck, 0);
292 
293     // Check string comparison functionality no copy
294     spaceCheck = checkPointSpace();
295     test1 = OSString::withCStringNoCopy(testC00);
296     test2 = OSString::withCStringNoCopy(testC01);
297     TEST_ASSERT('s', "4a", test1 && test2);
298     TEST_ASSERT('s', "4b", !test1->isEqualTo(test2));
299     TEST_ASSERT('s', "4c", !test1->isEqualTo(testC01));
300     TEST_ASSERT('s', "4d", test1->isEqualTo(testC00));
301     if (test1) test1->release();
302     if (test2) test2->release();
303     res = res && checkSpace("(s)4", spaceCheck, 0);
304 
305     // Check string comparison functionality with copy
306     spaceCheck = checkPointSpace();
307     test1 = OSString::withCString(testC00);
308     test2 = OSString::withCString(testC01);
309     TEST_ASSERT('s', "5a", test1 && test2);
310     TEST_ASSERT('s', "5b", !test1->isEqualTo(test2));
311     TEST_ASSERT('s', "5c", !test1->isEqualTo(testC01));
312     TEST_ASSERT('s', "5d", test1->isEqualTo(testC00));
313     if (test1) test1->release();
314     if (test2) test2->release();
315     res = res && checkSpace("(s)5", spaceCheck, 0);
316 
317     // Check string inplace modifications
318     spaceCheck = checkPointSpace();
319     test1 = OSString::withCString(testC00);
320     TEST_ASSERT('s', "6a", test1);
321     for (i = 0; (c = test1->getChar(i)); i++)
322         if (c != testC00[i]) {
323             verPrintf(("testString(s) test 6b failed\n")); res = false;
324             break;
325         }
326     TEST_ASSERT('s', "6c", !c);
327     TEST_ASSERT('s', "6d", test1->setChar(' ', 0));
328     TEST_ASSERT('s', "6e", !test1->isEqualTo(testC00));
329     TEST_ASSERT('s', "6f", test1->setChar('T', 0));
330     TEST_ASSERT('s', "6g", !test1->setChar(' ', sizeof(testC00)));
331     TEST_ASSERT('s', "6h", test1->isEqualTo(testC00));
332     if (test1) test1->release();
333     res = res && checkSpace("(s)6", spaceCheck, 0);
334 
335     // Check const string fail inplace modifications
336     spaceCheck = checkPointSpace();
337     test1 = OSString::withCStringNoCopy(testC00);
338     TEST_ASSERT('s', "7a", test1);
339     for (i = 0; (c = test1->getChar(i)); i++)
340         if (c != testC00[i]) {
341             verPrintf(("testString(s) test 7b failed\n")); res = false;
342             break;
343         }
344     TEST_ASSERT('s', "7c", !c);
345     TEST_ASSERT('s', "7d", !test1->setChar(' ', 0));
346     TEST_ASSERT('s', "7e", test1->isEqualTo(testC00));
347     TEST_ASSERT('s', "7f", !test1->setChar(' ', sizeof(testC00)));
348     TEST_ASSERT('s', "7g", test1->isEqualTo(testC00));
349     if (test1) test1->release();
350     res = res && checkSpace("(s)7", spaceCheck, 0);
351 
352     if (res)
353         verPrintf(("testString: All OSString Tests passed\n"));
354     else
355         logPrintf(("testString: Some OSString Tests failed\n"));
356 }
357 
358 void testSymbol()
359 {
360     bool res = true;
361     int i, j;
362     int countDups;
363     const OSSymbol *cache[numStrCache];
364     void *spaceCheck;
365 
366     // very first test initialises the OSMetaClass cache.
367     cache[0] = IOSymbol::withCStringNoCopy(testC00);
368     TEST_ASSERT('u', "0a", cache[0]);
369     if (cache[0])
370         cache[0]->release();
371 
372     spaceCheck = checkPointSpace();
373 
374     // Setup the symbol cache, make sure it grows the symbol unique'ing
375     // hash table.  Also determine that the symbol is created ok and that
376     // it is indeed equal to the creating cString by strcmp.
377     for (i = 0; i < numStrCache; i++) {
378         cache[i] = OSSymbol::withCStringNoCopy(strCache[i]);
379         if (!cache[i]) {
380             verPrintf(("testSymbol(u) test 1a%d failed\n", i)); res = false;
381         }
382         else if (!cache[i]->isEqualTo(strCache[i])) {
383             verPrintf(("testSymbol(u) test 1b%d failed\n", i)); res = false;
384         }
385     }
386 
387     // The strCache does have some duplicates in it, mostly 'the'.  Make
388     // sure that we wind them and that different cache entries really are
389     // different by strcmp.  Fundamental to OSSymbol semantics.
390     countDups = 0;
391     for (i = 0; i < numStrCache; i++)
392         for (j = i+1; j < numStrCache; j++) {
393             if (cache[i] != cache[j] && cache[i]->isEqualTo(cache[j])) {
394                 verPrintf(("testSymbol(u) test 2a%d,%d failed\n", i, j));
395                 res = false;
396             }
397             else if (cache[i] == cache[j]) {
398                 if (cache[i]->getRetainCount() == 1) {
399                     verPrintf(("testSymbol(u) test 2b%d,%d failed\n", i, j));
400                     res = false;
401                 }
402                 countDups++;
403             }
404         }
405     TEST_ASSERT('u', "2c", countDups);
406 
407     // Clear out the cache and check that the unique'ing hashtable has grown
408     for (i = 0; i < numStrCache; i++) {
409         if (cache[i]) {
410             cache[i]->release();
411             cache[i] = 0;
412         }
413     }
414     // As of 1998-11-17 the hash growth is 364.
415     res = res && checkSpace("(u)3", spaceCheck, 972);
416     logSpace();
417 
418     // Check for leaks by repeating the cacheing and freeing
419     spaceCheck = checkPointSpace();
420     for (i = 0; i < numStrCache; i++)
421         cache[i] = OSSymbol::withCString(strCache[i]);
422     for (i = 0; i < numStrCache; i++) {
423         if (cache[i]) {
424             cache[i]->release();
425             cache[i] = 0;
426         }
427     }
428     res = res && checkSpace("(u)4", spaceCheck, 0);
429 
430     // Check that the OSString based symbol constructors work
431     // and that they don't leak, and finally double check that while
432     // the cache is active the symbol semantics still work.
433     spaceCheck = checkPointSpace();
434     for (i = 0; i < numStrCache; i++) {
435         OSString *tmpStr;
436 
437         tmpStr = (i&1)
438                ? OSString::withCString(strCache[i])
439                : OSString::withCStringNoCopy(strCache[i]);
440         if (tmpStr) {
441             cache[i] = OSSymbol::withString(tmpStr);
442             if (!cache[i]) {
443                 verPrintf(("testSymbol(u) test 5a%d failed\n", i));
444                 res = false;
445             }
446             tmpStr->release();
447         }
448     }
449 
450     for (i = 0; i < numStrCache; i++) {
451         if (cache[i]) {
452             const OSSymbol *tmpSymb;
453 
454             tmpSymb = OSSymbol::withCStringNoCopy(strCache[i]);
455             if (cache[i] != tmpSymb) {
456                 verPrintf(("testSymbol(u) test 5b%d failed\n", i));
457                 res = false;
458             }
459             tmpSymb->release();
460             cache[i]->release();
461             cache[i] = 0;
462         }
463         else {
464             verPrintf(("testSymbol(u) test 5c%d failed\n", i));
465             res = false;
466         }
467     }
468     res = res && checkSpace("(u)5", spaceCheck, 0);
469 
470     if (res)
471         verPrintf(("testSymbol: All OSSymbol Tests passed\n"));
472     else
473         logPrintf(("testSymbol: Some OSSymbol Tests failed\n"));
474 }
475 
476 #endif /* DEBUG */
477