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.
5 #include "base/mac/foundation_util.h"
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"
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));
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));
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);
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));
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));
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));
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));
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));
160 TEST(FoundationUtilTest, ObjCCast) {
161 ScopedNSAutoreleasePool pool;
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];
169 [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:42]
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];
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);
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));
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));
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));
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));
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));
271 TEST(FoundationUtilTest, GetValueFromDictionary) {
272 int one = 1, two = 2, three = 3;
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));
281 CFStringRef keys[] = { CFSTR("one"), CFSTR("two"), CFSTR("three") };
282 CFNumberRef values[] = { cf_one, cf_two, cf_three };
284 COMPILE_ASSERT(arraysize(keys) == arraysize(values),
285 keys_and_values_arraysizes_are_different);
287 ScopedCFTypeRef<CFDictionaryRef> test_dict(
288 CFDictionaryCreate(kCFAllocatorDefault,
289 reinterpret_cast<const void**>(keys),
290 reinterpret_cast<const void**>(values),
292 &kCFCopyStringDictionaryKeyCallBacks,
293 &kCFTypeDictionaryValueCallBacks));
295 // GetValueFromDictionary<>(_, _) should produce the correct
298 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("one")));
300 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("two")));
302 GetValueFromDictionary<CFNumberRef>(test_dict, CFSTR("three")));
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")));
309 TEST(FoundationUtilTest, FilePathToNSString) {
310 EXPECT_NSEQ(nil, FilePathToNSString(FilePath()));
311 EXPECT_NSEQ(@"/a/b", FilePathToNSString(FilePath("/a/b")));
314 TEST(FoundationUtilTest, NSStringToFilePath) {
315 EXPECT_EQ(FilePath(), NSStringToFilePath(nil));
316 EXPECT_EQ(FilePath(), NSStringToFilePath(@""));
317 EXPECT_EQ(FilePath("/a/b"), NSStringToFilePath(@"/a/b"));
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;
329 typedef int FormatNSIntegerAsType;
330 typedef unsigned int FormatNSUIntegerAsType;
331 #endif // defined(ARCH_CPU_64_BITS)
333 NSInteger some_nsinteger;
334 FormatNSIntegerAsType* pointer_to_some_nsinteger ALLOW_UNUSED =
337 NSUInteger some_nsuinteger;
338 FormatNSUIntegerAsType* pointer_to_some_nsuinteger ALLOW_UNUSED =
341 // Check that format specifier works correctly for NSInteger.
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"},
351 {12345678, "12345678", "bc614e"},
352 {-12345678, "-12345678", "ffffffffff439eb2"},
353 {137451299150l, "137451299150", "2000bc614e"},
354 {-137451299150l, "-137451299150", "ffffffdfff439eb2"},
355 #endif // !defined(ARCH_CPU_64_BITS)
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));
365 // Check that format specifier works correctly for NSUInteger.
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"},
375 {12345678u, "12345678", "bc614e"},
376 {4282621618u, "4282621618", "ff439eb2"},
377 {137451299150ul, "137451299150", "2000bc614e"},
378 {18446743936258252466ul, "18446743936258252466", "ffffffdfff439eb2"},
379 #endif // !defined(ARCH_CPU_64_BITS)
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));