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