blob: 87c52f6cdd22c721f72ee0e331bb9a3145891651 [file] [log] [blame]
Joshua Pawlickibae1c6d2352020-03-19 19:21:441// Copyright 2020 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
Mila Greena3991ae2020-10-16 00:10:555#include <stdint.h>
Joshua Pawlicki6867d7c2021-01-06 15:51:096#include <string>
Mila Greena3991ae2020-10-16 00:10:557
Joshua Pawlickibae1c6d2352020-03-19 19:21:448#include "base/command_line.h"
9#include "base/files/file_path.h"
10#include "base/files/file_util.h"
11#include "base/mac/foundation_util.h"
12#include "base/path_service.h"
Joshua Pawlickicd6925c92020-12-15 15:07:5013#include "base/run_loop.h"
14#include "base/strings/sys_string_conversions.h"
15#include "base/test/bind.h"
Mila Greena3991ae2020-10-16 00:10:5516#include "base/version.h"
Joshua Pawlicki8f755d382020-03-20 19:51:1017#include "chrome/common/mac/launchd.h"
Mila Green8ddc4e02020-05-01 00:15:0218#include "chrome/updater/constants.h"
Joshua Pawlickicd6925c92020-12-15 15:07:5019#include "chrome/updater/launchd_util.h"
Mila Greena3991ae2020-10-16 00:10:5520#import "chrome/updater/mac/util.h"
Joshua Pawlicki8f755d382020-03-20 19:51:1021#include "chrome/updater/mac/xpc_service_names.h"
Mila Greena3991ae2020-10-16 00:10:5522#include "chrome/updater/prefs.h"
Joshua Pawlicki83d1d8232020-10-23 20:13:3123#include "chrome/updater/test/integration_tests.h"
Mila Green3e3058a2020-08-27 16:59:2724#include "chrome/updater/test/test_app/constants.h"
25#include "chrome/updater/test/test_app/test_app_version.h"
Joshua Pawlickibae1c6d2352020-03-19 19:21:4426#include "chrome/updater/updater_version.h"
Joshua Pawlicki4abd1322020-08-19 22:05:5727#include "chrome/updater/util.h"
Joshua Pawlickibae1c6d2352020-03-19 19:21:4428#include "testing/gtest/include/gtest/gtest.h"
Joshua Pawlicki6867d7c2021-01-06 15:51:0929#include "url/gurl.h"
Joshua Pawlickibae1c6d2352020-03-19 19:21:4430
31namespace updater {
Joshua Pawlickibae1c6d2352020-03-19 19:21:4432namespace test {
33
Joshua Pawlicki83d1d8232020-10-23 20:13:3134// crbug.com/1112527: These tests are not compatible with component build.
35#if !defined(COMPONENT_BUILD)
36
Joshua Pawlickibae1c6d2352020-03-19 19:21:4437namespace {
38
Joshua Pawlickicd6925c92020-12-15 15:07:5039void RemoveJobFromLaunchd(Launchd::Domain domain,
40 Launchd::Type type,
41 base::ScopedCFTypeRef<CFStringRef> name) {
42 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(domain, type, name))
43 << "Failed to delete plist for " << name;
44
45 // Return value is ignored, since RemoveJob returns false if the job already
46 // doesn't exist.
47 Launchd::GetInstance()->RemoveJob(base::SysCFStringRefToUTF8(name));
48}
49
Joshua Pawlickibae1c6d2352020-03-19 19:21:4450base::FilePath GetExecutablePath() {
51 base::FilePath test_executable;
52 if (!base::PathService::Get(base::FILE_EXE, &test_executable))
53 return base::FilePath();
54 return test_executable.DirName()
Mila Greena3991ae2020-10-16 00:10:5555 .Append(FILE_PATH_LITERAL(PRODUCT_FULLNAME_STRING ".app"))
Joshua Pawlickibae1c6d2352020-03-19 19:21:4456 .Append(FILE_PATH_LITERAL("Contents"))
57 .Append(FILE_PATH_LITERAL("MacOS"))
58 .Append(FILE_PATH_LITERAL(PRODUCT_FULLNAME_STRING));
59}
60
Mila Green3e3058a2020-08-27 16:59:2761base::FilePath GetTestAppExecutablePath() {
62 base::FilePath test_executable;
63 if (!base::PathService::Get(base::FILE_EXE, &test_executable))
64 return base::FilePath();
65 return test_executable.DirName()
Mila Greena3991ae2020-10-16 00:10:5566 .Append(FILE_PATH_LITERAL(TEST_APP_FULLNAME_STRING ".app"))
Mila Green3e3058a2020-08-27 16:59:2767 .Append(FILE_PATH_LITERAL("Contents"))
68 .Append(FILE_PATH_LITERAL("MacOS"))
69 .Append(FILE_PATH_LITERAL(TEST_APP_FULLNAME_STRING));
70}
71
Joshua Pawlicki8f755d382020-03-20 19:51:1072base::FilePath GetProductPath() {
73 return base::mac::GetUserLibraryPath()
74 .AppendASCII(COMPANY_SHORTNAME_STRING)
75 .AppendASCII(PRODUCT_FULLNAME_STRING);
76}
77
Joshua Pawlicki6867d7c2021-01-06 15:51:0978base::FilePath GetActiveFile(const std::string& id) {
79 return base::GetHomeDir()
80 .AppendASCII("Library")
81 .AppendASCII(COMPANY_SHORTNAME_STRING)
82 .AppendASCII(COMPANY_SHORTNAME_STRING "SoftwareUpdate")
83 .AppendASCII("Actives")
84 .AppendASCII(id);
85}
86
Joshua Pawlickicd6925c92020-12-15 15:07:5087void ExpectServiceAbsent(const std::string& service) {
88 bool success = false;
89 base::RunLoop loop;
90 PollLaunchctlList(service, LaunchctlPresence::kAbsent,
91 base::TimeDelta::FromSeconds(7),
92 base::BindLambdaForTesting([&](bool result) {
93 success = result;
94 loop.QuitClosure().Run();
95 }));
96 loop.Run();
97 EXPECT_TRUE(success) << service << " is unexpectedly present.";
98}
99
Joshua Pawlicki83d1d8232020-10-23 20:13:31100} // namespace
101
Joshua Pawlicki6867d7c2021-01-06 15:51:09102#endif // defined(COMPONENT_BUILD
103
104void EnterTestMode(const GURL& url) {
105 @autoreleasepool {
106 NSUserDefaults* userDefaults = [[NSUserDefaults alloc]
107 initWithSuiteName:[NSString
108 stringWithUTF8String:kUserDefaultsSuiteName]];
109 [userDefaults
110 setURL:[NSURL URLWithString:base::SysUTF8ToNSString(url.spec())]
111 forKey:[NSString stringWithUTF8String:kDevOverrideKeyUrl]];
112 [userDefaults
113 setBool:NO
114 forKey:[NSString stringWithUTF8String:kDevOverrideKeyUseCUP]];
115 }
116}
117
118// crbug.com/1112527: These tests are not compatible with component build.
119#if !defined(COMPONENT_BUILD)
120
Joshua Pawlicki9d1340fc2020-08-14 20:59:35121base::FilePath GetDataDirPath() {
122 return base::mac::GetUserLibraryPath()
123 .AppendASCII("Application Support")
124 .AppendASCII(COMPANY_SHORTNAME_STRING)
125 .AppendASCII(PRODUCT_FULLNAME_STRING);
126}
127
Joshua Pawlickibae1c6d2352020-03-19 19:21:44128void Clean() {
Lei Zhang329c5bc2020-07-07 21:09:11129 EXPECT_TRUE(base::DeletePathRecursively(GetProductPath()));
Joshua Pawlicki8f755d382020-03-20 19:51:10130 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green7414a0ed2020-07-21 21:30:42131 Launchd::User, Launchd::Agent, updater::CopyWakeLaunchdName()));
Joshua Pawlicki8f755d382020-03-20 19:51:10132 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green80845642020-12-10 03:44:51133 Launchd::User, Launchd::Agent,
134 updater::CopyUpdateServiceInternalLaunchdName()));
Mila Green7414a0ed2020-07-21 21:30:42135 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green80845642020-12-10 03:44:51136 Launchd::User, Launchd::Agent, updater::CopyUpdateServiceLaunchdName()));
Joshua Pawlicki9d1340fc2020-08-14 20:59:35137 EXPECT_TRUE(base::DeletePathRecursively(GetDataDirPath()));
Joshua Pawlicki3f645882020-08-21 20:36:17138
139 @autoreleasepool {
Joshua Pawlicki6867d7c2021-01-06 15:51:09140 NSUserDefaults* userDefaults = [[NSUserDefaults alloc]
141 initWithSuiteName:[NSString
142 stringWithUTF8String:kUserDefaultsSuiteName]];
Joshua Pawlicki3f645882020-08-21 20:36:17143 [userDefaults
144 removeObjectForKey:[NSString stringWithUTF8String:kDevOverrideKeyUrl]];
145 [userDefaults
146 removeObjectForKey:[NSString
147 stringWithUTF8String:kDevOverrideKeyUseCUP]];
Joshua Pawlickicd6925c92020-12-15 15:07:50148
149 // TODO(crbug.com/1096654): support machine case (Launchd::Domain::Local and
150 // Launchd::Type::Daemon).
151 RemoveJobFromLaunchd(Launchd::Domain::User, Launchd::Type::Agent,
152 CopyUpdateServiceLaunchdName());
153 RemoveJobFromLaunchd(Launchd::Domain::User, Launchd::Type::Agent,
154 CopyUpdateServiceInternalLaunchdName());
Joshua Pawlicki3f645882020-08-21 20:36:17155 }
Joshua Pawlickibae1c6d2352020-03-19 19:21:44156}
157
158void ExpectClean() {
159 // Files must not exist on the file system.
Joshua Pawlicki8f755d382020-03-20 19:51:10160 EXPECT_FALSE(base::PathExists(GetProductPath()));
161 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green7414a0ed2020-07-21 21:30:42162 Launchd::User, Launchd::Agent, updater::CopyWakeLaunchdName()));
Mila Green8ddc4e02020-05-01 00:15:02163 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51164 Launchd::User, Launchd::Agent,
165 updater::CopyUpdateServiceInternalLaunchdName()));
Mila Green7414a0ed2020-07-21 21:30:42166 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51167 Launchd::User, Launchd::Agent, updater::CopyUpdateServiceLaunchdName()));
Joshua Pawlicki9d1340fc2020-08-14 20:59:35168 EXPECT_FALSE(base::PathExists(GetDataDirPath()));
Joshua Pawlickicd6925c92020-12-15 15:07:50169 ExpectServiceAbsent(kUpdateServiceLaunchdName);
170 ExpectServiceAbsent(kUpdateServiceInternalLaunchdName);
Joshua Pawlickibae1c6d2352020-03-19 19:21:44171}
172
Joshua Pawlickibae1c6d2352020-03-19 19:21:44173void ExpectInstalled() {
174 // Files must exist on the file system.
Joshua Pawlicki8f755d382020-03-20 19:51:10175 EXPECT_TRUE(base::PathExists(GetProductPath()));
Mila Green7414a0ed2020-07-21 21:30:42176 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(Launchd::User, Launchd::Agent,
177 CopyWakeLaunchdName()));
Mila Green80845642020-12-10 03:44:51178 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(
179 Launchd::User, Launchd::Agent, CopyUpdateServiceInternalLaunchdName()));
Joshua Pawlickibae1c6d2352020-03-19 19:21:44180}
181
182void Install() {
Mila Green8ddc4e02020-05-01 00:15:02183 const base::FilePath path = GetExecutablePath();
Joshua Pawlickibae1c6d2352020-03-19 19:21:44184 ASSERT_FALSE(path.empty());
Michael Change4785a822020-03-26 20:55:01185 base::CommandLine command_line(path);
Joshua Pawlicki91ce318b2020-09-15 14:35:38186 command_line.AppendSwitch(kInstallSwitch);
Mila Green8ddc4e02020-05-01 00:15:02187 int exit_code = -1;
188 ASSERT_TRUE(Run(command_line, &exit_code));
189 EXPECT_EQ(0, exit_code);
190}
191
Mila Green9056ede2020-05-18 20:48:40192void ExpectActive() {
Mila Green8ddc4e02020-05-01 00:15:02193 // Files must exist on the file system.
194 EXPECT_TRUE(base::PathExists(GetProductPath()));
Mila Green80845642020-12-10 03:44:51195 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(
196 Launchd::User, Launchd::Agent, CopyUpdateServiceLaunchdName()));
Mila Green8ddc4e02020-05-01 00:15:02197}
198
Mila Green3e3058a2020-08-27 16:59:27199void RegisterTestApp() {
200 const base::FilePath path = GetTestAppExecutablePath();
201 ASSERT_FALSE(path.empty());
202 base::CommandLine command_line(path);
203 command_line.AppendSwitch(kRegisterUpdaterSwitch);
204 int exit_code = -1;
205 ASSERT_TRUE(Run(command_line, &exit_code));
206 EXPECT_EQ(0, exit_code);
207}
208
Mila Greena3991ae2020-10-16 00:10:55209base::FilePath GetInstalledExecutablePath() {
210 return GetUpdaterExecutablePath();
211}
212
213void ExpectCandidateUninstalled() {
214 base::FilePath versioned_folder_path = GetVersionedUpdaterFolderPath();
215 EXPECT_FALSE(base::PathExists(versioned_folder_path));
216 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
217 Launchd::User, Launchd::Agent, CopyWakeLaunchdName()));
218 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51219 Launchd::User, Launchd::Agent, CopyUpdateServiceInternalLaunchdName()));
Joshua Pawlicki4abd1322020-08-19 22:05:57220}
221
Joshua Pawlickibae1c6d2352020-03-19 19:21:44222void Uninstall() {
Joshua Pawlicki6867d7c2021-01-06 15:51:09223 if (::testing::Test::HasFailure())
224 PrintLog();
adoneria1762dd72020-12-17 17:33:08225 // Copy logs from GetDataDirPath() before updater uninstalls itself
226 // and deletes the path.
227 CopyLog(GetDataDirPath());
228
229 // Uninstall the updater.
Mila Green8ddc4e02020-05-01 00:15:02230 const base::FilePath path = GetExecutablePath();
Joshua Pawlickibae1c6d2352020-03-19 19:21:44231 ASSERT_FALSE(path.empty());
232 base::CommandLine command_line(path);
Mila Green8ddc4e02020-05-01 00:15:02233 command_line.AppendSwitch(kUninstallSwitch);
Joshua Pawlickibae1c6d2352020-03-19 19:21:44234 int exit_code = -1;
235 ASSERT_TRUE(Run(command_line, &exit_code));
236 EXPECT_EQ(0, exit_code);
237}
238
Mila Greena3991ae2020-10-16 00:10:55239base::FilePath GetFakeUpdaterInstallFolderPath(const base::Version& version) {
240 return GetExecutableFolderPathForVersion(version);
241}
242
Joshua Pawlicki6867d7c2021-01-06 15:51:09243void SetActive(const std::string& app_id) {
244 base::File::Error err = base::File::FILE_OK;
245 base::FilePath actives_file = GetActiveFile(app_id);
246 EXPECT_TRUE(base::CreateDirectoryAndGetError(actives_file.DirName(), &err))
247 << "Error: " << err;
248 EXPECT_TRUE(base::WriteFile(actives_file, ""));
249}
250
251void ExpectActive(const std::string& app_id) {
252 base::FilePath path = GetActiveFile(app_id);
253 EXPECT_TRUE(base::PathExists(path) && base::PathIsWritable(path))
254 << app_id << " is not active";
255}
256
257void ExpectNotActive(const std::string& app_id) {
258 base::FilePath path = GetActiveFile(app_id);
259 EXPECT_FALSE(base::PathExists(path) && base::PathIsWritable(path))
260 << app_id << " is active.";
261}
262
Joshua Pawlicki83d1d8232020-10-23 20:13:31263#endif // !defined(COMPONENT_BUILD)
264
Joshua Pawlickibae1c6d2352020-03-19 19:21:44265} // namespace test
Joshua Pawlickibae1c6d2352020-03-19 19:21:44266} // namespace updater