blob: ef2cb548364b54c82cb100c386cd33e0fc7766bc [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>
Adam Norberg14b66a12021-01-20 21:54:037#include <vector>
Mila Greena3991ae2020-10-16 00:10:558
Joshua Pawlickibae1c6d2352020-03-19 19:21:449#include "base/command_line.h"
10#include "base/files/file_path.h"
11#include "base/files/file_util.h"
12#include "base/mac/foundation_util.h"
13#include "base/path_service.h"
Joshua Pawlickicd6925c92020-12-15 15:07:5014#include "base/run_loop.h"
15#include "base/strings/sys_string_conversions.h"
16#include "base/test/bind.h"
Mila Greena3991ae2020-10-16 00:10:5517#include "base/version.h"
Joshua Pawlicki8f755d382020-03-20 19:51:1018#include "chrome/common/mac/launchd.h"
Mila Green8ddc4e02020-05-01 00:15:0219#include "chrome/updater/constants.h"
Adam Norberg14b66a12021-01-20 21:54:0320#include "chrome/updater/external_constants_builder.h"
Joshua Pawlickicd6925c92020-12-15 15:07:5021#include "chrome/updater/launchd_util.h"
Mila Greena3991ae2020-10-16 00:10:5522#import "chrome/updater/mac/util.h"
Joshua Pawlicki8f755d382020-03-20 19:51:1023#include "chrome/updater/mac/xpc_service_names.h"
Mila Greena3991ae2020-10-16 00:10:5524#include "chrome/updater/prefs.h"
Joshua Pawlicki83d1d8232020-10-23 20:13:3125#include "chrome/updater/test/integration_tests.h"
Mila Green3e3058a2020-08-27 16:59:2726#include "chrome/updater/test/test_app/constants.h"
27#include "chrome/updater/test/test_app/test_app_version.h"
Mila Greenaff086902021-01-07 22:00:5228#include "chrome/updater/updater_branding.h"
Joshua Pawlicki4abd1322020-08-19 22:05:5729#include "chrome/updater/util.h"
Joshua Pawlickibae1c6d2352020-03-19 19:21:4430#include "testing/gtest/include/gtest/gtest.h"
Joshua Pawlicki6867d7c2021-01-06 15:51:0931#include "url/gurl.h"
Joshua Pawlickibae1c6d2352020-03-19 19:21:4432
33namespace updater {
Joshua Pawlickibae1c6d2352020-03-19 19:21:4434namespace test {
35
Joshua Pawlicki83d1d8232020-10-23 20:13:3136// crbug.com/1112527: These tests are not compatible with component build.
37#if !defined(COMPONENT_BUILD)
38
Joshua Pawlickibae1c6d2352020-03-19 19:21:4439namespace {
40
Joshua Pawlickicd6925c92020-12-15 15:07:5041void RemoveJobFromLaunchd(Launchd::Domain domain,
42 Launchd::Type type,
43 base::ScopedCFTypeRef<CFStringRef> name) {
44 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(domain, type, name))
45 << "Failed to delete plist for " << name;
46
47 // Return value is ignored, since RemoveJob returns false if the job already
48 // doesn't exist.
49 Launchd::GetInstance()->RemoveJob(base::SysCFStringRefToUTF8(name));
50}
51
Joshua Pawlickibae1c6d2352020-03-19 19:21:4452base::FilePath GetExecutablePath() {
53 base::FilePath test_executable;
54 if (!base::PathService::Get(base::FILE_EXE, &test_executable))
55 return base::FilePath();
56 return test_executable.DirName()
Mila Greena3991ae2020-10-16 00:10:5557 .Append(FILE_PATH_LITERAL(PRODUCT_FULLNAME_STRING ".app"))
Joshua Pawlickibae1c6d2352020-03-19 19:21:4458 .Append(FILE_PATH_LITERAL("Contents"))
59 .Append(FILE_PATH_LITERAL("MacOS"))
60 .Append(FILE_PATH_LITERAL(PRODUCT_FULLNAME_STRING));
61}
62
Mila Green3e3058a2020-08-27 16:59:2763base::FilePath GetTestAppExecutablePath() {
64 base::FilePath test_executable;
65 if (!base::PathService::Get(base::FILE_EXE, &test_executable))
66 return base::FilePath();
67 return test_executable.DirName()
Mila Greena3991ae2020-10-16 00:10:5568 .Append(FILE_PATH_LITERAL(TEST_APP_FULLNAME_STRING ".app"))
Mila Green3e3058a2020-08-27 16:59:2769 .Append(FILE_PATH_LITERAL("Contents"))
70 .Append(FILE_PATH_LITERAL("MacOS"))
71 .Append(FILE_PATH_LITERAL(TEST_APP_FULLNAME_STRING));
72}
73
Joshua Pawlicki8f755d382020-03-20 19:51:1074base::FilePath GetProductPath() {
75 return base::mac::GetUserLibraryPath()
76 .AppendASCII(COMPANY_SHORTNAME_STRING)
77 .AppendASCII(PRODUCT_FULLNAME_STRING);
78}
79
Joshua Pawlicki6867d7c2021-01-06 15:51:0980base::FilePath GetActiveFile(const std::string& id) {
81 return base::GetHomeDir()
82 .AppendASCII("Library")
83 .AppendASCII(COMPANY_SHORTNAME_STRING)
84 .AppendASCII(COMPANY_SHORTNAME_STRING "SoftwareUpdate")
85 .AppendASCII("Actives")
86 .AppendASCII(id);
87}
88
Joshua Pawlickicd6925c92020-12-15 15:07:5089void ExpectServiceAbsent(const std::string& service) {
90 bool success = false;
91 base::RunLoop loop;
92 PollLaunchctlList(service, LaunchctlPresence::kAbsent,
93 base::TimeDelta::FromSeconds(7),
94 base::BindLambdaForTesting([&](bool result) {
95 success = result;
96 loop.QuitClosure().Run();
97 }));
98 loop.Run();
99 EXPECT_TRUE(success) << service << " is unexpectedly present.";
100}
101
Joshua Pawlicki83d1d8232020-10-23 20:13:31102} // namespace
103
Joshua Pawlicki6867d7c2021-01-06 15:51:09104#endif // defined(COMPONENT_BUILD
105
106void EnterTestMode(const GURL& url) {
Adam Norberg14b66a12021-01-20 21:54:03107 ASSERT_TRUE(ExternalConstantsBuilder()
108 .SetUpdateURL(std::vector<std::string>{url.spec()})
109 .SetUseCUP(false)
Mila Green1cb26962021-01-21 01:00:00110 .SetInitialDelay(0.1)
Adam Norberg14b66a12021-01-20 21:54:03111 .Overwrite());
Joshua Pawlicki6867d7c2021-01-06 15:51:09112}
113
114// crbug.com/1112527: These tests are not compatible with component build.
115#if !defined(COMPONENT_BUILD)
116
Joshua Pawlicki9d1340fc2020-08-14 20:59:35117base::FilePath GetDataDirPath() {
118 return base::mac::GetUserLibraryPath()
119 .AppendASCII("Application Support")
120 .AppendASCII(COMPANY_SHORTNAME_STRING)
121 .AppendASCII(PRODUCT_FULLNAME_STRING);
122}
123
Joshua Pawlickibae1c6d2352020-03-19 19:21:44124void Clean() {
Lei Zhang329c5bc2020-07-07 21:09:11125 EXPECT_TRUE(base::DeletePathRecursively(GetProductPath()));
Joshua Pawlicki8f755d382020-03-20 19:51:10126 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green7414a0ed2020-07-21 21:30:42127 Launchd::User, Launchd::Agent, updater::CopyWakeLaunchdName()));
Joshua Pawlicki8f755d382020-03-20 19:51:10128 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green80845642020-12-10 03:44:51129 Launchd::User, Launchd::Agent,
130 updater::CopyUpdateServiceInternalLaunchdName()));
Mila Green7414a0ed2020-07-21 21:30:42131 EXPECT_TRUE(Launchd::GetInstance()->DeletePlist(
Mila Green80845642020-12-10 03:44:51132 Launchd::User, Launchd::Agent, updater::CopyUpdateServiceLaunchdName()));
Joshua Pawlicki9d1340fc2020-08-14 20:59:35133 EXPECT_TRUE(base::DeletePathRecursively(GetDataDirPath()));
Joshua Pawlicki3f645882020-08-21 20:36:17134
135 @autoreleasepool {
Joshua Pawlickicd6925c92020-12-15 15:07:50136 // TODO(crbug.com/1096654): support machine case (Launchd::Domain::Local and
137 // Launchd::Type::Daemon).
138 RemoveJobFromLaunchd(Launchd::Domain::User, Launchd::Type::Agent,
139 CopyUpdateServiceLaunchdName());
140 RemoveJobFromLaunchd(Launchd::Domain::User, Launchd::Type::Agent,
141 CopyUpdateServiceInternalLaunchdName());
Joshua Pawlicki3f645882020-08-21 20:36:17142 }
Joshua Pawlickibae1c6d2352020-03-19 19:21:44143}
144
145void ExpectClean() {
146 // Files must not exist on the file system.
Joshua Pawlicki8f755d382020-03-20 19:51:10147 EXPECT_FALSE(base::PathExists(GetProductPath()));
148 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green7414a0ed2020-07-21 21:30:42149 Launchd::User, Launchd::Agent, updater::CopyWakeLaunchdName()));
Mila Green8ddc4e02020-05-01 00:15:02150 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51151 Launchd::User, Launchd::Agent,
152 updater::CopyUpdateServiceInternalLaunchdName()));
Mila Green7414a0ed2020-07-21 21:30:42153 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51154 Launchd::User, Launchd::Agent, updater::CopyUpdateServiceLaunchdName()));
Joshua Pawlicki9d1340fc2020-08-14 20:59:35155 EXPECT_FALSE(base::PathExists(GetDataDirPath()));
Joshua Pawlickicd6925c92020-12-15 15:07:50156 ExpectServiceAbsent(kUpdateServiceLaunchdName);
157 ExpectServiceAbsent(kUpdateServiceInternalLaunchdName);
Joshua Pawlickibae1c6d2352020-03-19 19:21:44158}
159
Joshua Pawlickibae1c6d2352020-03-19 19:21:44160void ExpectInstalled() {
161 // Files must exist on the file system.
Joshua Pawlicki8f755d382020-03-20 19:51:10162 EXPECT_TRUE(base::PathExists(GetProductPath()));
Mila Green7414a0ed2020-07-21 21:30:42163 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(Launchd::User, Launchd::Agent,
164 CopyWakeLaunchdName()));
Mila Green80845642020-12-10 03:44:51165 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(
166 Launchd::User, Launchd::Agent, CopyUpdateServiceInternalLaunchdName()));
Joshua Pawlickibae1c6d2352020-03-19 19:21:44167}
168
169void Install() {
Mila Green8ddc4e02020-05-01 00:15:02170 const base::FilePath path = GetExecutablePath();
Joshua Pawlickibae1c6d2352020-03-19 19:21:44171 ASSERT_FALSE(path.empty());
Michael Change4785a822020-03-26 20:55:01172 base::CommandLine command_line(path);
Joshua Pawlicki91ce318b2020-09-15 14:35:38173 command_line.AppendSwitch(kInstallSwitch);
Mila Green8ddc4e02020-05-01 00:15:02174 int exit_code = -1;
175 ASSERT_TRUE(Run(command_line, &exit_code));
176 EXPECT_EQ(0, exit_code);
177}
178
Mila Green9056ede2020-05-18 20:48:40179void ExpectActive() {
Mila Green8ddc4e02020-05-01 00:15:02180 // Files must exist on the file system.
181 EXPECT_TRUE(base::PathExists(GetProductPath()));
Mila Green80845642020-12-10 03:44:51182 EXPECT_TRUE(Launchd::GetInstance()->PlistExists(
183 Launchd::User, Launchd::Agent, CopyUpdateServiceLaunchdName()));
Mila Green8ddc4e02020-05-01 00:15:02184}
185
Mila Green3e3058a2020-08-27 16:59:27186void RegisterTestApp() {
187 const base::FilePath path = GetTestAppExecutablePath();
188 ASSERT_FALSE(path.empty());
189 base::CommandLine command_line(path);
190 command_line.AppendSwitch(kRegisterUpdaterSwitch);
191 int exit_code = -1;
192 ASSERT_TRUE(Run(command_line, &exit_code));
193 EXPECT_EQ(0, exit_code);
194}
195
Mila Greena3991ae2020-10-16 00:10:55196base::FilePath GetInstalledExecutablePath() {
197 return GetUpdaterExecutablePath();
198}
199
200void ExpectCandidateUninstalled() {
201 base::FilePath versioned_folder_path = GetVersionedUpdaterFolderPath();
202 EXPECT_FALSE(base::PathExists(versioned_folder_path));
203 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
204 Launchd::User, Launchd::Agent, CopyWakeLaunchdName()));
205 EXPECT_FALSE(Launchd::GetInstance()->PlistExists(
Mila Green80845642020-12-10 03:44:51206 Launchd::User, Launchd::Agent, CopyUpdateServiceInternalLaunchdName()));
Joshua Pawlicki4abd1322020-08-19 22:05:57207}
208
Joshua Pawlickibae1c6d2352020-03-19 19:21:44209void Uninstall() {
Joshua Pawlicki6867d7c2021-01-06 15:51:09210 if (::testing::Test::HasFailure())
211 PrintLog();
adoneria1762dd72020-12-17 17:33:08212 // Copy logs from GetDataDirPath() before updater uninstalls itself
213 // and deletes the path.
214 CopyLog(GetDataDirPath());
215
216 // Uninstall the updater.
Mila Green8ddc4e02020-05-01 00:15:02217 const base::FilePath path = GetExecutablePath();
Joshua Pawlickibae1c6d2352020-03-19 19:21:44218 ASSERT_FALSE(path.empty());
219 base::CommandLine command_line(path);
Mila Green8ddc4e02020-05-01 00:15:02220 command_line.AppendSwitch(kUninstallSwitch);
Joshua Pawlickibae1c6d2352020-03-19 19:21:44221 int exit_code = -1;
222 ASSERT_TRUE(Run(command_line, &exit_code));
223 EXPECT_EQ(0, exit_code);
224}
225
Mila Greena3991ae2020-10-16 00:10:55226base::FilePath GetFakeUpdaterInstallFolderPath(const base::Version& version) {
227 return GetExecutableFolderPathForVersion(version);
228}
229
Joshua Pawlicki6867d7c2021-01-06 15:51:09230void SetActive(const std::string& app_id) {
231 base::File::Error err = base::File::FILE_OK;
232 base::FilePath actives_file = GetActiveFile(app_id);
233 EXPECT_TRUE(base::CreateDirectoryAndGetError(actives_file.DirName(), &err))
234 << "Error: " << err;
235 EXPECT_TRUE(base::WriteFile(actives_file, ""));
236}
237
238void ExpectActive(const std::string& app_id) {
239 base::FilePath path = GetActiveFile(app_id);
240 EXPECT_TRUE(base::PathExists(path) && base::PathIsWritable(path))
241 << app_id << " is not active";
242}
243
244void ExpectNotActive(const std::string& app_id) {
245 base::FilePath path = GetActiveFile(app_id);
246 EXPECT_FALSE(base::PathExists(path) && base::PathIsWritable(path))
247 << app_id << " is active.";
248}
249
Joshua Pawlicki83d1d8232020-10-23 20:13:31250#endif // !defined(COMPONENT_BUILD)
251
Joshua Pawlickibae1c6d2352020-03-19 19:21:44252} // namespace test
Joshua Pawlickibae1c6d2352020-03-19 19:21:44253} // namespace updater