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.
9 #include "base/base_paths.h"
10 #include "base/command_line.h"
11 #include "base/files/file_enumerator.h"
12 #include "base/files/file_path.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/path_service.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/test/scoped_path_override.h"
19 #include "base/test/test_reg_util_win.h"
20 #include "base/version.h"
21 #include "base/win/registry.h"
22 #include "base/win/scoped_handle.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "chrome/installer/test/alternate_version_generator.h"
25 #include "chrome/installer/util/fake_installation_state.h"
26 #include "chrome/installer/util/fake_product_state.h"
27 #include "chrome/installer/util/google_update_constants.h"
28 #include "chrome/installer/util/helper.h"
29 #include "chrome/installer/util/installation_state.h"
30 #include "chrome/installer/util/installer_state.h"
31 #include "chrome/installer/util/installer_util_strings.h"
32 #include "chrome/installer/util/master_preferences.h"
33 #include "chrome/installer/util/product_unittest.h"
34 #include "chrome/installer/util/util_constants.h"
35 #include "chrome/installer/util/work_item.h"
36 #include "testing/gtest/include/gtest/gtest.h"
38 using base::win::RegKey
;
39 using installer::InstallationState
;
40 using installer::InstallerState
;
41 using installer::MasterPreferences
;
42 using registry_util::RegistryOverrideManager
;
44 class InstallerStateTest
: public TestWithTempDirAndDeleteTempOverrideKeys
{
48 // An installer state on which we can access otherwise protected members.
49 class MockInstallerState
: public InstallerState
{
51 MockInstallerState() : InstallerState() { }
52 void set_target_path(const base::FilePath
& target_path
) {
53 target_path_
= target_path
;
55 static bool IsFileInUse(const base::FilePath
& file
) {
56 return InstallerState::IsFileInUse(file
);
58 const Version
& critical_update_version() const {
59 return critical_update_version_
;
61 void GetExistingExeVersions(std::set
<std::string
>* existing_version_strings
) {
62 return InstallerState::GetExistingExeVersions(existing_version_strings
);
66 // Simple function to dump some text into a new file.
67 void CreateTextFile(const std::wstring
& filename
,
68 const std::wstring
& contents
) {
70 file
.open(filename
.c_str());
71 ASSERT_TRUE(file
.is_open());
76 void BuildSingleChromeState(const base::FilePath
& target_dir
,
77 MockInstallerState
* installer_state
) {
78 base::CommandLine cmd_line
= base::CommandLine::FromString(L
"setup.exe");
79 MasterPreferences
prefs(cmd_line
);
80 InstallationState machine_state
;
81 machine_state
.Initialize();
82 installer_state
->Initialize(cmd_line
, prefs
, machine_state
);
83 installer_state
->set_target_path(target_dir
);
84 EXPECT_TRUE(installer_state
->FindProduct(BrowserDistribution::CHROME_BROWSER
)
88 wchar_t text_content_1
[] = L
"delete me";
89 wchar_t text_content_2
[] = L
"delete me as well";
91 // Delete version directories. Everything lower than the given version
93 TEST_F(InstallerStateTest
, Delete
) {
94 // TODO(grt): move common stuff into the test fixture.
95 // Create a Chrome dir
96 base::FilePath
chrome_dir(test_dir_
.path());
97 chrome_dir
= chrome_dir
.AppendASCII("chrome");
98 base::CreateDirectory(chrome_dir
);
99 ASSERT_TRUE(base::PathExists(chrome_dir
));
101 base::FilePath
chrome_dir_1(chrome_dir
);
102 chrome_dir_1
= chrome_dir_1
.AppendASCII("1.0.1.0");
103 base::CreateDirectory(chrome_dir_1
);
104 ASSERT_TRUE(base::PathExists(chrome_dir_1
));
106 base::FilePath
chrome_dir_2(chrome_dir
);
107 chrome_dir_2
= chrome_dir_2
.AppendASCII("1.0.2.0");
108 base::CreateDirectory(chrome_dir_2
);
109 ASSERT_TRUE(base::PathExists(chrome_dir_2
));
111 base::FilePath
chrome_dir_3(chrome_dir
);
112 chrome_dir_3
= chrome_dir_3
.AppendASCII("1.0.3.0");
113 base::CreateDirectory(chrome_dir_3
);
114 ASSERT_TRUE(base::PathExists(chrome_dir_3
));
116 base::FilePath
chrome_dir_4(chrome_dir
);
117 chrome_dir_4
= chrome_dir_4
.AppendASCII("1.0.4.0");
118 base::CreateDirectory(chrome_dir_4
);
119 ASSERT_TRUE(base::PathExists(chrome_dir_4
));
121 base::FilePath
chrome_dll_1(chrome_dir_1
);
122 chrome_dll_1
= chrome_dll_1
.AppendASCII("chrome.dll");
123 CreateTextFile(chrome_dll_1
.value(), text_content_1
);
124 ASSERT_TRUE(base::PathExists(chrome_dll_1
));
126 base::FilePath
chrome_dll_2(chrome_dir_2
);
127 chrome_dll_2
= chrome_dll_2
.AppendASCII("chrome.dll");
128 CreateTextFile(chrome_dll_2
.value(), text_content_1
);
129 ASSERT_TRUE(base::PathExists(chrome_dll_2
));
131 base::FilePath
chrome_dll_3(chrome_dir_3
);
132 chrome_dll_3
= chrome_dll_3
.AppendASCII("chrome.dll");
133 CreateTextFile(chrome_dll_3
.value(), text_content_1
);
134 ASSERT_TRUE(base::PathExists(chrome_dll_3
));
136 base::FilePath
chrome_dll_4(chrome_dir_4
);
137 chrome_dll_4
= chrome_dll_4
.AppendASCII("chrome.dll");
138 CreateTextFile(chrome_dll_4
.value(), text_content_1
);
139 ASSERT_TRUE(base::PathExists(chrome_dll_4
));
141 MockInstallerState installer_state
;
142 BuildSingleChromeState(chrome_dir
, &installer_state
);
143 Version
latest_version("1.0.4.0");
145 base::ScopedTempDir temp_dir
;
146 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
147 installer_state
.RemoveOldVersionDirectories(latest_version
, NULL
,
151 // old versions should be gone
152 EXPECT_FALSE(base::PathExists(chrome_dir_1
));
153 EXPECT_FALSE(base::PathExists(chrome_dir_2
));
154 EXPECT_FALSE(base::PathExists(chrome_dir_3
));
155 // the latest version should stay
156 EXPECT_TRUE(base::PathExists(chrome_dll_4
));
159 // Delete older version directories, keeping the one in used intact.
160 TEST_F(InstallerStateTest
, DeleteInUsed
) {
161 // Create a Chrome dir
162 base::FilePath
chrome_dir(test_dir_
.path());
163 chrome_dir
= chrome_dir
.AppendASCII("chrome");
164 base::CreateDirectory(chrome_dir
);
165 ASSERT_TRUE(base::PathExists(chrome_dir
));
167 base::FilePath
chrome_dir_1(chrome_dir
);
168 chrome_dir_1
= chrome_dir_1
.AppendASCII("1.0.1.0");
169 base::CreateDirectory(chrome_dir_1
);
170 ASSERT_TRUE(base::PathExists(chrome_dir_1
));
172 base::FilePath
chrome_dir_2(chrome_dir
);
173 chrome_dir_2
= chrome_dir_2
.AppendASCII("1.0.2.0");
174 base::CreateDirectory(chrome_dir_2
);
175 ASSERT_TRUE(base::PathExists(chrome_dir_2
));
177 base::FilePath
chrome_dir_3(chrome_dir
);
178 chrome_dir_3
= chrome_dir_3
.AppendASCII("1.0.3.0");
179 base::CreateDirectory(chrome_dir_3
);
180 ASSERT_TRUE(base::PathExists(chrome_dir_3
));
182 base::FilePath
chrome_dir_4(chrome_dir
);
183 chrome_dir_4
= chrome_dir_4
.AppendASCII("1.0.4.0");
184 base::CreateDirectory(chrome_dir_4
);
185 ASSERT_TRUE(base::PathExists(chrome_dir_4
));
187 base::FilePath
chrome_dll_1(chrome_dir_1
);
188 chrome_dll_1
= chrome_dll_1
.AppendASCII("chrome.dll");
189 CreateTextFile(chrome_dll_1
.value(), text_content_1
);
190 ASSERT_TRUE(base::PathExists(chrome_dll_1
));
192 base::FilePath
chrome_dll_2(chrome_dir_2
);
193 chrome_dll_2
= chrome_dll_2
.AppendASCII("chrome.dll");
194 CreateTextFile(chrome_dll_2
.value(), text_content_1
);
195 ASSERT_TRUE(base::PathExists(chrome_dll_2
));
197 // Open the file to make it in use.
199 file
.open(chrome_dll_2
.value().c_str());
201 base::FilePath
chrome_othera_2(chrome_dir_2
);
202 chrome_othera_2
= chrome_othera_2
.AppendASCII("othera.dll");
203 CreateTextFile(chrome_othera_2
.value(), text_content_2
);
204 ASSERT_TRUE(base::PathExists(chrome_othera_2
));
206 base::FilePath
chrome_otherb_2(chrome_dir_2
);
207 chrome_otherb_2
= chrome_otherb_2
.AppendASCII("otherb.dll");
208 CreateTextFile(chrome_otherb_2
.value(), text_content_2
);
209 ASSERT_TRUE(base::PathExists(chrome_otherb_2
));
211 base::FilePath
chrome_dll_3(chrome_dir_3
);
212 chrome_dll_3
= chrome_dll_3
.AppendASCII("chrome.dll");
213 CreateTextFile(chrome_dll_3
.value(), text_content_1
);
214 ASSERT_TRUE(base::PathExists(chrome_dll_3
));
216 base::FilePath
chrome_dll_4(chrome_dir_4
);
217 chrome_dll_4
= chrome_dll_4
.AppendASCII("chrome.dll");
218 CreateTextFile(chrome_dll_4
.value(), text_content_1
);
219 ASSERT_TRUE(base::PathExists(chrome_dll_4
));
221 MockInstallerState installer_state
;
222 BuildSingleChromeState(chrome_dir
, &installer_state
);
223 Version
latest_version("1.0.4.0");
224 Version
existing_version("1.0.1.0");
226 base::ScopedTempDir temp_dir
;
227 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
228 installer_state
.RemoveOldVersionDirectories(latest_version
,
233 // the version defined as the existing version should stay
234 EXPECT_TRUE(base::PathExists(chrome_dir_1
));
235 // old versions not in used should be gone
236 EXPECT_FALSE(base::PathExists(chrome_dir_3
));
237 // every thing under in used version should stay
238 EXPECT_TRUE(base::PathExists(chrome_dir_2
));
239 EXPECT_TRUE(base::PathExists(chrome_dll_2
));
240 EXPECT_TRUE(base::PathExists(chrome_othera_2
));
241 EXPECT_TRUE(base::PathExists(chrome_otherb_2
));
242 // the latest version should stay
243 EXPECT_TRUE(base::PathExists(chrome_dll_4
));
246 // Tests a few basic things of the Package class. Makes sure that the path
247 // operations are correct
248 TEST_F(InstallerStateTest
, Basic
) {
249 const bool multi_install
= false;
250 const bool system_level
= true;
251 base::CommandLine cmd_line
= base::CommandLine::FromString(
252 std::wstring(L
"setup.exe") +
253 (multi_install
? L
" --multi-install --chrome" : L
"") +
254 (system_level
? L
" --system-level" : L
""));
255 MasterPreferences
prefs(cmd_line
);
256 InstallationState machine_state
;
257 machine_state
.Initialize();
258 MockInstallerState installer_state
;
259 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
260 installer_state
.set_target_path(test_dir_
.path());
261 EXPECT_EQ(test_dir_
.path().value(), installer_state
.target_path().value());
262 EXPECT_EQ(1U, installer_state
.products().size());
264 const char kOldVersion
[] = "1.2.3.4";
265 const char kNewVersion
[] = "2.3.4.5";
267 Version
new_version(kNewVersion
);
268 Version
old_version(kOldVersion
);
269 ASSERT_TRUE(new_version
.IsValid());
270 ASSERT_TRUE(old_version
.IsValid());
272 base::FilePath
installer_dir(
273 installer_state
.GetInstallerDirectory(new_version
));
274 EXPECT_FALSE(installer_dir
.empty());
276 base::FilePath
new_version_dir(installer_state
.target_path().Append(
277 base::UTF8ToWide(new_version
.GetString())));
278 base::FilePath
old_version_dir(installer_state
.target_path().Append(
279 base::UTF8ToWide(old_version
.GetString())));
281 EXPECT_FALSE(base::PathExists(new_version_dir
));
282 EXPECT_FALSE(base::PathExists(old_version_dir
));
284 EXPECT_FALSE(base::PathExists(installer_dir
));
285 base::CreateDirectory(installer_dir
);
286 EXPECT_TRUE(base::PathExists(new_version_dir
));
288 base::CreateDirectory(old_version_dir
);
289 EXPECT_TRUE(base::PathExists(old_version_dir
));
291 // Create a fake chrome.dll key file in the old version directory. This
292 // should prevent the old version directory from getting deleted.
293 base::FilePath
old_chrome_dll(old_version_dir
.Append(installer::kChromeDll
));
294 EXPECT_FALSE(base::PathExists(old_chrome_dll
));
296 // Hold on to the file exclusively to prevent the directory from
298 base::win::ScopedHandle
file(
299 ::CreateFile(old_chrome_dll
.value().c_str(), GENERIC_READ
,
300 0, NULL
, OPEN_ALWAYS
, 0, NULL
));
301 EXPECT_TRUE(file
.IsValid());
302 EXPECT_TRUE(base::PathExists(old_chrome_dll
));
304 base::ScopedTempDir temp_dir
;
305 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
307 // Don't explicitly tell the directory cleanup logic not to delete the
308 // old version, rely on the key files to keep it around.
309 installer_state
.RemoveOldVersionDirectories(new_version
,
313 // The old directory should still exist.
314 EXPECT_TRUE(base::PathExists(old_version_dir
));
315 EXPECT_TRUE(base::PathExists(new_version_dir
));
317 // Now close the file handle to make it possible to delete our key file.
320 installer_state
.RemoveOldVersionDirectories(new_version
,
323 // The new directory should still exist.
324 EXPECT_TRUE(base::PathExists(new_version_dir
));
326 // Now, the old directory and key file should be gone.
327 EXPECT_FALSE(base::PathExists(old_chrome_dll
));
328 EXPECT_FALSE(base::PathExists(old_version_dir
));
331 TEST_F(InstallerStateTest
, WithProduct
) {
332 const bool multi_install
= false;
333 const bool system_level
= true;
334 base::CommandLine cmd_line
= base::CommandLine::FromString(
335 std::wstring(L
"setup.exe") +
336 (multi_install
? L
" --multi-install --chrome" : L
"") +
337 (system_level
? L
" --system-level" : L
""));
338 MasterPreferences
prefs(cmd_line
);
339 InstallationState machine_state
;
340 machine_state
.Initialize();
341 MockInstallerState installer_state
;
342 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
343 installer_state
.set_target_path(test_dir_
.path());
344 EXPECT_EQ(1U, installer_state
.products().size());
345 EXPECT_EQ(system_level
, installer_state
.system_install());
347 const char kCurrentVersion
[] = "1.2.3.4";
348 Version
current_version(kCurrentVersion
);
350 HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
351 EXPECT_EQ(root
, installer_state
.root_key());
354 RegistryOverrideManager override_manager
;
355 override_manager
.OverrideRegistry(root
);
356 BrowserDistribution
* dist
= BrowserDistribution::GetSpecificDistribution(
357 BrowserDistribution::CHROME_BROWSER
);
358 RegKey
chrome_key(root
, dist
->GetVersionKey().c_str(), KEY_ALL_ACCESS
);
359 EXPECT_TRUE(chrome_key
.Valid());
360 if (chrome_key
.Valid()) {
361 chrome_key
.WriteValue(google_update::kRegVersionField
,
363 current_version
.GetString()).c_str());
364 machine_state
.Initialize();
365 // TODO(tommi): Also test for when there exists a new_chrome.exe.
366 Version
found_version(*installer_state
.GetCurrentVersion(machine_state
));
367 EXPECT_TRUE(found_version
.IsValid());
368 if (found_version
.IsValid())
369 EXPECT_TRUE(current_version
.Equals(found_version
));
374 TEST_F(InstallerStateTest
, InstallerResult
) {
375 const bool system_level
= true;
376 HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
379 std::wstring launch_cmd
= L
"hey diddle diddle";
383 // check results for a fresh install of single Chrome
385 RegistryOverrideManager override_manager
;
386 override_manager
.OverrideRegistry(root
);
387 base::CommandLine cmd_line
=
388 base::CommandLine::FromString(L
"setup.exe --system-level");
389 const MasterPreferences
prefs(cmd_line
);
390 InstallationState machine_state
;
391 machine_state
.Initialize();
392 InstallerState state
;
393 state
.Initialize(cmd_line
, prefs
, machine_state
);
394 state
.WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS
,
395 IDS_INSTALL_OS_ERROR_BASE
, &launch_cmd
);
396 BrowserDistribution
* distribution
=
397 BrowserDistribution::GetSpecificDistribution(
398 BrowserDistribution::CHROME_BROWSER
);
399 EXPECT_EQ(ERROR_SUCCESS
,
400 key
.Open(root
, distribution
->GetStateKey().c_str(), KEY_READ
));
401 EXPECT_EQ(ERROR_SUCCESS
,
402 key
.ReadValueDW(installer::kInstallerResult
, &dw_value
));
403 EXPECT_EQ(static_cast<DWORD
>(0), dw_value
);
404 EXPECT_EQ(ERROR_SUCCESS
,
405 key
.ReadValueDW(installer::kInstallerError
, &dw_value
));
406 EXPECT_EQ(static_cast<DWORD
>(installer::FIRST_INSTALL_SUCCESS
), dw_value
);
407 EXPECT_EQ(ERROR_SUCCESS
,
408 key
.ReadValue(installer::kInstallerResultUIString
, &value
));
409 EXPECT_FALSE(value
.empty());
410 EXPECT_EQ(ERROR_SUCCESS
,
411 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
412 EXPECT_EQ(launch_cmd
, value
);
415 // check results for a fresh install of multi Chrome
417 RegistryOverrideManager override_manager
;
418 override_manager
.OverrideRegistry(root
);
419 base::CommandLine cmd_line
= base::CommandLine::FromString(
420 L
"setup.exe --system-level --multi-install --chrome");
421 const MasterPreferences
prefs(cmd_line
);
422 InstallationState machine_state
;
423 machine_state
.Initialize();
424 InstallerState state
;
425 state
.Initialize(cmd_line
, prefs
, machine_state
);
426 state
.WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS
, 0,
428 BrowserDistribution
* distribution
=
429 BrowserDistribution::GetSpecificDistribution(
430 BrowserDistribution::CHROME_BROWSER
);
431 BrowserDistribution
* binaries
=
432 BrowserDistribution::GetSpecificDistribution(
433 BrowserDistribution::CHROME_BINARIES
);
434 EXPECT_EQ(ERROR_SUCCESS
,
435 key
.Open(root
, distribution
->GetStateKey().c_str(), KEY_READ
));
436 EXPECT_EQ(ERROR_SUCCESS
,
437 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
438 EXPECT_EQ(launch_cmd
, value
);
439 EXPECT_EQ(ERROR_SUCCESS
,
440 key
.Open(root
, binaries
->GetStateKey().c_str(), KEY_READ
));
441 EXPECT_EQ(ERROR_SUCCESS
,
442 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
443 EXPECT_EQ(launch_cmd
, value
);
448 // Test GetCurrentVersion when migrating single Chrome to multi
449 TEST_F(InstallerStateTest
, GetCurrentVersionMigrateChrome
) {
450 using installer::FakeInstallationState
;
452 const bool system_install
= false;
453 FakeInstallationState machine_state
;
455 // Pretend that this version of single-install Chrome is already installed.
456 machine_state
.AddChrome(system_install
, false,
457 new Version(chrome::kChromeVersion
));
459 // Now we're invoked to install multi Chrome.
460 base::CommandLine
cmd_line(
461 base::CommandLine::FromString(L
"setup.exe --multi-install --chrome"));
462 MasterPreferences
prefs(cmd_line
);
463 InstallerState installer_state
;
464 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
466 // Is the Chrome version picked up?
467 scoped_ptr
<Version
> version(installer_state
.GetCurrentVersion(machine_state
));
468 EXPECT_TRUE(version
.get() != NULL
);
471 TEST_F(InstallerStateTest
, IsFileInUse
) {
472 base::ScopedTempDir temp_dir
;
473 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
475 base::FilePath temp_file
;
476 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir
.path(), &temp_file
));
478 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file
));
481 // Open a handle to the file with the same access mode and sharing options
483 base::win::ScopedHandle
temp_handle(
484 CreateFile(temp_file
.value().c_str(),
485 SYNCHRONIZE
| FILE_EXECUTE
,
486 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
487 NULL
, OPEN_EXISTING
, 0, 0));
488 ASSERT_TRUE(temp_handle
.IsValid());
490 // The file should now be in use.
491 EXPECT_TRUE(MockInstallerState::IsFileInUse(temp_file
));
494 // And once the handle is gone, it should no longer be in use.
495 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file
));
498 TEST_F(InstallerStateTest
, RemoveOldVersionDirs
) {
499 MockInstallerState installer_state
;
500 installer_state
.set_target_path(test_dir_
.path());
501 EXPECT_EQ(test_dir_
.path().value(), installer_state
.target_path().value());
503 const char kOldVersion
[] = "2.0.0.0";
504 const char kNewVersion
[] = "3.0.0.0";
505 const char kOldChromeExeVersion
[] = "2.1.0.0";
506 const char kChromeExeVersion
[] = "2.1.1.1";
507 const char kNewChromeExeVersion
[] = "3.0.0.0";
509 Version
new_version(kNewVersion
);
510 Version
old_version(kOldVersion
);
511 Version
old_chrome_exe_version(kOldChromeExeVersion
);
512 Version
chrome_exe_version(kChromeExeVersion
);
513 Version
new_chrome_exe_version(kNewChromeExeVersion
);
515 ASSERT_TRUE(new_version
.IsValid());
516 ASSERT_TRUE(old_version
.IsValid());
517 ASSERT_TRUE(old_chrome_exe_version
.IsValid());
518 ASSERT_TRUE(chrome_exe_version
.IsValid());
519 ASSERT_TRUE(new_chrome_exe_version
.IsValid());
521 // Set up a bunch of version dir paths.
522 base::FilePath version_dirs
[] = {
523 installer_state
.target_path().Append(L
"1.2.3.4"),
524 installer_state
.target_path().Append(L
"1.2.3.5"),
525 installer_state
.target_path().Append(L
"1.2.3.6"),
526 installer_state
.target_path().AppendASCII(kOldVersion
),
527 installer_state
.target_path().AppendASCII(kOldChromeExeVersion
),
528 installer_state
.target_path().Append(L
"2.1.1.0"),
529 installer_state
.target_path().AppendASCII(kChromeExeVersion
),
530 installer_state
.target_path().AppendASCII(kNewVersion
),
531 installer_state
.target_path().Append(L
"3.9.1.1"),
534 // Create the version directories.
535 for (int i
= 0; i
< arraysize(version_dirs
); i
++) {
536 base::CreateDirectory(version_dirs
[i
]);
537 EXPECT_TRUE(base::PathExists(version_dirs
[i
]));
540 // Create exes with the appropriate version resource.
541 // Use the current test exe as a baseline.
542 base::FilePath exe_path
;
543 ASSERT_TRUE(PathService::Get(base::FILE_EXE
, &exe_path
));
546 base::FilePath target_file
;
547 const Version
& target_version
;
549 { installer_state
.target_path().Append(installer::kChromeOldExe
),
550 old_chrome_exe_version
},
551 { installer_state
.target_path().Append(installer::kChromeExe
),
552 chrome_exe_version
},
553 { installer_state
.target_path().Append(installer::kChromeNewExe
),
554 new_chrome_exe_version
},
556 for (int i
= 0; i
< arraysize(targets
); ++i
) {
557 ASSERT_TRUE(upgrade_test::GenerateSpecificPEFileVersion(
558 exe_path
, targets
[i
].target_file
, targets
[i
].target_version
));
561 // Call GetExistingExeVersions, validate that picks up the
563 std::set
<std::string
> expected_exe_versions
;
564 expected_exe_versions
.insert(kOldChromeExeVersion
);
565 expected_exe_versions
.insert(kChromeExeVersion
);
566 expected_exe_versions
.insert(kNewChromeExeVersion
);
568 std::set
<std::string
> actual_exe_versions
;
569 installer_state
.GetExistingExeVersions(&actual_exe_versions
);
570 EXPECT_EQ(expected_exe_versions
, actual_exe_versions
);
572 // Call RemoveOldVersionDirectories
573 installer_state
.RemoveOldVersionDirectories(new_version
,
575 installer_state
.target_path());
577 // What we expect to have left.
578 std::set
<std::string
> expected_remaining_dirs
;
579 expected_remaining_dirs
.insert(kOldVersion
);
580 expected_remaining_dirs
.insert(kNewVersion
);
581 expected_remaining_dirs
.insert(kOldChromeExeVersion
);
582 expected_remaining_dirs
.insert(kChromeExeVersion
);
583 expected_remaining_dirs
.insert(kNewChromeExeVersion
);
585 // Enumerate dirs in target_path(), ensure only desired remain.
586 base::FileEnumerator
version_enum(installer_state
.target_path(), false,
587 base::FileEnumerator::DIRECTORIES
);
588 for (base::FilePath next_version
= version_enum
.Next(); !next_version
.empty();
589 next_version
= version_enum
.Next()) {
590 base::FilePath
dir_name(next_version
.BaseName());
591 Version
version(base::UTF16ToASCII(dir_name
.value()));
592 if (version
.IsValid()) {
593 EXPECT_TRUE(expected_remaining_dirs
.erase(version
.GetString()))
594 << "Unexpected version dir found: " << version
.GetString();
598 std::set
<std::string
>::const_iterator
iter(
599 expected_remaining_dirs
.begin());
600 for (; iter
!= expected_remaining_dirs
.end(); ++iter
)
601 ADD_FAILURE() << "Expected to find version dir for " << *iter
;
604 TEST_F(InstallerStateTest
, InitializeTwice
) {
605 // Override these paths so that they can be found after the registry override
606 // manager is in place.
608 PathService::Get(base::DIR_PROGRAM_FILES
, &temp
);
609 base::ScopedPathOverride
program_files_override(base::DIR_PROGRAM_FILES
,
611 PathService::Get(base::DIR_PROGRAM_FILESX86
, &temp
);
612 base::ScopedPathOverride
program_filesx86_override(base::DIR_PROGRAM_FILESX86
,
614 PathService::Get(base::DIR_LOCAL_APP_DATA
, &temp
);
615 base::ScopedPathOverride
local_app_data_override(base::DIR_LOCAL_APP_DATA
,
617 registry_util::RegistryOverrideManager override_manager
;
618 override_manager
.OverrideRegistry(HKEY_CURRENT_USER
);
619 override_manager
.OverrideRegistry(HKEY_LOCAL_MACHINE
);
621 InstallationState machine_state
;
622 machine_state
.Initialize();
624 InstallerState installer_state
;
626 // Initialize the instance to install multi Chrome.
628 base::CommandLine
cmd_line(
629 base::CommandLine::FromString(L
"setup.exe --multi-install --chrome"));
630 MasterPreferences
prefs(cmd_line
);
631 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
633 // Confirm the expected state.
634 EXPECT_EQ(InstallerState::USER_LEVEL
, installer_state
.level());
635 EXPECT_EQ(InstallerState::MULTI_PACKAGE
, installer_state
.package_type());
636 EXPECT_EQ(InstallerState::MULTI_INSTALL
, installer_state
.operation());
637 EXPECT_TRUE(wcsstr(installer_state
.target_path().value().c_str(),
638 BrowserDistribution::GetSpecificDistribution(
639 BrowserDistribution::CHROME_BINARIES
)->
640 GetInstallSubDir().c_str()));
641 EXPECT_FALSE(installer_state
.verbose_logging());
642 EXPECT_EQ(installer_state
.state_key(),
643 BrowserDistribution::GetSpecificDistribution(
644 BrowserDistribution::CHROME_BROWSER
)->GetStateKey());
645 EXPECT_EQ(installer_state
.state_type(), BrowserDistribution::CHROME_BROWSER
);
646 EXPECT_TRUE(installer_state
.multi_package_binaries_distribution());
647 EXPECT_TRUE(installer_state
.FindProduct(BrowserDistribution::CHROME_BROWSER
));
649 // Now initialize it to install system-level single Chrome.
651 base::CommandLine
cmd_line(base::CommandLine::FromString(
652 L
"setup.exe --system-level --verbose-logging"));
653 MasterPreferences
prefs(cmd_line
);
654 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
657 // Confirm that the old state is gone.
658 EXPECT_EQ(InstallerState::SYSTEM_LEVEL
, installer_state
.level());
659 EXPECT_EQ(InstallerState::SINGLE_PACKAGE
, installer_state
.package_type());
660 EXPECT_EQ(InstallerState::SINGLE_INSTALL_OR_UPDATE
,
661 installer_state
.operation());
662 EXPECT_TRUE(wcsstr(installer_state
.target_path().value().c_str(),
663 BrowserDistribution::GetSpecificDistribution(
664 BrowserDistribution::CHROME_BROWSER
)->
665 GetInstallSubDir().c_str()));
666 EXPECT_TRUE(installer_state
.verbose_logging());
667 EXPECT_EQ(installer_state
.state_key(),
668 BrowserDistribution::GetSpecificDistribution(
669 BrowserDistribution::CHROME_BROWSER
)->GetStateKey());
670 EXPECT_EQ(installer_state
.state_type(), BrowserDistribution::CHROME_BROWSER
);
671 EXPECT_TRUE(installer_state
.FindProduct(BrowserDistribution::CHROME_BROWSER
));
674 // A fixture for testing InstallerState::DetermineCriticalVersion. Individual
675 // tests must invoke Initialize() with a critical version.
676 class InstallerStateCriticalVersionTest
: public ::testing::Test
{
678 InstallerStateCriticalVersionTest()
679 : cmd_line_(base::CommandLine::NO_PROGRAM
) {}
681 // Creates a set of versions for use by all test runs.
682 static void SetUpTestCase() {
683 low_version_
= new Version("15.0.874.106");
684 opv_version_
= new Version("15.0.874.255");
685 middle_version_
= new Version("16.0.912.32");
686 pv_version_
= new Version("16.0.912.255");
687 high_version_
= new Version("17.0.932.0");
690 // Cleans up versions used by all test runs.
691 static void TearDownTestCase() {
694 delete middle_version_
;
696 delete high_version_
;
699 // Initializes the InstallerState to use for a test run. The returned
700 // instance's critical update version is set to |version|. |version| may be
701 // NULL, in which case the critical update version is unset.
702 MockInstallerState
& Initialize(const Version
* version
) {
703 cmd_line_
= version
== NULL
? base::CommandLine::FromString(L
"setup.exe")
704 : base::CommandLine::FromString(
705 L
"setup.exe --critical-update-version=" +
706 base::ASCIIToUTF16(version
->GetString()));
707 prefs_
.reset(new MasterPreferences(cmd_line_
));
708 machine_state_
.Initialize();
709 installer_state_
.Initialize(cmd_line_
, *prefs_
, machine_state_
);
710 return installer_state_
;
713 static Version
* low_version_
;
714 static Version
* opv_version_
;
715 static Version
* middle_version_
;
716 static Version
* pv_version_
;
717 static Version
* high_version_
;
719 base::CommandLine cmd_line_
;
720 scoped_ptr
<MasterPreferences
> prefs_
;
721 InstallationState machine_state_
;
722 MockInstallerState installer_state_
;
725 Version
* InstallerStateCriticalVersionTest::low_version_
= NULL
;
726 Version
* InstallerStateCriticalVersionTest::opv_version_
= NULL
;
727 Version
* InstallerStateCriticalVersionTest::middle_version_
= NULL
;
728 Version
* InstallerStateCriticalVersionTest::pv_version_
= NULL
;
729 Version
* InstallerStateCriticalVersionTest::high_version_
= NULL
;
731 // Test the case where the critical version is less than the currently-running
732 // Chrome. The critical version is ignored since it doesn't apply.
733 TEST_F(InstallerStateCriticalVersionTest
, CriticalBeforeOpv
) {
734 MockInstallerState
& installer_state(Initialize(low_version_
));
736 EXPECT_TRUE(installer_state
.critical_update_version().Equals(*low_version_
));
737 // Unable to determine the installed version, so assume critical update.
739 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
740 // Installed version is past the critical update.
742 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
744 // Installed version is past the critical update.
746 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
750 // Test the case where the critical version is equal to the currently-running
751 // Chrome. The critical version is ignored since it doesn't apply.
752 TEST_F(InstallerStateCriticalVersionTest
, CriticalEqualsOpv
) {
753 MockInstallerState
& installer_state(Initialize(opv_version_
));
755 EXPECT_TRUE(installer_state
.critical_update_version().Equals(*opv_version_
));
756 // Unable to determine the installed version, so assume critical update.
758 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
759 // Installed version equals the critical update.
761 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
763 // Installed version equals the critical update.
765 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
769 // Test the case where the critical version is between the currently-running
770 // Chrome and the to-be-installed Chrome.
771 TEST_F(InstallerStateCriticalVersionTest
, CriticalBetweenOpvAndPv
) {
772 MockInstallerState
& installer_state(Initialize(middle_version_
));
774 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
776 // Unable to determine the installed version, so assume critical update.
778 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
779 // Installed version before the critical update.
781 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
783 // Installed version is past the critical update.
785 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
789 // Test the case where the critical version is the same as the to-be-installed
791 TEST_F(InstallerStateCriticalVersionTest
, CriticalEqualsPv
) {
792 MockInstallerState
& installer_state(Initialize(pv_version_
));
794 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
796 // Unable to determine the installed version, so assume critical update.
798 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
799 // Installed version before the critical update.
801 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
803 // Installed version equals the critical update.
805 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
809 // Test the case where the critical version is greater than the to-be-installed
811 TEST_F(InstallerStateCriticalVersionTest
, CriticalAfterPv
) {
812 MockInstallerState
& installer_state(Initialize(high_version_
));
814 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
816 // Critical update newer than the new version.
818 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
820 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
823 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)