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/master_preferences.h"
32 #include "chrome/installer/util/product_unittest.h"
33 #include "chrome/installer/util/util_constants.h"
34 #include "chrome/installer/util/work_item.h"
35 #include "testing/gtest/include/gtest/gtest.h"
37 #include "installer_util_strings.h" // NOLINT
39 using base::win::RegKey
;
40 using installer::InstallationState
;
41 using installer::InstallerState
;
42 using installer::MasterPreferences
;
43 using registry_util::RegistryOverrideManager
;
45 class InstallerStateTest
: public TestWithTempDirAndDeleteTempOverrideKeys
{
49 // An installer state on which we can access otherwise protected members.
50 class MockInstallerState
: public InstallerState
{
52 MockInstallerState() : InstallerState() { }
53 void set_target_path(const base::FilePath
& target_path
) {
54 target_path_
= target_path
;
56 static bool IsFileInUse(const base::FilePath
& file
) {
57 return InstallerState::IsFileInUse(file
);
59 const Version
& critical_update_version() const {
60 return critical_update_version_
;
62 void GetExistingExeVersions(std::set
<std::string
>* existing_version_strings
) {
63 return InstallerState::GetExistingExeVersions(existing_version_strings
);
67 // Simple function to dump some text into a new file.
68 void CreateTextFile(const std::wstring
& filename
,
69 const std::wstring
& contents
) {
71 file
.open(filename
.c_str());
72 ASSERT_TRUE(file
.is_open());
77 void BuildSingleChromeState(const base::FilePath
& target_dir
,
78 MockInstallerState
* installer_state
) {
79 CommandLine cmd_line
= CommandLine::FromString(L
"setup.exe");
80 MasterPreferences
prefs(cmd_line
);
81 InstallationState machine_state
;
82 machine_state
.Initialize();
83 installer_state
->Initialize(cmd_line
, prefs
, machine_state
);
84 installer_state
->set_target_path(target_dir
);
85 EXPECT_TRUE(installer_state
->FindProduct(BrowserDistribution::CHROME_BROWSER
)
89 wchar_t text_content_1
[] = L
"delete me";
90 wchar_t text_content_2
[] = L
"delete me as well";
92 // Delete version directories. Everything lower than the given version
94 TEST_F(InstallerStateTest
, Delete
) {
95 // TODO(grt): move common stuff into the test fixture.
96 // Create a Chrome dir
97 base::FilePath
chrome_dir(test_dir_
.path());
98 chrome_dir
= chrome_dir
.AppendASCII("chrome");
99 base::CreateDirectory(chrome_dir
);
100 ASSERT_TRUE(base::PathExists(chrome_dir
));
102 base::FilePath
chrome_dir_1(chrome_dir
);
103 chrome_dir_1
= chrome_dir_1
.AppendASCII("1.0.1.0");
104 base::CreateDirectory(chrome_dir_1
);
105 ASSERT_TRUE(base::PathExists(chrome_dir_1
));
107 base::FilePath
chrome_dir_2(chrome_dir
);
108 chrome_dir_2
= chrome_dir_2
.AppendASCII("1.0.2.0");
109 base::CreateDirectory(chrome_dir_2
);
110 ASSERT_TRUE(base::PathExists(chrome_dir_2
));
112 base::FilePath
chrome_dir_3(chrome_dir
);
113 chrome_dir_3
= chrome_dir_3
.AppendASCII("1.0.3.0");
114 base::CreateDirectory(chrome_dir_3
);
115 ASSERT_TRUE(base::PathExists(chrome_dir_3
));
117 base::FilePath
chrome_dir_4(chrome_dir
);
118 chrome_dir_4
= chrome_dir_4
.AppendASCII("1.0.4.0");
119 base::CreateDirectory(chrome_dir_4
);
120 ASSERT_TRUE(base::PathExists(chrome_dir_4
));
122 base::FilePath
chrome_dll_1(chrome_dir_1
);
123 chrome_dll_1
= chrome_dll_1
.AppendASCII("chrome.dll");
124 CreateTextFile(chrome_dll_1
.value(), text_content_1
);
125 ASSERT_TRUE(base::PathExists(chrome_dll_1
));
127 base::FilePath
chrome_dll_2(chrome_dir_2
);
128 chrome_dll_2
= chrome_dll_2
.AppendASCII("chrome.dll");
129 CreateTextFile(chrome_dll_2
.value(), text_content_1
);
130 ASSERT_TRUE(base::PathExists(chrome_dll_2
));
132 base::FilePath
chrome_dll_3(chrome_dir_3
);
133 chrome_dll_3
= chrome_dll_3
.AppendASCII("chrome.dll");
134 CreateTextFile(chrome_dll_3
.value(), text_content_1
);
135 ASSERT_TRUE(base::PathExists(chrome_dll_3
));
137 base::FilePath
chrome_dll_4(chrome_dir_4
);
138 chrome_dll_4
= chrome_dll_4
.AppendASCII("chrome.dll");
139 CreateTextFile(chrome_dll_4
.value(), text_content_1
);
140 ASSERT_TRUE(base::PathExists(chrome_dll_4
));
142 MockInstallerState installer_state
;
143 BuildSingleChromeState(chrome_dir
, &installer_state
);
144 Version
latest_version("1.0.4.0");
146 base::ScopedTempDir temp_dir
;
147 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
148 installer_state
.RemoveOldVersionDirectories(latest_version
, NULL
,
152 // old versions should be gone
153 EXPECT_FALSE(base::PathExists(chrome_dir_1
));
154 EXPECT_FALSE(base::PathExists(chrome_dir_2
));
155 EXPECT_FALSE(base::PathExists(chrome_dir_3
));
156 // the latest version should stay
157 EXPECT_TRUE(base::PathExists(chrome_dll_4
));
160 // Delete older version directories, keeping the one in used intact.
161 TEST_F(InstallerStateTest
, DeleteInUsed
) {
162 // Create a Chrome dir
163 base::FilePath
chrome_dir(test_dir_
.path());
164 chrome_dir
= chrome_dir
.AppendASCII("chrome");
165 base::CreateDirectory(chrome_dir
);
166 ASSERT_TRUE(base::PathExists(chrome_dir
));
168 base::FilePath
chrome_dir_1(chrome_dir
);
169 chrome_dir_1
= chrome_dir_1
.AppendASCII("1.0.1.0");
170 base::CreateDirectory(chrome_dir_1
);
171 ASSERT_TRUE(base::PathExists(chrome_dir_1
));
173 base::FilePath
chrome_dir_2(chrome_dir
);
174 chrome_dir_2
= chrome_dir_2
.AppendASCII("1.0.2.0");
175 base::CreateDirectory(chrome_dir_2
);
176 ASSERT_TRUE(base::PathExists(chrome_dir_2
));
178 base::FilePath
chrome_dir_3(chrome_dir
);
179 chrome_dir_3
= chrome_dir_3
.AppendASCII("1.0.3.0");
180 base::CreateDirectory(chrome_dir_3
);
181 ASSERT_TRUE(base::PathExists(chrome_dir_3
));
183 base::FilePath
chrome_dir_4(chrome_dir
);
184 chrome_dir_4
= chrome_dir_4
.AppendASCII("1.0.4.0");
185 base::CreateDirectory(chrome_dir_4
);
186 ASSERT_TRUE(base::PathExists(chrome_dir_4
));
188 base::FilePath
chrome_dll_1(chrome_dir_1
);
189 chrome_dll_1
= chrome_dll_1
.AppendASCII("chrome.dll");
190 CreateTextFile(chrome_dll_1
.value(), text_content_1
);
191 ASSERT_TRUE(base::PathExists(chrome_dll_1
));
193 base::FilePath
chrome_dll_2(chrome_dir_2
);
194 chrome_dll_2
= chrome_dll_2
.AppendASCII("chrome.dll");
195 CreateTextFile(chrome_dll_2
.value(), text_content_1
);
196 ASSERT_TRUE(base::PathExists(chrome_dll_2
));
198 // Open the file to make it in use.
200 file
.open(chrome_dll_2
.value().c_str());
202 base::FilePath
chrome_othera_2(chrome_dir_2
);
203 chrome_othera_2
= chrome_othera_2
.AppendASCII("othera.dll");
204 CreateTextFile(chrome_othera_2
.value(), text_content_2
);
205 ASSERT_TRUE(base::PathExists(chrome_othera_2
));
207 base::FilePath
chrome_otherb_2(chrome_dir_2
);
208 chrome_otherb_2
= chrome_otherb_2
.AppendASCII("otherb.dll");
209 CreateTextFile(chrome_otherb_2
.value(), text_content_2
);
210 ASSERT_TRUE(base::PathExists(chrome_otherb_2
));
212 base::FilePath
chrome_dll_3(chrome_dir_3
);
213 chrome_dll_3
= chrome_dll_3
.AppendASCII("chrome.dll");
214 CreateTextFile(chrome_dll_3
.value(), text_content_1
);
215 ASSERT_TRUE(base::PathExists(chrome_dll_3
));
217 base::FilePath
chrome_dll_4(chrome_dir_4
);
218 chrome_dll_4
= chrome_dll_4
.AppendASCII("chrome.dll");
219 CreateTextFile(chrome_dll_4
.value(), text_content_1
);
220 ASSERT_TRUE(base::PathExists(chrome_dll_4
));
222 MockInstallerState installer_state
;
223 BuildSingleChromeState(chrome_dir
, &installer_state
);
224 Version
latest_version("1.0.4.0");
225 Version
existing_version("1.0.1.0");
227 base::ScopedTempDir temp_dir
;
228 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
229 installer_state
.RemoveOldVersionDirectories(latest_version
,
234 // the version defined as the existing version should stay
235 EXPECT_TRUE(base::PathExists(chrome_dir_1
));
236 // old versions not in used should be gone
237 EXPECT_FALSE(base::PathExists(chrome_dir_3
));
238 // every thing under in used version should stay
239 EXPECT_TRUE(base::PathExists(chrome_dir_2
));
240 EXPECT_TRUE(base::PathExists(chrome_dll_2
));
241 EXPECT_TRUE(base::PathExists(chrome_othera_2
));
242 EXPECT_TRUE(base::PathExists(chrome_otherb_2
));
243 // the latest version should stay
244 EXPECT_TRUE(base::PathExists(chrome_dll_4
));
247 // Tests a few basic things of the Package class. Makes sure that the path
248 // operations are correct
249 TEST_F(InstallerStateTest
, Basic
) {
250 const bool multi_install
= false;
251 const bool system_level
= true;
252 CommandLine cmd_line
= CommandLine::FromString(
253 std::wstring(L
"setup.exe") +
254 (multi_install
? L
" --multi-install --chrome" : L
"") +
255 (system_level
? L
" --system-level" : L
""));
256 MasterPreferences
prefs(cmd_line
);
257 InstallationState machine_state
;
258 machine_state
.Initialize();
259 MockInstallerState installer_state
;
260 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
261 installer_state
.set_target_path(test_dir_
.path());
262 EXPECT_EQ(test_dir_
.path().value(), installer_state
.target_path().value());
263 EXPECT_EQ(1U, installer_state
.products().size());
265 const char kOldVersion
[] = "1.2.3.4";
266 const char kNewVersion
[] = "2.3.4.5";
268 Version
new_version(kNewVersion
);
269 Version
old_version(kOldVersion
);
270 ASSERT_TRUE(new_version
.IsValid());
271 ASSERT_TRUE(old_version
.IsValid());
273 base::FilePath
installer_dir(
274 installer_state
.GetInstallerDirectory(new_version
));
275 EXPECT_FALSE(installer_dir
.empty());
277 base::FilePath
new_version_dir(installer_state
.target_path().Append(
278 base::UTF8ToWide(new_version
.GetString())));
279 base::FilePath
old_version_dir(installer_state
.target_path().Append(
280 base::UTF8ToWide(old_version
.GetString())));
282 EXPECT_FALSE(base::PathExists(new_version_dir
));
283 EXPECT_FALSE(base::PathExists(old_version_dir
));
285 EXPECT_FALSE(base::PathExists(installer_dir
));
286 base::CreateDirectory(installer_dir
);
287 EXPECT_TRUE(base::PathExists(new_version_dir
));
289 base::CreateDirectory(old_version_dir
);
290 EXPECT_TRUE(base::PathExists(old_version_dir
));
292 // Create a fake chrome.dll key file in the old version directory. This
293 // should prevent the old version directory from getting deleted.
294 base::FilePath
old_chrome_dll(old_version_dir
.Append(installer::kChromeDll
));
295 EXPECT_FALSE(base::PathExists(old_chrome_dll
));
297 // Hold on to the file exclusively to prevent the directory from
299 base::win::ScopedHandle
file(
300 ::CreateFile(old_chrome_dll
.value().c_str(), GENERIC_READ
,
301 0, NULL
, OPEN_ALWAYS
, 0, NULL
));
302 EXPECT_TRUE(file
.IsValid());
303 EXPECT_TRUE(base::PathExists(old_chrome_dll
));
305 base::ScopedTempDir temp_dir
;
306 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
308 // Don't explicitly tell the directory cleanup logic not to delete the
309 // old version, rely on the key files to keep it around.
310 installer_state
.RemoveOldVersionDirectories(new_version
,
314 // The old directory should still exist.
315 EXPECT_TRUE(base::PathExists(old_version_dir
));
316 EXPECT_TRUE(base::PathExists(new_version_dir
));
318 // Now close the file handle to make it possible to delete our key file.
321 installer_state
.RemoveOldVersionDirectories(new_version
,
324 // The new directory should still exist.
325 EXPECT_TRUE(base::PathExists(new_version_dir
));
327 // Now, the old directory and key file should be gone.
328 EXPECT_FALSE(base::PathExists(old_chrome_dll
));
329 EXPECT_FALSE(base::PathExists(old_version_dir
));
332 TEST_F(InstallerStateTest
, WithProduct
) {
333 const bool multi_install
= false;
334 const bool system_level
= true;
335 CommandLine cmd_line
= CommandLine::FromString(
336 std::wstring(L
"setup.exe") +
337 (multi_install
? L
" --multi-install --chrome" : L
"") +
338 (system_level
? L
" --system-level" : L
""));
339 MasterPreferences
prefs(cmd_line
);
340 InstallationState machine_state
;
341 machine_state
.Initialize();
342 MockInstallerState installer_state
;
343 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
344 installer_state
.set_target_path(test_dir_
.path());
345 EXPECT_EQ(1U, installer_state
.products().size());
346 EXPECT_EQ(system_level
, installer_state
.system_install());
348 const char kCurrentVersion
[] = "1.2.3.4";
349 Version
current_version(kCurrentVersion
);
351 HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
352 EXPECT_EQ(root
, installer_state
.root_key());
355 RegistryOverrideManager override_manager
;
356 override_manager
.OverrideRegistry(root
);
357 BrowserDistribution
* dist
= BrowserDistribution::GetSpecificDistribution(
358 BrowserDistribution::CHROME_BROWSER
);
359 RegKey
chrome_key(root
, dist
->GetVersionKey().c_str(), KEY_ALL_ACCESS
);
360 EXPECT_TRUE(chrome_key
.Valid());
361 if (chrome_key
.Valid()) {
362 chrome_key
.WriteValue(google_update::kRegVersionField
,
364 current_version
.GetString()).c_str());
365 machine_state
.Initialize();
366 // TODO(tommi): Also test for when there exists a new_chrome.exe.
367 Version
found_version(*installer_state
.GetCurrentVersion(machine_state
));
368 EXPECT_TRUE(found_version
.IsValid());
369 if (found_version
.IsValid())
370 EXPECT_TRUE(current_version
.Equals(found_version
));
375 TEST_F(InstallerStateTest
, InstallerResult
) {
376 const bool system_level
= true;
377 bool multi_install
= false;
378 HKEY root
= system_level
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
;
381 std::wstring launch_cmd
= L
"hey diddle diddle";
385 // check results for a fresh install of single Chrome
387 RegistryOverrideManager override_manager
;
388 override_manager
.OverrideRegistry(root
);
389 CommandLine cmd_line
= CommandLine::FromString(L
"setup.exe --system-level");
390 const MasterPreferences
prefs(cmd_line
);
391 InstallationState machine_state
;
392 machine_state
.Initialize();
393 InstallerState state
;
394 state
.Initialize(cmd_line
, prefs
, machine_state
);
395 state
.WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS
,
396 IDS_INSTALL_OS_ERROR_BASE
, &launch_cmd
);
397 BrowserDistribution
* distribution
=
398 BrowserDistribution::GetSpecificDistribution(
399 BrowserDistribution::CHROME_BROWSER
);
400 EXPECT_EQ(ERROR_SUCCESS
,
401 key
.Open(root
, distribution
->GetStateKey().c_str(), KEY_READ
));
402 EXPECT_EQ(ERROR_SUCCESS
,
403 key
.ReadValueDW(installer::kInstallerResult
, &dw_value
));
404 EXPECT_EQ(static_cast<DWORD
>(0), dw_value
);
405 EXPECT_EQ(ERROR_SUCCESS
,
406 key
.ReadValueDW(installer::kInstallerError
, &dw_value
));
407 EXPECT_EQ(static_cast<DWORD
>(installer::FIRST_INSTALL_SUCCESS
), dw_value
);
408 EXPECT_EQ(ERROR_SUCCESS
,
409 key
.ReadValue(installer::kInstallerResultUIString
, &value
));
410 EXPECT_FALSE(value
.empty());
411 EXPECT_EQ(ERROR_SUCCESS
,
412 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
413 EXPECT_EQ(launch_cmd
, value
);
416 // check results for a fresh install of multi Chrome
418 RegistryOverrideManager override_manager
;
419 override_manager
.OverrideRegistry(root
);
420 CommandLine cmd_line
= CommandLine::FromString(
421 L
"setup.exe --system-level --multi-install --chrome");
422 const MasterPreferences
prefs(cmd_line
);
423 InstallationState machine_state
;
424 machine_state
.Initialize();
425 InstallerState state
;
426 state
.Initialize(cmd_line
, prefs
, machine_state
);
427 state
.WriteInstallerResult(installer::FIRST_INSTALL_SUCCESS
, 0,
429 BrowserDistribution
* distribution
=
430 BrowserDistribution::GetSpecificDistribution(
431 BrowserDistribution::CHROME_BROWSER
);
432 BrowserDistribution
* binaries
=
433 BrowserDistribution::GetSpecificDistribution(
434 BrowserDistribution::CHROME_BINARIES
);
435 EXPECT_EQ(ERROR_SUCCESS
,
436 key
.Open(root
, distribution
->GetStateKey().c_str(), KEY_READ
));
437 EXPECT_EQ(ERROR_SUCCESS
,
438 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
439 EXPECT_EQ(launch_cmd
, value
);
440 EXPECT_EQ(ERROR_SUCCESS
,
441 key
.Open(root
, binaries
->GetStateKey().c_str(), KEY_READ
));
442 EXPECT_EQ(ERROR_SUCCESS
,
443 key
.ReadValue(installer::kInstallerSuccessLaunchCmdLine
, &value
));
444 EXPECT_EQ(launch_cmd
, value
);
449 // Test GetCurrentVersion when migrating single Chrome to multi
450 TEST_F(InstallerStateTest
, GetCurrentVersionMigrateChrome
) {
451 using installer::FakeInstallationState
;
453 const bool system_install
= false;
454 FakeInstallationState machine_state
;
456 // Pretend that this version of single-install Chrome is already installed.
457 machine_state
.AddChrome(system_install
, false,
458 new Version(chrome::kChromeVersion
));
460 // Now we're invoked to install multi Chrome.
461 CommandLine
cmd_line(
462 CommandLine::FromString(L
"setup.exe --multi-install --chrome"));
463 MasterPreferences
prefs(cmd_line
);
464 InstallerState installer_state
;
465 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
467 // Is the Chrome version picked up?
468 scoped_ptr
<Version
> version(installer_state
.GetCurrentVersion(machine_state
));
469 EXPECT_TRUE(version
.get() != NULL
);
472 TEST_F(InstallerStateTest
, IsFileInUse
) {
473 base::ScopedTempDir temp_dir
;
474 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
476 base::FilePath temp_file
;
477 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir
.path(), &temp_file
));
479 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file
));
482 // Open a handle to the file with the same access mode and sharing options
484 base::win::ScopedHandle
temp_handle(
485 CreateFile(temp_file
.value().c_str(),
486 SYNCHRONIZE
| FILE_EXECUTE
,
487 FILE_SHARE_DELETE
| FILE_SHARE_READ
,
488 NULL
, OPEN_EXISTING
, 0, 0));
489 ASSERT_TRUE(temp_handle
.IsValid());
491 // The file should now be in use.
492 EXPECT_TRUE(MockInstallerState::IsFileInUse(temp_file
));
495 // And once the handle is gone, it should no longer be in use.
496 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file
));
499 TEST_F(InstallerStateTest
, RemoveOldVersionDirs
) {
500 MockInstallerState installer_state
;
501 installer_state
.set_target_path(test_dir_
.path());
502 EXPECT_EQ(test_dir_
.path().value(), installer_state
.target_path().value());
504 const char kOldVersion
[] = "2.0.0.0";
505 const char kNewVersion
[] = "3.0.0.0";
506 const char kOldChromeExeVersion
[] = "2.1.0.0";
507 const char kChromeExeVersion
[] = "2.1.1.1";
508 const char kNewChromeExeVersion
[] = "3.0.0.0";
510 Version
new_version(kNewVersion
);
511 Version
old_version(kOldVersion
);
512 Version
old_chrome_exe_version(kOldChromeExeVersion
);
513 Version
chrome_exe_version(kChromeExeVersion
);
514 Version
new_chrome_exe_version(kNewChromeExeVersion
);
516 ASSERT_TRUE(new_version
.IsValid());
517 ASSERT_TRUE(old_version
.IsValid());
518 ASSERT_TRUE(old_chrome_exe_version
.IsValid());
519 ASSERT_TRUE(chrome_exe_version
.IsValid());
520 ASSERT_TRUE(new_chrome_exe_version
.IsValid());
522 // Set up a bunch of version dir paths.
523 base::FilePath version_dirs
[] = {
524 installer_state
.target_path().Append(L
"1.2.3.4"),
525 installer_state
.target_path().Append(L
"1.2.3.5"),
526 installer_state
.target_path().Append(L
"1.2.3.6"),
527 installer_state
.target_path().Append(base::ASCIIToWide(kOldVersion
)),
528 installer_state
.target_path().Append(
529 base::ASCIIToWide(kOldChromeExeVersion
)),
530 installer_state
.target_path().Append(L
"2.1.1.0"),
531 installer_state
.target_path().Append(base::ASCIIToWide(kChromeExeVersion
)),
532 installer_state
.target_path().Append(base::ASCIIToWide(kNewVersion
)),
533 installer_state
.target_path().Append(L
"3.9.1.1"),
536 // Create the version directories.
537 for (int i
= 0; i
< arraysize(version_dirs
); i
++) {
538 base::CreateDirectory(version_dirs
[i
]);
539 EXPECT_TRUE(base::PathExists(version_dirs
[i
]));
542 // Create exes with the appropriate version resource.
543 // Use the current test exe as a baseline.
544 base::FilePath exe_path
;
545 ASSERT_TRUE(PathService::Get(base::FILE_EXE
, &exe_path
));
548 base::FilePath target_file
;
549 const Version
& target_version
;
551 { installer_state
.target_path().Append(installer::kChromeOldExe
),
552 old_chrome_exe_version
},
553 { installer_state
.target_path().Append(installer::kChromeExe
),
554 chrome_exe_version
},
555 { installer_state
.target_path().Append(installer::kChromeNewExe
),
556 new_chrome_exe_version
},
558 for (int i
= 0; i
< arraysize(targets
); ++i
) {
559 ASSERT_TRUE(upgrade_test::GenerateSpecificPEFileVersion(
560 exe_path
, targets
[i
].target_file
, targets
[i
].target_version
));
563 // Call GetExistingExeVersions, validate that picks up the
565 std::set
<std::string
> expected_exe_versions
;
566 expected_exe_versions
.insert(kOldChromeExeVersion
);
567 expected_exe_versions
.insert(kChromeExeVersion
);
568 expected_exe_versions
.insert(kNewChromeExeVersion
);
570 std::set
<std::string
> actual_exe_versions
;
571 installer_state
.GetExistingExeVersions(&actual_exe_versions
);
572 EXPECT_EQ(expected_exe_versions
, actual_exe_versions
);
574 // Call RemoveOldVersionDirectories
575 installer_state
.RemoveOldVersionDirectories(new_version
,
577 installer_state
.target_path());
579 // What we expect to have left.
580 std::set
<std::string
> expected_remaining_dirs
;
581 expected_remaining_dirs
.insert(kOldVersion
);
582 expected_remaining_dirs
.insert(kNewVersion
);
583 expected_remaining_dirs
.insert(kOldChromeExeVersion
);
584 expected_remaining_dirs
.insert(kChromeExeVersion
);
585 expected_remaining_dirs
.insert(kNewChromeExeVersion
);
587 // Enumerate dirs in target_path(), ensure only desired remain.
588 base::FileEnumerator
version_enum(installer_state
.target_path(), false,
589 base::FileEnumerator::DIRECTORIES
);
590 for (base::FilePath next_version
= version_enum
.Next(); !next_version
.empty();
591 next_version
= version_enum
.Next()) {
592 base::FilePath
dir_name(next_version
.BaseName());
593 Version
version(base::UTF16ToASCII(dir_name
.value()));
594 if (version
.IsValid()) {
595 EXPECT_TRUE(expected_remaining_dirs
.erase(version
.GetString()))
596 << "Unexpected version dir found: " << version
.GetString();
600 std::set
<std::string
>::const_iterator
iter(
601 expected_remaining_dirs
.begin());
602 for (; iter
!= expected_remaining_dirs
.end(); ++iter
)
603 ADD_FAILURE() << "Expected to find version dir for " << *iter
;
606 TEST_F(InstallerStateTest
, InitializeTwice
) {
607 // Override these paths so that they can be found after the registry override
608 // manager is in place.
610 PathService::Get(base::DIR_PROGRAM_FILES
, &temp
);
611 base::ScopedPathOverride
program_files_override(base::DIR_PROGRAM_FILES
,
613 PathService::Get(base::DIR_PROGRAM_FILESX86
, &temp
);
614 base::ScopedPathOverride
program_filesx86_override(base::DIR_PROGRAM_FILESX86
,
616 PathService::Get(base::DIR_LOCAL_APP_DATA
, &temp
);
617 base::ScopedPathOverride
local_app_data_override(base::DIR_LOCAL_APP_DATA
,
619 registry_util::RegistryOverrideManager override_manager
;
620 override_manager
.OverrideRegistry(HKEY_CURRENT_USER
);
621 override_manager
.OverrideRegistry(HKEY_LOCAL_MACHINE
);
623 InstallationState machine_state
;
624 machine_state
.Initialize();
626 InstallerState installer_state
;
628 // Initialize the instance to install multi Chrome.
630 CommandLine
cmd_line(
631 CommandLine::FromString(L
"setup.exe --multi-install --chrome"));
632 MasterPreferences
prefs(cmd_line
);
633 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
635 // Confirm the expected state.
636 EXPECT_EQ(InstallerState::USER_LEVEL
, installer_state
.level());
637 EXPECT_EQ(InstallerState::MULTI_PACKAGE
, installer_state
.package_type());
638 EXPECT_EQ(InstallerState::MULTI_INSTALL
, installer_state
.operation());
639 EXPECT_TRUE(wcsstr(installer_state
.target_path().value().c_str(),
640 BrowserDistribution::GetSpecificDistribution(
641 BrowserDistribution::CHROME_BINARIES
)->
642 GetInstallSubDir().c_str()));
643 EXPECT_FALSE(installer_state
.verbose_logging());
644 EXPECT_EQ(installer_state
.state_key(),
645 BrowserDistribution::GetSpecificDistribution(
646 BrowserDistribution::CHROME_BROWSER
)->GetStateKey());
647 EXPECT_EQ(installer_state
.state_type(), BrowserDistribution::CHROME_BROWSER
);
648 EXPECT_TRUE(installer_state
.multi_package_binaries_distribution());
649 EXPECT_TRUE(installer_state
.FindProduct(BrowserDistribution::CHROME_BROWSER
));
651 // Now initialize it to install system-level single Chrome.
653 CommandLine
cmd_line(
654 CommandLine::FromString(L
"setup.exe --system-level --verbose-logging"));
655 MasterPreferences
prefs(cmd_line
);
656 installer_state
.Initialize(cmd_line
, prefs
, machine_state
);
659 // Confirm that the old state is gone.
660 EXPECT_EQ(InstallerState::SYSTEM_LEVEL
, installer_state
.level());
661 EXPECT_EQ(InstallerState::SINGLE_PACKAGE
, installer_state
.package_type());
662 EXPECT_EQ(InstallerState::SINGLE_INSTALL_OR_UPDATE
,
663 installer_state
.operation());
664 EXPECT_TRUE(wcsstr(installer_state
.target_path().value().c_str(),
665 BrowserDistribution::GetSpecificDistribution(
666 BrowserDistribution::CHROME_BROWSER
)->
667 GetInstallSubDir().c_str()));
668 EXPECT_TRUE(installer_state
.verbose_logging());
669 EXPECT_EQ(installer_state
.state_key(),
670 BrowserDistribution::GetSpecificDistribution(
671 BrowserDistribution::CHROME_BROWSER
)->GetStateKey());
672 EXPECT_EQ(installer_state
.state_type(), BrowserDistribution::CHROME_BROWSER
);
673 EXPECT_TRUE(installer_state
.FindProduct(BrowserDistribution::CHROME_BROWSER
));
676 // A fixture for testing InstallerState::DetermineCriticalVersion. Individual
677 // tests must invoke Initialize() with a critical version.
678 class InstallerStateCriticalVersionTest
: public ::testing::Test
{
680 InstallerStateCriticalVersionTest() : cmd_line_(CommandLine::NO_PROGRAM
) {}
682 // Creates a set of versions for use by all test runs.
683 static void SetUpTestCase() {
684 low_version_
= new Version("15.0.874.106");
685 opv_version_
= new Version("15.0.874.255");
686 middle_version_
= new Version("16.0.912.32");
687 pv_version_
= new Version("16.0.912.255");
688 high_version_
= new Version("17.0.932.0");
691 // Cleans up versions used by all test runs.
692 static void TearDownTestCase() {
695 delete middle_version_
;
697 delete high_version_
;
700 // Initializes the InstallerState to use for a test run. The returned
701 // instance's critical update version is set to |version|. |version| may be
702 // NULL, in which case the critical update version is unset.
703 MockInstallerState
& Initialize(const Version
* version
) {
704 cmd_line_
= version
== NULL
?
705 CommandLine::FromString(L
"setup.exe") :
706 CommandLine::FromString(
707 L
"setup.exe --critical-update-version=" +
708 base::ASCIIToWide(version
->GetString()));
709 prefs_
.reset(new MasterPreferences(cmd_line_
));
710 machine_state_
.Initialize();
711 installer_state_
.Initialize(cmd_line_
, *prefs_
, machine_state_
);
712 return installer_state_
;
715 static Version
* low_version_
;
716 static Version
* opv_version_
;
717 static Version
* middle_version_
;
718 static Version
* pv_version_
;
719 static Version
* high_version_
;
721 CommandLine cmd_line_
;
722 scoped_ptr
<MasterPreferences
> prefs_
;
723 InstallationState machine_state_
;
724 MockInstallerState installer_state_
;
727 Version
* InstallerStateCriticalVersionTest::low_version_
= NULL
;
728 Version
* InstallerStateCriticalVersionTest::opv_version_
= NULL
;
729 Version
* InstallerStateCriticalVersionTest::middle_version_
= NULL
;
730 Version
* InstallerStateCriticalVersionTest::pv_version_
= NULL
;
731 Version
* InstallerStateCriticalVersionTest::high_version_
= NULL
;
733 // Test the case where the critical version is less than the currently-running
734 // Chrome. The critical version is ignored since it doesn't apply.
735 TEST_F(InstallerStateCriticalVersionTest
, CriticalBeforeOpv
) {
736 MockInstallerState
& installer_state(Initialize(low_version_
));
738 EXPECT_TRUE(installer_state
.critical_update_version().Equals(*low_version_
));
739 // Unable to determine the installed version, so assume critical update.
741 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
742 // Installed version is past the critical update.
744 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
746 // Installed version is past the critical update.
748 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
752 // Test the case where the critical version is equal to the currently-running
753 // Chrome. The critical version is ignored since it doesn't apply.
754 TEST_F(InstallerStateCriticalVersionTest
, CriticalEqualsOpv
) {
755 MockInstallerState
& installer_state(Initialize(opv_version_
));
757 EXPECT_TRUE(installer_state
.critical_update_version().Equals(*opv_version_
));
758 // Unable to determine the installed version, so assume critical update.
760 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
761 // Installed version equals the critical update.
763 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
765 // Installed version equals the critical update.
767 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
771 // Test the case where the critical version is between the currently-running
772 // Chrome and the to-be-installed Chrome.
773 TEST_F(InstallerStateCriticalVersionTest
, CriticalBetweenOpvAndPv
) {
774 MockInstallerState
& installer_state(Initialize(middle_version_
));
776 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
778 // Unable to determine the installed version, so assume critical update.
780 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
781 // Installed version before the critical update.
783 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
785 // Installed version is past the critical update.
787 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
791 // Test the case where the critical version is the same as the to-be-installed
793 TEST_F(InstallerStateCriticalVersionTest
, CriticalEqualsPv
) {
794 MockInstallerState
& installer_state(Initialize(pv_version_
));
796 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
798 // Unable to determine the installed version, so assume critical update.
800 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
801 // Installed version before the critical update.
803 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
805 // Installed version equals the critical update.
807 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)
811 // Test the case where the critical version is greater than the to-be-installed
813 TEST_F(InstallerStateCriticalVersionTest
, CriticalAfterPv
) {
814 MockInstallerState
& installer_state(Initialize(high_version_
));
816 EXPECT_TRUE(installer_state
.critical_update_version().Equals(
818 // Critical update newer than the new version.
820 installer_state
.DetermineCriticalVersion(NULL
, *pv_version_
).IsValid());
822 installer_state
.DetermineCriticalVersion(opv_version_
, *pv_version_
)
825 installer_state
.DetermineCriticalVersion(pv_version_
, *pv_version_
)