1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/mac/foundation_util.h" 6 7 #include "base/basictypes.h" 8 #include "base/compiler_specific.h" 9 #include "base/files/file_path.h" 10 #include "base/format_macros.h" 11 #include "base/mac/scoped_cftyperef.h" 12 #include "base/mac/scoped_nsautorelease_pool.h" 13 #include "base/strings/stringprintf.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 #import "testing/gtest_mac.h" 16 17 namespace base { 18 namespace mac { 19 20 TEST(FoundationUtilTest, CFCast) { 21 // Build out the CF types to be tested as empty containers. 22 ScopedCFTypeRef<CFTypeRef> test_array( 23 CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks)); 24 ScopedCFTypeRef<CFTypeRef> test_array_mutable( 25 CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks)); 26 ScopedCFTypeRef<CFTypeRef> test_bag( 27 CFBagCreate(NULL, NULL, 0, &kCFTypeBagCallBacks)); 28 ScopedCFTypeRef<CFTypeRef> test_bag_mutable( 29 CFBagCreateMutable(NULL, 0, &kCFTypeBagCallBacks)); 30 CFTypeRef test_bool = kCFBooleanTrue; 31 ScopedCFTypeRef<CFTypeRef> test_data( 32 CFDataCreate(NULL, NULL, 0)); 33 ScopedCFTypeRef<CFTypeRef> test_data_mutable( 34 CFDataCreateMutable(NULL, 0)); 35 ScopedCFTypeRef<CFTypeRef> test_date( 36 CFDateCreate(NULL, 0)); 37 ScopedCFTypeRef<CFTypeRef> test_dict( 38 CFDictionaryCreate(NULL, NULL, NULL, 0, 39 &kCFCopyStringDictionaryKeyCallBacks, 40 &kCFTypeDictionaryValueCallBacks)); 41 ScopedCFTypeRef<CFTypeRef> test_dict_mutable( 42 CFDictionaryCreateMutable(NULL, 0, 43 &kCFCopyStringDictionaryKeyCallBacks, 44 &kCFTypeDictionaryValueCallBacks)); 45 int int_val = 256; 46 ScopedCFTypeRef<CFTypeRef> test_number( 47 CFNumberCreate(NULL, kCFNumberIntType, &int_val)); 48 CFTypeRef test_null = kCFNull; 49 ScopedCFTypeRef<CFTypeRef> test_set( 50 CFSetCreate(NULL, NULL, 0, &kCFTypeSetCallBacks)); 51 ScopedCFTypeRef<CFTypeRef> test_set_mutable( 52 CFSetCreateMutable(NULL, 0, &kCFTypeSetCallBacks)); 53 ScopedCFTypeRef<CFTypeRef> test_str( 54 CFStringCreateWithBytes(NULL, NULL, 0, kCFStringEncodingASCII, false)); 55 CFTypeRef test_str_const = CFSTR("hello"); 56 ScopedCFTypeRef<CFTypeRef> test_str_mutable(CFStringCreateMutable(NULL, 0)); 57 58 // Make sure the allocations of CF types are good. 59 EXPECT_TRUE(test_array); 60 EXPECT_TRUE(test_array_mutable); 61 EXPECT_TRUE(test_bag); 62 EXPECT_TRUE(test_bag_mutable); 63 EXPECT_TRUE(test_bool); 64 EXPECT_TRUE(test_data); 65 EXPECT_TRUE(test_data_mutable); 66 EXPECT_TRUE(test_date); 67 EXPECT_TRUE(test_dict); 68 EXPECT_TRUE(test_dict_mutable); 69 EXPECT_TRUE(test_number); 70 EXPECT_TRUE(test_null); 71 EXPECT_TRUE(test_set); 72 EXPECT_TRUE(test_set_mutable); 73 EXPECT_TRUE(test_str); 74 EXPECT_TRUE(test_str_const); 75 EXPECT_TRUE(test_str_mutable); 76 77 // Casting the CFTypeRef objects correctly provides the same pointer. 78 EXPECT_EQ(test_array, CFCast<CFArrayRef>(test_array)); 79 EXPECT_EQ(test_array_mutable, CFCast<CFArrayRef>(test_array_mutable)); 80 EXPECT_EQ(test_bag, CFCast<CFBagRef>(test_bag)); 81 EXPECT_EQ(test_bag_mutable, CFCast<CFBagRef>(test_bag_mutable)); 82 EXPECT_EQ(test_bool, CFCast<CFBooleanRef>(test_bool)); 83 EXPECT_EQ(test_data, CFCast<CFDataRef>(test_data)); 84 EXPECT_EQ(test_data_mutable, CFCast<CFDataRef>(test_data_mutable)); 85 EXPECT_EQ(test_date, CFCast<CFDateRef>(test_date)); 86 EXPECT_EQ(test_dict, CFCast<CFDictionaryRef>(test_dict)); 87 EXPECT_EQ(test_dict_mutable, CFCast<CFDictionaryRef>(test_dict_mutable)); 88 EXPECT_EQ(test_number, CFCast<CFNumberRef>(test_number)); 89 EXPECT_EQ(test_null, CFCast<CFNullRef>(test_null)); 90 EXPECT_EQ(test_set, CFCast<CFSetRef>(test_set)); 91 EXPECT_EQ(test_set_mutable, CFCast<CFSetRef>(test_set_mutable)); 92 EXPECT_EQ(test_str, CFCast<CFStringRef>(test_str)); 93 EXPECT_EQ(test_str_const, CFCast<CFStringRef>(test_str_const)); 94 EXPECT_EQ(test_str_mutable, CFCast<CFStringRef>(test_str_mutable)); 95 96 // When given an incorrect CF cast, provide NULL. 97 EXPECT_FALSE(CFCast<CFStringRef>(test_array)); 98 EXPECT_FALSE(CFCast<CFStringRef>(test_array_mutable)); 99 EXPECT_FALSE(CFCast<CFStringRef>(test_bag)); 100 EXPECT_FALSE(CFCast<CFSetRef>(test_bag_mutable)); 101 EXPECT_FALSE(CFCast<CFSetRef>(test_bool)); 102 EXPECT_FALSE(CFCast<CFNullRef>(test_data)); 103 EXPECT_FALSE(CFCast<CFDictionaryRef>(test_data_mutable)); 104 EXPECT_FALSE(CFCast<CFDictionaryRef>(test_date)); 105 EXPECT_FALSE(CFCast<CFNumberRef>(test_dict)); 106 EXPECT_FALSE(CFCast<CFDateRef>(test_dict_mutable)); 107 EXPECT_FALSE(CFCast<CFDataRef>(test_number)); 108 EXPECT_FALSE(CFCast<CFDataRef>(test_null)); 109 EXPECT_FALSE(CFCast<CFBooleanRef>(test_set)); 110 EXPECT_FALSE(CFCast<CFBagRef>(test_set_mutable)); 111 EXPECT_FALSE(CFCast<CFBagRef>(test_str)); 112 EXPECT_FALSE(CFCast<CFArrayRef>(test_str_const)); 113 EXPECT_FALSE(CFCast<CFArrayRef>(test_str_mutable)); 114 115 // Giving a NULL provides a NULL. 116 EXPECT_FALSE(CFCast<CFArrayRef>(NULL)); 117 EXPECT_FALSE(CFCast<CFBagRef>(NULL)); 118 EXPECT_FALSE(CFCast<CFBooleanRef>(NULL)); 119 EXPECT_FALSE(CFCast<CFDataRef>(NULL)); 120 EXPECT_FALSE(CFCast<CFDateRef>(NULL)); 121 EXPECT_FALSE(CFCast<CFDictionaryRef>(NULL)); 122 EXPECT_FALSE(CFCast<CFNullRef>(NULL)); 123 EXPECT_FALSE(CFCast<CFNumberRef>(NULL)); 124 EXPECT_FALSE(CFCast<CFSetRef>(NULL)); 125 EXPECT_FALSE(CFCast<CFStringRef>(NULL)); 126 127 // CFCastStrict: correct cast results in correct pointer being returned. 128 EXPECT_EQ(test_array, CFCastStrict<CFArrayRef>(test_array)); 129 EXPECT_EQ(test_array_mutable, CFCastStrict<CFArrayRef>(test_array_mutable)); 130 EXPECT_EQ(test_bag, CFCastStrict<CFBagRef>(test_bag)); 131 EXPECT_EQ(test_bag_mutable, CFCastStrict<CFBagRef>(test_bag_mutable)); 132 EXPECT_EQ(test_bool, CFCastStrict<CFBooleanRef>(test_bool)); 133 EXPECT_EQ(test_data, CFCastStrict<CFDataRef>(test_data)); 134 EXPECT_EQ(test_data_mutable, CFCastStrict<CFDataRef>(test_data_mutable)); 135 EXPECT_EQ(test_date, CFCastStrict<CFDateRef>(test_date)); 136 EXPECT_EQ(test_dict, CFCastStrict<CFDictionaryRef>(test_dict)); 137 EXPECT_EQ(test_dict_mutable, 138 CFCastStrict<CFDictionaryRef>(test_dict_mutable)); 139 EXPECT_EQ(test_number, CFCastStrict<CFNumberRef>(test_number)); 140 EXPECT_EQ(test_null, CFCastStrict<CFNullRef>(test_null)); 141 EXPECT_EQ(test_set, CFCastStrict<CFSetRef>(test_set)); 142 EXPECT_EQ(test_set_mutable, CFCastStrict<CFSetRef>(test_set_mutable)); 143 EXPECT_EQ(test_str, CFCastStrict<CFStringRef>(test_str)); 144 EXPECT_EQ(test_str_const, CFCastStrict<CFStringRef>(test_str_const)); 145 EXPECT_EQ(test_str_mutable, CFCastStrict<CFStringRef>(test_str_mutable)); 146 147 // CFCastStrict: Giving a NULL provides a NULL. 148 EXPECT_FALSE(CFCastStrict<CFArrayRef>(NULL)); 149 EXPECT_FALSE(CFCastStrict<CFBagRef>(NULL)); 150 EXPECT_FALSE(CFCastStrict<CFBooleanRef>(NULL)); 151 EXPECT_FALSE(CFCastStrict<CFDataRef>(NULL)); 152 EXPECT_FALSE(CFCastStrict<CFDateRef>(NULL)); 153 EXPECT_FALSE(CFCastStrict<CFDictionaryRef>(NULL)); 154 EXPECT_FALSE(CFCastStrict<CFNullRef>(NULL)); 155 EXPECT_FALSE(CFCastStrict<CFNumberRef>(NULL)); 156 EXPECT_FALSE(CFCastStrict<CFSetRef>(NULL)); 157 EXPECT_FALSE(CFCastStrict<CFStringRef>(NULL)); 158 } 159 160 TEST(FoundationUtilTest, ObjCCast) { 161 ScopedNSAutoreleasePool pool; 162 163 id test_array = [NSArray array]; 164 id test_array_mutable = [NSMutableArray array]; 165 id test_data = [NSData data]; 166 id test_data_mutable = [NSMutableData dataWithCapacity:10]; 167 id test_date = [NSDate date]; 168 id test_dict = 169 [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:42] 170 forKey:@"meaning"]; 171 id test_dict_mutable = [NSMutableDictionary dictionaryWithCapacity:10]; 172 id test_number = [NSNumber numberWithInt:42]; 173 id test_null = [NSNull null]; 174 id test_set = [NSSet setWithObject:@"string object"]; 175 id test_set_mutable = [NSMutableSet setWithCapacity:10]; 176 id test_str = [NSString string]; 177 id test_str_const = @"bonjour"; 178 id test_str_mutable = [NSMutableString stringWithCapacity:10]; 179 180 // Make sure the allocations of NS types are good. 181 EXPECT_TRUE(test_array); 182 EXPECT_TRUE(test_array_mutable); 183 EXPECT_TRUE(test_data); 184 EXPECT_TRUE(test_data_mutable); 185 EXPECT_TRUE(test_date); 186 EXPECT_TRUE(test_dict); 187 EXPECT_TRUE(test_dict_mutable); 188 EXPECT_TRUE(test_number); 189 EXPECT_TRUE(test_null); 190 EXPECT_TRUE(test_set); 191 EXPECT_TRUE(test_set_mutable); 192 EXPECT_TRUE(test_str); 193 EXPECT_TRUE(test_str_const); 194 EXPECT_TRUE(test_str_mutable); 195 196 // Casting the id correctly provides the same pointer. 197 EXPECT_EQ(test_array, ObjCCast<NSArray>(test_array)); 198 EXPECT_EQ(test_array_mutable, ObjCCast<NSArray>(test_array_mutable)); 199 EXPECT_EQ(test_data, ObjCCast<NSData>(test_data)); 200 EXPECT_EQ(test_data_mutable, ObjCCast<NSData>(test_data_mutable)); 201 EXPECT_EQ(test_date, ObjCCast<NSDate>(test_date)); 202 EXPECT_EQ(test_dict, ObjCCast<NSDictionary>(test_dict)); 203 EXPECT_EQ(test_dict_mutable, ObjCCast<NSDictionary>(test_dict_mutable)); 204 EXPECT_EQ(test_number, ObjCCast<NSNumber>(test_number)); 205 EXPECT_EQ(test_null, ObjCCast<NSNull>(test_null)); 206 EXPECT_EQ(test_set, ObjCCast<NSSet>(test_set)); 207 EXPECT_EQ(test_set_mutable, ObjCCast<NSSet>(test_set_mutable)); 208 EXPECT_EQ(test_str, ObjCCast<NSString>(test_str)); 209 EXPECT_EQ(test_str_const, ObjCCast<NSString>(test_str_const)); 210 EXPECT_EQ(test_str_mutable, ObjCCast<NSString>(test_str_mutable)); 211 212 // When given an incorrect ObjC cast, provide nil. 213 EXPECT_FALSE(ObjCCast<NSString>(test_array)); 214 EXPECT_FALSE(ObjCCast<NSString>(test_array_mutable)); 215 EXPECT_FALSE(ObjCCast<NSString>(test_data)); 216 EXPECT_FALSE(ObjCCast<NSString>(test_data_mutable)); 217 EXPECT_FALSE(ObjCCast<NSSet>(test_date)); 218 EXPECT_FALSE(ObjCCast<NSSet>(test_dict)); 219 EXPECT_FALSE(ObjCCast<NSNumber>(test_dict_mutable)); 220 EXPECT_FALSE(ObjCCast<NSNull>(test_number)); 221 EXPECT_FALSE(ObjCCast<NSDictionary>(test_null)); 222 EXPECT_FALSE(ObjCCast<NSDictionary>(test_set)); 223 EXPECT_FALSE(ObjCCast<NSDate>(test_set_mutable)); 224 EXPECT_FALSE(ObjCCast<NSData>(test_str)); 225 EXPECT_FALSE(ObjCCast<NSData>(test_str_const)); 226 EXPECT_FALSE(ObjCCast<NSArray>(test_str_mutable)); 227 228 // Giving a nil provides a nil. 229 EXPECT_FALSE(ObjCCast<NSArray>(nil)); 230 EXPECT_FALSE(ObjCCast<NSData>(nil)); 231 EXPECT_FALSE(ObjCCast<NSDate>(nil)); 232 EXPECT_FALSE(ObjCCast<NSDictionary>(nil)); 233 EXPECT_FALSE(ObjCCast<NSNull>(nil)); 234 EXPECT_FALSE(ObjCCast<NSNumber>(nil)); 235 EXPECT_FALSE(ObjCCast<NSSet>(nil)); 236 EXPECT_FALSE(ObjCCast<NSString>(nil)); 237 238 // ObjCCastStrict: correct cast results in correct pointer being returned. 239 EXPECT_EQ(test_array, ObjCCastStrict<NSArray>(test_array)); 240 EXPECT_EQ(test_array_mutable, 241 ObjCCastStrict<NSArray>(test_array_mutable)); 242 EXPECT_EQ(test_data, ObjCCastStrict<NSData>(test_data)); 243 EXPECT_EQ(test_data_mutable, 244 ObjCCastStrict<NSData>(test_data_mutable)); 245 EXPECT_EQ(test_date, ObjCCastStrict<NSDate>(test_date)); 246 EXPECT_EQ(test_dict, ObjCCastStrict<NSDictionary>(test_dict)); 247 EXPECT_EQ(test_dict_mutable, 248 ObjCCastStrict<NSDictionary>(test_dict_mutable)); 249 EXPECT_EQ(test_number, ObjCCastStrict<NSNumber>(test_number)); 250 EXPECT_EQ(test_null, ObjCCastStrict<NSNull>(test_null)); 251 EXPECT_EQ(test_set, ObjCCastStrict<NSSet>(test_set)); 252 EXPECT_EQ(test_set_mutable, 253 ObjCCastStrict<NSSet>(test_set_mutable)); 254 EXPECT_EQ(test_str, ObjCCastStrict<NSString>(test_str)); 255 EXPECT_EQ(test_str_const, 256 ObjCCastStrict<NSString>(test_str_const)); 257 EXPECT_EQ(test_str_mutable, 258 ObjCCastStrict<NSString>(test_str_mutable)); 259 260 // ObjCCastStrict: Giving a nil provides a nil. 261 EXPECT_FALSE(ObjCCastStrict<NSArray>(nil)); 262 EXPECT_FALSE(ObjCCastStrict<NSData>(nil)); 263 EXPECT_FALSE(ObjCCastStrict<NSDate>(nil)); 264 EXPECT_FALSE(ObjCCastStrict<NSDictionary>(nil)); 265 EXPECT_FALSE(ObjCCastStrict<NSNull>(nil)); 266 EXPECT_FALSE(ObjCCastStrict<NSNumber>(nil)); 267 EXPECT_FALSE(ObjCCastStrict<NSSet>(nil)); 268 EXPECT_FALSE(ObjCCastStrict<NSString>(nil)); 269 } 270 271 TEST(FoundationUtilTest, GetValueFromDictionary) { 272 int one = 1, two = 2, three = 3; 273 274 ScopedCFTypeRef<CFNumberRef> cf_one( 275 CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &one)); 276 ScopedCFTypeRef<CFNumberRef> cf_two( 277 CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &two)); 278 ScopedCFTypeRef<CFNumberRef> cf_three( 279 CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &three)); 280 281 CFStringRef keys[] = { CFSTR("one"), CFSTR("two"), CFSTR("three") }; 282 CFNumberRef values[] = { cf_one, cf_two, cf_three }; 283 284 COMPILE_ASSERT(arraysize(keys) == arraysize(values), 285 keys_and_values_arraysizes_are_different); 286 287 ScopedCFTypeRef<CFDictionaryRef> test_dict( 288 CFDictionaryCreate(kCFAllocatorDefault, 289 reinterpret_cast<const void**>(keys), 290 reinterpret_cast<const void**>(values), 291 arraysize(values), 292 &kCFCopyStringDictionaryKeyCallBacks, 293 &kCFTypeDictionaryValueCallBacks)); 294 295 // GetValueFromDictionary<>(_, _) should produce the correct 296 // expected output. 297 EXPECT_EQ(values[0], 298 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("one"))); 299 EXPECT_EQ(values[1], 300 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("two"))); 301 EXPECT_EQ(values[2], 302 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("three"))); 303 304 // Bad input should produce bad output. 305 EXPECT_FALSE(GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("four"))); 306 EXPECT_FALSE(GetValueFromDictionary<CFStringRef>(test_dict, CFSTR("one"))); 307 } 308 309 TEST(FoundationUtilTest, FilePathToNSString) { 310 EXPECT_NSEQ(nil, FilePathToNSString(FilePath())); 311 EXPECT_NSEQ(@"/a/b", FilePathToNSString(FilePath("/a/b"))); 312 } 313 314 TEST(FoundationUtilTest, NSStringToFilePath) { 315 EXPECT_EQ(FilePath(), NSStringToFilePath(nil)); 316 EXPECT_EQ(FilePath(), NSStringToFilePath(@"")); 317 EXPECT_EQ(FilePath("/a/b"), NSStringToFilePath(@"/a/b")); 318 } 319 320 TEST(StringNumberConversionsTest, FormatNSInteger) { 321 // The PRI[dxu]NS macro assumes that NSInteger is a typedef to "int" on 322 // 32-bit architecture and a typedef to "long" on 64-bit architecture 323 // (respectively "unsigned int" and "unsigned long" for NSUInteger). Use 324 // pointer incompatibility to validate this at compilation. 325 #if defined(ARCH_CPU_64_BITS) 326 typedef long FormatNSIntegerAsType; 327 typedef unsigned long FormatNSUIntegerAsType; 328 #else 329 typedef int FormatNSIntegerAsType; 330 typedef unsigned int FormatNSUIntegerAsType; 331 #endif // defined(ARCH_CPU_64_BITS) 332 333 NSInteger some_nsinteger; 334 FormatNSIntegerAsType* pointer_to_some_nsinteger ALLOW_UNUSED = 335 &some_nsinteger; 336 337 NSUInteger some_nsuinteger; 338 FormatNSUIntegerAsType* pointer_to_some_nsuinteger ALLOW_UNUSED = 339 &some_nsuinteger; 340 341 // Check that format specifier works correctly for NSInteger. 342 const struct { 343 NSInteger value; 344 const char* expected; 345 const char* expected_hex; 346 } nsinteger_cases[] = { 347 #if !defined(ARCH_CPU_64_BITS) 348 {12345678, "12345678", "bc614e"}, 349 {-12345678, "-12345678", "ff439eb2"}, 350 #else 351 {12345678, "12345678", "bc614e"}, 352 {-12345678, "-12345678", "ffffffffff439eb2"}, 353 {137451299150l, "137451299150", "2000bc614e"}, 354 {-137451299150l, "-137451299150", "ffffffdfff439eb2"}, 355 #endif // !defined(ARCH_CPU_64_BITS) 356 }; 357 358 for (size_t i = 0; i < arraysize(nsinteger_cases); ++i) { 359 EXPECT_EQ(nsinteger_cases[i].expected, 360 StringPrintf("%" PRIdNS, nsinteger_cases[i].value)); 361 EXPECT_EQ(nsinteger_cases[i].expected_hex, 362 StringPrintf("%" PRIxNS, nsinteger_cases[i].value)); 363 } 364 365 // Check that format specifier works correctly for NSUInteger. 366 const struct { 367 NSUInteger value; 368 const char* expected; 369 const char* expected_hex; 370 } nsuinteger_cases[] = { 371 #if !defined(ARCH_CPU_64_BITS) 372 {12345678u, "12345678", "bc614e"}, 373 {4282621618u, "4282621618", "ff439eb2"}, 374 #else 375 {12345678u, "12345678", "bc614e"}, 376 {4282621618u, "4282621618", "ff439eb2"}, 377 {137451299150ul, "137451299150", "2000bc614e"}, 378 {18446743936258252466ul, "18446743936258252466", "ffffffdfff439eb2"}, 379 #endif // !defined(ARCH_CPU_64_BITS) 380 }; 381 382 for (size_t i = 0; i < arraysize(nsuinteger_cases); ++i) { 383 EXPECT_EQ(nsuinteger_cases[i].expected, 384 StringPrintf("%" PRIuNS, nsuinteger_cases[i].value)); 385 EXPECT_EQ(nsuinteger_cases[i].expected_hex, 386 StringPrintf("%" PRIxNS, nsuinteger_cases[i].value)); 387 } 388 } 389 390 } // namespace mac 391 } // namespace base 392