From 721e03bf2cf93584569ae1200a6a4d50d536d105 Mon Sep 17 00:00:00 2001 From: "gtm.daemon" Date: Tue, 31 Aug 2010 13:06:43 +0000 Subject: [Author: thomasvl] Removed iPhone/GTMABAddressBook in favor of AddressBook/GTMABAddressBook. Removed Foundation/GTMHTTPServer and UnitTesting/GTMTestHTTPServer, they are going to go live with the fetcher used by GData (since they were done for that testing). Removed Foundation/GTMBase64 and Foundation/GTMNSData+Hex in favor of Foundation/GTMStringEncoding. R=dmaclach DELTA=5118 (13 added, 5105 deleted, 0 changed) --- iPhone/GTMABAddressBook.h | 328 --------------- iPhone/GTMABAddressBook.m | 901 ---------------------------------------- iPhone/GTMABAddressBook.strings | Bin 1428 -> 0 bytes iPhone/GTMABAddressBookTest.m | 608 --------------------------- 4 files changed, 1837 deletions(-) delete mode 100644 iPhone/GTMABAddressBook.h delete mode 100644 iPhone/GTMABAddressBook.m delete mode 100644 iPhone/GTMABAddressBook.strings delete mode 100644 iPhone/GTMABAddressBookTest.m (limited to 'iPhone') diff --git a/iPhone/GTMABAddressBook.h b/iPhone/GTMABAddressBook.h deleted file mode 100644 index 828f05a..0000000 --- a/iPhone/GTMABAddressBook.h +++ /dev/null @@ -1,328 +0,0 @@ -// -// GTMABAddressBook.h -// -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -// These classes wrap up the iPhone AddressBook 'C' API in a manner very -// similar to that found on Mac OS X. They differ only in that none of these -// routines throws, and some of the types are different as necessitated by -// the APIs that they wrap. These wrappers also protect you from a number -// of issues in the AddressBook API (as of iPhone SDK 2.0/2.1) -// -// Note that there is a strings file that you may want to localize -// (GTMABAddressBook.strings). -// -// If things seem strange, it may be due to one of the following radars: -// 6240394 AddressBook framework constants not initialized until -// ABCreateAddressBook called -// -- CLOSED as designed -// 6208390 Integer and real values don't work in ABMultiValueRefs -// (and this isn't part of the title, but dictionaries don't work -// either) -// 6207605 RecordIDs for people and groups are not unique in AddressBook -// -- CLOSED as designed -// 6204021 kABGroupNameProperty and kABPersonFirstNameProperty have the same -// value -// 6203982 ABPersonCopyLocalizedPropertyName returns name for -// kABGroupNameProperty -// 6203961 ABPersonGetTypeOfProperty returns a type for kABGroupNameProperty -// 6203854 ABMultiValues hash to their address -// 6203836 ABRecords hash to their address -// -- CLOSED behaves correctly -// 6203606 Need CFTypeIDs for AddressBook CFTypes -// 6202868 ABPersonSetImageData should validate image data -// 6202860 Passing nil person into ABGroupAddMember crashes -// -- CLOSED behaves correctly -// 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash -// -- CLOSED behaves correctly -// 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert values -// past end -// 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes -// -- CLOSED behaves correctly -// 6201258 Adding a NULL record using ABAddressBookAddRecord crashes -// -- CLOSED behaves correctly -// 6201046 ABRecordSetValue returns true even if you pass in a bad type for a -// value -// 6201005 ABRecordRemoveValue returns true for value that aren't in the record -// -- CLOSED behaves correctly -// 6200703 ABAddressBookAddRecord doesn't add an item to the people array until -// it's saved -// 6200638 ABAddressBookHasUnsavedChanges doesn't work - -#import -#import -#import "GTMDefines.h" - -#if !GTM_IPHONE_SDK -#error This file is for iPhone use only use ABAddressBook on Mac OS X -#endif - -@class GTMABPerson; -@class GTMABGroup; -@class GTMABRecord; - -GTM_EXTERN NSString *const kGTMABUnknownPropertyName; - -// Wrapper for an AddressBook on iPhone -@interface GTMABAddressBook : NSObject { - @private - ABAddressBookRef addressBook_; -} - -// Returns a new instance of an address book. -+ (GTMABAddressBook *)addressBook; - -// Return the address book reference -- (ABAddressBookRef)addressBookRef; - -// Saves changes made since the last save -// Return YES if successful (or there was no change) -- (BOOL)save; - -// Saves changes made since the last save -// Return YES if successful (or there was no change) -- (BOOL)saveAndReturnError:(NSError **)error; - -// Returns YES if there are unsaved changes -// The unsaved changes flag is automatically set when changes are made -// As of iPhone 2.1, this does not work, and will always return NO. -// Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work -- (BOOL)hasUnsavedChanges; - -// Reverts any changes that have been made and resets the unsaved flag -// Be sure to read notes for -hasUnsavedChanges and -people and -groups. -- (void)revert; - -// Returns a GTMABPerson matching an ID -// Returns nil if the record could not be found -- (GTMABPerson *)personForId:(ABRecordID)uniqueId; - -// Returns a GTMABGroup matching an ID -// Returns nil if the record could not be found -- (GTMABGroup *)groupForId:(ABRecordID)uniqueId; - -// Adds a record (ABPerson or ABGroup) to the AddressBook database -// Be sure to read notes for -people and -group. -- (BOOL)addRecord:(GTMABRecord *)record; - -// Removes a record (ABPerson or ABGroup) from the AddressBook database -- (BOOL)removeRecord:(GTMABRecord *)record; - -// Returns an array (GTMABPerson) of all the people in the AddressBook database -// As of iPhone 2.1, this array will not contain new entries until you save -// the address book. -// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array -// until it's saved -- (NSArray *)people; - -// Returns an array of all the groups (GTMABGroup) in the AddressBook database -// As of iPhone 2.1, this array will not contain new entries until you save -// the address book. -// Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people array -// until it's saved -- (NSArray *)groups; - -// Returns a localized name for a given label -+ (NSString *)localizedLabel:(CFStringRef)label; - -@end - -// Wrapper for a ABRecord on iPhone. -// A abstract class. Instantiate one of the concrete subclasses, GTMABPerson or -// GTMABGroup. -@interface GTMABRecord : NSObject { - @private - ABRecordRef record_; -} - -// Create a record with a recordRef. -// Since GTMABRecord is an abstract base class, attempting to create one -// of these directly will throw an exception. Use with one of the concrete -// subclasses. -+ (id)recordWithRecord:(ABRecordRef)record; - -// Designated initializer -// Since GTMABRecord is an abstract base class, attempting to create one -// of these directly will throw an exception. Use with one of the concrete -// subclasses. -- (id)initWithRecord:(ABRecordRef)record; - -// Return our recordRef -- (ABRecordRef)recordRef; - -// Return the recordID for the record -- (ABRecordID)recordID; - -// Returns the value of a given property. -// The type of the value depends on the property type. -- (id)valueForProperty:(ABPropertyID)property; - -// Set the value of a given property. -// The type of the value must match the property type. -// Returns YES if value set properly -- (BOOL)setValue:(id)value forProperty:(ABPropertyID)property; - -// Removes the value for the property -// Returns yes if value removed -- (BOOL)removeValueForProperty:(ABPropertyID)property; - -// returns a human friendly name for the record -- (NSString *)compositeName; - -// returns the type of a property -+ (ABPropertyType)typeOfProperty:(ABPropertyID)property; - -// returns a human friendly localized name for a property -+ (NSString *)localizedPropertyName:(ABPropertyID)property; -@end - -// Wrapper for an ABPerson on iPhone -@interface GTMABPerson : GTMABRecord - -// Creates a person with a first name and a last name. -+ (GTMABPerson *)personWithFirstName:(NSString *)first - lastName:(NSString *)last; - -// Sets image data for a person. Data must be to a block of data that -// will create a valid UIImage. -- (BOOL)setImageData:(NSData *)data; - -// Returns the image data. -- (NSData *)imageData; - -// Returns the image for a person -- (UIImage *)image; - -// Sets a the image for a person -- (BOOL)setImage:(UIImage *)image; - -// Returns the format in with names are composited -+ (ABPersonCompositeNameFormat)compositeNameFormat; -@end - -// Wrapper for a ABGroup on iPhone -@interface GTMABGroup : GTMABRecord -// Create a new group named |name| -+ (GTMABGroup *)groupNamed:(NSString *)name; - -// Return an array of members (GTMABPerson) -- (NSArray *)members; - -// Add a member to a group -- (BOOL)addMember:(GTMABPerson *)person; - -// Remove a member from a group -- (BOOL)removeMember:(GTMABPerson *)person; -@end - -// GTMABMultiValue does not supprt NSFastEnumeration because in -// the Apple frameworks it returns identifiers which are already NSStrings. -// In our case identifiers aren't NS types, and it doesn't make sense -// to convert them to NSNumbers just to convert them back so you can -// actually get at the values and labels. -// Instead we supply valueEnumerator and labelEnumerator which you can -// fast enumerate on to get values and labels directly. -@interface GTMABMultiValue : NSObject { - @protected - ABMultiValueRef multiValue_; -} - -// Create a multi value -- (id)initWithMultiValue:(ABMultiValueRef)multiValue; - -// return it's ref -- (ABMultiValueRef)multiValueRef; - -// Returns the number of value/label pairs -- (NSUInteger)count; - -// Returns a value at a given index -// Returns nil if index is out of bounds -- (id)valueAtIndex:(NSUInteger)idx; - -// Returns a label at a given index -// Returns nil if index is out of bounds -- (NSString *)labelAtIndex:(NSUInteger)idx; - -// Returns an identifier at a given index -// Returns kABMultiValueInvalidIdentifier if index is out of bounds -- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx; - -// Returns the index of a given identifier -// Returns NSNotFound if not found -- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier; - -// Type of the contents of this multivalue -- (ABPropertyType)propertyType; - -// Returns the value for a given identifier -// Returns nil if the identifier is not found -- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier; - -// Returns the value for a given identifier -// Returns nil if the identifier is not found -- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)identifier; - -// Returns an enumerator for enumerating through values -- (NSEnumerator *)valueEnumerator; - -// Returns an enumerator for enumerating through labels -- (NSEnumerator *)labelEnumerator; - -@end - -@interface GTMABMutableMultiValue : GTMABMultiValue { - @private - // Use unsigned long here instead of NSUInteger because that's what - // NSFastEnumeration Protocol wants currently (iPhone 2.1) - unsigned long mutations_; -} - -// Create a new mutable multivalue with a given type -+ (id)valueWithPropertyType:(ABPropertyType)type; - -// Create a new mutable multivalue with a given type -- (id)initWithPropertyType:(ABPropertyType)type; - -// Create a new mutable multivalue based on |multiValue| -- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue; - -// Adds a value with its label -// Returns the identifier if successful, kABMultiValueInvalidIdentifier -// otherwise. -- (ABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label; - -// Insert a value/label pair at a given index -// Returns the identifier if successful. kABMultiValueInvalidIdentifier -// otherwise -// If index is out of bounds, returns kABMultiValueInvalidIdentifier. -- (ABMultiValueIdentifier)insertValue:(id)value - withLabel:(CFStringRef)label - atIndex:(NSUInteger)index; - -// Removes a value/label pair at a given index -// Returns NO if index out of bounds -- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)index; - -// Replaces a value at a given index -// Returns NO if index out of bounds -- (BOOL)replaceValueAtIndex:(NSUInteger)index withValue:(id)value; - -// Replaces a label at a given index -// Returns NO if index out of bounds -- (BOOL)replaceLabelAtIndex:(NSUInteger)index withLabel:(CFStringRef)label; - -@end diff --git a/iPhone/GTMABAddressBook.m b/iPhone/GTMABAddressBook.m deleted file mode 100644 index bb84e61..0000000 --- a/iPhone/GTMABAddressBook.m +++ /dev/null @@ -1,901 +0,0 @@ -// -// GTMAddressBook.m -// -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -#import "GTMABAddressBook.h" -#import "GTMGarbageCollection.h" - -NSString *const kGTMABUnknownPropertyName = @"UNKNOWN_PROPERTY"; - -typedef struct { - ABPropertyType pType; - Class class; -} TypeClassNameMap; - -@interface GTMABMultiValue () -- (unsigned long*)mutations; -@end - -@interface GTMABMutableMultiValue () -// Checks to see if a value is a valid type to be stored in this multivalue -- (BOOL)checkValueType:(id)value; -@end - -@interface GTMABMultiValueEnumerator : NSEnumerator { - @private - __weak ABMultiValueRef ref_; // ref_ cached from enumeree_ - GTMABMultiValue *enumeree_; - unsigned long mutations_; - NSUInteger count_; - NSUInteger index_; - BOOL useLabels_; -} -+ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree; -+ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree; -- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels; -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(id *)stackbuf - count:(NSUInteger)len; -@end - -@implementation GTMABAddressBook -+ (GTMABAddressBook *)addressBook { - return [[[self alloc] init] autorelease]; -} - -- (id)init { - if ((self = [super init])) { - addressBook_ = ABAddressBookCreate(); - if (!addressBook_) { - // COV_NF_START - [self release]; - self = nil; - // COV_NF_END - } - } - return self; -} - -- (void)dealloc { - if (addressBook_) { - CFRelease(addressBook_); - } - [super dealloc]; -} - -- (BOOL)save { - return [self saveAndReturnError:NULL]; -} - -- (BOOL)saveAndReturnError:(NSError **)error { - CFErrorRef cfError = NULL; - bool wasGood = ABAddressBookSave(addressBook_, &cfError); - GTMCFAutorelease(cfError); - if (error) { - *error = (NSError *)cfError; // COV_NF_LINE - } - return wasGood ? YES : NO; -} - -- (BOOL)hasUnsavedChanges { - return ABAddressBookHasUnsavedChanges(addressBook_); -} - -- (void)revert { - ABAddressBookRevert(addressBook_); -} - -- (BOOL)addRecord:(GTMABRecord *)record { - // Note: we check for bad data here because of radar - // 6201258 Adding a NULL record using ABAddressBookAddRecord crashes - if (!record) return NO; - CFErrorRef cfError = NULL; - bool wasGood = ABAddressBookAddRecord(addressBook_, - [record recordRef], &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (BOOL)removeRecord:(GTMABRecord *)record { - // Note: we check for bad data here because of radar - // 6201276 Removing a NULL record using ABAddressBookRemoveRecord crashes - if (!record) return NO; - CFErrorRef cfError = NULL; - bool wasGood = ABAddressBookRemoveRecord(addressBook_, - [record recordRef], &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (NSArray *)people { - NSArray *people - = GTMCFAutorelease(ABAddressBookCopyArrayOfAllPeople(addressBook_)); - NSMutableArray *result = [NSMutableArray arrayWithCapacity:[people count]]; - for (id person in people) { - [result addObject:[GTMABPerson recordWithRecord:person]]; - } - return result; -} - -- (NSArray *)groups { - NSArray *groups - = GTMCFAutorelease(ABAddressBookCopyArrayOfAllGroups(addressBook_)); - NSMutableArray *result = [NSMutableArray arrayWithCapacity:[groups count]]; - for (id group in groups) { - [result addObject:[GTMABGroup recordWithRecord:group]]; - } - return result; -} - -- (ABAddressBookRef)addressBookRef { - return addressBook_; -} - -- (GTMABPerson *)personForId:(ABRecordID)uniqueId { - GTMABPerson *person = nil; - ABRecordRef ref = ABAddressBookGetPersonWithRecordID(addressBook_, uniqueId); - if (ref) { - person = [GTMABPerson recordWithRecord:ref]; - } - return person; -} - -- (GTMABGroup *)groupForId:(ABRecordID)uniqueId { - GTMABGroup *group = nil; - ABRecordRef ref = ABAddressBookGetGroupWithRecordID(addressBook_, uniqueId); - if (ref) { - group = [GTMABGroup recordWithRecord:ref]; - } - return group; -} - -+ (NSString *)localizedLabel:(CFStringRef)label { - return GTMCFAutorelease(ABAddressBookCopyLocalizedLabel(label)); -} - -@end - -@implementation GTMABRecord -+ (id)recordWithRecord:(ABRecordRef)record { - return [[[self alloc] initWithRecord:record] autorelease]; -} - -- (id)initWithRecord:(ABRecordRef)record { - if ((self = [super init])) { - if ([self class] == [GTMABRecord class]) { - [self autorelease]; - [self doesNotRecognizeSelector:_cmd]; - } - if (!record) { - [self release]; - self = nil; - } else { - record_ = CFRetain(record); - } - } - return self; -} - -- (NSUInteger)hash { - // This really isn't completely valid due to - // 6203836 ABRecords hash to their address - // but it's the best we can do without knowing what properties - // are in a record, and we don't have an API for that. - return CFHash(record_); -} - -- (BOOL)isEqual:(id)object { - // This really isn't completely valid due to - // 6203836 ABRecords hash to their address - // but it's the best we can do without knowing what properties - // are in a record, and we don't have an API for that. - return [object respondsToSelector:@selector(recordRef)] - && CFEqual(record_, [object recordRef]); -} - -- (void)dealloc { - if (record_) { - CFRelease(record_); - } - [super dealloc]; -} - -- (ABRecordRef)recordRef { - return record_; -} - -- (ABRecordID)recordID { - return ABRecordGetRecordID(record_); -} - -- (id)valueForProperty:(ABPropertyID)property { - id value = GTMCFAutorelease(ABRecordCopyValue(record_, property)); - if (value) { - if ([[self class] typeOfProperty:property] & kABMultiValueMask) { - value = [[[GTMABMultiValue alloc] initWithMultiValue:value] autorelease]; - } - } - return value; -} - -- (BOOL)setValue:(id)value forProperty:(ABPropertyID)property { - if (!value) return NO; - // We check the type here because of - // Radar 6201046 ABRecordSetValue returns true even if you pass in a bad type - // for a value - TypeClassNameMap fullTypeMap[] = { - { kABStringPropertyType, [NSString class] }, - { kABIntegerPropertyType, [NSNumber class] }, - { kABRealPropertyType, [NSNumber class] }, - { kABDateTimePropertyType, [NSDate class] }, - { kABDictionaryPropertyType, [NSDictionary class] }, - { kABMultiStringPropertyType, [GTMABMultiValue class] }, - { kABMultiRealPropertyType, [GTMABMultiValue class] }, - { kABMultiDateTimePropertyType, [GTMABMultiValue class] }, - { kABMultiDictionaryPropertyType, [GTMABMultiValue class] } - }; - ABPropertyType type = [[self class] typeOfProperty:property]; - BOOL wasFound = NO; - for (size_t i = 0; i < sizeof(fullTypeMap) / sizeof(TypeClassNameMap); ++i) { - if (fullTypeMap[i].pType == type) { - wasFound = YES; - if (![[value class] isSubclassOfClass:fullTypeMap[i].class]) { - return NO; - } - } - } - if (!wasFound) { - return NO; - } - if (type & kABMultiValueMask) { - value = (id)[value multiValueRef]; - } - CFErrorRef cfError = nil; - bool wasGood = ABRecordSetValue(record_, property, (CFTypeRef)value, &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (BOOL)removeValueForProperty:(ABPropertyID)property { - CFErrorRef cfError = nil; - // We check to see if the value is in the property because of: - // Radar 6201005 ABRecordRemoveValue returns true for value that aren't - // in the record - id value = [self valueForProperty:property]; - bool wasGood = value && ABRecordRemoveValue(record_, property, &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (NSString *)compositeName { - return GTMCFAutorelease(ABRecordCopyCompositeName(record_)); -} - -// COV_NF_START -// Both of these methods are to be overridden by their subclasses -+ (ABPropertyType)typeOfProperty:(ABPropertyID)property { - [self doesNotRecognizeSelector:_cmd]; - return kABInvalidPropertyType; -} - -+ (NSString *)localizedPropertyName:(ABPropertyID)property { - [self doesNotRecognizeSelector:_cmd]; - return nil; -} -// COV_NF_END -@end - -@implementation GTMABPerson - -+ (GTMABPerson *)personWithFirstName:(NSString *)first - lastName:(NSString *)last { - GTMABPerson *person = [[[self alloc] init] autorelease]; - if (person) { - BOOL isGood = YES; - if (first) { - isGood = [person setValue:first forProperty:kABPersonFirstNameProperty]; - } - if (isGood && last) { - isGood = [person setValue:last forProperty:kABPersonLastNameProperty]; - } - if (!isGood) { - // COV_NF_START - // Marked as NF because I don't know how to force an error - person = nil; - // COV_NF_END - } - } - return person; -} - -- (id)init { - ABRecordRef person = ABPersonCreate(); - self = [super initWithRecord:person]; - if (person) { - CFRelease(person); - } - return self; -} - -- (BOOL)setImageData:(NSData *)data { - CFErrorRef cfError = NULL; - bool wasGood = NO; - if (!data) { - wasGood = ABPersonRemoveImageData([self recordRef], &cfError); - } else { - // We verify that the data is good because of: - // Radar 6202868 ABPersonSetImageData should validate image data - UIImage *image = [UIImage imageWithData:data]; - wasGood = image && ABPersonSetImageData([self recordRef], - (CFDataRef)data, &cfError); - } - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (UIImage *)image { - return [UIImage imageWithData:[self imageData]]; -} - -- (BOOL)setImage:(UIImage *)image { - NSData *data = UIImagePNGRepresentation(image); - return [self setImageData:data]; -} - -- (NSData *)imageData { - return GTMCFAutorelease(ABPersonCopyImageData([self recordRef])); -} - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ %@ %@ %d", - [self class], - [self valueForProperty:kABPersonFirstNameProperty], - [self valueForProperty:kABPersonLastNameProperty], - [self recordID]]; -} - -+ (NSString *)localizedPropertyName:(ABPropertyID)property { - return GTMCFAutorelease(ABPersonCopyLocalizedPropertyName(property)); -} - -+ (ABPersonCompositeNameFormat)compositeNameFormat { - return ABPersonGetCompositeNameFormat(); -} - -+ (ABPropertyType)typeOfProperty:(ABPropertyID)property { - return ABPersonGetTypeOfProperty(property); -} -@end - -@implementation GTMABGroup - -+ (GTMABGroup *)groupNamed:(NSString *)name { - GTMABGroup *group = [[[self alloc] init] autorelease]; - if (group) { - if (![group setValue:name forProperty:kABGroupNameProperty]) { - // COV_NF_START - // Can't get setValue to fail for me - group = nil; - // COV_NF_END - } - } - return group; -} - -- (id)init { - ABRecordRef group = ABGroupCreate(); - self = [super initWithRecord:group]; - if (group) { - CFRelease(group); - } - return self; -} - -- (NSArray *)members { - NSArray *people - = GTMCFAutorelease(ABGroupCopyArrayOfAllMembers([self recordRef])); - NSMutableArray *gtmPeople = [NSMutableArray arrayWithCapacity:[people count]]; - for (id person in people) { - [gtmPeople addObject:[GTMABPerson recordWithRecord:(ABRecordRef)person]]; - } - return gtmPeople; -} - -- (BOOL)addMember:(GTMABPerson *)person { - CFErrorRef cfError = nil; - // We check for person because of - // Radar 6202860 Passing nil person into ABGroupAddMember crashes - bool wasGood = person && ABGroupAddMember([self recordRef], - [person recordRef], &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -- (BOOL)removeMember:(GTMABPerson *)person { - CFErrorRef cfError = nil; - // We check for person because of - // Radar 6202860 Passing nil person into ABGroupAddMember crashes - // (I know this is remove, but it crashes there too) - bool wasGood = person && ABGroupRemoveMember([self recordRef], - [person recordRef], &cfError); - if (cfError) { - // COV_NF_START - _GTMDevLog(@"Error in [%@ %@]: %@", - [self class], NSStringFromSelector(_cmd), cfError); - CFRelease(cfError); - // COV_NF_END - } - return wasGood ? YES : NO; -} - -+ (ABPropertyType)typeOfProperty:(ABPropertyID)property { - ABPropertyType type = kABInvalidPropertyType; - if (property == kABGroupNameProperty) { - type = kABStringPropertyType; - } - return type; -} - -+ (NSString *)localizedPropertyName:(ABPropertyID)property { - NSString *name = kGTMABUnknownPropertyName; - if (property == kABGroupNameProperty) { - name = NSLocalizedStringFromTable(@"Name", - @"GTMABAddressBook", - @"name property"); - } - return name; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"%@ %@ %d", - [self class], - [self valueForProperty:kABGroupNameProperty], - [self recordID]]; -} -@end - -@implementation GTMABMultiValue -- (id)init { - // Call super init and release so we don't leak - [[super init] autorelease]; - [self doesNotRecognizeSelector:_cmd]; - return nil; // COV_NF_LINE -} - -- (id)initWithMultiValue:(ABMultiValueRef)multiValue { - if ((self = [super init])) { - if (!multiValue) { - [self release]; - self = nil; - } else { - multiValue_ = CFRetain(multiValue); - } - } - return self; -} - -- (id)copyWithZone:(NSZone *)zone { - return [[GTMABMultiValue alloc] initWithMultiValue:multiValue_]; -} - -- (id)mutableCopyWithZone:(NSZone *)zone { - return [[GTMABMutableMultiValue alloc] initWithMultiValue:multiValue_]; -} - -- (NSUInteger)hash { - // I'm implementing hash instead of using CFHash(multiValue_) because - // 6203854 ABMultiValues hash to their address - NSUInteger count = [self count]; - NSUInteger hash = 0; - for (NSUInteger i = 0; i < count; ++i) { - NSString *label = [self labelAtIndex:i]; - id value = [self valueAtIndex:i]; - hash += [label hash]; - hash += [value hash]; - } - return hash; -} - -- (BOOL)isEqual:(id)object { - // I'm implementing isEqual instea of using CFEquals(multiValue,...) because - // 6203854 ABMultiValues hash to their address - // and it appears CFEquals just calls through to hash to compare them. - BOOL isEqual = NO; - if ([object respondsToSelector:@selector(multiValueRef)]) { - isEqual = multiValue_ == [object multiValueRef]; - if (!isEqual) { - NSUInteger count = [self count]; - NSUInteger objCount = [object count]; - isEqual = count == objCount; - for (NSUInteger i = 0; isEqual && i < count; ++i) { - NSString *label = [self labelAtIndex:i]; - NSString *objLabel = [object labelAtIndex:i]; - isEqual = [label isEqual:objLabel]; - if (isEqual) { - id value = [self valueAtIndex:i]; - id objValue = [object valueAtIndex:i]; - isEqual = [value isEqual:objValue]; - } - } - } - } - return isEqual; -} - -- (void)dealloc { - if (multiValue_) { - CFRelease(multiValue_); - } - [super dealloc]; -} - -- (ABMultiValueRef)multiValueRef { - return multiValue_; -} - -- (NSUInteger)count { - return ABMultiValueGetCount(multiValue_); -} - -- (id)valueAtIndex:(NSUInteger)idx { - id value = nil; - if (idx < [self count]) { - value = GTMCFAutorelease(ABMultiValueCopyValueAtIndex(multiValue_, idx)); - ABPropertyType type = [self propertyType]; - if (type == kABIntegerPropertyType - || type == kABRealPropertyType - || type == kABDictionaryPropertyType) { - // This is because of - // 6208390 Integer and real values don't work in ABMultiValueRefs - // Apparently they forget to add a ref count on int, real and - // dictionary values in ABMultiValueCopyValueAtIndex, although they do - // remember them for all other types. - // Once they fix this, this will lead to a leak, but I figure the leak - // is better than the crash. Our unittests will test to make sure that - // this is the case, and once we find a system that has this fixed, we - // can conditionalize this code. Look for testRadar6208390 in - // GTMABAddressBookTest.m - // Also, search for 6208390 below and fix the fast enumerator to actually - // be somewhat performant when this is fixed. - [value retain]; - } - } - return value; -} - -- (NSString *)labelAtIndex:(NSUInteger)idx { - NSString *label = nil; - if (idx < [self count]) { - label = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(multiValue_, idx)); - } - return label; -} - -- (ABMultiValueIdentifier)identifierAtIndex:(NSUInteger)idx { - ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; - if (idx < [self count]) { - identifier = ABMultiValueGetIdentifierAtIndex(multiValue_, idx); - } - return identifier; -} - -- (NSUInteger)indexForIdentifier:(ABMultiValueIdentifier)identifier { - NSUInteger idx = ABMultiValueGetIndexForIdentifier(multiValue_, identifier); - return idx == (NSUInteger)kCFNotFound ? (NSUInteger)NSNotFound : idx; -} - -- (ABPropertyType)propertyType { - return ABMultiValueGetPropertyType(multiValue_); -} - -- (id)valueForIdentifier:(ABMultiValueIdentifier)identifier { - return [self valueAtIndex:[self indexForIdentifier:identifier]]; -} - -- (NSString *)labelForIdentifier:(ABMultiValueIdentifier)identifier { - return [self labelAtIndex:[self indexForIdentifier:identifier]]; -} - -- (unsigned long*)mutations { - // We just need some constant non-zero value here so fast enumeration works. - // Dereferencing self should give us the isa which will stay constant - // over the enumeration. - return (unsigned long*)self; -} - -- (NSEnumerator *)valueEnumerator { - return [GTMABMultiValueEnumerator valueEnumeratorFor:self]; -} - -- (NSEnumerator *)labelEnumerator { - return [GTMABMultiValueEnumerator labelEnumeratorFor:self]; -} - -@end - -@implementation GTMABMutableMultiValue -+ (id)valueWithPropertyType:(ABPropertyType)type { - return [[[self alloc] initWithPropertyType:type] autorelease]; -} - -- (id)initWithPropertyType:(ABPropertyType)type { - ABMutableMultiValueRef ref = nil; - if (type != kABInvalidPropertyType) { - ref = ABMultiValueCreateMutable(type); - } - self = [super initWithMultiValue:ref]; - if (ref) { - CFRelease(ref); - } - return self; -} - -- (id)initWithMultiValue:(ABMultiValueRef)multiValue { - ABMutableMultiValueRef ref = nil; - if (multiValue) { - ref = ABMultiValueCreateMutableCopy(multiValue); - } - self = [super initWithMultiValue:ref]; - if (ref) { - CFRelease(ref); - } - return self; -} - -- (id)initWithMutableMultiValue:(ABMutableMultiValueRef)multiValue { - return [super initWithMultiValue:multiValue]; -} - -- (BOOL)checkValueType:(id)value { - BOOL isGood = NO; - if (value) { - TypeClassNameMap singleValueTypeMap[] = { - { kABStringPropertyType, [NSString class] }, - { kABIntegerPropertyType, [NSNumber class] }, - { kABRealPropertyType, [NSNumber class] }, - { kABDateTimePropertyType, [NSDate class] }, - { kABDictionaryPropertyType, [NSDictionary class] }, - }; - ABPropertyType type = [self propertyType]; - for (size_t i = 0; - i < sizeof(singleValueTypeMap) / sizeof(TypeClassNameMap); ++i) { - if (singleValueTypeMap[i].pType == type) { - if ([[value class] isSubclassOfClass:singleValueTypeMap[i].class]) { - isGood = YES; - break; - } - } - } - } - return isGood; -} - -- (ABMultiValueIdentifier)addValue:(id)value withLabel:(CFStringRef)label { - ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; - // We check label and value here because of - // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash - if (!label - || ![self checkValueType:value] - || !ABMultiValueAddValueAndLabel(multiValue_, - value, - label, - &identifier)) { - identifier = kABMultiValueInvalidIdentifier; - } else { - mutations_++; - } - return identifier; -} - -- (ABMultiValueIdentifier)insertValue:(id)value - withLabel:(CFStringRef)label - atIndex:(NSUInteger)idx { - ABMultiValueIdentifier identifier = kABMultiValueInvalidIdentifier; - // We perform a check here to ensure that we don't get bitten by - // Radar 6202807 ABMultiValueInsertValueAndLabelAtIndex allows you to insert - // values past end - NSUInteger count = [self count]; - // We check label and value here because of - // radar 6202827 Passing nil info ABMultiValueAddValueAndLabel causes crash - if (idx > count - || !label - || ![self checkValueType:value] - || !ABMultiValueInsertValueAndLabelAtIndex(multiValue_, - value, - label, - idx, - &identifier)) { - identifier = kABMultiValueInvalidIdentifier; - } else { - mutations_++; - } - return identifier; -} - -- (BOOL)removeValueAndLabelAtIndex:(NSUInteger)idx { - BOOL isGood = NO; - NSUInteger count = [self count]; - if (idx < count) { - if (ABMultiValueRemoveValueAndLabelAtIndex(multiValue_, - idx)) { - mutations_++; - isGood = YES; - } - } - return isGood; -} - -- (BOOL)replaceValueAtIndex:(NSUInteger)idx withValue:(id)value { - BOOL isGood = NO; - NSUInteger count = [self count]; - if (idx < count && [self checkValueType:value]) { - if (ABMultiValueReplaceValueAtIndex(multiValue_, - value, idx)) { - mutations_++; - isGood = YES; - } - } - return isGood; -} - -- (BOOL)replaceLabelAtIndex:(NSUInteger)idx withLabel:(CFStringRef)label{ - BOOL isGood = NO; - NSUInteger count = [self count]; - if (idx < count) { - if (ABMultiValueReplaceLabelAtIndex(multiValue_, - label, - idx)) { - mutations_++; - isGood = YES; - } - } - return isGood; -} - -- (unsigned long*)mutations { - return &mutations_; -} -@end - - -@implementation GTMABMultiValueEnumerator - -+ (id)valueEnumeratorFor:(GTMABMultiValue*)enumeree { - return [[[self alloc] initWithEnumeree:enumeree useLabels:NO] autorelease]; -} - -+ (id)labelEnumeratorFor:(GTMABMultiValue*)enumeree { - return [[[self alloc] initWithEnumeree:enumeree useLabels:YES] autorelease]; -} - -- (id)initWithEnumeree:(GTMABMultiValue*)enumeree useLabels:(BOOL)useLabels { - if ((self = [super init])) { - if (enumeree) { - enumeree_ = [enumeree retain]; - useLabels_ = useLabels; - } else { - // COV_NF_START - // Since this is a private class where the enumeree creates us - // there is no way we should ever get here. - [self release]; - self = nil; - // COV_NF_END - } - } - return self; -} - -- (void)dealloc { - [enumeree_ release]; - [super dealloc]; -} - -- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state - objects:(id *)stackbuf - count:(NSUInteger)len { - NSUInteger i; - if (!ref_) { - count_ = [enumeree_ count]; - ref_ = [enumeree_ multiValueRef]; - } - - for (i = 0; state->state < count_ && i < len; ++i, ++state->state) { - if (useLabels_) { - stackbuf[i] = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_, - state->state)); - } else { - // Yes this is slow, but necessary in light of radar 6208390 - // Once this is fixed we can go to something similar to the label - // case which should speed stuff up again. Hopefully anybody who wants - // real performance is willing to move down to the C API anyways. - stackbuf[i] = [enumeree_ valueAtIndex:state->state]; - } - } - - state->itemsPtr = stackbuf; - state->mutationsPtr = [enumeree_ mutations]; - return i; -} - -- (id)nextObject { - id value = nil; - if (!ref_) { - count_ = [enumeree_ count]; - mutations_ = *[enumeree_ mutations]; - ref_ = [enumeree_ multiValueRef]; - - } - if (mutations_ != *[enumeree_ mutations]) { - NSString *reason = [NSString stringWithFormat:@"*** Collection <%@> was " - "mutated while being enumerated", enumeree_]; - [[NSException exceptionWithName:NSGenericException - reason:reason - userInfo:nil] raise]; - } - if (index_ < count_) { - if (useLabels_) { - value = GTMCFAutorelease(ABMultiValueCopyLabelAtIndex(ref_, - index_)); - } else { - // Yes this is slow, but necessary in light of radar 6208390 - // Once this is fixed we can go to something similar to the label - // case which should speed stuff up again. Hopefully anybody who wants - // real performance is willing to move down to the C API anyways. - value = [enumeree_ valueAtIndex:index_]; - } - index_ += 1; - } - return value; -} -@end - diff --git a/iPhone/GTMABAddressBook.strings b/iPhone/GTMABAddressBook.strings deleted file mode 100644 index b5e010e..0000000 Binary files a/iPhone/GTMABAddressBook.strings and /dev/null differ diff --git a/iPhone/GTMABAddressBookTest.m b/iPhone/GTMABAddressBookTest.m deleted file mode 100644 index 17a3096..0000000 --- a/iPhone/GTMABAddressBookTest.m +++ /dev/null @@ -1,608 +0,0 @@ -// -// GTMAddressBookTest.m -// -// Copyright 2008 Google Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy -// of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -// License for the specific language governing permissions and limitations under -// the License. -// - -#import "GTMSenTestCase.h" -#import "GTMABAddressBook.h" - -@interface GTMABAddressBookTest : GTMTestCase { - @private - GTMABAddressBook *book_; -} -@end - - -@implementation GTMABAddressBookTest -- (void)setUp { - // Create a book forcing it out of it's autorelease pool. - // I force it out of the release pool, so that we will see any errors - // for it immediately at teardown, and it will be clear which release - // caused us problems. - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - book_ = [[GTMABAddressBook addressBook] retain]; - [pool release]; - STAssertNotNil(book_, nil); - STAssertFalse([book_ hasUnsavedChanges], nil); -} - -- (void)tearDown { - [book_ release]; -} - -- (void)testGenericAddressBook { - STAssertEqualObjects([GTMABAddressBook localizedLabel:kABHomeLabel], - @"home", - nil); - STAssertThrows([GTMABRecord recordWithRecord:nil], nil); -} - -- (void)testAddingAndRemovingPerson { - // Create a person - GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart" - lastName:@"Simpson"]; - STAssertNotNil(person, nil); - - // Add person - NSArray *people = [book_ people]; - STAssertFalse([people containsObject:person], nil); - STAssertTrue([book_ addRecord:person], nil); - - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - people = [book_ people]; - STAssertNotNil(people, nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people - // array until it's saved - // We will check to make sure it stays broken ;-) - STAssertFalse([people containsObject:person], nil); - - // Save book_ - STAssertTrue([book_ save], nil); - people = [book_ people]; - STAssertNotNil(people, nil); - STAssertTrue([people containsObject:person], nil); - - ABRecordID recordID = [person recordID]; - STAssertNotEquals(recordID, kABRecordInvalidID, nil); - - GTMABRecord *record = [book_ personForId:recordID]; - STAssertEqualObjects(record, person, nil); - - // Remove person - STAssertTrue([book_ removeRecord:person], nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - // Normally this next line would be STAssertFalse, however due to - // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the people - // array until it's saved - // We will check to make sure it stays broken ;-) - STAssertTrue([people containsObject:person], nil); - - // Save Book - STAssertTrue([book_ save], nil); - people = [book_ people]; - STAssertFalse([book_ hasUnsavedChanges], nil); - STAssertFalse([people containsObject:person], nil); - record = [book_ personForId:recordID]; - STAssertNil(record, nil); - - // Revert book_ - STAssertTrue([book_ addRecord:person], nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - [book_ revert]; - STAssertFalse([book_ hasUnsavedChanges], nil); - - // Bogus data - STAssertFalse([book_ addRecord:nil], nil); - STAssertFalse([book_ removeRecord:nil], nil); - - STAssertNotNULL([book_ addressBookRef], nil); - -} - -- (void)testAddingAndRemovingGroup { - // Create a group - GTMABGroup *group = [GTMABGroup groupNamed:@"Test"]; - STAssertNotNil(group, nil); - - // Add group - NSArray *groups = [book_ groups]; - STAssertFalse([groups containsObject:group], nil); - STAssertTrue([book_ addRecord:group], nil); - - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - groups = [book_ groups]; - STAssertNotNil(groups, nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups - // array until it's saved - // We will check to make sure it stays broken ;-) - STAssertFalse([groups containsObject:group], nil); - - // Save book_ - STAssertTrue([book_ save], nil); - groups = [book_ groups]; - STAssertNotNil(groups, nil); - STAssertTrue([groups containsObject:group], nil); - - ABRecordID recordID = [group recordID]; - STAssertNotEquals(recordID, kABRecordInvalidID, nil); - - GTMABRecord *record = [book_ groupForId:recordID]; - STAssertEqualObjects(record, group, nil); - - // Remove group - STAssertTrue([book_ removeRecord:group], nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - // Normally this next line would be STAssertFalse, however due to - // Radar 6200703: ABAddressBookAddRecord doesn't add an item to the groups - // array until it's saved - // We will check to make sure it stays broken ;-) - STAssertTrue([groups containsObject:group], nil); - - // Save Book - STAssertTrue([book_ save], nil); - groups = [book_ groups]; - STAssertFalse([book_ hasUnsavedChanges], nil); - STAssertFalse([groups containsObject:group], nil); - record = [book_ groupForId:recordID]; - STAssertNil(record, nil); - - // Revert book_ - STAssertTrue([book_ addRecord:group], nil); - // Normally this next line would be STAssertTrue, however due to - // Radar 6200638: ABAddressBookHasUnsavedChanges doesn't work - // We will check to make sure it stays broken ;-) - STAssertFalse([book_ hasUnsavedChanges], nil); - - [book_ revert]; - STAssertFalse([book_ hasUnsavedChanges], nil); -} - -- (void)testPerson { - GTMABPerson *person = [[[GTMABPerson alloc] initWithRecord:nil] autorelease]; - STAssertNil(person, nil); - person = [GTMABPerson personWithFirstName:@"Bart" - lastName:nil]; - STAssertNotNil(person, nil); - STAssertEqualObjects([person compositeName], @"Bart", nil); - NSString *firstName = [person valueForProperty:kABPersonFirstNameProperty]; - STAssertEqualObjects(firstName, @"Bart", nil); - NSString *lastName = [person valueForProperty:kABPersonLastNameProperty]; - STAssertNil(lastName, nil); - STAssertTrue([person removeValueForProperty:kABPersonFirstNameProperty], nil); - STAssertFalse([person removeValueForProperty:kABPersonFirstNameProperty], nil); - STAssertFalse([person removeValueForProperty:kABPersonLastNameProperty], nil); - STAssertFalse([person setValue:nil forProperty:kABPersonFirstNameProperty], nil); - STAssertFalse([person setValue:[NSNumber numberWithInt:1] - forProperty:kABPersonFirstNameProperty], nil); - STAssertFalse([person setValue:@"Bart" - forProperty:kABPersonBirthdayProperty], nil); - - ABPropertyType property - = [GTMABPerson typeOfProperty:kABPersonLastNameProperty]; - STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil); - - NSString *string - = [GTMABPerson localizedPropertyName:kABPersonLastNameProperty]; - STAssertEqualObjects(string, @"Last", nil); - - string = [GTMABPerson localizedPropertyName:kABRecordInvalidID]; - STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); - - string = [person description]; - STAssertNotNil(string, nil); - - ABPersonCompositeNameFormat format = [GTMABPerson compositeNameFormat]; - STAssertTrue(format == kABPersonCompositeNameFormatFirstNameFirst || - format == kABPersonCompositeNameFormatLastNameFirst, nil); - - NSData *data = [person imageData]; - STAssertNil(data, nil); - STAssertTrue([person setImageData:nil], nil); - data = [person imageData]; - STAssertNil(data, nil); - UIImage *image = [UIImage imageNamed:@"phone.png"]; - STAssertNotNil(image, nil); - data = UIImagePNGRepresentation(image); - STAssertTrue([person setImageData:data], nil); - NSData *data2 = [person imageData]; - STAssertEqualObjects(data, data2, nil); - STAssertTrue([person setImageData:nil], nil); - data = [person imageData]; - STAssertNil(data, nil); - - STAssertTrue([person setImage:image], nil); - UIImage *image2 = [person image]; - STAssertNotNil(image2, nil); - STAssertEqualObjects(UIImagePNGRepresentation(image), - UIImagePNGRepresentation(image2), nil); - - person = [GTMABPerson personWithFirstName:@"Bart" - lastName:@"Simpson"]; - - data = [NSData dataWithBytes:"a" length:1]; - STAssertFalse([person setImageData:data], nil); - - GTMABMutableMultiValue *value - = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType]; - STAssertNotNil(value, nil); - STAssertNotEquals([value addValue:@"222-222-2222" - withLabel:kABHomeLabel], - kABMultiValueInvalidIdentifier, nil); - STAssertNotEquals([value addValue:@"333-333-3333" - withLabel:kABWorkLabel], - kABMultiValueInvalidIdentifier, nil); - STAssertTrue([person setValue:value forProperty:kABPersonPhoneProperty], nil); - id value2 = [person valueForProperty:kABPersonPhoneProperty]; - STAssertNotNil(value2, nil); - STAssertEqualObjects(value, value2, nil); - STAssertEquals([value hash], [value2 hash], nil); - STAssertNotEquals([person hash], (NSUInteger)0, nil); -} - -- (void)testGroup { - GTMABGroup *group = [[[GTMABGroup alloc] initWithRecord:nil] autorelease]; - STAssertNil(group, nil); - group = [GTMABGroup groupNamed:@"TestGroup"]; - STAssertNotNil(group, nil); - STAssertEqualObjects([group compositeName], @"TestGroup", nil); - NSString *name = [group valueForProperty:kABGroupNameProperty]; - STAssertEqualObjects(name, @"TestGroup", nil); - NSString *lastName = [group valueForProperty:kABPersonLastNameProperty]; - STAssertNil(lastName, nil); - STAssertTrue([group removeValueForProperty:kABGroupNameProperty], nil); - STAssertFalse([group removeValueForProperty:kABGroupNameProperty], nil); - STAssertFalse([group removeValueForProperty:kABPersonLastNameProperty], nil); - STAssertFalse([group setValue:nil forProperty:kABGroupNameProperty], nil); - STAssertFalse([group setValue:[NSNumber numberWithInt:1] - forProperty:kABGroupNameProperty], nil); - STAssertFalse([group setValue:@"Bart" - forProperty:kABPersonBirthdayProperty], nil); - - ABPropertyType property = [GTMABGroup typeOfProperty:kABGroupNameProperty]; - STAssertEquals(property, (ABPropertyType)kABStringPropertyType, nil); - - property = [GTMABGroup typeOfProperty:kABPersonLastNameProperty]; - STAssertEquals(property, (ABPropertyType)kABInvalidPropertyType, nil); - - NSString *string = [GTMABGroup localizedPropertyName:kABGroupNameProperty]; - STAssertEqualObjects(string, @"Name", nil); - - string = [GTMABGroup localizedPropertyName:kABPersonLastNameProperty]; - STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); - - string = [GTMABGroup localizedPropertyName:kABRecordInvalidID]; - STAssertEqualObjects(string, kGTMABUnknownPropertyName, nil); - - string = [group description]; - STAssertNotNil(string, nil); - - // Adding and removing members - group = [GTMABGroup groupNamed:@"TestGroup2"]; - NSArray *members = [group members]; - STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); - - STAssertFalse([group addMember:nil], nil); - - members = [group members]; - STAssertEquals([members count], (NSUInteger)0, @"Members: %@", members); - - GTMABPerson *person = [GTMABPerson personWithFirstName:@"Bart" - lastName:@"Simpson"]; - STAssertNotNil(person, nil); - STAssertTrue([book_ addRecord:person], nil); - STAssertTrue([book_ save], nil); - STAssertTrue([group addMember:person], nil); - STAssertTrue([book_ addRecord:group], nil); - STAssertTrue([book_ save], nil); - members = [group members]; - STAssertEquals([members count], (NSUInteger)1, @"Members: %@", members); - STAssertTrue([group removeMember:person], nil); - STAssertFalse([group removeMember:person], nil); - STAssertFalse([group removeMember:nil], nil); - STAssertTrue([book_ removeRecord:group], nil); - STAssertTrue([book_ removeRecord:person], nil); - STAssertTrue([book_ save], nil); -} - - -- (void)testMultiValues { - STAssertThrows([[GTMABMultiValue alloc] init], nil); - STAssertThrows([[GTMABMutableMultiValue alloc] init], nil); - GTMABMultiValue *value = [[GTMABMultiValue alloc] initWithMultiValue:nil]; - STAssertNil(value, nil); - GTMABMutableMultiValue *mutValue - = [GTMABMutableMultiValue valueWithPropertyType:kABInvalidPropertyType]; - STAssertNil(mutValue, nil); - mutValue - = [[[GTMABMutableMultiValue alloc] - initWithMutableMultiValue:nil] autorelease]; - STAssertNil(mutValue, nil); - mutValue - = [[[GTMABMutableMultiValue alloc] - initWithMultiValue:nil] autorelease]; - STAssertNil(mutValue, nil); - const ABPropertyType types[] = { - kABStringPropertyType, - kABIntegerPropertyType, - kABRealPropertyType, - kABDateTimePropertyType, - kABDictionaryPropertyType, - kABMultiStringPropertyType, - kABMultiIntegerPropertyType, - kABMultiRealPropertyType, - kABMultiDateTimePropertyType, - kABMultiDictionaryPropertyType - }; - for (size_t i = 0; i < sizeof(types) / sizeof(ABPropertyType); ++i) { - mutValue = [GTMABMutableMultiValue valueWithPropertyType:types[i]]; - STAssertNotNil(mutValue, nil); - // Oddly the Apple APIs allow you to create a mutable multi value with - // either a property type of kABFooPropertyType or kABMultiFooPropertyType - // and apparently you get back basically the same thing. However if you - // ask a type that you created with kABMultiFooPropertyType for it's type - // it returns just kABFooPropertyType. - STAssertEquals([mutValue propertyType], - types[i] & ~kABMultiValueMask, nil); - } - mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABStringPropertyType]; - STAssertNotNil(mutValue, nil); - value = [[mutValue copy] autorelease]; - STAssertEqualObjects([value class], [GTMABMultiValue class], nil); - mutValue = [[value mutableCopy] autorelease]; - STAssertEqualObjects([mutValue class], [GTMABMutableMultiValue class], nil); - STAssertEquals([mutValue count], (NSUInteger)0, nil); - STAssertNil([mutValue valueAtIndex:0], nil); - STAssertNil([mutValue labelAtIndex:0], nil); - STAssertEquals([mutValue identifierAtIndex:0], - kABMultiValueInvalidIdentifier, nil); - STAssertEquals([mutValue propertyType], - (ABPropertyType)kABStringPropertyType, nil); - ABMultiValueIdentifier ident = [mutValue addValue:nil - withLabel:kABHomeLabel]; - STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); - ident = [mutValue addValue:@"val1" - withLabel:nil]; - STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); - ident = [mutValue insertValue:@"val1" - withLabel:nil - atIndex:0]; - STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); - ident = [mutValue insertValue:nil - withLabel:kABHomeLabel - atIndex:0]; - STAssertEquals(ident, kABMultiValueInvalidIdentifier, nil); - ident = [mutValue addValue:@"val1" - withLabel:kABHomeLabel]; - STAssertNotEquals(ident, kABMultiValueInvalidIdentifier, nil); - ABMultiValueIdentifier identCheck = [mutValue identifierAtIndex:0]; - STAssertEquals(ident, identCheck, nil); - NSUInteger idx = [mutValue indexForIdentifier:ident]; - STAssertEquals(idx, (NSUInteger)0, nil); - STAssertTrue([mutValue replaceLabelAtIndex:0 - withLabel:kABWorkLabel], nil); - STAssertFalse([mutValue replaceLabelAtIndex:10 - withLabel:kABWorkLabel], nil); - STAssertTrue([mutValue replaceValueAtIndex:0 - withValue:@"newVal1"], nil); - STAssertFalse([mutValue replaceValueAtIndex:10 - withValue:@"newVal1"], nil); - - STAssertEqualObjects([mutValue valueForIdentifier:ident], @"newVal1", nil); - STAssertEqualObjects([mutValue labelForIdentifier:ident], - (NSString *)kABWorkLabel, nil); - - ABMultiValueIdentifier ident2 = [mutValue insertValue:@"val2" - withLabel:kABOtherLabel - atIndex:0]; - STAssertNotEquals(ident2, kABMultiValueInvalidIdentifier, nil); - STAssertNotEquals(ident2, ident, nil); - ABMultiValueIdentifier ident3 = [mutValue insertValue:@"val3" - withLabel:kABPersonPhoneMainLabel - atIndex:10]; - STAssertEquals(ident3, kABMultiValueInvalidIdentifier, nil); - NSUInteger idx3 = [mutValue indexForIdentifier:ident3]; - STAssertEquals(idx3, (NSUInteger)NSNotFound, nil); - STAssertTrue([mutValue removeValueAndLabelAtIndex:1], nil); - STAssertFalse([mutValue removeValueAndLabelAtIndex:1], nil); - - NSUInteger idx4 - = [mutValue indexForIdentifier:kABMultiValueInvalidIdentifier]; - STAssertEquals(idx4, (NSUInteger)NSNotFound, nil); - - STAssertNotNULL([mutValue multiValueRef], nil); - - // Enumerator test - mutValue = [GTMABMutableMultiValue valueWithPropertyType:kABIntegerPropertyType]; - STAssertNotNil(mutValue, nil); - for (int i = 0; i < 100; i++) { - NSString *label = [NSString stringWithFormat:@"label %d", i]; - NSNumber *val = [NSNumber numberWithInt:i]; - STAssertNotEquals([mutValue addValue:val - withLabel:(CFStringRef)label], - kABMultiValueInvalidIdentifier, nil); - } - int count = 0; - for (NSString *label in [mutValue labelEnumerator]) { - NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; - STAssertEqualObjects(label, testLabel, nil); - } - count = 0; - value = [[mutValue copy] autorelease]; - for (NSNumber *val in [value valueEnumerator]) { - STAssertEqualObjects(val, [NSNumber numberWithInt:count++], nil); - } - - // Test messing with the values while we're enumerating them - NSEnumerator *labelEnum = [mutValue labelEnumerator]; - NSEnumerator *valueEnum = [mutValue valueEnumerator]; - STAssertNotNil(labelEnum, nil); - STAssertNotNil(valueEnum, nil); - STAssertNotNil([labelEnum nextObject], nil); - STAssertNotNil([valueEnum nextObject], nil); - STAssertTrue([mutValue removeValueAndLabelAtIndex:0], nil); - STAssertThrows([labelEnum nextObject], nil); - STAssertThrows([valueEnum nextObject], nil); - - // Test messing with the values while we're fast enumerating them - // Should throw an exception on the second access. - BOOL exceptionThrown = NO; - // Start at one because we removed index 0 above. - count = 1; - @try { - for (NSString *label in [mutValue labelEnumerator]) { - NSString *testLabel = [NSString stringWithFormat:@"label %d", count++]; - STAssertEqualObjects(label, testLabel, nil); - STAssertTrue([mutValue removeValueAndLabelAtIndex:50], nil); - } - } @catch(NSException *e) { - STAssertEqualObjects([e name], NSGenericException, @"Got %@ instead", e); - STAssertEquals(count, 2, - @"Should have caught it on the second access"); - exceptionThrown = YES; - } // COV_NF_LINE - because we always catch, this brace doesn't get exec'd - STAssertTrue(exceptionThrown, @"We should have thrown an exception" - @" because the values under the enumerator were modified"); - -} - -- (void)testRadar6208390 { - ABPropertyType types[] = { - kABStringPropertyType, - kABIntegerPropertyType, - kABRealPropertyType, - kABDateTimePropertyType, - kABDictionaryPropertyType - }; - for (size_t j = 0; j < sizeof(types) / sizeof(ABPropertyType); ++j) { - ABPropertyType type = types[j]; - ABMultiValueRef ref = ABMultiValueCreateMutable(type); - STAssertNotNULL(ref, nil); - NSString *label = [[NSString alloc] initWithString:@"label"]; - STAssertNotNil(label, nil); - id val = nil; - switch (type) { - case kABDictionaryPropertyType: - val = [[NSDictionary alloc] initWithObjectsAndKeys:@"1", @"1", nil]; - break; - - case kABStringPropertyType: - val = [[NSString alloc] initWithFormat:@"value %d"]; - break; - - case kABIntegerPropertyType: - case kABRealPropertyType: - val = [[NSNumber alloc] initWithInt:143]; - break; - - case kABDateTimePropertyType: - val = [[NSDate alloc] init]; - break; - } - STAssertNotNil(val, - @"Testing type %d, %@", type, val); - NSUInteger firstRetainCount = [val retainCount]; - STAssertNotEquals(firstRetainCount, - (NSUInteger)0, - @"Testing type %d, %@", type, val); - - ABMultiValueIdentifier identifier; - STAssertTrue(ABMultiValueAddValueAndLabel(ref, - val, - (CFStringRef)label, - &identifier), - @"Testing type %d, %@", type, val); - NSUInteger secondRetainCount = [val retainCount]; - STAssertEquals(firstRetainCount + 1, - secondRetainCount, - @"Testing type %d, %@", type, val); - [label release]; - [val release]; - NSUInteger thirdRetainCount = [val retainCount]; - STAssertEquals(firstRetainCount, - thirdRetainCount, - @"Testing type %d, %@", type, val); - - id oldVal = val; - val = (id)ABMultiValueCopyValueAtIndex(ref, 0); - NSUInteger fourthRetainCount = [val retainCount]; - - // kABDictionaryPropertyTypes appear to do an actual copy, so the retain - // count checking trick won't work. We only check the retain count if - // we didn't get a new version. - if (val == oldVal) { - if (type == kABIntegerPropertyType - || type == kABRealPropertyType) { - // We are verifying that yes indeed 6208390 is still broken - STAssertEquals(fourthRetainCount, - thirdRetainCount, - @"Testing type %d, %@. If you see this error it may " - @"be time to update the code to change retain behaviors" - @"with this os version", type, val); - } else { - STAssertEquals(fourthRetainCount, - thirdRetainCount + 1, - @"Testing type %d, %@", type, val); - [val release]; - } - } else { - [val release]; - } - CFRelease(ref); - } -} - -// Globals used by testRadar6240394. -static ABPropertyID gGTMTestID; -static const ABPropertyID *gGTMTestIDPtr; - -void __attribute__((constructor))SetUpIDForTestRadar6240394(void) { - // These must be set up BEFORE ABAddressBookCreate is called. - gGTMTestID = kABPersonLastNameProperty; - gGTMTestIDPtr = &kABPersonLastNameProperty; -} - -- (void)testRadar6240394 { - // As of iPhone SDK 2.1, the property IDs aren't initialized until - // ABAddressBookCreate is actually called. They will return zero until - // then. Logged as radar 6240394. - STAssertEquals(gGTMTestID, 0, @"If this isn't zero, Apple has fixed 6240394"); - (void)ABAddressBookCreate(); - STAssertEquals(*gGTMTestIDPtr, kABPersonLastNameProperty, - @"If this doesn't work, something else has broken"); -} -@end -- cgit v1.2.3