| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "base/mac/foundation_util.h" |
| |
| #include "base/basictypes.h" |
| #include "base/file_path.h" |
| #include "base/mac/scoped_cftyperef.h" |
| #include "base/mac/scoped_nsautorelease_pool.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #import "testing/gtest_mac.h" |
| |
| TEST(FoundationUtilTest, CFCast) { |
| // Build out the CF types to be tested as empty containers. |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_array( |
| CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_array_mutable( |
| CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_bag( |
| CFBagCreate(NULL, NULL, 0, &kCFTypeBagCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_bag_mutable( |
| CFBagCreateMutable(NULL, 0, &kCFTypeBagCallBacks)); |
| CFTypeRef test_bool = kCFBooleanTrue; |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_data( |
| CFDataCreate(NULL, NULL, 0)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_data_mutable( |
| CFDataCreateMutable(NULL, 0)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_date( |
| CFDateCreate(NULL, 0)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_dict( |
| CFDictionaryCreate(NULL, NULL, NULL, 0, |
| &kCFCopyStringDictionaryKeyCallBacks, |
| &kCFTypeDictionaryValueCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_dict_mutable( |
| CFDictionaryCreateMutable(NULL, 0, |
| &kCFCopyStringDictionaryKeyCallBacks, |
| &kCFTypeDictionaryValueCallBacks)); |
| int int_val = 256; |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_number( |
| CFNumberCreate(NULL, kCFNumberIntType, &int_val)); |
| CFTypeRef test_null = kCFNull; |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_set( |
| CFSetCreate(NULL, NULL, 0, &kCFTypeSetCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_set_mutable( |
| CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks)); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_str( |
| CFStringCreateWithBytes(NULL, NULL, 0, kCFStringEncodingASCII, |
| false)); |
| CFTypeRef test_str_const = CFSTR("hello"); |
| base::mac::ScopedCFTypeRef<CFTypeRef> test_str_mutable( |
| CFStringCreateMutable(NULL, 0)); |
| |
| // Make sure the allocations of CF types are good. |
| EXPECT_TRUE(test_array); |
| EXPECT_TRUE(test_array_mutable); |
| EXPECT_TRUE(test_bag); |
| EXPECT_TRUE(test_bag_mutable); |
| EXPECT_TRUE(test_bool); |
| EXPECT_TRUE(test_data); |
| EXPECT_TRUE(test_data_mutable); |
| EXPECT_TRUE(test_date); |
| EXPECT_TRUE(test_dict); |
| EXPECT_TRUE(test_dict_mutable); |
| EXPECT_TRUE(test_number); |
| EXPECT_TRUE(test_null); |
| EXPECT_TRUE(test_set); |
| EXPECT_TRUE(test_set_mutable); |
| EXPECT_TRUE(test_str); |
| EXPECT_TRUE(test_str_const); |
| EXPECT_TRUE(test_str_mutable); |
| |
| // Casting the CFTypeRef objects correctly provides the same pointer. |
| EXPECT_EQ(test_array, base::mac::CFCast<CFArrayRef>(test_array)); |
| EXPECT_EQ(test_array_mutable, |
| base::mac::CFCast<CFArrayRef>(test_array_mutable)); |
| EXPECT_EQ(test_bag, base::mac::CFCast<CFBagRef>(test_bag)); |
| EXPECT_EQ(test_bag_mutable, |
| base::mac::CFCast<CFBagRef>(test_bag_mutable)); |
| EXPECT_EQ(test_bool, base::mac::CFCast<CFBooleanRef>(test_bool)); |
| EXPECT_EQ(test_data, base::mac::CFCast<CFDataRef>(test_data)); |
| EXPECT_EQ(test_data_mutable, |
| base::mac::CFCast<CFDataRef>(test_data_mutable)); |
| EXPECT_EQ(test_date, base::mac::CFCast<CFDateRef>(test_date)); |
| EXPECT_EQ(test_dict, base::mac::CFCast<CFDictionaryRef>(test_dict)); |
| EXPECT_EQ(test_dict_mutable, |
| base::mac::CFCast<CFDictionaryRef>(test_dict_mutable)); |
| EXPECT_EQ(test_number, base::mac::CFCast<CFNumberRef>(test_number)); |
| EXPECT_EQ(test_null, base::mac::CFCast<CFNullRef>(test_null)); |
| EXPECT_EQ(test_set, base::mac::CFCast<CFSetRef>(test_set)); |
| EXPECT_EQ(test_set_mutable, base::mac::CFCast<CFSetRef>(test_set_mutable)); |
| EXPECT_EQ(test_str, base::mac::CFCast<CFStringRef>(test_str)); |
| EXPECT_EQ(test_str_const, base::mac::CFCast<CFStringRef>(test_str_const)); |
| EXPECT_EQ(test_str_mutable, |
| base::mac::CFCast<CFStringRef>(test_str_mutable)); |
| |
| // When given an incorrect CF cast, provide NULL. |
| EXPECT_FALSE(base::mac::CFCast<CFStringRef>(test_array)); |
| EXPECT_FALSE(base::mac::CFCast<CFStringRef>(test_array_mutable)); |
| EXPECT_FALSE(base::mac::CFCast<CFStringRef>(test_bag)); |
| EXPECT_FALSE(base::mac::CFCast<CFSetRef>(test_bag_mutable)); |
| EXPECT_FALSE(base::mac::CFCast<CFSetRef>(test_bool)); |
| EXPECT_FALSE(base::mac::CFCast<CFNullRef>(test_data)); |
| EXPECT_FALSE(base::mac::CFCast<CFDictionaryRef>(test_data_mutable)); |
| EXPECT_FALSE(base::mac::CFCast<CFDictionaryRef>(test_date)); |
| EXPECT_FALSE(base::mac::CFCast<CFNumberRef>(test_dict)); |
| EXPECT_FALSE(base::mac::CFCast<CFDateRef>(test_dict_mutable)); |
| EXPECT_FALSE(base::mac::CFCast<CFDataRef>(test_number)); |
| EXPECT_FALSE(base::mac::CFCast<CFDataRef>(test_null)); |
| EXPECT_FALSE(base::mac::CFCast<CFBooleanRef>(test_set)); |
| EXPECT_FALSE(base::mac::CFCast<CFBagRef>(test_set_mutable)); |
| EXPECT_FALSE(base::mac::CFCast<CFBagRef>(test_str)); |
| EXPECT_FALSE(base::mac::CFCast<CFArrayRef>(test_str_const)); |
| EXPECT_FALSE(base::mac::CFCast<CFArrayRef>(test_str_mutable)); |
| |
| // Giving a NULL provides a NULL. |
| EXPECT_FALSE(base::mac::CFCast<CFArrayRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFBagRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFBooleanRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFDataRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFDateRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFDictionaryRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFNullRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFNumberRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFSetRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCast<CFStringRef>(NULL)); |
| |
| // CFCastStrict: correct cast results in correct pointer being returned. |
| EXPECT_EQ(test_array, base::mac::CFCastStrict<CFArrayRef>(test_array)); |
| EXPECT_EQ(test_array_mutable, |
| base::mac::CFCastStrict<CFArrayRef>(test_array_mutable)); |
| EXPECT_EQ(test_bag, base::mac::CFCastStrict<CFBagRef>(test_bag)); |
| EXPECT_EQ(test_bag_mutable, |
| base::mac::CFCastStrict<CFBagRef>(test_bag_mutable)); |
| EXPECT_EQ(test_bool, base::mac::CFCastStrict<CFBooleanRef>(test_bool)); |
| EXPECT_EQ(test_data, base::mac::CFCastStrict<CFDataRef>(test_data)); |
| EXPECT_EQ(test_data_mutable, |
| base::mac::CFCastStrict<CFDataRef>(test_data_mutable)); |
| EXPECT_EQ(test_date, base::mac::CFCastStrict<CFDateRef>(test_date)); |
| EXPECT_EQ(test_dict, base::mac::CFCastStrict<CFDictionaryRef>(test_dict)); |
| EXPECT_EQ(test_dict_mutable, |
| base::mac::CFCastStrict<CFDictionaryRef>(test_dict_mutable)); |
| EXPECT_EQ(test_number, base::mac::CFCastStrict<CFNumberRef>(test_number)); |
| EXPECT_EQ(test_null, base::mac::CFCastStrict<CFNullRef>(test_null)); |
| EXPECT_EQ(test_set, base::mac::CFCastStrict<CFSetRef>(test_set)); |
| EXPECT_EQ(test_set_mutable, |
| base::mac::CFCastStrict<CFSetRef>(test_set_mutable)); |
| EXPECT_EQ(test_str, base::mac::CFCastStrict<CFStringRef>(test_str)); |
| EXPECT_EQ(test_str_const, |
| base::mac::CFCastStrict<CFStringRef>(test_str_const)); |
| EXPECT_EQ(test_str_mutable, |
| base::mac::CFCastStrict<CFStringRef>(test_str_mutable)); |
| |
| // CFCastStrict: Giving a NULL provides a NULL. |
| EXPECT_FALSE(base::mac::CFCastStrict<CFArrayRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFBagRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFBooleanRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFDataRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFDateRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFDictionaryRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFNullRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFNumberRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFSetRef>(NULL)); |
| EXPECT_FALSE(base::mac::CFCastStrict<CFStringRef>(NULL)); |
| } |
| |
| TEST(FoundationUtilTest, ObjCCast) { |
| base::mac::ScopedNSAutoreleasePool pool; |
| |
| id test_array = [NSArray array]; |
| id test_array_mutable = [NSMutableArray array]; |
| id test_data = [NSData data]; |
| id test_data_mutable = [NSMutableData dataWithCapacity:10]; |
| id test_date = [NSDate date]; |
| id test_dict = |
| [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:42] |
| forKey:@"meaning"]; |
| id test_dict_mutable = [NSMutableDictionary dictionaryWithCapacity:10]; |
| id test_number = [NSNumber numberWithInt:42]; |
| id test_null = [NSNull null]; |
| id test_set = [NSSet setWithObject:@"string object"]; |
| id test_set_mutable = [NSMutableSet setWithCapacity:10]; |
| id test_str = [NSString string]; |
| id test_str_const = @"bonjour"; |
| id test_str_mutable = [NSMutableString stringWithCapacity:10]; |
| |
| // Make sure the allocations of NS types are good. |
| EXPECT_TRUE(test_array); |
| EXPECT_TRUE(test_array_mutable); |
| EXPECT_TRUE(test_data); |
| EXPECT_TRUE(test_data_mutable); |
| EXPECT_TRUE(test_date); |
| EXPECT_TRUE(test_dict); |
| EXPECT_TRUE(test_dict_mutable); |
| EXPECT_TRUE(test_number); |
| EXPECT_TRUE(test_null); |
| EXPECT_TRUE(test_set); |
| EXPECT_TRUE(test_set_mutable); |
| EXPECT_TRUE(test_str); |
| EXPECT_TRUE(test_str_const); |
| EXPECT_TRUE(test_str_mutable); |
| |
| // Casting the id correctly provides the same pointer. |
| EXPECT_EQ(test_array, base::mac::ObjCCast<NSArray>(test_array)); |
| EXPECT_EQ(test_array_mutable, |
| base::mac::ObjCCast<NSArray>(test_array_mutable)); |
| EXPECT_EQ(test_data, base::mac::ObjCCast<NSData>(test_data)); |
| EXPECT_EQ(test_data_mutable, |
| base::mac::ObjCCast<NSData>(test_data_mutable)); |
| EXPECT_EQ(test_date, base::mac::ObjCCast<NSDate>(test_date)); |
| EXPECT_EQ(test_dict, base::mac::ObjCCast<NSDictionary>(test_dict)); |
| EXPECT_EQ(test_dict_mutable, |
| base::mac::ObjCCast<NSDictionary>(test_dict_mutable)); |
| EXPECT_EQ(test_number, base::mac::ObjCCast<NSNumber>(test_number)); |
| EXPECT_EQ(test_null, base::mac::ObjCCast<NSNull>(test_null)); |
| EXPECT_EQ(test_set, base::mac::ObjCCast<NSSet>(test_set)); |
| EXPECT_EQ(test_set_mutable, base::mac::ObjCCast<NSSet>(test_set_mutable)); |
| EXPECT_EQ(test_str, base::mac::ObjCCast<NSString>(test_str)); |
| EXPECT_EQ(test_str_const, base::mac::ObjCCast<NSString>(test_str_const)); |
| EXPECT_EQ(test_str_mutable, |
| base::mac::ObjCCast<NSString>(test_str_mutable)); |
| |
| // When given an incorrect ObjC cast, provide nil. |
| EXPECT_FALSE(base::mac::ObjCCast<NSString>(test_array)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSString>(test_array_mutable)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSString>(test_data)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSString>(test_data_mutable)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSSet>(test_date)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSSet>(test_dict)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSNumber>(test_dict_mutable)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSNull>(test_number)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSDictionary>(test_null)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSDictionary>(test_set)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSDate>(test_set_mutable)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSData>(test_str)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSData>(test_str_const)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSArray>(test_str_mutable)); |
| |
| // Giving a nil provides a nil. |
| EXPECT_FALSE(base::mac::ObjCCast<NSArray>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSData>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSDate>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSDictionary>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSNull>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSNumber>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSSet>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCast<NSString>(nil)); |
| |
| // ObjCCastStrict: correct cast results in correct pointer being returned. |
| EXPECT_EQ(test_array, base::mac::ObjCCastStrict<NSArray>(test_array)); |
| EXPECT_EQ(test_array_mutable, |
| base::mac::ObjCCastStrict<NSArray>(test_array_mutable)); |
| EXPECT_EQ(test_data, base::mac::ObjCCastStrict<NSData>(test_data)); |
| EXPECT_EQ(test_data_mutable, |
| base::mac::ObjCCastStrict<NSData>(test_data_mutable)); |
| EXPECT_EQ(test_date, base::mac::ObjCCastStrict<NSDate>(test_date)); |
| EXPECT_EQ(test_dict, base::mac::ObjCCastStrict<NSDictionary>(test_dict)); |
| EXPECT_EQ(test_dict_mutable, |
| base::mac::ObjCCastStrict<NSDictionary>(test_dict_mutable)); |
| EXPECT_EQ(test_number, base::mac::ObjCCastStrict<NSNumber>(test_number)); |
| EXPECT_EQ(test_null, base::mac::ObjCCastStrict<NSNull>(test_null)); |
| EXPECT_EQ(test_set, base::mac::ObjCCastStrict<NSSet>(test_set)); |
| EXPECT_EQ(test_set_mutable, |
| base::mac::ObjCCastStrict<NSSet>(test_set_mutable)); |
| EXPECT_EQ(test_str, base::mac::ObjCCastStrict<NSString>(test_str)); |
| EXPECT_EQ(test_str_const, |
| base::mac::ObjCCastStrict<NSString>(test_str_const)); |
| EXPECT_EQ(test_str_mutable, |
| base::mac::ObjCCastStrict<NSString>(test_str_mutable)); |
| |
| // ObjCCastStrict: Giving a nil provides a nil. |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSArray>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSData>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSDate>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSDictionary>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSNull>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSNumber>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSSet>(nil)); |
| EXPECT_FALSE(base::mac::ObjCCastStrict<NSString>(nil)); |
| } |
| |
| TEST(FoundationUtilTest, GetValueFromDictionary) { |
| int one = 1, two = 2, three = 3; |
| |
| base::mac::ScopedCFTypeRef<CFNumberRef> cf_one( |
| CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &one)); |
| base::mac::ScopedCFTypeRef<CFNumberRef> cf_two( |
| CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &two)); |
| base::mac::ScopedCFTypeRef<CFNumberRef> cf_three( |
| CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &three)); |
| |
| CFStringRef keys[] = { CFSTR("one"), CFSTR("two"), CFSTR("three") }; |
| CFNumberRef values[] = { cf_one, cf_two, cf_three }; |
| |
| COMPILE_ASSERT(arraysize(keys) == arraysize(values), |
| keys_and_values_arraysizes_are_different); |
| |
| base::mac::ScopedCFTypeRef<CFDictionaryRef> test_dict( |
| CFDictionaryCreate(kCFAllocatorDefault, |
| reinterpret_cast<const void**>(keys), |
| reinterpret_cast<const void**>(values), |
| arraysize(values), |
| &kCFCopyStringDictionaryKeyCallBacks, |
| &kCFTypeDictionaryValueCallBacks)); |
| |
| // base::mac::GetValueFromDictionary<>(_, _) should produce the correct |
| // expected output. |
| EXPECT_EQ(values[0], |
| base::mac::GetValueFromDictionary<CFNumberRef>(test_dict, |
| CFSTR("one"))); |
| EXPECT_EQ(values[1], |
| base::mac::GetValueFromDictionary<CFNumberRef>(test_dict, |
| CFSTR("two"))); |
| EXPECT_EQ(values[2], |
| base::mac::GetValueFromDictionary<CFNumberRef>(test_dict, |
| CFSTR("three"))); |
| |
| // Bad input should produce bad output. |
| EXPECT_FALSE(base::mac::GetValueFromDictionary<CFNumberRef>(test_dict, |
| CFSTR("four"))); |
| EXPECT_FALSE(base::mac::GetValueFromDictionary<CFStringRef>(test_dict, |
| CFSTR("one"))); |
| } |
| |
| TEST(FoundationUtilTest, FilePathToNSString) { |
| EXPECT_NSEQ(nil, base::mac::FilePathToNSString(FilePath())); |
| EXPECT_NSEQ(@"/a/b", base::mac::FilePathToNSString(FilePath("/a/b"))); |
| } |
| |
| TEST(FoundationUtilTest, NSStringToFilePath) { |
| EXPECT_EQ(FilePath(), base::mac::NSStringToFilePath(nil)); |
| EXPECT_EQ(FilePath(), base::mac::NSStringToFilePath(@"")); |
| EXPECT_EQ(FilePath("/a/b"), base::mac::NSStringToFilePath(@"/a/b")); |
| } |