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
17namespace base {
18namespace mac {
19
20TEST(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
160TEST(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
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, 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
309TEST(FoundationUtilTest, FilePathToNSString) {
310  EXPECT_NSEQ(nil, FilePathToNSString(FilePath()));
311  EXPECT_NSEQ(@"/a/b", FilePathToNSString(FilePath("/a/b")));
312}
313
314TEST(FoundationUtilTest, NSStringToFilePath) {
315  EXPECT_EQ(FilePath(), NSStringToFilePath(nil));
316  EXPECT_EQ(FilePath(), NSStringToFilePath(@""));
317  EXPECT_EQ(FilePath("/a/b"), NSStringToFilePath(@"/a/b"));
318}
319
320TEST(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