installer_state_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h> 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fstream> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_path.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/process_util.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/scoped_temp_dir.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/string_util.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/test/test_reg_util_win.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/utf_string_conversions.h" 19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/version.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/registry.h" 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/win/scoped_handle.h" 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/chrome_constants.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/installer/test/alternate_version_generator.h" 24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/installer/util/fake_installation_state.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/fake_product_state.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/google_update_constants.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/helper.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installation_state.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/installer_state.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/master_preferences.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/product_unittest.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/util_constants.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/util/work_item.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "installer_util_strings.h" // NOLINT 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::RegKey; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::InstallationState; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::InstallerState; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using installer::MasterPreferences; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using registry_util::RegistryOverrideManager; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InstallerStateTest : public TestWithTempDirAndDeleteTempOverrideKeys { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An installer state on which we can access otherwise protected members. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockInstallerState : public InstallerState { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockInstallerState() : InstallerState() { } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_target_path(const FilePath& target_path) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_path_ = target_path; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool IsFileInUse(const FilePath& file) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InstallerState::IsFileInUse(file); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Version& critical_update_version() const { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return critical_update_version_; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void GetExistingExeVersions(std::set<std::string>* existing_version_strings) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return InstallerState::GetExistingExeVersions(existing_version_strings); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple function to dump some text into a new file. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CreateTextFile(const std::wstring& filename, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::wstring& contents) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::ofstream file; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file.open(filename.c_str()); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file.is_open()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file << contents; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file.close(); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BuildSingleChromeState(const FilePath& target_dir, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockInstallerState* installer_state) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandLine cmd_line = CommandLine::FromString(L"setup.exe"); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MasterPreferences prefs(cmd_line); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallationState machine_state; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) machine_state.Initialize(); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->Initialize(cmd_line, prefs, machine_state); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) installer_state->set_target_path(target_dir); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(installer_state->FindProduct(BrowserDistribution::CHROME_BROWSER) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) != NULL); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(installer_state->FindProduct(BrowserDistribution::CHROME_FRAME) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) == NULL); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wchar_t text_content_1[] = L"delete me"; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)wchar_t text_content_2[] = L"delete me as well"; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Delete version directories. Everything lower than the given version 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// should be deleted. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(InstallerStateTest, Delete) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(grt): move common stuff into the test fixture. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create a Chrome dir 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dir(test_dir_.path()); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dir = chrome_dir.AppendASCII("chrome"); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(chrome_dir); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dir)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dir_1(chrome_dir); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0"); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(chrome_dir_1); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dir_1)); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dir_2(chrome_dir); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0"); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(chrome_dir_2); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dir_2)); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dir_3(chrome_dir); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0"); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(chrome_dir_3); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dir_3)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dir_4(chrome_dir); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0"); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::CreateDirectory(chrome_dir_4); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dir_4)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dll_1(chrome_dir_1); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll"); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateTextFile(chrome_dll_1.value(), text_content_1); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dll_1)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dll_2(chrome_dir_2); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll"); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateTextFile(chrome_dll_2.value(), text_content_1); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dll_2)); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dll_3(chrome_dir_3); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll"); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateTextFile(chrome_dll_3.value(), text_content_1); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dll_3)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilePath chrome_dll_4(chrome_dir_4); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll"); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateTextFile(chrome_dll_4.value(), text_content_1); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(file_util::PathExists(chrome_dll_4)); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MockInstallerState installer_state; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BuildSingleChromeState(chrome_dir, &installer_state); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Version latest_version("1.0.4.0"); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedTempDir temp_dir; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) installer_state.RemoveOldVersionDirectories(latest_version, NULL, 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) temp_dir.path()); 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // old versions should be gone 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(file_util::PathExists(chrome_dir_1)); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(file_util::PathExists(chrome_dir_2)); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_FALSE(file_util::PathExists(chrome_dir_3)); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the latest version should stay 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(file_util::PathExists(chrome_dll_4)); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Delete older version directories, keeping the one in used intact. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(InstallerStateTest, DeleteInUsed) { 163 // Create a Chrome dir 164 FilePath chrome_dir(test_dir_.path()); 165 chrome_dir = chrome_dir.AppendASCII("chrome"); 166 file_util::CreateDirectory(chrome_dir); 167 ASSERT_TRUE(file_util::PathExists(chrome_dir)); 168 169 FilePath chrome_dir_1(chrome_dir); 170 chrome_dir_1 = chrome_dir_1.AppendASCII("1.0.1.0"); 171 file_util::CreateDirectory(chrome_dir_1); 172 ASSERT_TRUE(file_util::PathExists(chrome_dir_1)); 173 174 FilePath chrome_dir_2(chrome_dir); 175 chrome_dir_2 = chrome_dir_2.AppendASCII("1.0.2.0"); 176 file_util::CreateDirectory(chrome_dir_2); 177 ASSERT_TRUE(file_util::PathExists(chrome_dir_2)); 178 179 FilePath chrome_dir_3(chrome_dir); 180 chrome_dir_3 = chrome_dir_3.AppendASCII("1.0.3.0"); 181 file_util::CreateDirectory(chrome_dir_3); 182 ASSERT_TRUE(file_util::PathExists(chrome_dir_3)); 183 184 FilePath chrome_dir_4(chrome_dir); 185 chrome_dir_4 = chrome_dir_4.AppendASCII("1.0.4.0"); 186 file_util::CreateDirectory(chrome_dir_4); 187 ASSERT_TRUE(file_util::PathExists(chrome_dir_4)); 188 189 FilePath chrome_dll_1(chrome_dir_1); 190 chrome_dll_1 = chrome_dll_1.AppendASCII("chrome.dll"); 191 CreateTextFile(chrome_dll_1.value(), text_content_1); 192 ASSERT_TRUE(file_util::PathExists(chrome_dll_1)); 193 194 FilePath chrome_dll_2(chrome_dir_2); 195 chrome_dll_2 = chrome_dll_2.AppendASCII("chrome.dll"); 196 CreateTextFile(chrome_dll_2.value(), text_content_1); 197 ASSERT_TRUE(file_util::PathExists(chrome_dll_2)); 198 199 // Open the file to make it in use. 200 std::ofstream file; 201 file.open(chrome_dll_2.value().c_str()); 202 203 FilePath chrome_othera_2(chrome_dir_2); 204 chrome_othera_2 = chrome_othera_2.AppendASCII("othera.dll"); 205 CreateTextFile(chrome_othera_2.value(), text_content_2); 206 ASSERT_TRUE(file_util::PathExists(chrome_othera_2)); 207 208 FilePath chrome_otherb_2(chrome_dir_2); 209 chrome_otherb_2 = chrome_otherb_2.AppendASCII("otherb.dll"); 210 CreateTextFile(chrome_otherb_2.value(), text_content_2); 211 ASSERT_TRUE(file_util::PathExists(chrome_otherb_2)); 212 213 FilePath chrome_dll_3(chrome_dir_3); 214 chrome_dll_3 = chrome_dll_3.AppendASCII("chrome.dll"); 215 CreateTextFile(chrome_dll_3.value(), text_content_1); 216 ASSERT_TRUE(file_util::PathExists(chrome_dll_3)); 217 218 FilePath chrome_dll_4(chrome_dir_4); 219 chrome_dll_4 = chrome_dll_4.AppendASCII("chrome.dll"); 220 CreateTextFile(chrome_dll_4.value(), text_content_1); 221 ASSERT_TRUE(file_util::PathExists(chrome_dll_4)); 222 223 MockInstallerState installer_state; 224 BuildSingleChromeState(chrome_dir, &installer_state); 225 Version latest_version("1.0.4.0"); 226 Version existing_version("1.0.1.0"); 227 { 228 ScopedTempDir temp_dir; 229 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 230 installer_state.RemoveOldVersionDirectories(latest_version, 231 &existing_version, 232 temp_dir.path()); 233 } 234 235 // the version defined as the existing version should stay 236 EXPECT_TRUE(file_util::PathExists(chrome_dir_1)); 237 // old versions not in used should be gone 238 EXPECT_FALSE(file_util::PathExists(chrome_dir_3)); 239 // every thing under in used version should stay 240 EXPECT_TRUE(file_util::PathExists(chrome_dir_2)); 241 EXPECT_TRUE(file_util::PathExists(chrome_dll_2)); 242 EXPECT_TRUE(file_util::PathExists(chrome_othera_2)); 243 EXPECT_TRUE(file_util::PathExists(chrome_otherb_2)); 244 // the latest version should stay 245 EXPECT_TRUE(file_util::PathExists(chrome_dll_4)); 246} 247 248// Tests a few basic things of the Package class. Makes sure that the path 249// operations are correct 250TEST_F(InstallerStateTest, Basic) { 251 const bool multi_install = false; 252 const bool system_level = true; 253 CommandLine cmd_line = CommandLine::FromString( 254 std::wstring(L"setup.exe") + 255 (multi_install ? L" --multi-install --chrome" : L"") + 256 (system_level ? L" --system-level" : L"")); 257 MasterPreferences prefs(cmd_line); 258 InstallationState machine_state; 259 machine_state.Initialize(); 260 MockInstallerState installer_state; 261 installer_state.Initialize(cmd_line, prefs, machine_state); 262 installer_state.set_target_path(test_dir_.path()); 263 EXPECT_EQ(test_dir_.path().value(), installer_state.target_path().value()); 264 EXPECT_EQ(1U, installer_state.products().size()); 265 266 const char kOldVersion[] = "1.2.3.4"; 267 const char kNewVersion[] = "2.3.4.5"; 268 269 Version new_version(kNewVersion); 270 Version old_version(kOldVersion); 271 ASSERT_TRUE(new_version.IsValid()); 272 ASSERT_TRUE(old_version.IsValid()); 273 274 FilePath installer_dir(installer_state.GetInstallerDirectory(new_version)); 275 EXPECT_FALSE(installer_dir.empty()); 276 277 FilePath new_version_dir(installer_state.target_path().Append( 278 UTF8ToWide(new_version.GetString()))); 279 FilePath old_version_dir(installer_state.target_path().Append( 280 UTF8ToWide(old_version.GetString()))); 281 282 EXPECT_FALSE(file_util::PathExists(new_version_dir)); 283 EXPECT_FALSE(file_util::PathExists(old_version_dir)); 284 285 EXPECT_FALSE(file_util::PathExists(installer_dir)); 286 file_util::CreateDirectory(installer_dir); 287 EXPECT_TRUE(file_util::PathExists(new_version_dir)); 288 289 file_util::CreateDirectory(old_version_dir); 290 EXPECT_TRUE(file_util::PathExists(old_version_dir)); 291 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 FilePath old_chrome_dll(old_version_dir.Append(installer::kChromeDll)); 295 EXPECT_FALSE(file_util::PathExists(old_chrome_dll)); 296 297 // Hold on to the file exclusively to prevent the directory from 298 // being deleted. 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(file_util::PathExists(old_chrome_dll)); 304 305 ScopedTempDir temp_dir; 306 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 307 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, 311 NULL, 312 temp_dir.path()); 313 314 // The old directory should still exist. 315 EXPECT_TRUE(file_util::PathExists(old_version_dir)); 316 EXPECT_TRUE(file_util::PathExists(new_version_dir)); 317 318 // Now close the file handle to make it possible to delete our key file. 319 file.Close(); 320 321 installer_state.RemoveOldVersionDirectories(new_version, 322 NULL, 323 temp_dir.path()); 324 // The new directory should still exist. 325 EXPECT_TRUE(file_util::PathExists(new_version_dir)); 326 327 // Now, the old directory and key file should be gone. 328 EXPECT_FALSE(file_util::PathExists(old_chrome_dll)); 329 EXPECT_FALSE(file_util::PathExists(old_version_dir)); 330} 331 332TEST_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()); 347 348 const char kCurrentVersion[] = "1.2.3.4"; 349 Version current_version(kCurrentVersion); 350 351 HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 352 EXPECT_EQ(root, installer_state.root_key()); 353 354 { 355 RegistryOverrideManager override_manager; 356 override_manager.OverrideRegistry(root, L"root_pit"); 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, 363 UTF8ToWide(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)); 370 } 371 } 372} 373 374TEST_F(InstallerStateTest, InstallerResult) { 375 const bool system_level = true; 376 bool multi_install = false; 377 HKEY root = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 378 379 RegKey key; 380 std::wstring launch_cmd = L"hey diddle diddle"; 381 std::wstring value; 382 DWORD dw_value; 383 384 // check results for a fresh install of single Chrome 385 { 386 RegistryOverrideManager override_manager; 387 override_manager.OverrideRegistry(root, L"root_inst_res"); 388 CommandLine cmd_line = 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); 413 } 414 415 // check results for a fresh install of multi Chrome 416 { 417 RegistryOverrideManager override_manager; 418 override_manager.OverrideRegistry(root, L"root_inst_res"); 419 CommandLine cmd_line = 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, 427 &launch_cmd); 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); 444 key.Close(); 445 } 446} 447 448// Test GetCurrentVersion when migrating single Chrome to multi 449TEST_F(InstallerStateTest, GetCurrentVersionMigrateChrome) { 450 using installer::FakeInstallationState; 451 452 const bool system_install = false; 453 FakeInstallationState machine_state; 454 455 // Pretend that this version of single-install Chrome is already installed. 456 machine_state.AddChrome(system_install, false, 457 new Version(chrome::kChromeVersion)); 458 459 // Now we're invoked to install multi Chrome. 460 CommandLine cmd_line( 461 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); 465 466 // Is the Chrome version picked up? 467 scoped_ptr<Version> version(installer_state.GetCurrentVersion(machine_state)); 468 EXPECT_TRUE(version.get() != NULL); 469} 470 471TEST_F(InstallerStateTest, IsFileInUse) { 472 ScopedTempDir temp_dir; 473 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 474 475 FilePath temp_file; 476 ASSERT_TRUE(file_util::CreateTemporaryFileInDir(temp_dir.path(), &temp_file)); 477 478 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file)); 479 480 { 481 // Open a handle to the file with the same access mode and sharing options 482 // as the loader. 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 != NULL); 489 490 // The file should now be in use. 491 EXPECT_TRUE(MockInstallerState::IsFileInUse(temp_file)); 492 } 493 494 // And once the handle is gone, it should no longer be in use. 495 EXPECT_FALSE(MockInstallerState::IsFileInUse(temp_file)); 496} 497 498 499TEST_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()); 503 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"; 509 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); 515 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()); 521 522 // Set up a bunch of version dir paths. 523 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(ASCIIToWide(kOldVersion)), 528 installer_state.target_path().Append(ASCIIToWide(kOldChromeExeVersion)), 529 installer_state.target_path().Append(L"2.1.1.0"), 530 installer_state.target_path().Append(ASCIIToWide(kChromeExeVersion)), 531 installer_state.target_path().Append(ASCIIToWide(kNewVersion)), 532 installer_state.target_path().Append(L"3.9.1.1"), 533 }; 534 535 // Create the version directories. 536 for (int i = 0; i < arraysize(version_dirs); i++) { 537 file_util::CreateDirectory(version_dirs[i]); 538 EXPECT_TRUE(file_util::PathExists(version_dirs[i])); 539 } 540 541 // Create exes with the appropriate version resource. 542 // Use the current test exe as a baseline. 543 FilePath exe_path; 544 ASSERT_TRUE(PathService::Get(base::FILE_EXE, &exe_path)); 545 546 struct target_info { 547 FilePath target_file; 548 const Version& target_version; 549 } targets[] = { 550 { installer_state.target_path().Append(installer::kChromeOldExe), 551 old_chrome_exe_version }, 552 { installer_state.target_path().Append(installer::kChromeExe), 553 chrome_exe_version }, 554 { installer_state.target_path().Append(installer::kChromeNewExe), 555 new_chrome_exe_version }, 556 }; 557 for (int i = 0; i < arraysize(targets); ++i) { 558 ASSERT_TRUE(upgrade_test::GenerateSpecificPEFileVersion( 559 exe_path, targets[i].target_file, targets[i].target_version)); 560 } 561 562 // Call GetExistingExeVersions, validate that picks up the 563 // exe resources. 564 std::set<std::string> expected_exe_versions; 565 expected_exe_versions.insert(kOldChromeExeVersion); 566 expected_exe_versions.insert(kChromeExeVersion); 567 expected_exe_versions.insert(kNewChromeExeVersion); 568 569 std::set<std::string> actual_exe_versions; 570 installer_state.GetExistingExeVersions(&actual_exe_versions); 571 EXPECT_EQ(expected_exe_versions, actual_exe_versions); 572 573 // Call RemoveOldVersionDirectories 574 installer_state.RemoveOldVersionDirectories(new_version, 575 &old_version, 576 installer_state.target_path()); 577 578 // What we expect to have left. 579 std::set<std::string> expected_remaining_dirs; 580 expected_remaining_dirs.insert(kOldVersion); 581 expected_remaining_dirs.insert(kNewVersion); 582 expected_remaining_dirs.insert(kOldChromeExeVersion); 583 expected_remaining_dirs.insert(kChromeExeVersion); 584 expected_remaining_dirs.insert(kNewChromeExeVersion); 585 586 // Enumerate dirs in target_path(), ensure only desired remain. 587 file_util::FileEnumerator version_enum(installer_state.target_path(), false, 588 file_util::FileEnumerator::DIRECTORIES); 589 for (FilePath next_version = version_enum.Next(); !next_version.empty(); 590 next_version = version_enum.Next()) { 591 FilePath dir_name(next_version.BaseName()); 592 Version version(WideToASCII(dir_name.value())); 593 if (version.IsValid()) { 594 EXPECT_TRUE(expected_remaining_dirs.erase(version.GetString())) 595 << "Unexpected version dir found: " << version.GetString(); 596 } 597 } 598 599 std::set<std::string>::const_iterator iter( 600 expected_remaining_dirs.begin()); 601 for (; iter != expected_remaining_dirs.end(); ++iter) 602 ADD_FAILURE() << "Expected to find version dir for " << *iter; 603} 604 605 606// A fixture for testing InstallerState::DetermineCriticalVersion. Individual 607// tests must invoke Initialize() with a critical version. 608class InstallerStateCriticalVersionTest : public ::testing::Test { 609 protected: 610 InstallerStateCriticalVersionTest() : cmd_line_(CommandLine::NO_PROGRAM) {} 611 612 // Creates a set of versions for use by all test runs. 613 static void SetUpTestCase() { 614 low_version_ = new Version("15.0.874.106"); 615 opv_version_ = new Version("15.0.874.255"); 616 middle_version_ = new Version("16.0.912.32"); 617 pv_version_ = new Version("16.0.912.255"); 618 high_version_ = new Version("17.0.932.0"); 619 } 620 621 // Cleans up versions used by all test runs. 622 static void TearDownTestCase() { 623 delete low_version_; 624 delete opv_version_; 625 delete middle_version_; 626 delete pv_version_; 627 delete high_version_; 628 } 629 630 // Initializes the InstallerState to use for a test run. The returned 631 // instance's critical update version is set to |version|. |version| may be 632 // NULL, in which case the critical update version is unset. 633 MockInstallerState& Initialize(const Version* version) { 634 cmd_line_ = version == NULL ? 635 CommandLine::FromString(L"setup.exe") : 636 CommandLine::FromString( 637 L"setup.exe --critical-update-version=" + 638 ASCIIToWide(version->GetString())); 639 prefs_.reset(new MasterPreferences(cmd_line_)); 640 machine_state_.Initialize(); 641 installer_state_.Initialize(cmd_line_, *prefs_, machine_state_); 642 return installer_state_; 643 } 644 645 static Version* low_version_; 646 static Version* opv_version_; 647 static Version* middle_version_; 648 static Version* pv_version_; 649 static Version* high_version_; 650 651 CommandLine cmd_line_; 652 scoped_ptr<MasterPreferences> prefs_; 653 InstallationState machine_state_; 654 MockInstallerState installer_state_; 655}; 656 657Version* InstallerStateCriticalVersionTest::low_version_ = NULL; 658Version* InstallerStateCriticalVersionTest::opv_version_ = NULL; 659Version* InstallerStateCriticalVersionTest::middle_version_ = NULL; 660Version* InstallerStateCriticalVersionTest::pv_version_ = NULL; 661Version* InstallerStateCriticalVersionTest::high_version_ = NULL; 662 663// Test the case where the critical version is less than the currently-running 664// Chrome. The critical version is ignored since it doesn't apply. 665TEST_F(InstallerStateCriticalVersionTest, CriticalBeforeOpv) { 666 MockInstallerState& installer_state(Initialize(low_version_)); 667 668 EXPECT_TRUE(installer_state.critical_update_version().Equals(*low_version_)); 669 // Unable to determine the installed version, so assume critical update. 670 EXPECT_TRUE( 671 installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid()); 672 // Installed version is past the critical update. 673 EXPECT_FALSE( 674 installer_state.DetermineCriticalVersion(opv_version_, *pv_version_) 675 .IsValid()); 676 // Installed version is past the critical update. 677 EXPECT_FALSE( 678 installer_state.DetermineCriticalVersion(pv_version_, *pv_version_) 679 .IsValid()); 680} 681 682// Test the case where the critical version is equal to the currently-running 683// Chrome. The critical version is ignored since it doesn't apply. 684TEST_F(InstallerStateCriticalVersionTest, CriticalEqualsOpv) { 685 MockInstallerState& installer_state(Initialize(opv_version_)); 686 687 EXPECT_TRUE(installer_state.critical_update_version().Equals(*opv_version_)); 688 // Unable to determine the installed version, so assume critical update. 689 EXPECT_TRUE( 690 installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid()); 691 // Installed version equals the critical update. 692 EXPECT_FALSE( 693 installer_state.DetermineCriticalVersion(opv_version_, *pv_version_) 694 .IsValid()); 695 // Installed version equals the critical update. 696 EXPECT_FALSE( 697 installer_state.DetermineCriticalVersion(pv_version_, *pv_version_) 698 .IsValid()); 699} 700 701// Test the case where the critical version is between the currently-running 702// Chrome and the to-be-installed Chrome. 703TEST_F(InstallerStateCriticalVersionTest, CriticalBetweenOpvAndPv) { 704 MockInstallerState& installer_state(Initialize(middle_version_)); 705 706 EXPECT_TRUE(installer_state.critical_update_version().Equals( 707 *middle_version_)); 708 // Unable to determine the installed version, so assume critical update. 709 EXPECT_TRUE( 710 installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid()); 711 // Installed version before the critical update. 712 EXPECT_TRUE( 713 installer_state.DetermineCriticalVersion(opv_version_, *pv_version_) 714 .IsValid()); 715 // Installed version is past the critical update. 716 EXPECT_FALSE( 717 installer_state.DetermineCriticalVersion(pv_version_, *pv_version_) 718 .IsValid()); 719} 720 721// Test the case where the critical version is the same as the to-be-installed 722// Chrome. 723TEST_F(InstallerStateCriticalVersionTest, CriticalEqualsPv) { 724 MockInstallerState& installer_state(Initialize(pv_version_)); 725 726 EXPECT_TRUE(installer_state.critical_update_version().Equals( 727 *pv_version_)); 728 // Unable to determine the installed version, so assume critical update. 729 EXPECT_TRUE( 730 installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid()); 731 // Installed version before the critical update. 732 EXPECT_TRUE( 733 installer_state.DetermineCriticalVersion(opv_version_, *pv_version_) 734 .IsValid()); 735 // Installed version equals the critical update. 736 EXPECT_FALSE( 737 installer_state.DetermineCriticalVersion(pv_version_, *pv_version_) 738 .IsValid()); 739} 740 741// Test the case where the critical version is greater than the to-be-installed 742// Chrome. 743TEST_F(InstallerStateCriticalVersionTest, CriticalAfterPv) { 744 MockInstallerState& installer_state(Initialize(high_version_)); 745 746 EXPECT_TRUE(installer_state.critical_update_version().Equals( 747 *high_version_)); 748 // Critical update newer than the new version. 749 EXPECT_FALSE( 750 installer_state.DetermineCriticalVersion(NULL, *pv_version_).IsValid()); 751 EXPECT_FALSE( 752 installer_state.DetermineCriticalVersion(opv_version_, *pv_version_) 753 .IsValid()); 754 EXPECT_FALSE( 755 installer_state.DetermineCriticalVersion(pv_version_, *pv_version_) 756 .IsValid()); 757} 758