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

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: Created 4 years, 4 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
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 an executable with |name| in |install_dir_|. Depending on
grt (UTC plus 2) 2016/08/25 11:24:47 the second sentence implies that the created execu
fdoray 2016/08/26 15:16:15 Done.
37 // |direction|, the version of the created executable is higher or lower than
38 // the version of the current executable.
39 base::string16 CreateExecutable(const base::string16& name,
40 Direction direction) {
41 base::FilePath current_exe_path;
42 if (!base::PathService::Get(base::FILE_EXE, &current_exe_path))
43 return std::wstring();
grt (UTC plus 2) 2016/08/25 11:24:47 base::string16()
fdoray 2016/08/26 15:16:15 Done.
44
45 return upgrade_test::GenerateAlternatePEFileVersion(
46 current_exe_path, install_dir().Append(name), direction);
47 }
48
49 // Creates a version directory named |name| in |install_dir_|.
grt (UTC plus 2) 2016/08/25 11:24:47 "Creates a version directory containing a subset o
fdoray 2016/08/26 15:16:15 Done.
50 bool CreateVersionDirectory(const base::string16& name) {
51 static const char kDummyContent[] = "dummy";
grt (UTC plus 2) 2016/08/25 11:24:47 static constexpr
fdoray 2016/08/26 15:16:15 Done.
52 const base::FilePath version_dir_path(install_dir().Append(name));
53
54 return base::CreateDirectory(install_dir().Append(name)) &&
55 base::CreateDirectory(version_dir_path.Append(L"Installer")) &&
56 base::WriteFile(version_dir_path.Append(L"chrome.dll"),
57 kDummyContent, sizeof(kDummyContent)) &&
58 base::WriteFile(version_dir_path.Append(L"nacl64.exe"),
59 kDummyContent, sizeof(kDummyContent)) &&
60 base::WriteFile(version_dir_path.Append(L"icudtl.dat"),
61 kDummyContent, sizeof(kDummyContent)) &&
62 base::WriteFile(version_dir_path.Append(L"Installer\\setup.exe"),
63 kDummyContent, sizeof(kDummyContent));
64 }
65
66 // Returns the relative paths of all files and directories in |install_dir_|.
67 using FilePathSet = std::set<base::FilePath>;
68 FilePathSet GetInstallDirContent() const {
69 std::set<base::FilePath> content;
70 base::FileEnumerator file_enumerator(
71 install_dir(), true,
72 base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
73 for (base::FilePath path = file_enumerator.Next(); !path.empty();
74 path = file_enumerator.Next()) {
75 DCHECK(base::StartsWith(path.value(), install_dir().value(),
76 base::CompareCase::SENSITIVE));
77 content.insert(base::FilePath(
78 path.value().substr(install_dir().value().size() + 1)));
79 }
80 return content;
81 }
82
83 // Adds to |file_path_set| all files and directories that are expected to be
84 // found in the version directory |version| before any attempt to delete it.
85 void AddVersionFiles(const base::string16& version,
86 FilePathSet* file_path_set) {
87 file_path_set->insert(base::FilePath(version));
88 file_path_set->insert(base::FilePath(version).Append(L"chrome.dll"));
89 file_path_set->insert(base::FilePath(version).Append(L"nacl64.exe"));
90 file_path_set->insert(base::FilePath(version).Append(L"icudtl.dat"));
91 file_path_set->insert(base::FilePath(version).Append(L"Installer"));
92 file_path_set->insert(
93 base::FilePath(version).Append(L"Installer\\setup.exe"));
94 }
95
96 base::FilePath install_dir() const { return install_dir_.path(); }
97
98 private:
99 base::ScopedTempDir install_dir_;
100
101 DISALLOW_COPY_AND_ASSIGN(DeleteOldVersionsTest);
102 };
103
104 } // namespace
105
106 // An old executable without a matching directory should be deleted.
107 TEST_F(DeleteOldVersionsTest, DeleteOldExecutableWithoutMatchingDirectory) {
108 ASSERT_FALSE(
109 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION)
110 .empty());
111
112 DeleteOldVersions(install_dir());
113 EXPECT_TRUE(GetInstallDirContent().empty());
114 }
115
116 // chrome.exe and new_chrome.exe should never be deleted.
117 TEST_F(DeleteOldVersionsTest, DeleteNewExecutablesWithoutMatchingDirectory) {
118 ASSERT_FALSE(
119 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION)
120 .empty());
121 ASSERT_FALSE(
122 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION)
123 .empty());
124
125 DeleteOldVersions(install_dir());
126 FilePathSet expected_install_dir_content;
127 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
128 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
129 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
130 }
131
132 // A directory without a matching executable should be deleted.
133 TEST_F(DeleteOldVersionsTest, DeleteDirectoryWithoutMatchingExecutable) {
134 static constexpr base::char16 kVersion[] = L"48.0.0.0";
grt (UTC plus 2) 2016/08/25 11:24:47 48 was a very good milestone. ;-)
fdoray 2016/08/26 15:16:15 :)
135 ASSERT_TRUE(CreateVersionDirectory(kVersion));
136
137 DeleteOldVersions(install_dir());
138 EXPECT_TRUE(GetInstallDirContent().empty());
139 }
140
141 // A pair of matching old executable/version directory that is not in use should
142 // be deleted.
143 TEST_F(DeleteOldVersionsTest, DeleteOldExecutableWithMatchingDirectory) {
144 const base::string16 version_a =
145 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
146 ASSERT_FALSE(version_a.empty());
147 ASSERT_TRUE(CreateVersionDirectory(version_a));
148
149 DeleteOldVersions(install_dir());
150 EXPECT_TRUE(GetInstallDirContent().empty());
151 }
152
153 // chrome.exe, new_chrome.exe and their matching version directories should
154 // never be deleted.
155 TEST_F(DeleteOldVersionsTest, DeleteNewExecutablesWithMatchingDirectory) {
156 const base::string16 version_a =
157 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION);
158 ASSERT_FALSE(version_a.empty());
159 ASSERT_TRUE(CreateVersionDirectory(version_a));
160 const base::string16 version_b =
161 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION);
162 ASSERT_FALSE(version_b.empty());
163 ASSERT_TRUE(CreateVersionDirectory(version_b));
164
165 DeleteOldVersions(install_dir());
166
167 FilePathSet expected_install_dir_content;
168 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
169 AddVersionFiles(version_a, &expected_install_dir_content);
170 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
171 AddVersionFiles(version_b, &expected_install_dir_content);
172 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
173 }
174
175 // chrome.exe, new_chrome.exe and their matching version directories should
176 // never be deleted, even when files named old_chrome*.exe have the same
177 // versions as chrome.exe/new_chrome.exe. The old_chrome*.exe files, however,
178 // should be deleted.
179 TEST_F(DeleteOldVersionsTest,
180 DeleteNewExecutablesWithMatchingDirectoryAndOldExecutables) {
181 const base::string16 version_a =
182 CreateExecutable(installer::kChromeExe, Direction::PREVIOUS_VERSION);
183 ASSERT_FALSE(version_a.empty());
184 ASSERT_TRUE(CreateVersionDirectory(version_a));
185 const base::string16 version_b =
186 CreateExecutable(installer::kChromeNewExe, Direction::NEXT_VERSION);
187 ASSERT_FALSE(version_b.empty());
188 ASSERT_TRUE(CreateVersionDirectory(version_b));
189 EXPECT_EQ(version_a,
190 CreateExecutable(L"old_chrome.exe", Direction::PREVIOUS_VERSION));
191 EXPECT_EQ(version_b,
192 CreateExecutable(L"old_chrome2.exe", Direction::NEXT_VERSION));
193
194 DeleteOldVersions(install_dir());
195
196 FilePathSet expected_install_dir_content;
197 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
198 AddVersionFiles(version_a, &expected_install_dir_content);
199 expected_install_dir_content.insert(base::FilePath(installer::kChromeNewExe));
200 AddVersionFiles(version_b, &expected_install_dir_content);
201 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
202 }
203
204 // No file should be deleted for a given version if the executable is in use.
205 TEST_F(DeleteOldVersionsTest, DeleteVersionWithExecutableInUse) {
206 const base::string16 version_a =
207 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
208 ASSERT_FALSE(version_a.empty());
209 ASSERT_TRUE(CreateVersionDirectory(version_a));
210
211 base::File file_in_use(install_dir().Append(installer::kChromeOldExe),
212 base::File::FLAG_OPEN | base::File::FLAG_READ);
213 ASSERT_TRUE(file_in_use.IsValid());
214
215 DeleteOldVersions(install_dir());
216
217 FilePathSet expected_install_dir_content;
218 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
219 AddVersionFiles(version_a, &expected_install_dir_content);
220 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
221 }
222
223 // No file should be deleted for a given version if a .dll file in the version
224 // directory is in use.
225 TEST_F(DeleteOldVersionsTest, DeleteVersionWithVersionDirectoryDllInUse) {
226 const base::string16 version_a =
227 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
228 ASSERT_FALSE(version_a.empty());
229 ASSERT_TRUE(CreateVersionDirectory(version_a));
230
231 base::File file_in_use(install_dir().Append(version_a).Append(L"chrome.dll"),
232 base::File::FLAG_OPEN | base::File::FLAG_READ);
233 ASSERT_TRUE(file_in_use.IsValid());
234
235 DeleteOldVersions(install_dir());
236
237 FilePathSet expected_install_dir_content;
238 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
239 AddVersionFiles(version_a, &expected_install_dir_content);
240 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
241 }
242
243 // No file should be deleted for a given version if a .exe file in the version
244 // directory is in use.
245 TEST_F(DeleteOldVersionsTest, DeleteVersionWithVersionDirectoryExeInUse) {
246 const base::string16 version_a =
247 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
248 ASSERT_FALSE(version_a.empty());
249 ASSERT_TRUE(CreateVersionDirectory(version_a));
250
251 base::File file_in_use(
252 install_dir().Append(version_a).Append(L"Installer\\setup.exe"),
253 base::File::FLAG_OPEN | base::File::FLAG_READ);
254 ASSERT_TRUE(file_in_use.IsValid());
255
256 DeleteOldVersions(install_dir());
257
258 FilePathSet expected_install_dir_content;
259 expected_install_dir_content.insert(base::FilePath(installer::kChromeOldExe));
260 AddVersionFiles(version_a, &expected_install_dir_content);
261 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
262 }
263
264 // If an installation directory contains a file named chrome.exe with a matching
265 // directory v1 and a file named old_chrome.exe with a matching directory v2,
266 // old_chrome.exe and v2 should be deleted but chrome.exe and v1 shouldn't.
267 TEST_F(DeleteOldVersionsTest, TypicalAfterRenameState) {
268 const base::string16 version_a =
269 CreateExecutable(installer::kChromeOldExe, Direction::PREVIOUS_VERSION);
270 ASSERT_FALSE(version_a.empty());
271 ASSERT_TRUE(CreateVersionDirectory(version_a));
272 const base::string16 version_b =
273 CreateExecutable(installer::kChromeExe, Direction::NEXT_VERSION);
274 ASSERT_FALSE(version_b.empty());
275 ASSERT_TRUE(CreateVersionDirectory(version_b));
276
277 DeleteOldVersions(install_dir());
278
279 FilePathSet expected_install_dir_content;
280 expected_install_dir_content.insert(base::FilePath(installer::kChromeExe));
281 AddVersionFiles(version_b, &expected_install_dir_content);
282 EXPECT_EQ(expected_install_dir_content, GetInstallDirContent());
283 }
284
285 } // namespace installer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698