/core/externals/google-toolbox-for-mac/AddressBook/GTMABAddressBookTest.m
Objective C | 695 lines | 552 code | 69 blank | 74 comment | 30 complexity | b8098fd9faf5c8bdc7712b2871acda5d MD5 | raw file
1// 2// GTMAddressBookTest.m 3// 4// Copyright 2008 Google Inc. 5// 6// Licensed under the Apache License, Version 2.0 (the "License"); you may not 7// use this file except in compliance with the License. You may obtain a copy 8// 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, WITHOUT 14// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15// License for the specific language governing permissions and limitations under 16// the License. 17// 18 19#import "GTMSenTestCase.h" 20#import "GTMABAddressBook.h" 21 22#if GTM_IPHONE_SDK 23#import "UIKit/UIKit.h" 24#else 25#import <AppKit/AppKit.h> 26#endif // GTM_IPHONE_SDK 27 28static NSString *const kGTMABTestFirstName = @"GTMABAddressBookTestFirstName"; 29static NSString *const kGTMABTestLastName = @"GTMABAddressBookTestLastName"; 30static NSString *const kGTMABTestGroupName = @"GTMABAddressBookTestGroupName"; 31 32@interface GTMABAddressBookTest : GTMTestCase { 33 @private 34 GTMABAddressBook *book_; 35} 36@end 37 38 39@implementation GTMABAddressBookTest 40- (void)setUp { 41 // Create a book forcing it out of it's autorelease pool. 42 // I force it out of the release pool, so that we will see any errors 43 // for it immediately at teardown, and it will be clear which release 44 // caused us problems. 45 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 46 book_ = [[GTMABAddressBook addressBook] retain]; 47 [pool release]; 48 STAssertNotNil(book_, nil); 49 NSArray *people 50 = [book_ peopleWithCompositeNameWithPrefix:kGTMABTestFirstName]; 51 GTMABPerson *person; 52 GTM_FOREACH_OBJECT(person, people) { 53 [book_ removeRecord:person]; 54 } 55 NSArray *groups 56 = [book_ groupsWithCompositeNameWithPrefix:kGTMABTestGroupName]; 57 GTMABGroup *group; 58 GTM_FOREACH_OBJECT(group, groups) { 59 [book_ removeRecord:group]; 60 } 61 [book_ save]; 62} 63 64- (void)tearDown { 65 [book_ release]; 66} 67 68- (void)testGenericAddressBook { 69 STAssertEqualObjects([GTMABAddressBook localizedLabel:(NSString *)kABHomeLabel], 70 @"home", 71 nil); 72 STAssertThrows([GTMABRecord recordWithRecord:nil], nil); 73} 74 75- (void)testAddingAndRemovingPerson { 76 // Create a person 77 GTMABPerson *person = [GTMABPerson personWithFirstName:kGTMABTestFirstName 78 lastName:kGTMABTestLastName]; 79 STAssertNotNil(person, nil); 80 81 // Add person 82 NSArray *people = [book_ people]; 83 STAssertFalse([people containsObject:person], nil); 84 STAssertTrue([book_ addRecord:person], nil); 85#if GTM_IPHONE_SDK && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2) 86 // Normally this next line would be STAssertTrue, however due to 87 // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work 88 // We will check to make sure it stays broken ;-) 89 STAssertFalse([book_ hasUnsavedChanges], nil); 90#else // GTM_IPHONE_SDK 91 STAssertTrue([book_ hasUnsavedChanges], nil); 92#endif // GTM_IPHONE_SDK 93 94 people = [book_ people]; 95 STAssertNotNil(people, nil); 96#if GTM_IPHONE_SDK 97 // Normally this next line would be STAssertTrue, however due to 98 // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people 99 // array until it's saved 100 // We will check to make sure it stays broken ;-) 101 STAssertFalse([people containsObject:person], nil); 102#else // GTM_IPHONE_SDK 103 STAssertTrue([people containsObject:person], nil); 104#endif // GTM_IPHONE_SDK 105 106 // Save book_ 107 STAssertTrue([book_ save], nil); 108 people = [book_ people]; 109 STAssertNotNil(people, nil); 110 STAssertTrue([people containsObject:person], nil); 111 people = [book_ peopleWithCompositeNameWithPrefix:kGTMABTestFirstName]; 112 STAssertEqualObjects([people objectAtIndex:0], person, nil); 113 114 GTMABRecordID recordID = [person recordID]; 115 STAssertNotEquals(recordID, kGTMABRecordInvalidID, nil); 116 117 GTMABRecord *record = [book_ personForId:recordID]; 118 STAssertEqualObjects(record, person, nil); 119 120 // Remove person 121 STAssertTrue([book_ removeRecord:person], nil); 122 people = [book_ peopleWithCompositeNameWithPrefix:kGTMABTestFirstName]; 123 STAssertEquals([people count], (NSUInteger)0, nil); 124 125#if GTM_IPHONE_SDK && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2) 126 // Normally this next line would be STAssertTrue, however due to 127 // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work 128 // We will check to make sure it stays broken ;-) 129 STAssertFalse([book_ hasUnsavedChanges], nil); 130#else // GTM_IPHONE_SDK 131 STAssertTrue([book_ hasUnsavedChanges], nil); 132#endif // GTM_IPHONE_SDK 133 people = [book_ people]; 134 STAssertFalse([people containsObject:person], nil); 135 136 // Save Book 137 STAssertTrue([book_ save], nil); 138 people = [book_ people]; 139 STAssertFalse([book_ hasUnsavedChanges], nil); 140 STAssertFalse([people containsObject:person], nil); 141 record = [book_ personForId:recordID]; 142 STAssertNil(record, nil); 143 144 // Bogus data 145 STAssertFalse([book_ addRecord:nil], nil); 146 STAssertFalse([book_ removeRecord:nil], nil); 147 148 STAssertNotNULL([book_ addressBookRef], nil); 149 150} 151 152- (void)testAddingAndRemovingGroup { 153 // Create a group 154 GTMABGroup *group = [GTMABGroup groupNamed:kGTMABTestGroupName]; 155 STAssertNotNil(group, nil); 156 157 // Add group 158 NSArray *groups = [book_ groups]; 159 STAssertFalse([groups containsObject:group], nil); 160 STAssertTrue([book_ addRecord:group], nil); 161#if GTM_IPHONE_SDK && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2) 162 // Normally this next line would be STAssertTrue, however due to 163 // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work 164 // We will check to make sure it stays broken ;-) 165 STAssertFalse([book_ hasUnsavedChanges], nil); 166#else // GTM_IPHONE_SDK 167 STAssertTrue([book_ hasUnsavedChanges], nil); 168#endif // GTM_IPHONE_SDK 169 170 groups = [book_ groups]; 171 STAssertNotNil(groups, nil); 172#if GTM_IPHONE_SDK 173 // Normally this next line would be STAssertTrue, however due to 174 // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups 175 // array until it's saved 176 // We will check to make sure it stays broken ;-) 177 STAssertFalse([groups containsObject:group], nil); 178#else // GTM_IPHONE_SDK 179 STAssertTrue([groups containsObject:group], nil); 180#endif // GTM_IPHONE_SDK 181 182 // Save book_ 183 STAssertTrue([book_ save], nil); 184 groups = [book_ groups]; 185 STAssertNotNil(groups, nil); 186 STAssertTrue([groups containsObject:group], nil); 187 groups = [book_ groupsWithCompositeNameWithPrefix:kGTMABTestGroupName]; 188 STAssertEqualObjects([groups objectAtIndex:0], group, nil); 189 190 GTMABRecordID recordID = [group recordID]; 191 STAssertNotEquals(recordID, kGTMABRecordInvalidID, nil); 192 193 GTMABRecord *record = [book_ groupForId:recordID]; 194 STAssertEqualObjects(record, group, nil); 195 196 // Remove group 197 STAssertTrue([book_ removeRecord:group], nil); 198 199#if GTM_IPHONE_SDK && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2) 200 // Normally this next line would be STAssertTrue, however due to 201 // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work 202 // We will check to make sure it stays broken ;-) 203 STAssertFalse([book_ hasUnsavedChanges], nil); 204#else // GTM_IPHONE_SDK 205 STAssertTrue([book_ hasUnsavedChanges], nil); 206#endif // GTM_IPHONE_SDK 207 groups = [book_ groups]; 208 STAssertFalse([groups containsObject:group], nil); 209 210 // Save Book 211 STAssertTrue([book_ save], nil); 212 groups = [book_ groups]; 213 STAssertFalse([book_ hasUnsavedChanges], nil); 214 STAssertFalse([groups containsObject:group], nil); 215 groups = [book_ groupsWithCompositeNameWithPrefix:kGTMABTestGroupName]; 216 STAssertEquals([groups count], (NSUInteger)0, nil); 217 record = [book_ groupForId:recordID]; 218 STAssertNil(record, nil); 219} 220 221- (void)testPerson { 222 GTMABPerson *person = [[[GTMABPerson alloc] initWithRecord:nil] autorelease]; 223 STAssertNil(person, nil); 224 person = [GTMABPerson personWithFirstName:kGTMABTestFirstName 225 lastName:nil]; 226 STAssertNotNil(person, nil); 227 STAssertEqualObjects([person compositeName], kGTMABTestFirstName, nil); 228 NSString *firstName = [person valueForProperty:kGTMABPersonFirstNameProperty]; 229 STAssertEqualObjects(firstName, kGTMABTestFirstName, nil); 230 NSString *lastName = [person valueForProperty:kGTMABPersonLastNameProperty]; 231 STAssertNil(lastName, nil); 232 STAssertTrue([person removeValueForProperty:kGTMABPersonFirstNameProperty], nil); 233 STAssertFalse([person removeValueForProperty:kGTMABPersonFirstNameProperty], nil); 234 STAssertFalse([person removeValueForProperty:kGTMABPersonLastNameProperty], nil); 235 STAssertFalse([person setValue:nil forProperty:kGTMABPersonFirstNameProperty], nil); 236 STAssertFalse([person setValue:[NSNumber numberWithInt:1] 237 forProperty:kGTMABPersonFirstNameProperty], nil); 238 STAssertFalse([person setValue:@"Bart" 239 forProperty:kGTMABPersonBirthdayProperty], nil); 240 241 GTMABPropertyType property 242 = [GTMABPerson typeOfProperty:kGTMABPersonLastNameProperty]; 243 STAssertEquals(property, (GTMABPropertyType)kGTMABStringPropertyType, nil); 244 245 NSString *string 246 = [GTMABPerson localizedPropertyName:kGTMABPersonLastNameProperty]; 247 STAssertEqualObjects(string, @"Last", nil); 248 249 string = [GTMABPerson localizedPropertyName:kGTMABRecordInvalidID]; 250#if GTM_IPHONE_SDK 251 STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); 252#else // GTM_IPHONE_SDK 253 STAssertEqualObjects(string, kGTMABRecordInvalidID, nil); 254#endif // GTM_IPHONE_SDK 255 string = [person description]; 256 STAssertNotNil(string, nil); 257 258 GTMABPersonCompositeNameFormat format = [GTMABPerson compositeNameFormat]; 259 STAssertTrue(format == kABPersonCompositeNameFormatFirstNameFirst || 260 format == kABPersonCompositeNameFormatLastNameFirst, nil); 261 262 NSData *data = [person imageData]; 263 STAssertNil(data, nil); 264 STAssertTrue([person setImageData:nil], nil); 265 data = [person imageData]; 266 STAssertNil(data, nil); 267 NSBundle *bundle = [NSBundle bundleForClass:[self class]]; 268 NSString *phonePath = [bundle pathForResource:@"phone" ofType:@"png"]; 269 STAssertNotNil(phonePath, nil); 270 GTMABImage *image 271 = [[[GTMABImage alloc] initWithContentsOfFile:phonePath] autorelease]; 272 STAssertNotNil(image, nil); 273#if GTM_IPHONE_SDK 274 data = UIImagePNGRepresentation(image); 275#else // GTM_IPHONE_SDK 276 data = [image TIFFRepresentation]; 277#endif // GTM_IPHONE_SDK 278 STAssertTrue([person setImageData:data], nil); 279 NSData *data2 = [person imageData]; 280 STAssertEqualObjects(data, data2, nil); 281 STAssertTrue([person setImageData:nil], nil); 282 data = [person imageData]; 283 STAssertNil(data, nil); 284 285 STAssertTrue([person setImage:image], nil); 286 GTMABImage *image2 = [person image]; 287 STAssertNotNil(image2, nil); 288#if GTM_IPHONE_SDK 289 STAssertEqualObjects(UIImagePNGRepresentation(image), 290 UIImagePNGRepresentation(image2), nil); 291#else // GTM_IPHONE_SDK 292 STAssertEqualObjects([image TIFFRepresentation], 293 [image2 TIFFRepresentation], nil); 294#endif // GTM_IPHONE_SDK 295 296 person = [GTMABPerson personWithFirstName:kGTMABTestFirstName 297 lastName:kGTMABTestLastName]; 298 299 data = [NSData dataWithBytes:"a" length:1]; 300 STAssertFalse([person setImageData:data], nil); 301 302 GTMABMutableMultiValue *value 303 = [GTMABMutableMultiValue valueWithPropertyType:kGTMABStringPropertyType]; 304 STAssertNotNil(value, nil); 305 STAssertNotEquals([value addValue:@"222-222-2222" 306 withLabel:(CFStringRef)kABHomeLabel], 307 kGTMABMultiValueInvalidIdentifier, nil); 308 STAssertNotEquals([value addValue:@"333-333-3333" 309 withLabel:(CFStringRef)kABWorkLabel], 310 kGTMABMultiValueInvalidIdentifier, nil); 311 STAssertTrue([person setValue:value 312 forProperty:kGTMABPersonPhoneProperty], nil); 313 id value2 = [person valueForProperty:kGTMABPersonPhoneProperty]; 314 STAssertNotNil(value2, nil); 315 STAssertEqualObjects(value, value2, nil); 316 STAssertEquals([value hash], [value2 hash], nil); 317 STAssertNotEquals([person hash], (NSUInteger)0, nil); 318} 319 320- (void)testGroup { 321 GTMABGroup *group = [[[GTMABGroup alloc] initWithRecord:nil] autorelease]; 322 STAssertNil(group, nil); 323 group = [GTMABGroup groupNamed:kGTMABTestGroupName]; 324 STAssertNotNil(group, nil); 325 STAssertEqualObjects([group compositeName], kGTMABTestGroupName, nil); 326 NSString *name = [group valueForProperty:kABGroupNameProperty]; 327 STAssertEqualObjects(name, kGTMABTestGroupName, nil); 328 NSString *lastName = [group valueForProperty:kGTMABPersonLastNameProperty]; 329 STAssertNil(lastName, nil); 330 STAssertTrue([group removeValueForProperty:kABGroupNameProperty], nil); 331 STAssertFalse([group removeValueForProperty:kABGroupNameProperty], nil); 332 STAssertFalse([group removeValueForProperty:kGTMABPersonLastNameProperty], nil); 333 STAssertFalse([group setValue:nil forProperty:kABGroupNameProperty], nil); 334 STAssertFalse([group setValue:[NSNumber numberWithInt:1] 335 forProperty:kABGroupNameProperty], nil); 336 STAssertFalse([group setValue:@"Bart" 337 forProperty:kGTMABPersonBirthdayProperty], nil); 338 339 ABPropertyType property = [GTMABGroup typeOfProperty:kABGroupNameProperty]; 340 STAssertEquals(property, (ABPropertyType)kGTMABStringPropertyType, nil); 341 342 property = [GTMABGroup typeOfProperty:kGTMABPersonLastNameProperty]; 343 STAssertEquals(property, (ABPropertyType)kGTMABInvalidPropertyType, nil); 344 345 NSString *string = [GTMABGroup localizedPropertyName:kABGroupNameProperty]; 346 STAssertEqualObjects(string, @"Name", nil); 347 348 string = [GTMABGroup localizedPropertyName:kGTMABPersonLastNameProperty]; 349 STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); 350 351 string = [GTMABGroup localizedPropertyName:kGTMABRecordInvalidID]; 352 STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); 353 354 string = [group description]; 355 STAssertNotNil(string, nil); 356 357 // Adding and removing members 358 group = [GTMABGroup groupNamed:kGTMABTestGroupName]; 359 NSArray *members = [group members]; 360 STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); 361 362 STAssertFalse([group addMember:nil], nil); 363 364 members = [group members]; 365 STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); 366 367 GTMABPerson *person = [GTMABPerson personWithFirstName:kGTMABTestFirstName 368 lastName:kGTMABTestLastName]; 369 STAssertNotNil(person, nil); 370 STAssertTrue([book_ addRecord:person], nil); 371 STAssertTrue([book_ save], nil); 372 STAssertTrue([book_ addRecord:group], nil); 373 STAssertTrue([book_ save], nil); 374 STAssertTrue([group addMember:person], nil); 375 STAssertTrue([book_ save], nil); 376 members = [group members]; 377 STAssertEquals([members count], (NSUInteger)1, @"Members: %@", members); 378 STAssertTrue([group removeMember:person], nil); 379 STAssertFalse([group removeMember:person], nil); 380 STAssertFalse([group removeMember:nil], nil); 381 STAssertTrue([book_ removeRecord:group], nil); 382 STAssertTrue([book_ removeRecord:person], nil); 383 STAssertTrue([book_ save], nil); 384} 385 386 387- (void)testMultiValues { 388 STAssertThrows([[GTMABMultiValue alloc] init], nil); 389 STAssertThrows([[GTMABMutableMultiValue alloc] init], nil); 390 GTMABMultiValue *value = [[GTMABMultiValue alloc] initWithMultiValue:nil]; 391 STAssertNil(value, nil); 392 GTMABMutableMultiValue *mutValue 393 = [GTMABMutableMultiValue valueWithPropertyType:kGTMABInvalidPropertyType]; 394 STAssertNil(mutValue, nil); 395 mutValue 396 = [[[GTMABMutableMultiValue alloc] 397 initWithMutableMultiValue:nil] autorelease]; 398 STAssertNil(mutValue, nil); 399 mutValue 400 = [[[GTMABMutableMultiValue alloc] 401 initWithMultiValue:nil] autorelease]; 402 STAssertNil(mutValue, nil); 403#if GTM_IPHONE_SDK 404 // Only the IPhone version actually allows you to check types of a multivalue 405 // before you stick anything in it 406 const GTMABPropertyType types[] = { 407 kGTMABStringPropertyType, 408 kGTMABIntegerPropertyType, 409 kGTMABRealPropertyType, 410 kGTMABDateTimePropertyType, 411 kGTMABDictionaryPropertyType, 412 kGTMABMultiStringPropertyType, 413 kGTMABMultiIntegerPropertyType, 414 kGTMABMultiRealPropertyType, 415 kGTMABMultiDateTimePropertyType, 416 kGTMABMultiDictionaryPropertyType 417 }; 418 for (size_t i = 0; i < sizeof(types) / sizeof(GTMABPropertyType); ++i) { 419 mutValue = [GTMABMutableMultiValue valueWithPropertyType:types[i]]; 420 STAssertNotNil(mutValue, nil); 421 // Oddly the Apple APIs allow you to create a mutable multi value with 422 // either a property type of kABFooPropertyType or kABMultiFooPropertyType 423 // and apparently you get back basically the same thing. However if you 424 // ask a type that you created with kABMultiFooPropertyType for it's type 425 // it returns just kABFooPropertyType. 426 STAssertEquals([mutValue propertyType], 427 (GTMABPropertyType)(types[i] & ~kABMultiValueMask), nil); 428 } 429#endif // GTM_IPHONE_SDK 430 mutValue 431 = [GTMABMutableMultiValue valueWithPropertyType:kGTMABStringPropertyType]; 432 STAssertNotNil(mutValue, nil); 433 value = [[mutValue copy] autorelease]; 434 STAssertEqualObjects([value class], [GTMABMultiValue class], nil); 435 mutValue = [[value mutableCopy] autorelease]; 436 STAssertEqualObjects([mutValue class], [GTMABMutableMultiValue class], nil); 437 STAssertEquals([mutValue count], (NSUInteger)0, nil); 438 STAssertNil([mutValue valueAtIndex:0], nil); 439 STAssertNil([mutValue labelAtIndex:0], nil); 440#if GTM_IPHONE_SDK 441 STAssertEquals([mutValue identifierAtIndex:0], 442 kGTMABMultiValueInvalidIdentifier, nil); 443 STAssertEquals([mutValue propertyType], 444 (GTMABPropertyType)kGTMABStringPropertyType, nil); 445#else // GTM_IPHONE_SDK 446 STAssertEqualObjects([mutValue identifierAtIndex:0], 447 kGTMABMultiValueInvalidIdentifier, nil); 448#endif // GTM_IPHONE_SDK 449 GTMABMultiValueIdentifier ident 450 = [mutValue addValue:nil withLabel:(CFStringRef)kABHomeLabel]; 451#if GTM_IPHONE_SDK 452 STAssertEquals(ident, kGTMABMultiValueInvalidIdentifier, nil); 453#else // GTM_IPHONE_SDK 454 STAssertEqualObjects(ident, kGTMABMultiValueInvalidIdentifier, nil); 455#endif // GTM_IPHONE_SDK 456 457 ident = [mutValue addValue:@"val1" 458 withLabel:nil]; 459#if GTM_IPHONE_SDK 460 STAssertEquals(ident, kGTMABMultiValueInvalidIdentifier, nil); 461#else // GTM_IPHONE_SDK 462 STAssertEqualObjects(ident, kGTMABMultiValueInvalidIdentifier, nil); 463#endif // GTM_IPHONE_SDK 464 ident = [mutValue insertValue:@"val1" 465 withLabel:nil 466 atIndex:0]; 467#if GTM_IPHONE_SDK 468 STAssertEquals(ident, kGTMABMultiValueInvalidIdentifier, nil); 469#else // GTM_IPHONE_SDK 470 STAssertEqualObjects(ident, kGTMABMultiValueInvalidIdentifier, nil); 471#endif // GTM_IPHONE_SDK 472 ident = [mutValue insertValue:nil 473 withLabel:(CFStringRef)kABHomeLabel 474 atIndex:0]; 475#if GTM_IPHONE_SDK 476 STAssertEquals(ident, kGTMABMultiValueInvalidIdentifier, nil); 477#else // GTM_IPHONE_SDK 478 STAssertEqualObjects(ident, kGTMABMultiValueInvalidIdentifier, nil); 479#endif // GTM_IPHONE_SDK 480 ident = [mutValue addValue:@"val1" 481 withLabel:(CFStringRef)kABHomeLabel]; 482#if GTM_IPHONE_SDK 483 STAssertNotEquals(ident, kGTMABMultiValueInvalidIdentifier, nil); 484#else // GTM_IPHONE_SDK 485 STAssertNotEqualObjects(ident, kGTMABMultiValueInvalidIdentifier, nil); 486#endif // GTM_IPHONE_SDK 487 GTMABMultiValueIdentifier identCheck = [mutValue identifierAtIndex:0]; 488#if GTM_IPHONE_SDK 489 STAssertEquals(ident, identCheck, nil); 490#else // GTM_IPHONE_SDK 491 STAssertEqualObjects(ident, identCheck, nil); 492#endif // GTM_IPHONE_SDK 493 NSUInteger idx = [mutValue indexForIdentifier:ident]; 494 STAssertEquals(idx, (NSUInteger)0, nil); 495 STAssertTrue([mutValue replaceLabelAtIndex:0 496 withLabel:(CFStringRef)kABWorkLabel], nil); 497 STAssertFalse([mutValue replaceLabelAtIndex:10 498 withLabel:(CFStringRef)kABWorkLabel], nil); 499 STAssertTrue([mutValue replaceValueAtIndex:0 500 withValue:@"newVal1"], nil); 501 STAssertFalse([mutValue replaceValueAtIndex:10 502 withValue:@"newVal1"], nil); 503 504 STAssertEqualObjects([mutValue valueForIdentifier:ident], @"newVal1", nil); 505 STAssertEqualObjects([mutValue labelForIdentifier:ident], 506 (NSString *)kABWorkLabel, nil); 507 508 GTMABMultiValueIdentifier ident2 509 = [mutValue insertValue:@"val2" 510 withLabel:(CFStringRef)kABOtherLabel 511 atIndex:0]; 512 STAssertNotEquals(ident2, kGTMABMultiValueInvalidIdentifier, nil); 513 STAssertNotEquals(ident2, ident, nil); 514 GTMABMultiValueIdentifier ident3 515 = [mutValue insertValue:@"val3" 516 withLabel:(CFStringRef)kGTMABPersonPhoneMainLabel 517 atIndex:10]; 518#if GTM_IPHONE_SDK 519 STAssertEquals(ident3, kGTMABMultiValueInvalidIdentifier, nil); 520#else // GTM_IPHONE_SDK 521 STAssertEqualObjects(ident3, kGTMABMultiValueInvalidIdentifier, nil); 522#endif // GTM_IPHONE_SDK 523 NSUInteger idx3 = [mutValue indexForIdentifier:ident3]; 524 STAssertEquals(idx3, (NSUInteger)NSNotFound, nil); 525 STAssertTrue([mutValue removeValueAndLabelAtIndex:1], nil); 526 STAssertFalse([mutValue removeValueAndLabelAtIndex:1], nil); 527 528 NSUInteger idx4 529 = [mutValue indexForIdentifier:kGTMABMultiValueInvalidIdentifier]; 530 STAssertEquals(idx4, (NSUInteger)NSNotFound, nil); 531 532 STAssertNotNULL([mutValue multiValueRef], nil); 533 534 // Enumerator test 535 mutValue 536 = [GTMABMutableMultiValue valueWithPropertyType:kGTMABIntegerPropertyType]; 537 STAssertNotNil(mutValue, nil); 538 for (int i = 0; i < 100; i++) { 539 NSString *label = [NSString stringWithFormat:@"label %d", i]; 540 NSNumber *val = [NSNumber numberWithInt:i]; 541 STAssertNotEquals([mutValue addValue:val 542 withLabel:(CFStringRef)label], 543 kGTMABMultiValueInvalidIdentifier, nil); 544 } 545 int count = 0; 546 NSString *label; 547 GTM_FOREACH_ENUMEREE(label, [mutValue labelEnumerator]) { 548 NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; 549 STAssertEqualObjects(label, testLabel, nil); 550 } 551 count = 0; 552 value = [[mutValue copy] autorelease]; 553 NSNumber *val; 554 GTM_FOREACH_ENUMEREE(val, [value valueEnumerator]) { 555 STAssertEqualObjects(val, [NSNumber numberWithInt:count++], nil); 556 } 557 558 // Test messing with the values while we're enumerating them 559 NSEnumerator *labelEnum = [mutValue labelEnumerator]; 560 NSEnumerator *valueEnum = [mutValue valueEnumerator]; 561 STAssertNotNil(labelEnum, nil); 562 STAssertNotNil(valueEnum, nil); 563 STAssertNotNil([labelEnum nextObject], nil); 564 STAssertNotNil([valueEnum nextObject], nil); 565 STAssertTrue([mutValue removeValueAndLabelAtIndex:0], nil); 566 STAssertThrows([labelEnum nextObject], nil); 567 STAssertThrows([valueEnum nextObject], nil); 568 569 // Test messing with the values while we're fast enumerating them 570 // Should throw an exception on the second access. 571 BOOL exceptionThrown = NO; 572 // Start at one because we removed index 0 above. 573 count = 1; 574 @try { 575 GTM_FOREACH_ENUMEREE(label, [mutValue labelEnumerator]) { 576 NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; 577 STAssertEqualObjects(label, testLabel, nil); 578 STAssertTrue([mutValue removeValueAndLabelAtIndex:50], nil); 579 } 580 } @catch(NSException *e) { 581 STAssertEqualObjects([e name], NSGenericException, @"Got %@ instead", e); 582 STAssertEquals(count, 2, 583 @"Should have caught it on the second access"); 584 exceptionThrown = YES; 585 } // COV_NF_LINE - because we always catch, this brace doesn't get exec'd 586 STAssertTrue(exceptionThrown, @"We should have thrown an exception" 587 @" because the values under the enumerator were modified"); 588 589} 590 591#if GTM_IPHONE_SDK 592- (void)testRadar6208390 { 593 GTMABPropertyType types[] = { 594 kGTMABStringPropertyType, 595 kGTMABIntegerPropertyType, 596 kGTMABRealPropertyType, 597 kGTMABDateTimePropertyType, 598 kGTMABDictionaryPropertyType 599 }; 600 for (size_t j = 0; j < sizeof(types) / sizeof(ABPropertyType); ++j) { 601 ABPropertyType type = types[j]; 602#if GTM_IPHONE_SDK 603 ABMultiValueRef ref = ABMultiValueCreateMutable(type); 604#else // GTM_IPHONE_SDK 605 ABMutableMultiValueRef ref = ABMultiValueCreateMutable(); 606#endif // GTM_IPHONE_SDK 607 STAssertNotNULL(ref, nil); 608 NSString *label = [[NSString alloc] initWithString:@"label"]; 609 STAssertNotNil(label, nil); 610 id val = nil; 611 if (type == kGTMABDictionaryPropertyType) { 612 val = [[NSDictionary alloc] initWithObjectsAndKeys:@"1", @"1", nil]; 613 } else if (type == kGTMABStringPropertyType) { 614 val = [[NSString alloc] initWithFormat:@"value %zu", j]; 615 } else if (type == kGTMABIntegerPropertyType 616 || type == kGTMABRealPropertyType ) { 617 val = [[NSNumber alloc] initWithInt:143]; 618 } else if (type == kGTMABDateTimePropertyType) { 619 val = [[NSDate alloc] init]; 620 } 621 STAssertNotNil(val, 622 @"Testing type %d, %@", type, val); 623 NSUInteger firstRetainCount = [val retainCount]; 624 STAssertNotEquals(firstRetainCount, 625 (NSUInteger)0, 626 @"Testing type %d, %@", type, val); 627 628 GTMABMultiValueIdentifier identifier; 629 STAssertTrue(ABMultiValueAddValueAndLabel(ref, 630 val, 631 (CFStringRef)label, 632 &identifier), 633 @"Testing type %d, %@", type, val); 634 NSUInteger secondRetainCount = [val retainCount]; 635 STAssertEquals(firstRetainCount + 1, 636 secondRetainCount, 637 @"Testing type %d, %@", type, val); 638 [label release]; 639 [val release]; 640 NSUInteger thirdRetainCount = [val retainCount]; 641 STAssertEquals(firstRetainCount, 642 thirdRetainCount, 643 @"Testing type %d, %@", type, val); 644 645 id oldVal = val; 646 val = (id)ABMultiValueCopyValueAtIndex(ref, 0); 647 NSUInteger fourthRetainCount = [val retainCount]; 648 649 // kABDictionaryPropertyTypes appear to do an actual copy, so the retain 650 // count checking trick won't work. We only check the retain count if 651 // we didn't get a new version. 652 if (val == oldVal) { 653 if (type == kGTMABIntegerPropertyType 654 || type == kGTMABRealPropertyType) { 655 // We are verifying that yes indeed 6208390 is still broken 656 STAssertEquals(fourthRetainCount, 657 thirdRetainCount, 658 @"Testing type %d, %@. If you see this error it may " 659 @"be time to update the code to change retain behaviors" 660 @"with this os version", type, val); 661 } else { 662 STAssertEquals(fourthRetainCount, 663 thirdRetainCount + 1, 664 @"Testing type %d, %@", type, val); 665 [val release]; 666 } 667 } else { 668 [val release]; 669 } 670 CFRelease(ref); 671 } 672} 673 674// Globals used by testRadar6240394. 675static GTMABPropertyID gGTMTestID; 676static const GTMABPropertyID *gGTMTestIDPtr; 677 678void __attribute__((constructor))SetUpIDForTestRadar6240394(void) { 679 // These must be set up BEFORE ABAddressBookCreate is called. 680 gGTMTestID = kGTMABPersonLastNameProperty; 681 gGTMTestIDPtr = &kGTMABPersonLastNameProperty; 682} 683 684- (void)testRadar6240394 { 685 // As of iPhone SDK 2.1, the property IDs aren't initialized until 686 // ABAddressBookCreate is actually called. They will return zero until 687 // then. Logged as radar 6240394. 688 STAssertEquals(gGTMTestID, 0, @"If this isn't zero, Apple has fixed 6240394"); 689 (void)ABAddressBookCreate(); 690 STAssertEquals(*gGTMTestIDPtr, kGTMABPersonLastNameProperty, 691 @"If this doesn't work, something else has broken"); 692} 693 694#endif // GTM_IPHONE_SDK 695@end