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