PageRenderTime 328ms CodeModel.GetById 214ms app.highlight 107ms RepoModel.GetById 2ms app.codeStats 0ms

/core/externals/update-engine/externals/google-toolbox-for-mac/AddressBook/GTMABAddressBookTest.m

http://macfuse.googlecode.com/
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