xref: /aosp_15_r20/external/cronet/base/apple/foundation_util_unittest.mm (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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