blob: c5042a05f0be8b6a2bbeb49b1e9232eddf6b00a1 [file] [log] [blame]
[email protected]aebadfe2012-02-15 02:57:021// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]8b386ced2009-10-27 15:55:522// 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>
avidbcc8412015-12-24 06:28:326#include <stddef.h>
7#include <stdint.h>
[email protected]8b386ced2009-10-27 15:55:528
[email protected]0378bf42011-01-01 18:20:149#include "base/mac/mac_util.h"
[email protected]8b386ced2009-10-27 15:55:5210
[email protected]57999812013-02-24 05:40:5211#include "base/files/file_path.h"
[email protected]e3177dd52014-08-13 20:22:1412#include "base/files/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2313#include "base/files/scoped_temp_dir.h"
[email protected]22e0af92011-05-26 02:56:3414#include "base/mac/foundation_util.h"
[email protected]df0ca6c82010-10-17 04:09:0615#include "base/mac/scoped_cftyperef.h"
[email protected]a8522032013-06-24 22:51:4616#include "base/mac/scoped_nsobject.h"
avidbcc8412015-12-24 06:28:3217#include "base/macros.h"
[email protected]ba64e2b2011-06-14 18:18:3818#include "base/sys_info.h"
[email protected]8b386ced2009-10-27 15:55:5219#include "testing/gtest/include/gtest/gtest.h"
20#include "testing/platform_test.h"
21
[email protected]ccfab592013-01-15 06:24:3222#include <errno.h>
23#include <sys/xattr.h>
24
[email protected]0378bf42011-01-01 18:20:1425namespace base {
26namespace mac {
[email protected]400e7d6c2009-12-14 03:40:5527
28namespace {
29
[email protected]8b386ced2009-10-27 15:55:5230typedef PlatformTest MacUtilTest;
31
32TEST_F(MacUtilTest, TestFSRef) {
33 FSRef ref;
34 std::string path("/System/Library");
35
[email protected]400e7d6c2009-12-14 03:40:5536 ASSERT_TRUE(FSRefFromPath(path, &ref));
37 EXPECT_EQ(path, PathFromFSRef(ref));
[email protected]8b386ced2009-10-27 15:55:5238}
39
[email protected]2438b1722010-01-27 01:27:1940TEST_F(MacUtilTest, GetUserDirectoryTest) {
41 // Try a few keys, make sure they come back with non-empty paths.
42 FilePath caches_dir;
43 EXPECT_TRUE(GetUserDirectory(NSCachesDirectory, &caches_dir));
44 EXPECT_FALSE(caches_dir.empty());
45
46 FilePath application_support_dir;
47 EXPECT_TRUE(GetUserDirectory(NSApplicationSupportDirectory,
48 &application_support_dir));
49 EXPECT_FALSE(application_support_dir.empty());
50
51 FilePath library_dir;
52 EXPECT_TRUE(GetUserDirectory(NSLibraryDirectory, &library_dir));
53 EXPECT_FALSE(library_dir.empty());
54}
55
[email protected]8b386ced2009-10-27 15:55:5256TEST_F(MacUtilTest, TestLibraryPath) {
[email protected]400e7d6c2009-12-14 03:40:5557 FilePath library_dir = GetUserLibraryPath();
[email protected]8b386ced2009-10-27 15:55:5258 // Make sure the string isn't empty.
59 EXPECT_FALSE(library_dir.value().empty());
60}
61
[email protected]f164cea2009-11-05 23:37:4062TEST_F(MacUtilTest, TestGetAppBundlePath) {
63 FilePath out;
64
65 // Make sure it doesn't crash.
[email protected]400e7d6c2009-12-14 03:40:5566 out = GetAppBundlePath(FilePath());
[email protected]f164cea2009-11-05 23:37:4067 EXPECT_TRUE(out.empty());
68
69 // Some more invalid inputs.
thestig073d514d2014-10-21 03:11:2170 const char* const invalid_inputs[] = {
[email protected]f164cea2009-11-05 23:37:4071 "/", "/foo", "foo", "/foo/bar.", "foo/bar.", "/foo/bar./bazquux",
72 "foo/bar./bazquux", "foo/.app", "//foo",
73 };
74 for (size_t i = 0; i < arraysize(invalid_inputs); i++) {
[email protected]400e7d6c2009-12-14 03:40:5575 out = GetAppBundlePath(FilePath(invalid_inputs[i]));
[email protected]f164cea2009-11-05 23:37:4076 EXPECT_TRUE(out.empty()) << "loop: " << i;
77 }
78
79 // Some valid inputs; this and |expected_outputs| should be in sync.
80 struct {
81 const char *in;
82 const char *expected_out;
83 } valid_inputs[] = {
84 { "FooBar.app/", "FooBar.app" },
85 { "/FooBar.app", "/FooBar.app" },
86 { "/FooBar.app/", "/FooBar.app" },
87 { "//FooBar.app", "//FooBar.app" },
88 { "/Foo/Bar.app", "/Foo/Bar.app" },
89 { "/Foo/Bar.app/", "/Foo/Bar.app" },
90 { "/F/B.app", "/F/B.app" },
91 { "/F/B.app/", "/F/B.app" },
92 { "/Foo/Bar.app/baz", "/Foo/Bar.app" },
93 { "/Foo/Bar.app/baz/", "/Foo/Bar.app" },
94 { "/Foo/Bar.app/baz/quux.app/quuux", "/Foo/Bar.app" },
95 { "/Applications/Google Foo.app/bar/Foo Helper.app/quux/Foo Helper",
96 "/Applications/Google Foo.app" },
97 };
viettrungluu805eabb2014-10-16 04:02:4998 for (size_t i = 0; i < arraysize(valid_inputs); i++) {
[email protected]400e7d6c2009-12-14 03:40:5599 out = GetAppBundlePath(FilePath(valid_inputs[i].in));
[email protected]f164cea2009-11-05 23:37:40100 EXPECT_FALSE(out.empty()) << "loop: " << i;
101 EXPECT_STREQ(valid_inputs[i].expected_out,
102 out.value().c_str()) << "loop: " << i;
103 }
104}
[email protected]b4113d52009-11-11 02:49:05105
Dan Beamb31ff722014-12-30 18:42:44106// http://crbug.com/425745
107TEST_F(MacUtilTest, DISABLED_TestExcludeFileFromBackups) {
[email protected]22e0af92011-05-26 02:56:34108 // The file must already exist in order to set its exclusion property.
109 ScopedTempDir temp_dir_;
110 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
111 FilePath dummy_file_path = temp_dir_.path().Append("DummyFile");
112 const char dummy_data[] = "All your base are belong to us!";
113 // Dump something real into the file.
114 ASSERT_EQ(static_cast<int>(arraysize(dummy_data)),
[email protected]e5c2a22e2014-03-06 20:42:30115 WriteFile(dummy_file_path, dummy_data, arraysize(dummy_data)));
[email protected]22e0af92011-05-26 02:56:34116 NSString* fileURLString =
117 [NSString stringWithUTF8String:dummy_file_path.value().c_str()];
118 NSURL* fileURL = [NSURL URLWithString:fileURLString];
[email protected]b4113d52009-11-11 02:49:05119 // Initial state should be non-excluded.
[email protected]22e0af92011-05-26 02:56:34120 EXPECT_FALSE(CSBackupIsItemExcluded(base::mac::NSToCFCast(fileURL), NULL));
[email protected]b4113d52009-11-11 02:49:05121 // Exclude the file.
[email protected]22e0af92011-05-26 02:56:34122 EXPECT_TRUE(SetFileBackupExclusion(dummy_file_path));
123 // SetFileBackupExclusion never excludes by path.
124 Boolean excluded_by_path = FALSE;
125 Boolean excluded =
126 CSBackupIsItemExcluded(base::mac::NSToCFCast(fileURL), &excluded_by_path);
127 EXPECT_TRUE(excluded);
128 EXPECT_FALSE(excluded_by_path);
[email protected]b4113d52009-11-11 02:49:05129}
[email protected]a9944f02009-12-10 10:37:27130
[email protected]7fef9717a2010-10-02 19:08:44131TEST_F(MacUtilTest, NSObjectRetainRelease) {
[email protected]a8522032013-06-24 22:51:46132 base::scoped_nsobject<NSArray> array(
133 [[NSArray alloc] initWithObjects:@"foo", nil]);
[email protected]7fef9717a2010-10-02 19:08:44134 EXPECT_EQ(1U, [array retainCount]);
135
[email protected]0378bf42011-01-01 18:20:14136 NSObjectRetain(array);
[email protected]7fef9717a2010-10-02 19:08:44137 EXPECT_EQ(2U, [array retainCount]);
138
[email protected]0378bf42011-01-01 18:20:14139 NSObjectRelease(array);
[email protected]7fef9717a2010-10-02 19:08:44140 EXPECT_EQ(1U, [array retainCount]);
141}
142
[email protected]ba64e2b2011-06-14 18:18:38143TEST_F(MacUtilTest, IsOSEllipsis) {
avidbcc8412015-12-24 06:28:32144 int32_t major, minor, bugfix;
[email protected]ba64e2b2011-06-14 18:18:38145 base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
146
147 if (major == 10) {
[email protected]beee7a92012-08-09 20:27:26148 if (minor == 6) {
[email protected]ba64e2b2011-06-14 18:18:38149 EXPECT_TRUE(IsOSSnowLeopard());
[email protected]ba64e2b2011-06-14 18:18:38150 EXPECT_FALSE(IsOSLion());
[email protected]b1e697e2012-03-14 19:58:22151 EXPECT_TRUE(IsOSLionOrEarlier());
[email protected]ba64e2b2011-06-14 18:18:38152 EXPECT_FALSE(IsOSLionOrLater());
[email protected]b1e697e2012-03-14 19:58:22153 EXPECT_FALSE(IsOSMountainLion());
[email protected]aaf93de42013-10-02 07:41:57154 EXPECT_TRUE(IsOSMountainLionOrEarlier());
[email protected]b1e697e2012-03-14 19:58:22155 EXPECT_FALSE(IsOSMountainLionOrLater());
[email protected]aaf93de42013-10-02 07:41:57156 EXPECT_FALSE(IsOSMavericks());
[email protected]81ceb2b2014-06-12 18:28:19157 EXPECT_TRUE(IsOSMavericksOrEarlier());
[email protected]aaf93de42013-10-02 07:41:57158 EXPECT_FALSE(IsOSMavericksOrLater());
[email protected]81ceb2b2014-06-12 18:28:19159 EXPECT_FALSE(IsOSYosemite());
andresantosoff07cca2015-07-21 23:20:40160 EXPECT_TRUE(IsOSYosemiteOrEarlier());
[email protected]81ceb2b2014-06-12 18:28:19161 EXPECT_FALSE(IsOSYosemiteOrLater());
andresantosoff07cca2015-07-21 23:20:40162 EXPECT_FALSE(IsOSElCapitan());
163 EXPECT_FALSE(IsOSElCapitanOrLater());
164 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
[email protected]ba64e2b2011-06-14 18:18:38165 } else if (minor == 7) {
[email protected]ba64e2b2011-06-14 18:18:38166 EXPECT_FALSE(IsOSSnowLeopard());
[email protected]ba64e2b2011-06-14 18:18:38167 EXPECT_TRUE(IsOSLion());
[email protected]b1e697e2012-03-14 19:58:22168 EXPECT_TRUE(IsOSLionOrEarlier());
[email protected]ba64e2b2011-06-14 18:18:38169 EXPECT_TRUE(IsOSLionOrLater());
[email protected]b1e697e2012-03-14 19:58:22170 EXPECT_FALSE(IsOSMountainLion());
[email protected]aaf93de42013-10-02 07:41:57171 EXPECT_TRUE(IsOSMountainLionOrEarlier());
[email protected]b1e697e2012-03-14 19:58:22172 EXPECT_FALSE(IsOSMountainLionOrLater());
[email protected]aaf93de42013-10-02 07:41:57173 EXPECT_FALSE(IsOSMavericks());
[email protected]81ceb2b2014-06-12 18:28:19174 EXPECT_TRUE(IsOSMavericksOrEarlier());
[email protected]aaf93de42013-10-02 07:41:57175 EXPECT_FALSE(IsOSMavericksOrLater());
[email protected]81ceb2b2014-06-12 18:28:19176 EXPECT_FALSE(IsOSYosemite());
andresantosoff07cca2015-07-21 23:20:40177 EXPECT_TRUE(IsOSYosemiteOrEarlier());
[email protected]81ceb2b2014-06-12 18:28:19178 EXPECT_FALSE(IsOSYosemiteOrLater());
andresantosoff07cca2015-07-21 23:20:40179 EXPECT_FALSE(IsOSElCapitan());
180 EXPECT_FALSE(IsOSElCapitanOrLater());
181 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
[email protected]b1e697e2012-03-14 19:58:22182 } else if (minor == 8) {
[email protected]b1e697e2012-03-14 19:58:22183 EXPECT_FALSE(IsOSSnowLeopard());
[email protected]b1e697e2012-03-14 19:58:22184 EXPECT_FALSE(IsOSLion());
185 EXPECT_FALSE(IsOSLionOrEarlier());
186 EXPECT_TRUE(IsOSLionOrLater());
187 EXPECT_TRUE(IsOSMountainLion());
[email protected]aaf93de42013-10-02 07:41:57188 EXPECT_TRUE(IsOSMountainLionOrEarlier());
[email protected]b1e697e2012-03-14 19:58:22189 EXPECT_TRUE(IsOSMountainLionOrLater());
[email protected]aaf93de42013-10-02 07:41:57190 EXPECT_FALSE(IsOSMavericks());
[email protected]81ceb2b2014-06-12 18:28:19191 EXPECT_TRUE(IsOSMavericksOrEarlier());
[email protected]aaf93de42013-10-02 07:41:57192 EXPECT_FALSE(IsOSMavericksOrLater());
[email protected]81ceb2b2014-06-12 18:28:19193 EXPECT_FALSE(IsOSYosemite());
andresantosoff07cca2015-07-21 23:20:40194 EXPECT_TRUE(IsOSYosemiteOrEarlier());
[email protected]81ceb2b2014-06-12 18:28:19195 EXPECT_FALSE(IsOSYosemiteOrLater());
andresantosoff07cca2015-07-21 23:20:40196 EXPECT_FALSE(IsOSElCapitan());
197 EXPECT_FALSE(IsOSElCapitanOrLater());
198 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
[email protected]aaf93de42013-10-02 07:41:57199 } else if (minor == 9) {
200 EXPECT_FALSE(IsOSSnowLeopard());
201 EXPECT_FALSE(IsOSLion());
202 EXPECT_FALSE(IsOSLionOrEarlier());
203 EXPECT_TRUE(IsOSLionOrLater());
204 EXPECT_FALSE(IsOSMountainLion());
205 EXPECT_FALSE(IsOSMountainLionOrEarlier());
206 EXPECT_TRUE(IsOSMountainLionOrLater());
207 EXPECT_TRUE(IsOSMavericks());
[email protected]81ceb2b2014-06-12 18:28:19208 EXPECT_TRUE(IsOSMavericksOrEarlier());
[email protected]aaf93de42013-10-02 07:41:57209 EXPECT_TRUE(IsOSMavericksOrLater());
[email protected]81ceb2b2014-06-12 18:28:19210 EXPECT_FALSE(IsOSYosemite());
andresantosoff07cca2015-07-21 23:20:40211 EXPECT_TRUE(IsOSYosemiteOrEarlier());
[email protected]81ceb2b2014-06-12 18:28:19212 EXPECT_FALSE(IsOSYosemiteOrLater());
andresantosoff07cca2015-07-21 23:20:40213 EXPECT_FALSE(IsOSElCapitan());
214 EXPECT_FALSE(IsOSElCapitanOrLater());
215 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
[email protected]81ceb2b2014-06-12 18:28:19216 } else if (minor == 10) {
217 EXPECT_FALSE(IsOSSnowLeopard());
218 EXPECT_FALSE(IsOSLion());
219 EXPECT_FALSE(IsOSLionOrEarlier());
220 EXPECT_TRUE(IsOSLionOrLater());
221 EXPECT_FALSE(IsOSMountainLion());
222 EXPECT_FALSE(IsOSMountainLionOrEarlier());
223 EXPECT_TRUE(IsOSMountainLionOrLater());
224 EXPECT_FALSE(IsOSMavericks());
225 EXPECT_FALSE(IsOSMavericksOrEarlier());
226 EXPECT_TRUE(IsOSMavericksOrLater());
227 EXPECT_TRUE(IsOSYosemite());
andresantosoff07cca2015-07-21 23:20:40228 EXPECT_TRUE(IsOSYosemiteOrEarlier());
[email protected]81ceb2b2014-06-12 18:28:19229 EXPECT_TRUE(IsOSYosemiteOrLater());
andresantosoff07cca2015-07-21 23:20:40230 EXPECT_FALSE(IsOSElCapitan());
231 EXPECT_FALSE(IsOSElCapitanOrLater());
232 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
233 } else if (minor == 11) {
234 EXPECT_FALSE(IsOSSnowLeopard());
235 EXPECT_FALSE(IsOSLion());
236 EXPECT_FALSE(IsOSLionOrEarlier());
237 EXPECT_TRUE(IsOSLionOrLater());
238 EXPECT_FALSE(IsOSMountainLion());
239 EXPECT_FALSE(IsOSMountainLionOrEarlier());
240 EXPECT_TRUE(IsOSMountainLionOrLater());
241 EXPECT_FALSE(IsOSMavericks());
242 EXPECT_FALSE(IsOSMavericksOrEarlier());
243 EXPECT_TRUE(IsOSMavericksOrLater());
244 EXPECT_FALSE(IsOSYosemite());
245 EXPECT_FALSE(IsOSYosemiteOrEarlier());
246 EXPECT_TRUE(IsOSYosemiteOrLater());
247 EXPECT_TRUE(IsOSElCapitan());
248 EXPECT_TRUE(IsOSElCapitanOrLater());
249 EXPECT_FALSE(IsOSLaterThanElCapitan_DontCallThis());
[email protected]ba64e2b2011-06-14 18:18:38250 } else {
andresantosoff07cca2015-07-21 23:20:40251 // Not six, seven, eight, nine, ten, or eleven. Ah, ah, ah.
[email protected]ba64e2b2011-06-14 18:18:38252 EXPECT_TRUE(false);
253 }
254 } else {
255 // Not ten. What you gonna do?
256 EXPECT_FALSE(true);
257 }
258}
259
[email protected]aebadfe2012-02-15 02:57:02260TEST_F(MacUtilTest, ParseModelIdentifier) {
261 std::string model;
avidbcc8412015-12-24 06:28:32262 int32_t major = 1, minor = 2;
[email protected]aebadfe2012-02-15 02:57:02263
264 EXPECT_FALSE(ParseModelIdentifier("", &model, &major, &minor));
265 EXPECT_EQ(0U, model.length());
266 EXPECT_EQ(1, major);
267 EXPECT_EQ(2, minor);
268 EXPECT_FALSE(ParseModelIdentifier("FooBar", &model, &major, &minor));
269
270 EXPECT_TRUE(ParseModelIdentifier("MacPro4,1", &model, &major, &minor));
271 EXPECT_EQ(model, "MacPro");
272 EXPECT_EQ(4, major);
273 EXPECT_EQ(1, minor);
274
275 EXPECT_TRUE(ParseModelIdentifier("MacBookPro6,2", &model, &major, &minor));
276 EXPECT_EQ(model, "MacBookPro");
277 EXPECT_EQ(6, major);
278 EXPECT_EQ(2, minor);
279}
280
[email protected]ccfab592013-01-15 06:24:32281TEST_F(MacUtilTest, TestRemoveQuarantineAttribute) {
282 ScopedTempDir temp_dir_;
283 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
284 FilePath dummy_folder_path = temp_dir_.path().Append("DummyFolder");
[email protected]426d1c92013-12-03 20:08:54285 ASSERT_TRUE(base::CreateDirectory(dummy_folder_path));
[email protected]ccfab592013-01-15 06:24:32286 const char* quarantine_str = "0000;4b392bb2;Chromium;|org.chromium.Chromium";
287 const char* file_path_str = dummy_folder_path.value().c_str();
288 EXPECT_EQ(0, setxattr(file_path_str, "com.apple.quarantine",
289 quarantine_str, strlen(quarantine_str), 0, 0));
290 EXPECT_EQ(static_cast<long>(strlen(quarantine_str)),
291 getxattr(file_path_str, "com.apple.quarantine",
292 NULL, 0, 0, 0));
293 EXPECT_TRUE(RemoveQuarantineAttribute(dummy_folder_path));
294 EXPECT_EQ(-1, getxattr(file_path_str, "com.apple.quarantine", NULL, 0, 0, 0));
295 EXPECT_EQ(ENOATTR, errno);
296}
297
298TEST_F(MacUtilTest, TestRemoveQuarantineAttributeTwice) {
299 ScopedTempDir temp_dir_;
300 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
301 FilePath dummy_folder_path = temp_dir_.path().Append("DummyFolder");
302 const char* file_path_str = dummy_folder_path.value().c_str();
[email protected]426d1c92013-12-03 20:08:54303 ASSERT_TRUE(base::CreateDirectory(dummy_folder_path));
[email protected]ccfab592013-01-15 06:24:32304 EXPECT_EQ(-1, getxattr(file_path_str, "com.apple.quarantine", NULL, 0, 0, 0));
305 // No quarantine attribute to begin with, but RemoveQuarantineAttribute still
306 // succeeds because in the end the folder still doesn't have the quarantine
307 // attribute set.
308 EXPECT_TRUE(RemoveQuarantineAttribute(dummy_folder_path));
309 EXPECT_TRUE(RemoveQuarantineAttribute(dummy_folder_path));
310 EXPECT_EQ(ENOATTR, errno);
311}
312
313TEST_F(MacUtilTest, TestRemoveQuarantineAttributeNonExistentPath) {
314 ScopedTempDir temp_dir_;
315 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
316 FilePath non_existent_path = temp_dir_.path().Append("DummyPath");
[email protected]7567484142013-07-11 17:36:07317 ASSERT_FALSE(PathExists(non_existent_path));
[email protected]ccfab592013-01-15 06:24:32318 EXPECT_FALSE(RemoveQuarantineAttribute(non_existent_path));
319}
320
[email protected]400e7d6c2009-12-14 03:40:55321} // namespace
322
[email protected]0378bf42011-01-01 18:20:14323} // namespace mac
324} // namespace base