1/* 2 * Copyright (c) 2011 Apple Inc. All rights reserved. 3 * 4 * @APPLE_APACHE_LICENSE_HEADER_START@ 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * @APPLE_APACHE_LICENSE_HEADER_END@ 19 */ 20// 21// cfdata.m 22// Copyright (c) 2008-2001 Apple. All rights reserved. 23// 24 25 26#import <CoreFoundation/CFData.h> 27#import "BlackBoxTest.h" 28 29@interface _CFDataTestObject : NSObject { 30 __strong CFDataRef subject; 31 __strong CFMutableDataRef mutableSubject; 32 33 __strong CFDataRef subjectCopy; 34 __strong CFMutableDataRef mutableSubjectCopy; 35 36 __strong CFMutableDataRef subjectMutableCopy; 37 __strong CFMutableDataRef mutableSubjectMutableCopy; 38 39} 40 41- init; 42 43@end 44 45@interface _CFDataTestTestObject : _CFDataTestObject { 46 bool shouldDealloc; 47 __strong void *backingData; 48} 49@end 50 51 52@implementation _CFDataTestObject 53- (void) makeCopies { 54 CFIndex size = 32*sizeof(void *); 55 subjectCopy = CFDataCreateCopy(NULL, subject); 56 mutableSubjectCopy = CFDataCreateMutableCopy(NULL, size, mutableSubject); 57 58 subjectMutableCopy = CFDataCreateMutableCopy(NULL, size, subject); 59 mutableSubjectMutableCopy = CFDataCreateMutableCopy(NULL, size, mutableSubject); 60} 61 62- (void)makeCollectable { 63 CFMakeCollectable(subjectCopy); 64 CFMakeCollectable(mutableSubjectCopy); 65 CFMakeCollectable(subjectMutableCopy); 66 CFMakeCollectable(mutableSubjectMutableCopy); 67 CFMakeCollectable(subject); 68 CFMakeCollectable(mutableSubject); 69} 70 71- (void)grow { 72 CFIndex size = 32*sizeof(void *); 73 CFDataSetLength(mutableSubjectCopy, 2*size); 74 CFDataSetLength(subjectMutableCopy, 2*size); 75 CFDataSetLength(mutableSubjectMutableCopy, 2*size); 76 CFDataSetLength(mutableSubject, 2*size); 77} 78 79- (void)dealloc { 80 CFRelease(subjectCopy); 81 CFRelease(mutableSubjectCopy); 82 CFRelease(subjectMutableCopy); 83 CFRelease(mutableSubjectMutableCopy); 84 CFRelease(subject); 85 CFRelease(mutableSubject); 86 [super dealloc]; 87} 88 89- init { 90 id buffer[32]; 91 for (int i = 0; i < 32; ++i) 92 buffer[i] = self; 93 CFIndex size = sizeof(void *)*32; 94 if (!subject) subject = CFDataCreate(NULL, (uint8_t *)buffer, size); 95 mutableSubject = CFDataCreateMutable(NULL, size); 96 const UInt8 *bytes = CFDataGetBytePtr((CFMutableDataRef)mutableSubject); 97 memcpy((void *)bytes, buffer, size); 98 99 [self makeCopies]; 100 [self makeCollectable]; 101 [self grow]; 102 return self; 103} 104 105 106static bool allSame(void *value, void **items, int nitems) { 107 for (int i = 0; i < nitems; ++i) 108 if (items[i] != value) return false; 109 return true; 110} 111 112- (void)test { 113 bool result = true; 114 CFIndex count = CFDataGetLength(subject)/sizeof(void *); 115 result = result && allSame(self, (void **)CFDataGetBytePtr(subject), count); 116 result = result && allSame(self, (void **)CFDataGetBytePtr(mutableSubject), count); 117 result = result && allSame(self, (void **)CFDataGetBytePtr(subjectCopy), count); 118 result = result && allSame(self, (void **)CFDataGetBytePtr(mutableSubjectCopy), count); 119 result = result && allSame(self, (void **)CFDataGetBytePtr(subjectMutableCopy), count); 120 result = result && allSame(self, (void **)CFDataGetBytePtr(mutableSubjectMutableCopy), count); 121 if (!result) { 122 [[TestCase currentTestCase] fail:@"data changed!"]; 123 } 124} 125 126@end 127 128@implementation _CFDataTestTestObject 129 130- (void)allocateBacking:(CFIndex)size { 131 backingData = malloc_zone_malloc((malloc_zone_t*)NSDefaultMallocZone(), size); 132} 133 134- init { 135 id buffer[32]; 136 for (int i = 0; i < 32; ++i) 137 buffer[i] = self; 138 CFIndex size = sizeof(void *)*32; 139 [self allocateBacking:size]; 140 141 memcpy(backingData, buffer, size); 142 subject = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*)backingData, size, NULL); 143 //if ([NSGarbageCollector defaultCollector]) printf("backing data %p held by %p\n", backingData, subject); 144 return [super init]; 145} 146- initExplicit { 147 id buffer[32]; 148 for (int i = 0; i < 32; ++i) 149 buffer[i] = self; 150 CFIndex size = sizeof(void *)*32; 151 [self allocateBacking:size]; 152 memcpy(backingData, buffer, size); 153 // explicitly use kCFAllocatorDefault 154 subject = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*)backingData, size, kCFAllocatorDefault); 155 //if ([NSGarbageCollector defaultCollector]) printf("backing data %p held by %p\n", backingData, subject); 156 return [super init]; 157} 158- initOwned { 159 id buffer[32]; 160 for (int i = 0; i < 32; ++i) 161 buffer[i] = self; 162 CFIndex size = sizeof(void *)*32; 163 [self allocateBacking:size]; 164 memcpy(backingData, buffer, size); 165 // explicitly use kCFAllocatorNull to say that the memory is owned elsewhere 166 subject = CFDataCreateWithBytesNoCopy(NULL, (const UInt8*)backingData, size, kCFAllocatorNull); 167 shouldDealloc = true; 168 //if ([NSGarbageCollector defaultCollector]) printf("backing data %p held by %p, will dealloc\n", backingData, subject); 169 return [super init]; 170} 171- (void) dealloc { 172 if (shouldDealloc) free(backingData); 173 [super dealloc]; 174} 175- (void) finalize { 176 if (shouldDealloc) free(backingData); 177 [super finalize]; 178} 179@end 180 181#define LOOPS 10 182 183@interface CFDataTest : BlackBoxTest 184@end 185 186@implementation CFDataTest 187 188- (void)testLoop 189{ 190 NSMutableArray *array = [[NSMutableArray alloc] init]; 191 192 for (int i = 0; i < LOOPS; ++i) { 193 _CFDataTestObject *to = [[_CFDataTestObject alloc] init]; 194 [array addObject:to]; 195 [to release]; 196 } 197 for (int i = 0; i < LOOPS; ++i) { 198 _CFDataTestTestObject *to = [[_CFDataTestTestObject alloc] init]; 199 [array addObject:to]; 200 [to release]; 201 } 202 203 for (int i = 0; i < LOOPS; ++i) { 204 _CFDataTestTestObject *to = [[_CFDataTestTestObject alloc] initExplicit]; 205 [array addObject:to]; 206 [to release]; 207 } 208 209 for (int i = 0; i < LOOPS; ++i) { 210 _CFDataTestTestObject *to = [[_CFDataTestTestObject alloc] initOwned]; 211 [array addObject:to]; 212 [to release]; 213 } 214 215 [array release]; 216} 217 218- (void)performTest { 219 for (int i = 0; i < (1+LOOPS); ++i) { // just enough for GC to not find things on the stack 220 [self testLoop]; 221 } 222 [self clearStack]; 223 [self requestFullCollectionWithCompletionCallback:^{ 224 [self passed]; 225 [self testFinished]; 226 }]; 227} 228 229@end