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