mac_util_unittest.mm revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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#import <Cocoa/Cocoa.h>
6#include <vector>
7
8#include "base/mac/mac_util.h"
9
10#include "base/file_path.h"
11#include "base/file_util.h"
12#include "base/mac/scoped_cftyperef.h"
13#include "base/test/mock_chrome_application_mac.h"
14#include "base/scoped_nsobject.h"
15#include "base/scoped_ptr.h"
16#include "testing/gtest/include/gtest/gtest.h"
17#include "testing/platform_test.h"
18
19namespace base {
20namespace mac {
21
22namespace {
23
24typedef PlatformTest MacUtilTest;
25
26TEST_F(MacUtilTest, TestFSRef) {
27  FSRef ref;
28  std::string path("/System/Library");
29
30  ASSERT_TRUE(FSRefFromPath(path, &ref));
31  EXPECT_EQ(path, PathFromFSRef(ref));
32}
33
34TEST_F(MacUtilTest, GetUserDirectoryTest) {
35  // Try a few keys, make sure they come back with non-empty paths.
36  FilePath caches_dir;
37  EXPECT_TRUE(GetUserDirectory(NSCachesDirectory, &caches_dir));
38  EXPECT_FALSE(caches_dir.empty());
39
40  FilePath application_support_dir;
41  EXPECT_TRUE(GetUserDirectory(NSApplicationSupportDirectory,
42                               &application_support_dir));
43  EXPECT_FALSE(application_support_dir.empty());
44
45  FilePath library_dir;
46  EXPECT_TRUE(GetUserDirectory(NSLibraryDirectory, &library_dir));
47  EXPECT_FALSE(library_dir.empty());
48}
49
50TEST_F(MacUtilTest, TestLibraryPath) {
51  FilePath library_dir = GetUserLibraryPath();
52  // Make sure the string isn't empty.
53  EXPECT_FALSE(library_dir.value().empty());
54}
55
56TEST_F(MacUtilTest, TestGrabWindowSnapshot) {
57  // Launch a test window so we can take a snapshot.
58  [MockCrApp sharedApplication];
59  NSRect frame = NSMakeRect(0, 0, 400, 400);
60  scoped_nsobject<NSWindow> window(
61      [[NSWindow alloc] initWithContentRect:frame
62                                  styleMask:NSBorderlessWindowMask
63                                    backing:NSBackingStoreBuffered
64                                      defer:NO]);
65  [window setBackgroundColor:[NSColor whiteColor]];
66  [window makeKeyAndOrderFront:NSApp];
67
68  scoped_ptr<std::vector<unsigned char> > png_representation(
69      new std::vector<unsigned char>);
70  int width, height;
71  GrabWindowSnapshot(window, png_representation.get(),
72                     &width, &height);
73
74  // Copy png back into NSData object so we can make sure we grabbed a png.
75  scoped_nsobject<NSData> image_data(
76      [[NSData alloc] initWithBytes:&(*png_representation)[0]
77                             length:png_representation->size()]);
78  NSBitmapImageRep* rep = [NSBitmapImageRep imageRepWithData:image_data.get()];
79  EXPECT_TRUE([rep isKindOfClass:[NSBitmapImageRep class]]);
80  EXPECT_TRUE(CGImageGetWidth([rep CGImage]) == 400);
81  NSColor* color = [rep colorAtX:200 y:200];
82  CGFloat red = 0, green = 0, blue = 0, alpha = 0;
83  [color getRed:&red green:&green blue:&blue alpha:&alpha];
84  EXPECT_GE(red + green + blue, 3.0);
85}
86
87TEST_F(MacUtilTest, TestGetAppBundlePath) {
88  FilePath out;
89
90  // Make sure it doesn't crash.
91  out = GetAppBundlePath(FilePath());
92  EXPECT_TRUE(out.empty());
93
94  // Some more invalid inputs.
95  const char* invalid_inputs[] = {
96    "/", "/foo", "foo", "/foo/bar.", "foo/bar.", "/foo/bar./bazquux",
97    "foo/bar./bazquux", "foo/.app", "//foo",
98  };
99  for (size_t i = 0; i < arraysize(invalid_inputs); i++) {
100    out = GetAppBundlePath(FilePath(invalid_inputs[i]));
101    EXPECT_TRUE(out.empty()) << "loop: " << i;
102  }
103
104  // Some valid inputs; this and |expected_outputs| should be in sync.
105  struct {
106    const char *in;
107    const char *expected_out;
108  } valid_inputs[] = {
109    { "FooBar.app/", "FooBar.app" },
110    { "/FooBar.app", "/FooBar.app" },
111    { "/FooBar.app/", "/FooBar.app" },
112    { "//FooBar.app", "//FooBar.app" },
113    { "/Foo/Bar.app", "/Foo/Bar.app" },
114    { "/Foo/Bar.app/", "/Foo/Bar.app" },
115    { "/F/B.app", "/F/B.app" },
116    { "/F/B.app/", "/F/B.app" },
117    { "/Foo/Bar.app/baz", "/Foo/Bar.app" },
118    { "/Foo/Bar.app/baz/", "/Foo/Bar.app" },
119    { "/Foo/Bar.app/baz/quux.app/quuux", "/Foo/Bar.app" },
120    { "/Applications/Google Foo.app/bar/Foo Helper.app/quux/Foo Helper",
121        "/Applications/Google Foo.app" },
122  };
123  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(valid_inputs); i++) {
124    out = GetAppBundlePath(FilePath(valid_inputs[i].in));
125    EXPECT_FALSE(out.empty()) << "loop: " << i;
126    EXPECT_STREQ(valid_inputs[i].expected_out,
127        out.value().c_str()) << "loop: " << i;
128  }
129}
130
131TEST_F(MacUtilTest, TestExcludeFileFromBackups) {
132  NSString* homeDirectory = NSHomeDirectory();
133  NSString* dummyFilePath =
134      [homeDirectory stringByAppendingPathComponent:@"DummyFile"];
135  const char* dummy_file_path = [dummyFilePath fileSystemRepresentation];
136  ASSERT_TRUE(dummy_file_path);
137  FilePath file_path(dummy_file_path);
138  // It is not actually necessary to have a physical file in order to
139  // set its exclusion property.
140  NSURL* fileURL = [NSURL URLWithString:dummyFilePath];
141  // Reset the exclusion in case it was set previously.
142  SetFileBackupExclusion(file_path, false);
143  Boolean excludeByPath;
144  // Initial state should be non-excluded.
145  EXPECT_FALSE(CSBackupIsItemExcluded((CFURLRef)fileURL, &excludeByPath));
146  // Exclude the file.
147  EXPECT_TRUE(SetFileBackupExclusion(file_path, true));
148  EXPECT_TRUE(CSBackupIsItemExcluded((CFURLRef)fileURL, &excludeByPath));
149  // Un-exclude the file.
150  EXPECT_TRUE(SetFileBackupExclusion(file_path, false));
151  EXPECT_FALSE(CSBackupIsItemExcluded((CFURLRef)fileURL, &excludeByPath));
152}
153
154TEST_F(MacUtilTest, TestGetValueFromDictionary) {
155  ScopedCFTypeRef<CFMutableDictionaryRef> dict(
156      CFDictionaryCreateMutable(0, 0,
157                                &kCFTypeDictionaryKeyCallBacks,
158                                &kCFTypeDictionaryValueCallBacks));
159  CFDictionarySetValue(dict.get(), CFSTR("key"), CFSTR("value"));
160
161  EXPECT_TRUE(CFEqual(CFSTR("value"),
162                      GetValueFromDictionary(
163                          dict, CFSTR("key"), CFStringGetTypeID())));
164  EXPECT_FALSE(GetValueFromDictionary(dict, CFSTR("key"), CFNumberGetTypeID()));
165  EXPECT_FALSE(GetValueFromDictionary(
166                   dict, CFSTR("no-exist"), CFStringGetTypeID()));
167}
168
169TEST_F(MacUtilTest, CopyNSImageToCGImage) {
170  scoped_nsobject<NSImage> nsImage(
171      [[NSImage alloc] initWithSize:NSMakeSize(20, 20)]);
172  [nsImage lockFocus];
173  [[NSColor redColor] set];
174  NSRect rect = NSZeroRect;
175  rect.size = [nsImage size];
176  NSRectFill(rect);
177  [nsImage unlockFocus];
178
179  ScopedCFTypeRef<CGImageRef> cgImage(CopyNSImageToCGImage(nsImage.get()));
180  EXPECT_TRUE(cgImage.get());
181}
182
183TEST_F(MacUtilTest, NSObjectRetainRelease) {
184  scoped_nsobject<NSArray> array([[NSArray alloc] initWithObjects:@"foo", nil]);
185  EXPECT_EQ(1U, [array retainCount]);
186
187  NSObjectRetain(array);
188  EXPECT_EQ(2U, [array retainCount]);
189
190  NSObjectRelease(array);
191  EXPECT_EQ(1U, [array retainCount]);
192}
193
194}  // namespace
195
196}  // namespace mac
197}  // namespace base
198