Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: chrome/installer/util/delete_old_versions_unittest.cc

Issue 2273113002: Delete old files after an update. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@harvester
Patch Set: CR grt #4 Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/installer/util/delete_old_versions.cc ('k') | chrome/installer/util/installer_state.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/installer/util/delete_old_versions.h"
6
7 #include <set>
8
9 #include "base/files/file.h"
10 #include "base/files/file_enumerator.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/path_service.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/string_util.h"
19 #include "base/version.h"
20 #include "chrome/installer/test/alternate_version_generator.h"
21 #include "chrome/installer/util/util_constants.h"
22 #include "testing/gtest/include/gtest/gtest.h"
23
24 using upgrade_test::Direction;
25
26 namespace installer {
27
28 namespace {
29
30 class DeleteOldVersionsTest : public testing::Test {
31 protected:
32 DeleteOldVersionsTest() = default;
33
34 void SetUp() override { ASSERT_TRUE(install_dir_.CreateUniqueTempDir()); }
35
36 // Creates a copy of the current executable with a distinct version of name
37 // |name| in |install_dir_|. Depending on |direction|, the version of the
38 // created executable is higher or lower than the version of the current
39 // executable.
40 base::string16 CreateExecutable(const base::string16& name,
41 Direction direction) {
42 base::FilePath current_exe_path;
43 if (!base::PathService::Get(base::FILE_EXE, &current_exe_path))
44 return base::string16();
45
46 return upgrade_test::GenerateAlternatePEFileVersion(
47 current_exe_path, install_dir().Append(name), direction);
48 }
49
50 // Creates in |install_dir_| a directory named |name| containing a subset of
51 // dummy files impersonating a Chrome version directory.
52 bool CreateVersionDirectory(const base::string16& name) {
53 static constexpr char kDummyContent[] = "dummy";
54 const base::FilePath version_dir_path(install_dir().Append(name));
55
56 return base::CreateDirectory(install_dir().Append(name)) &&
57 base::CreateDirectory(version_dir_path.Append(L"Installer")) &&
58 base::WriteFile(version_dir_path.Append(L"chrome.dll"),
59 kDummyContent, sizeof(kDummyContent)) &&
60 base::WriteFile(version_dir_path.Append(L"nacl64.exe"),
61 kDummyContent, sizeof(kDummyContent)) &&
62 base::WriteFile(version_dir_path.Append(L"icudtl.dat"),
63 kDummyContent, sizeof(kDummyContent)) &&
64 base::WriteFile(version_dir_path.Append(L"Installer\\setup.exe"),
65 kDummyContent, sizeof(kDummyContent));
66 }
67
68 // Returns the relative paths of all files and directories in |install_dir_|.
69 using FilePathSet = std::set<base::FilePath>;
70 FilePathSet GetInstallDirContent() const {
71 std::set<base::FilePath> content;
72 base::FileEnumerator file_enumerator(
73 install_dir(), true,
74 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
75 for (base::FilePath path = file_enumerator.Next(); !path.empty();
76 path = file_enumerator.Next()) {
77 DCHECK(base::StartsWith(path.value(), install_dir().value(),
78 base::CompareCase::SENSITIVE));
79 content.insert(base::FilePath(
80 path.value().substr(install_dir().value().size() + 1)));
81 }
82 return content;
83 }
84
85 // Adds to |file_path_set| all files and directories that are expected to be
86 // found in the version directory |version| before any attempt to delete it.
87 void AddVersionFiles(const base::string16& version,
88 FilePathSet* file_path_set) {
89 file_path_set->insert(base::FilePath(version));
90 file_path_set->insert(base::FilePath(version).Append(L"chrome.dll"));
91 file_path_set->insert(base::FilePath(version).Append(L"nacl64.exe"));
92 file_path_set->insert(base::FilePath(version).Append(L"icudtl.dat"));
93 file_path_set->insert(base::FilePath(version).Append(L"Installer"));
94 file_path_set->insert(
95 base::FilePath(version).Append(L"Installer\\setup.exe"));
96 }
97
98 base::FilePath install_dir() const { return install_dir_.path(); }
99
100 private:
101 base::ScopedTempDir install_dir_;
102
103 DISALLOW_COPY_AND_ASSIGN(DeleteOldVersionsTest);
104 };
105
106 } // namespace
107
108 // An old executable without a matching directory should be deleted.
109 TEST_F(DeleteOldVersionsTest, DeleteOldExecutableWithoutMatchingDirectory) {
110 ASSERT_FALSE(
111 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION)
112 .empty());
113
114 DeleteOldVersions(install_dir());
115 EXPECT_TRUE(GetInstallDirContent().empty());
116 }
117
118 // chrome.exe and new_chrome.exe should never be deleted.
119 TEST_F(DeleteOldVersionsTest, DeleteNewExecutablesWithoutMatchingDirectory) {
120 ASSERT_FALSE(
121 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION)
122 .empty());
123 ASSERT_FALSE(
124 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION)
125 .empty());
126
127 DeleteOldVersions(install_dir());
128 FilePathSet expected_install_dir_content;
129 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
130 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
131 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
132 }
133
134 // A directory without a matching executable should be deleted.
135 TEST_F(DeleteOldVersionsTest, DeleteDirectoryWithoutMatchingExecutable) {
136 static constexpr base::char16 kVersion[] = L"48.0.0.0";
137 ASSERT_TRUE(CreateVersionDirectory(kVersion));
138
139 DeleteOldVersions(install_dir());
140 EXPECT_TRUE(GetInstallDirContent().empty());
141 }
142
143 // A pair of matching old executable/version directory that is not in use should
144 // be deleted.
145 TEST_F(DeleteOldVersionsTest, DeleteOldExecutableWithMatchingDirectory) {
146 const base::string16 version_a =
147 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
148 ASSERT_FALSE(version_a.empty());
149 ASSERT_TRUE(CreateVersionDirectory(version_a));
150
151 DeleteOldVersions(install_dir());
152 EXPECT_TRUE(GetInstallDirContent().empty());
153 }
154
155 // chrome.exe, new_chrome.exe and their matching version directories should
156 // never be deleted.
157 TEST_F(DeleteOldVersionsTest, DeleteNewExecutablesWithMatchingDirectory) {
158 const base::string16 version_a =
159 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION);
160 ASSERT_FALSE(version_a.empty());
161 ASSERT_TRUE(CreateVersionDirectory(version_a));
162 const base::string16 version_b =
163 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION);
164 ASSERT_FALSE(version_b.empty());
165 ASSERT_TRUE(CreateVersionDirectory(version_b));
166
167 DeleteOldVersions(install_dir());
168
169 FilePathSet expected_install_dir_content;
170 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
171 AddVersionFiles(version_a, &expected_install_dir_content);
172 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
173 AddVersionFiles(version_b, &expected_install_dir_content);
174 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
175 }
176
177 // chrome.exe, new_chrome.exe and their matching version directories should
178 // never be deleted, even when files named old_chrome*.exe have the same
179 // versions as chrome.exe/new_chrome.exe. The old_chrome*.exe files, however,
180 // should be deleted.
181 TEST_F(DeleteOldVersionsTest,
182 DeleteNewExecutablesWithMatchingDirectoryAndOldExecutables) {
183 const base::string16 version_a =
184 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION);
185 ASSERT_FALSE(version_a.empty());
186 ASSERT_TRUE(CreateVersionDirectory(version_a));
187 const base::string16 version_b =
188 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION);
189 ASSERT_FALSE(version_b.empty());
190 ASSERT_TRUE(CreateVersionDirectory(version_b));
191 EXPECT_EQ(version_a,
192 CreateExecutable(L"old_chrome.exe", Direction::PREVIOUS_VERSION));
193 EXPECT_EQ(version_b,
194 CreateExecutable(L"old_chrome2.exe", Direction::NEXT_VERSION));
195
196 DeleteOldVersions(install_dir());
197
198 FilePathSet expected_install_dir_content;
199 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
200 AddVersionFiles(version_a, &expected_install_dir_content);
201 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
202 AddVersionFiles(version_b, &expected_install_dir_content);
203 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
204 }
205
206 // No file should be deleted for a given version if the executable is in use.
207 TEST_F(DeleteOldVersionsTest, DeleteVersionWithExecutableInUse) {
208 const base::string16 version_a =
209 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
210 ASSERT_FALSE(version_a.empty());
211 ASSERT_TRUE(CreateVersionDirectory(version_a));
212
213 base::File file_in_use(install_dir().Append(installer::kChromeOldExe),
214 base::File::FLAG_OPEN | base::File::FLAG_READ);
215 ASSERT_TRUE(file_in_use.IsValid());
216
217 DeleteOldVersions(install_dir());
218
219 FilePathSet expected_install_dir_content;
220 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
221 AddVersionFiles(version_a, &expected_install_dir_content);
222 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
223 }
224
225 // No file should be deleted for a given version if a .dll file in the version
226 // directory is in use.
227 TEST_F(DeleteOldVersionsTest, DeleteVersionWithVersionDirectoryDllInUse) {
228 const base::string16 version_a =
229 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
230 ASSERT_FALSE(version_a.empty());
231 ASSERT_TRUE(CreateVersionDirectory(version_a));
232
233 base::File file_in_use(install_dir().Append(version_a).Append(L"chrome.dll"),
234 base::File::FLAG_OPEN | base::File::FLAG_READ);
235 ASSERT_TRUE(file_in_use.IsValid());
236
237 DeleteOldVersions(install_dir());
238
239 FilePathSet expected_install_dir_content;
240 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
241 AddVersionFiles(version_a, &expected_install_dir_content);
242 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
243 }
244
245 // No file should be deleted for a given version if a .exe file in the version
246 // directory is in use.
247 TEST_F(DeleteOldVersionsTest, DeleteVersionWithVersionDirectoryExeInUse) {
248 const base::string16 version_a =
249 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
250 ASSERT_FALSE(version_a.empty());
251 ASSERT_TRUE(CreateVersionDirectory(version_a));
252
253 base::File file_in_use(
254 install_dir().Append(version_a).Append(L"Installer\\setup.exe"),
255 base::File::FLAG_OPEN | base::File::FLAG_READ);
256 ASSERT_TRUE(file_in_use.IsValid());
257
258 DeleteOldVersions(install_dir());
259
260 FilePathSet expected_install_dir_content;
261 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
262 AddVersionFiles(version_a, &expected_install_dir_content);
263 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
264 }
265
266 // If an installation directory contains a file named chrome.exe with a matching
267 // directory v1 and a file named old_chrome.exe with a matching directory v2,
268 // old_chrome.exe and v2 should be deleted but chrome.exe and v1 shouldn't.
269 TEST_F(DeleteOldVersionsTest, TypicalAfterRenameState) {
270 const base::string16 version_a =
271 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
272 ASSERT_FALSE(version_a.empty());
273 ASSERT_TRUE(CreateVersionDirectory(version_a));
274 const base::string16 version_b =
275 CreateExecutable(installer::kChromeExe, Direction::NEXT_VERSION);
276 ASSERT_FALSE(version_b.empty());
277 ASSERT_TRUE(CreateVersionDirectory(version_b));
278
279 DeleteOldVersions(install_dir());
280
281 FilePathSet expected_install_dir_content;
282 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
283 AddVersionFiles(version_b, &expected_install_dir_content);
284 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
285 }
286
287 } // namespace installer
OLDNEW
« no previous file with comments | « chrome/installer/util/delete_old_versions.cc ('k') | chrome/installer/util/installer_state.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698