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