]> git.saurik.com Git - apple/xnu.git/blob - iokit/Tests/TestCollections.cpp
xnu-3789.70.16.tar.gz
[apple/xnu.git] / iokit / Tests / TestCollections.cpp
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++/OSArray.h>
32 #include <libkern/c++/OSSet.h>
33 #include <libkern/c++/OSDictionary.h>
34 #include <libkern/c++/OSString.h>
35 #include <libkern/c++/OSSymbol.h>
36 #include <libkern/c++/OSCollectionIterator.h>
37
38 void testArray()
39 {
40 bool res = true;
41 void *spaceCheck, *spaceCheck2 , *spaceCheck3;
42 int i, j, count, count2;
43 OSObject *cache[numStrCache], *str, *sym;
44 OSArray *array1, *array2;
45
46 // Do first test without memory leak tests to initialise the metaclass
47 array1 = OSArray::withCapacity(1);
48 TEST_ASSERT('A', "0a", array1);
49 if (array1)
50 array1->release();
51
52 // Grow the symbol pool to maximum
53 for (i = 0; i < numStrCache; i++)
54 cache[i] = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
55 for (i = 0; i < numStrCache; i++)
56 cache[i]->release();
57
58 // Create and destroy an array
59 spaceCheck = checkPointSpace();
60 array1 = OSArray::withCapacity(1);
61 TEST_ASSERT('A', "1a", array1);
62 if (array1) {
63 TEST_ASSERT('A', "1b", !array1->getCount());
64 TEST_ASSERT('A', "1c", 1 == array1->getCapacity());
65 TEST_ASSERT('A', "1d", 1 == array1->getCapacityIncrement());
66 TEST_ASSERT('A', "1e", 4 == array1->setCapacityIncrement(4));
67 TEST_ASSERT('A', "1f", 4 == array1->getCapacityIncrement());
68 TEST_ASSERT('A', "1g", 8 == array1->ensureCapacity(5));
69
70 spaceCheck2 = checkPointSpace();
71 cache[0] = IOString::withCStringNoCopy(strCache[0]);
72
73 spaceCheck3 = checkPointSpace();
74 TEST_ASSERT('A', "1h", array1->setObject(cache[0]));
75 TEST_ASSERT('A', "1i", cache[0] == array1->getObject(0));
76 cache[0]->release();
77 res = res && checkSpace("(A)1j", spaceCheck3, 0);
78
79 TEST_ASSERT('A', "1k", 1 == array1->getCount());
80 array1->flushCollection();
81 TEST_ASSERT('A', "1l", !array1->getCount());
82 res = res && checkSpace("(A)1m", spaceCheck2, 0);
83
84 array1->release();
85 }
86 res = res && checkSpace("(A)1", spaceCheck, 0);
87
88 // Check the creation of a sizable OSArray from an array of IOObjects
89 // Also check indexing into the array.
90 spaceCheck = checkPointSpace();
91 for (i = 0; i < numStrCache; i++)
92 cache[i] = OSString::withCStringNoCopy(strCache[i]);
93 array1 = OSArray::withObjects(cache, numStrCache, numStrCache);
94 TEST_ASSERT('A', "2a", array1);
95 for (i = 0; i < numStrCache; i++)
96 cache[i]->release();
97 if (array1) {
98 TEST_ASSERT('A', "2b", numStrCache == (int) array1->getCount());
99 TEST_ASSERT('A', "2c", numStrCache == (int) array1->getCapacity());
100 TEST_ASSERT('A', "2d",
101 numStrCache == (int) array1->getCapacityIncrement());
102
103 for (i = 0; (str = array1->getObject(i)); i++) {
104 if (str != cache[i]) {
105 verPrintf(("testArray(A) test 2e%d failed\n", i));
106 res = false;
107 }
108 }
109 TEST_ASSERT('A', "2f", numStrCache == i);
110 array1->release();
111 }
112 res = res && checkSpace("(A)2", spaceCheck, 0);
113
114 // Test array creation from another array by both the setObject method
115 // and the withArray factory. And test __takeObject code first
116 // with tail removal then with head removal
117 spaceCheck = checkPointSpace();
118 for (i = 0; i < numStrCache; i++)
119 cache[i] = OSString::withCStringNoCopy(strCache[i]);
120 array1 = OSArray::withObjects(cache, numStrCache, numStrCache);
121 TEST_ASSERT('A', "3a", array1);
122 for (i = 0; i < numStrCache; i++)
123 cache[i]->release();
124 array2 = 0;
125 if (array1) {
126 array2 = OSArray::withCapacity(1);
127 TEST_ASSERT('A', "3b", array2);
128 TEST_ASSERT('A', "3c", !array2->getCount());
129 TEST_ASSERT('A', "3d", array2->setObject(array1));
130 TEST_ASSERT('A', "3e", array1->getCount() == array2->getCount());
131 }
132 if (array2) {
133 count = 0;
134 TEST_ASSERT('A', "3f", numStrCache == (int) array2->getCount());
135 for (i = array2->getCount(); (str = array2->__takeObject(--i)); ) {
136 if (str != cache[i]) {
137 verPrintf(("testArray(A) test 3g%d failed\n", i));
138 res = false;
139 }
140 count += ((int) array2->getCount() == i);
141 str->release();
142 }
143 TEST_ASSERT('A', "3h", count == numStrCache);
144 TEST_ASSERT('A', "3i", -1 == i);
145 TEST_ASSERT('A', "3j", !array2->getCount());
146
147 spaceCheck2 = checkPointSpace();
148 array2->flushCollection();
149 res = res && checkSpace("(A)3k", spaceCheck2, 0);
150
151 array2->release();
152 array2 = 0;
153 }
154 if (array1) {
155 array2 = OSArray::withArray(array1, numStrCache - 1);
156 TEST_ASSERT('A', "3l", !array2);
157 array2 = OSArray::withArray(array1, array1->getCount());
158 TEST_ASSERT('A', "3m", array2);
159 array1->release();
160 }
161 if (array2) {
162 count = 0;
163 TEST_ASSERT('A', "3o", numStrCache == (int) array2->getCount());
164 for (i = 0; (str = array2->__takeObject(0)); i++) {
165 count += (str == cache[i]);
166 str->release();
167 }
168 TEST_ASSERT('A', "3p", count == numStrCache);
169 TEST_ASSERT('A', "3q", !array2->getCount());
170 array2->release();
171 array2 = 0;
172 }
173 res = res && checkSpace("(A)3", spaceCheck, 0);
174
175 // Test object replacement from one array to another
176 spaceCheck = checkPointSpace();
177 array1 = OSArray::withCapacity(numStrCache);
178 TEST_ASSERT('A', "4a", array1);
179 if (array1) {
180 count = count2 = 0;
181 for (i = 0; i < numStrCache; i++) {
182 str = OSString::withCStringNoCopy(strCache[i]);
183 count += array1->setObject(str);
184 count2 += (str == array1->lastObject());
185 str->release();
186 }
187 TEST_ASSERT('A', "4b", numStrCache == (int) array1->getCount());
188 TEST_ASSERT('A', "4c", count == numStrCache);
189 TEST_ASSERT('A', "4d", count2 == numStrCache);
190 }
191 array2 = OSArray::withCapacity(1);
192 TEST_ASSERT('A', "4e", array2);
193 if (array2) {
194 count = count2 = 0;
195 str = (OSObject *) OSSymbol::withCStringNoCopy(strCache[0]);
196 for (i = 0; i < numStrCache; i++) {
197 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
198 count += array2->setObject(sym, 0);
199 count2 += (str == array2->lastObject());
200 sym->release();
201 }
202 str->release();
203 TEST_ASSERT('A', "4f", numStrCache == (int) array2->getCount());
204 TEST_ASSERT('A', "4g", count == numStrCache);
205 TEST_ASSERT('A', "4h", count2 == numStrCache);
206 }
207 if (array1 && array2) {
208
209 count = count2 = 0;
210 for (i = array1->getCount() - 1; (sym = array2->__takeObject(0)); i--) {
211 str = array1->replaceObject(sym, i);
212 count += (str != 0);
213 count2 += (sym != str);
214 if (str)
215 str->release();
216 if (sym)
217 sym->release();
218 }
219 TEST_ASSERT('A', "4k", numStrCache == (int) array1->getCount());
220 TEST_ASSERT('A', "4l", count == numStrCache);
221 TEST_ASSERT('A', "4m", count2 == numStrCache);
222 array1->release();
223 array2->release();
224 }
225 else {
226 if (array1) array1->release();
227 if (array2) array2->release();
228 }
229 res = res && checkSpace("(A)4", spaceCheck, 0);
230
231 // Test array duplicate removal
232 spaceCheck = checkPointSpace();
233 array1 = OSArray::withCapacity(numStrCache);
234 TEST_ASSERT('A', "5a", array1);
235 if (array1) {
236 for (i = 0; i < numStrCache; i++) {
237 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
238 count += array1->setObject(sym);
239 sym->release();
240 }
241 TEST_ASSERT('A', "5b", numStrCache == (int) array1->getCount());
242
243 // remove duplicates
244 for (i = 0; (sym = array1->getObject(i)); )
245 if (sym->getRetainCount() == 1)
246 i++;
247 else {
248 //sym = array1->__takeObject(i);
249 //sym->release();
250 array1->removeObject(i);
251 }
252 TEST_ASSERT('A', "5c", numStrCache != (int) array1->getCount());
253
254 // check to see that all symbols are really there
255 for (count = 0, i = 0; i < numStrCache; i++) {
256 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
257 for (count2 = false, j = 0; (str = array1->getObject(j)); j++)
258 if (str == sym) {
259 count2 = true;
260 break;
261 }
262 count += count2;
263 sym->release();
264 }
265 TEST_ASSERT('A', "5c", count == numStrCache);
266 array1->release();
267 }
268 res = res && checkSpace("(S)5", spaceCheck, 0);
269
270 if (res)
271 verPrintf(("testArray: All OSArray Tests passed\n"));
272 else
273 logPrintf(("testArray: Some OSArray Tests failed\n"));
274 }
275
276 void testSet()
277 {
278 bool res = true;
279 void *spaceCheck, *spaceCheck2 , *spaceCheck3;
280 int i, count, count2;
281 OSObject *cache[numStrCache], *str, *sym;
282 OSSet *set1, *set2;
283 OSArray *array;
284
285 // Do first test without memory leak tests to initialise the metaclass
286 set1 = OSSet::withCapacity(1);
287 TEST_ASSERT('S', "0a", set1);
288 if (set1)
289 set1->release();
290
291 // Grow the symbol pool to maximum
292 for (i = 0; i < numStrCache; i++)
293 cache[i] = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
294 for (i = 0; i < numStrCache; i++)
295 cache[i]->release();
296
297 // Create and destroy an set
298 spaceCheck = checkPointSpace();
299 set1 = OSSet::withCapacity(1);
300 TEST_ASSERT('S', "1a", set1);
301 if (set1) {
302 TEST_ASSERT('S', "1b", !set1->getCount());
303 TEST_ASSERT('S', "1c", 1 == set1->getCapacity());
304 TEST_ASSERT('S', "1d", 1 == set1->getCapacityIncrement());
305 TEST_ASSERT('S', "1e", 4 == set1->setCapacityIncrement(4));
306 TEST_ASSERT('S', "1f", 4 == set1->getCapacityIncrement());
307 TEST_ASSERT('S', "1g", 8 == set1->ensureCapacity(5));
308
309 spaceCheck2 = checkPointSpace();
310 cache[0] = IOString::withCStringNoCopy(strCache[0]);
311
312 spaceCheck3 = checkPointSpace();
313 TEST_ASSERT('S', "1h", set1->setObject(cache[0]));
314 TEST_ASSERT('S', "1i", set1->containsObject(cache[0]));
315 TEST_ASSERT('S', "1j", cache[0] == set1->getAnyObject());
316 cache[0]->release();
317 res = res && checkSpace("(S)1k", spaceCheck3, 0);
318
319 TEST_ASSERT('S', "1l", 1 == set1->getCount());
320 set1->flushCollection();
321 TEST_ASSERT('S', "1m", !set1->getCount());
322 res = res && checkSpace("(S)1n", spaceCheck2, 0);
323
324 set1->release();
325 }
326 res = res && checkSpace("(S)1", spaceCheck, 0);
327
328 // Check the creation of a sizable OSSet from an set of IOObjects
329 // Also check member test of set.
330 spaceCheck = checkPointSpace();
331 for (i = 0; i < numStrCache; i++)
332 cache[i] = OSString::withCStringNoCopy(strCache[i]);
333 set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
334 TEST_ASSERT('S', "2a", set1);
335 for (i = 0; i < numStrCache; i++)
336 cache[i]->release();
337 if (set1) {
338 TEST_ASSERT('S', "2b", numStrCache == (int) set1->getCount());
339 TEST_ASSERT('S', "2c", numStrCache == (int) set1->getCapacity());
340 TEST_ASSERT('S', "2d",
341 numStrCache == (int) set1->getCapacityIncrement());
342
343 count = 0;
344 for (i = set1->getCount(); --i >= 0; )
345 count += set1->member(cache[i]);
346
347 TEST_ASSERT('S', "2e", numStrCache == count);
348 set1->release();
349 }
350 res = res && checkSpace("(S)2", spaceCheck, 0);
351
352 // Test set creation from another set by both the setObject method
353 // and the withArray factory. And test __takeObject code first
354 // with tail removal then with head removal
355 spaceCheck = checkPointSpace();
356 for (i = 0; i < numStrCache; i++)
357 cache[i] = OSString::withCStringNoCopy(strCache[i]);
358 set1 = OSSet::withObjects(cache, numStrCache, numStrCache);
359 TEST_ASSERT('S', "3a", set1);
360 for (i = 0; i < numStrCache; i++)
361 cache[i]->release();
362 set2 = 0;
363 if (set1) {
364 set2 = OSSet::withCapacity(set1->getCount());
365 TEST_ASSERT('S', "3b", set2);
366 TEST_ASSERT('S', "3c", !set2->getCount());
367 TEST_ASSERT('S', "3d", set2->setObject(set1));
368 TEST_ASSERT('S', "3e", set1->getCount() == set2->getCount());
369 }
370 if (set2) {
371 TEST_ASSERT('S', "3f", numStrCache == (int) set2->getCount());
372 count = count2 = 0;
373 while ( (str = set2->getAnyObject()) ) {
374 count += set2->__takeObject(str);
375 count2 += set1->member(str);
376 str->release();
377 }
378 TEST_ASSERT('S', "3g", !set2->getCount());
379 TEST_ASSERT('S', "3h", numStrCache == count);
380 TEST_ASSERT('S', "3i", numStrCache == count2);
381
382 spaceCheck2 = checkPointSpace();
383 set2->flushCollection();
384 res = res && checkSpace("(S)3j", spaceCheck2, 0);
385
386 set2->release();
387 set2 = 0;
388 }
389 if (set1) {
390 set2 = OSSet::withSet(set1, numStrCache - 1);
391 TEST_ASSERT('S', "3k", !set2);
392 set2 = OSSet::withSet(set1, set1->getCount());
393 TEST_ASSERT('S', "3l", set2);
394 set1->release();
395 }
396 if (set2) {
397 TEST_ASSERT('S', "3m", numStrCache == (int) set2->getCount());
398 i = count = count2 = 0;
399 while ( (str = set2->getAnyObject()) ) {
400 count += set2->__takeObject(str);
401 count2 += (cache[i++] == str);
402 str->release();
403 }
404 TEST_ASSERT('S', "3n", !set2->getCount());
405 TEST_ASSERT('S', "3o", numStrCache == count);
406 TEST_ASSERT('S', "3p", numStrCache == count2);
407
408 set2->release();
409 set2 = 0;
410 }
411 res = res && checkSpace("(S)3", spaceCheck, 0);
412
413 // Test duplicate removal
414 spaceCheck = checkPointSpace();
415 set2 = 0;
416 set1 = OSSet::withCapacity(numStrCache);
417 TEST_ASSERT('S', "4a", set1);
418 if (set1) {
419 count = 0;
420 for (i = 0; i < numStrCache; i++) {
421 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
422 count += set1->setObject(sym);
423 sym->release();
424 }
425 TEST_ASSERT('S', "4b", numStrCache != (int) set1->getCount());
426 TEST_ASSERT('S', "4c", count == (int) set1->getCount());
427
428 count = count2 = 0;
429 for (i = 0; i < numStrCache; i++) {
430 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
431 count += set1->member(sym);
432 count2 += sym->getRetainCount();
433 sym->release();
434 }
435 TEST_ASSERT('S', "4d", count == numStrCache);
436 TEST_ASSERT('S', "4e", count2 == numStrCache * 2);
437
438 set2 = OSSet::withSet(set1, 2 * set1->getCount());
439 }
440 TEST_ASSERT('S', "4f", set2);
441 if (set2) {
442 set2->setObject(set1);
443 TEST_ASSERT('S', "4g", set1->getCount() == set2->getCount());
444 set1->release();
445 set2->release();
446 }
447 res = res && checkSpace("(S)4", spaceCheck, 0);
448
449 // Test array duplicate removal
450 spaceCheck = checkPointSpace();
451 array = OSArray::withCapacity(numStrCache);
452 for (i = 0; i < numStrCache; i++) {
453 sym = (OSObject *) OSSymbol::withCStringNoCopy(strCache[i]);
454 count += array->setObject(sym);
455 sym->release();
456 }
457 set1 = OSSet::withArray(array, numStrCache);
458 TEST_ASSERT('S', "5a", set1);
459 if (set1) {
460 TEST_ASSERT('S', "5b", array->getCount() != set1->getCount());
461 array->release();
462
463 count = count2 = set1->getCount();
464 while ( (sym = set1->getAnyObject()) ) {
465 count -= set1->__takeObject(sym);
466 count2 -= sym->getRetainCount();
467 sym->release();
468 }
469 TEST_ASSERT('S', "5c", !count);
470 TEST_ASSERT('S', "5d", !count2);
471 set1->release();
472 }
473 res = res && checkSpace("(S)5", spaceCheck, 0);
474
475 if (res)
476 verPrintf(("testSet: All OSSet Tests passed\n"));
477 else
478 logPrintf(("testSet: Some OSSet Tests failed\n"));
479 }
480
481 void testDictionary()
482 {
483 bool res = true;
484 void *spaceCheck, *spaceCheck2, *spaceCheck3;
485 OSObject *cache[numStrCache];
486 OSString *str;
487 const OSSymbol *symCache[numStrCache], *sym;
488 OSDictionary *dict1, *dict2;
489 int i, numSymbols, count1, count2;
490
491 // Do first test without memory leak tests to initialise the metaclass
492 dict1 = OSDictionary::withCapacity(1);
493 TEST_ASSERT('D', "0a", dict1);
494 if (dict1)
495 dict1->release();
496
497 // Grow the symbol pool to maximum
498 for (i = 0; i < numStrCache; i++)
499 symCache[i] = OSSymbol::withCStringNoCopy(strCache[i]);
500 for (i = 0; i < numStrCache; i++)
501 symCache[i]->release();
502
503 // Create and destroy a dictionary
504 spaceCheck = checkPointSpace();
505 dict1 = OSDictionary::withCapacity(1);
506 TEST_ASSERT('D', "1a", dict1);
507 if (dict1) {
508 TEST_ASSERT('D', "1b", !dict1->getCount());
509 TEST_ASSERT('D', "1c", 1 == dict1->getCapacity());
510 TEST_ASSERT('D', "1d", 1 == dict1->getCapacityIncrement());
511 TEST_ASSERT('D', "1e", 4 == dict1->setCapacityIncrement(4));
512 TEST_ASSERT('D', "1f", 4 == dict1->getCapacityIncrement());
513 TEST_ASSERT('D', "1g", 8 == dict1->ensureCapacity(5));
514
515 spaceCheck2 = checkPointSpace();
516 sym = OSSymbol::withCStringNoCopy(strCache[0]);
517
518 spaceCheck3 = checkPointSpace();
519 TEST_ASSERT('D', "1h", dict1->setObject((OSObject *) sym, sym));
520 TEST_ASSERT('D', "1i", (OSObject *) sym == dict1->getObject(sym));
521 sym->release();
522 TEST_ASSERT('D', "1i", 2 == sym->getRetainCount());
523 res = res && checkSpace("(D)1j", spaceCheck3, 0);
524
525 TEST_ASSERT('D', "1k", 1 == dict1->getCount());
526 dict1->flushCollection();
527 TEST_ASSERT('D', "1l", !dict1->getCount());
528 res = res && checkSpace("(D)1m", spaceCheck2, 0);
529
530 dict1->release();
531 }
532 res = res && checkSpace("(D)1", spaceCheck, 0);
533
534 // Check the creation of a sizable OSDictionary from an array of IOObjects
535 // Also check indexing into the array.
536 spaceCheck = checkPointSpace();
537 for (i = 0, numSymbols = 0; i < numStrCache; i++) {
538 sym = OSSymbol::withCStringNoCopy(strCache[i]);
539 if (1 == sym->getRetainCount())
540 symCache[numSymbols++] = sym;
541 else
542 sym->release();
543 }
544 dict1 = OSDictionary::withObjects(
545 (OSObject **) symCache, symCache, numSymbols, numSymbols);
546 TEST_ASSERT('D', "2a", dict1);
547 count1 = count2 = 0;
548 for (i = 0; i < numSymbols; i++)
549 count1 += (symCache[i]->getRetainCount() == 3);
550 TEST_ASSERT('D', "2b", count1 == numSymbols);
551 if (dict1) {
552 TEST_ASSERT('D', "2c", numSymbols == (int) dict1->getCount());
553 TEST_ASSERT('D', "2d", numSymbols == (int) dict1->getCapacity());
554 TEST_ASSERT('D', "2e",
555 numSymbols == (int) dict1->getCapacityIncrement());
556
557 for (i = dict1->getCount(); --i >= 0; ) {
558 str = (OSString *) dict1->getObject(symCache[i]);
559 if (str != (OSString *) symCache[i]) {
560 verPrintf(("testDictionary(D) test 2f%d failed\n", i));
561 res = false;
562 }
563 }
564 dict1->release();
565 }
566 count1 = count2 = 0;
567 for (i = 0; i < numSymbols; i++) {
568 count1 += (symCache[i]->getRetainCount() == 1);
569 symCache[i]->release();
570 }
571 TEST_ASSERT('D', "2g", count1 == numSymbols);
572 res = res && checkSpace("(D)2", spaceCheck, 0);
573
574 // Check the creation of a sizable Dictionary from an array of IOStrings
575 // Also check searching dictionary use OSString for a key.
576 spaceCheck = checkPointSpace();
577 for (i = 0, numSymbols = 0; i < numStrCache; i++) {
578 sym = OSSymbol::withCStringNoCopy(strCache[i]);
579 if (1 == sym->getRetainCount()) {
580 cache[numSymbols] = OSString::withCStringNoCopy(strCache[i]);
581 symCache[numSymbols] = sym;
582 numSymbols++;
583 }
584 else
585 sym->release();
586 }
587 dict1 = OSDictionary::withObjects((OSObject **) symCache,
588 (OSString **) cache,
589 numSymbols, numSymbols);
590 TEST_ASSERT('D', "3a", dict1);
591 count1 = count2 = 0;
592 for (i = 0; i < numSymbols; i++) {
593 count1 += (symCache[i]->getRetainCount() == 3);
594 count2 += (cache[i]->getRetainCount() == 1);
595 }
596 TEST_ASSERT('D', "3b", count1 == numSymbols);
597 TEST_ASSERT('D', "3c", count2 == numSymbols);
598 if (dict1) {
599 count1 = count2 = 0;
600 for (i = 0; i < numSymbols; i++) {
601 str = (OSString *) cache[i];
602 count1 += (symCache[i] == (const OSSymbol *) dict1->getObject(str));
603 count2 += (symCache[i]->getRetainCount() == 3);
604 }
605 TEST_ASSERT('D', "3d", count1 == numSymbols);
606 TEST_ASSERT('D', "3e", count2 == numSymbols);
607
608 count1 = count2 = 0;
609 for (i = 0; i < numSymbols; i++) {
610 const char *cStr = ((OSString *) cache[i])->getCStringNoCopy();
611
612 count1 += (symCache[i] == (const OSSymbol *) dict1->getObject(cStr));
613 count2 += (symCache[i]->getRetainCount() == 3);
614 }
615 TEST_ASSERT('D', "3f", count1 == numSymbols);
616 TEST_ASSERT('D', "3g", count2 == numSymbols);
617
618 dict1->release();
619 }
620 count1 = count2 = 0;
621 for (i = 0; i < numSymbols; i++) {
622 count1 += (symCache[i]->getRetainCount() == 1);
623 count2 += (cache[i]->getRetainCount() == 1);
624 symCache[i]->release();
625 cache[i]->release();
626 }
627 TEST_ASSERT('D', "3h", count1 == numSymbols);
628 res = res && checkSpace("(D)3", spaceCheck, 0);
629
630 // Check the creation of a small dictionary then grow it one item at a time
631 // Create a new dictionary from the old dictionary.
632 // Finally remove each item permanently.
633 spaceCheck = checkPointSpace();
634 for (i = 0, numSymbols = 0; i < numStrCache; i++) {
635 sym = OSSymbol::withCStringNoCopy(strCache[i]);
636 if (1 == sym->getRetainCount()) {
637 cache[numSymbols] = OSString::withCStringNoCopy(strCache[i]);
638 symCache[numSymbols] = sym;
639 numSymbols++;
640 }
641 else
642 sym->release();
643 }
644 dict2 = 0;
645 dict1 = OSDictionary::withCapacity(1);
646 TEST_ASSERT('D', "4a", dict1);
647 if (dict1) {
648 count1 = count2 = 0;
649 for (i = 0; i < numSymbols; i++) {
650 sym = symCache[i];
651 count1 += ((OSObject *) sym == dict1->setObject((OSObject *) sym,
652 sym->getCStringNoCopy()));
653 count2 += (sym->getRetainCount() == 3);
654 }
655 TEST_ASSERT('D', "4b", numSymbols == (int) dict1->getCount());
656 TEST_ASSERT('D', "4c", numSymbols == count1);
657 TEST_ASSERT('D', "4d", numSymbols == count2);
658
659 dict2 = OSDictionary::withDictionary(dict1, numSymbols-1);
660 TEST_ASSERT('D', "4b", !dict2);
661 dict2 = OSDictionary::withDictionary(dict1, numSymbols);
662 }
663 TEST_ASSERT('D', "4e", dict2);
664 if (dict2) {
665 dict1->release(); dict1 = 0;
666
667 TEST_ASSERT('D', "4f", numSymbols == (int) dict2->getCount());
668
669 count1 = count2 = 0;
670 for (i = 0; i < numSymbols; i++) {
671 OSObject *replacedObject;
672
673 sym = symCache[i];
674 str = (OSString *) cache[i];
675 replacedObject = dict2->setObject(str, str);
676 count1 += ((OSString *) sym == replacedObject);
677 replacedObject->release();
678 count2 += (sym->getRetainCount() == 2);
679 str->release();
680 }
681 TEST_ASSERT('D', "4g", numSymbols == count1);
682 TEST_ASSERT('D', "4h", numSymbols == count2);
683
684 count1 = count2 = 0;
685 for (i = 0; i < numSymbols; i++) {
686 sym = symCache[i];
687 str = (OSString *) cache[i];
688 count1 += (str == dict2->__takeObject(sym));
689 str->release();
690 count2 += (sym->getRetainCount() == 1);
691 sym->release();
692 }
693 TEST_ASSERT('D', "4i", numSymbols == count1);
694 TEST_ASSERT('D', "4j", numSymbols == count2);
695 TEST_ASSERT('D', "4k", !dict2->getCount());
696 dict2->release(); dict2 = 0;
697 }
698 else if (dict1)
699 dict1->release();
700 res = res && checkSpace("(D)4", spaceCheck, 0);
701
702 if (res)
703 verPrintf(("testDictionary: All OSDictionary Tests passed\n"));
704 else
705 logPrintf(("testDictionary: Some OSDictionary Tests failed\n"));
706 }
707
708 void testIterator()
709 {
710 bool res = true;
711 void *spaceCheck;
712 OSObject *cache[numStrCache];
713 OSString *str = 0;
714 const OSSymbol *symCache[numStrCache], *sym;
715 OSDictionary *dict;
716 OSSet *set;
717 OSArray *array, *bigReturn;
718 OSCollectionIterator *iter1, *iter2;
719 int i, numSymbols, count1, count2, count3;
720
721 // Setup symbol and string pools
722 for (i = 0, numSymbols = 0; i < numStrCache; i++) {
723 sym = OSSymbol::withCStringNoCopy(strCache[i]);
724 if (1 == sym->getRetainCount()) {
725 cache[numSymbols] = OSString::withCStringNoCopy(strCache[i]);
726 symCache[numSymbols] = sym;
727 numSymbols++;
728 }
729 else
730 sym->release();
731 }
732
733 // Test the array iterator
734 spaceCheck = checkPointSpace();
735 iter1 = iter2 = 0;
736 array = OSArray::withCapacity(numSymbols);
737 TEST_ASSERT('I', "1a", array);
738 if (array) {
739 count1 = count2 = 0;
740 for (i = numSymbols; --i >= 0; )
741 count1 += array->setObject(cache[i], 0);
742 TEST_ASSERT('I', "1b", count1 == numSymbols);
743
744 iter1 = OSCollectionIterator::withCollection(array);
745 iter2 = OSCollectionIterator::withCollection(array);
746 }
747 TEST_ASSERT('I', "1c", iter1);
748 TEST_ASSERT('I', "1d", iter2);
749 if (iter1 && iter2) {
750 count1 = count2 = count3 = 0;
751 for (i = 0; (str = (IOString *) iter1->getNextObject()); i++) {
752 bigReturn = iter2->nextEntries();
753 count1 += (bigReturn->getCount() == 1);
754 count2 += (cache[i] == bigReturn->getObject(0));
755 count3 += (cache[i] == str);
756 }
757 TEST_ASSERT('I', "1e", count1 == numSymbols);
758 TEST_ASSERT('I', "1f", count2 == numSymbols);
759 TEST_ASSERT('I', "1g", count3 == numSymbols);
760 TEST_ASSERT('I', "1h", iter1->valid());
761 TEST_ASSERT('I', "1i", iter2->valid());
762
763 iter1->reset();
764 str = (OSString *) array->__takeObject(0);
765 array->setObject(str, 0);
766 str->release();
767 TEST_ASSERT('I', "1j", !iter1->getNextObject());
768 TEST_ASSERT('I', "1k", !iter1->valid());
769
770 iter1->reset();
771 count1 = count2 = count3 = 0;
772 for (i = 0; ; i++) {
773 if (i & 1)
774 str = (OSString *) iter1->getNextObject();
775 else if ( (bigReturn = iter1->nextEntries()) )
776 str = (OSString *) bigReturn->getObject(0);
777 else
778 str = 0;
779
780 if (!str)
781 break;
782 count1 += (cache[i] == str);
783 }
784 TEST_ASSERT('I', "1l", count1 == numSymbols);
785 TEST_ASSERT('I', "1m", i == numSymbols);
786 TEST_ASSERT('I', "1n", iter1->valid());
787
788 TEST_ASSERT('I', "1o", 3 == array->getRetainCount());
789 array->release();
790 }
791
792 if (iter1) iter1->release();
793 if (iter2) iter2->release();
794 res = res && checkSpace("(I)1", spaceCheck, 0);
795
796 // Test the set iterator
797 spaceCheck = checkPointSpace();
798 iter1 = 0;
799 set = OSSet::withCapacity(numSymbols);
800 TEST_ASSERT('I', "2a", set);
801 if (set) {
802 count1 = count2 = 0;
803 for (i = 0; i < numSymbols; i++)
804 count1 += set->setObject(cache[i]);
805 TEST_ASSERT('I', "2b", count1 == numSymbols);
806
807 iter1 = OSCollectionIterator::withCollection(set);
808 iter2 = OSCollectionIterator::withCollection(set);
809 }
810 TEST_ASSERT('I', "2c", iter1);
811 TEST_ASSERT('I', "2d", iter2);
812 if (iter1 && iter2) {
813 count1 = count2 = count3 = 0;
814 for (i = 0; (str = (IOString *) iter1->getNextObject()); i++) {
815 bigReturn = iter2->nextEntries();
816 count1 += (bigReturn->getCount() == 1);
817 count2 += (cache[i] == bigReturn->getObject(0));
818 count3 += (cache[i] == str);
819 }
820 TEST_ASSERT('I', "2e", count1 == numSymbols);
821 TEST_ASSERT('I', "2f", count2 == numSymbols);
822 TEST_ASSERT('I', "2g", count3 == numSymbols);
823 TEST_ASSERT('I', "2h", iter1->valid());
824 TEST_ASSERT('I', "2i", iter2->valid());
825
826 iter1->reset();
827 count1 = count2 = count3 = 0;
828 for (i = 0; ; i++) {
829 if (i & 1)
830 str = (OSString *) iter1->getNextObject();
831 else if ( (bigReturn = iter1->nextEntries()) )
832 str = (OSString *) bigReturn->getObject(0);
833 else
834 str = 0;
835
836 if (!str)
837 break;
838 count1 += (cache[i] == str);
839 }
840 TEST_ASSERT('I', "2l", count1 == numSymbols);
841 TEST_ASSERT('I', "2m", i == numSymbols);
842 TEST_ASSERT('I', "2n", iter1->valid());
843
844 iter1->reset();
845 str = (OSString *) set->getAnyObject();
846 (void) set->__takeObject(str);
847 set->setObject(str);
848 str->release();
849 TEST_ASSERT('I', "2j", !iter1->getNextObject());
850 TEST_ASSERT('I', "2k", !iter1->valid());
851
852 TEST_ASSERT('I', "2o", 3 == set->getRetainCount());
853 set->release();
854 }
855
856 if (iter1) iter1->release();
857 if (iter2) iter2->release();
858 res = res && checkSpace("(I)2", spaceCheck, 0);
859
860 // Test the dictionary iterator
861 spaceCheck = checkPointSpace();
862 iter1 = 0;
863 dict = OSDictionary::withCapacity(numSymbols);
864 TEST_ASSERT('I', "3a", dict);
865 if (dict) {
866 count1 = count2 = 0;
867 for (i = 0; i < numSymbols; i++)
868 count1 += (0 != dict->setObject(cache[i], symCache[i]));
869 TEST_ASSERT('I', "3b", count1 == numSymbols);
870
871 iter1 = OSCollectionIterator::withCollection(dict);
872 iter2 = OSCollectionIterator::withCollection(dict);
873 }
874 TEST_ASSERT('I', "3c", iter1);
875 TEST_ASSERT('I', "3d", iter2);
876 if (iter1 && iter2) {
877 count1 = count2 = count3 = 0;
878 for (i = 0; (sym = (const IOSymbol *) iter1->getNextObject()); i++) {
879 bigReturn = iter2->nextEntries();
880 count1 += (bigReturn->getCount() == 2);
881 count2 += (cache[i] == bigReturn->getObject(1));
882 count3 += (symCache[i] == sym);
883 }
884 TEST_ASSERT('I', "3e", count1 == numSymbols);
885 TEST_ASSERT('I', "3f", count2 == numSymbols);
886 TEST_ASSERT('I', "3g", count3 == numSymbols);
887 TEST_ASSERT('I', "3h", iter1->valid());
888 TEST_ASSERT('I', "3i", iter2->valid());
889
890 iter1->reset();
891 count1 = count2 = count3 = 0;
892 i = 0;
893 for (i = 0; ; i++) {
894 if (i & 1) {
895 sym = (const OSSymbol *) iter1->getNextObject();
896 str = 0;
897 }
898 else if ( (bigReturn = iter1->nextEntries()) ) {
899 sym = (const OSSymbol *) bigReturn->getObject(0);
900 str = (OSString *) bigReturn->getObject(1);
901 }
902 else
903 sym = 0;
904
905 if (!sym)
906 break;
907
908 count1 += (symCache[i] == sym);
909 count2 += (!str || cache[i] == str);
910 }
911 TEST_ASSERT('I', "3l", count1 == numSymbols);
912 TEST_ASSERT('I', "3m", count2 == numSymbols);
913 TEST_ASSERT('I', "3n", i == numSymbols);
914 TEST_ASSERT('I', "3o", iter1->valid());
915
916 iter1->reset();
917 str = (OSString *) dict->__takeObject(symCache[numSymbols-1]);
918 dict->setObject(str, symCache[numSymbols-1]);
919 str->release();
920 TEST_ASSERT('I', "3j", !iter1->getNextObject());
921 TEST_ASSERT('I', "3k", !iter1->valid());
922
923 TEST_ASSERT('I', "3p", 3 == dict->getRetainCount());
924 dict->release();
925 }
926
927 if (iter1) iter1->release();
928 if (iter2) iter2->release();
929 res = res && checkSpace("(I)3", spaceCheck, 0);
930
931 count1 = count2 = count3 = 0;
932 for (i = 0; i < numSymbols; i++) {
933 count1 += (1 == cache[i]->getRetainCount());
934 count2 += (1 == symCache[i]->getRetainCount());
935 cache[i]->release();
936 symCache[i]->release();
937 }
938 TEST_ASSERT('I', "4a", count1 == numSymbols);
939 TEST_ASSERT('I', "4b", count2 == numSymbols);
940
941 if (res)
942 verPrintf(("testIterator: All OSCollectionIterator Tests passed\n"));
943 else
944 logPrintf(("testIterator: Some OSCollectionIterator Tests failed\n"));
945 }
946
947 #endif /* DEBUG */