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

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

Issue 39048: Move files instead of copying them. (Closed)
Patch Set: More code review comments. Created 11 years, 9 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/move_tree_work_item.cc ('k') | chrome/installer/util/util.vcproj » ('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 (c) 2009 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 <windows.h>
6
7 #include <fstream>
8 #include <iostream>
9
10 #include "base/base_paths.h"
11 #include "base/file_util.h"
12 #include "base/logging.h"
13 #include "base/path_service.h"
14 #include "base/process_util.h"
15 #include "base/scoped_ptr.h"
16 #include "base/string_util.h"
17 #include "chrome/installer/util/work_item.h"
18 #include "chrome/installer/util/move_tree_work_item.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace {
22 class MoveTreeWorkItemTest : public testing::Test {
23 protected:
24 virtual void SetUp() {
25 // Name a subdirectory of the user temp directory.
26 ASSERT_TRUE(PathService::Get(base::DIR_TEMP, &test_dir_));
27 file_util::AppendToPath(&test_dir_, L"MoveTreeWorkItemTest");
28
29 // Create a fresh, empty copy of this test directory.
30 file_util::Delete(test_dir_, true);
31 CreateDirectory(test_dir_.c_str(), NULL);
32
33 // Create a tempory directory under the test directory.
34 temp_dir_.assign(test_dir_);
35 file_util::AppendToPath(&temp_dir_, L"temp");
36 CreateDirectory(temp_dir_.c_str(), NULL);
37
38 ASSERT_TRUE(file_util::PathExists(test_dir_));
39 ASSERT_TRUE(file_util::PathExists(temp_dir_));
40 }
41
42 virtual void TearDown() {
43 // Clean up test directory
44 ASSERT_TRUE(file_util::Delete(test_dir_, false));
45 ASSERT_FALSE(file_util::PathExists(test_dir_));
46 }
47
48 // the path to temporary directory used to contain the test operations
49 std::wstring test_dir_;
50 std::wstring temp_dir_;
51 };
52
53 // Simple function to dump some text into a new file.
54 void CreateTextFile(const std::wstring& filename,
55 const std::wstring& contents) {
56 std::ofstream file;
57 file.open(filename.c_str());
58 ASSERT_TRUE(file.is_open());
59 file << contents;
60 file.close();
61 }
62
63 // Simple function to read text from a file.
64 std::wstring ReadTextFile(const std::wstring& filename) {
65 WCHAR contents[64];
66 std::wifstream file;
67 file.open(filename.c_str());
68 EXPECT_TRUE(file.is_open());
69 file.getline(contents, 64);
70 file.close();
71 return std::wstring(contents);
72 }
73
74 wchar_t text_content_1[] = L"Gooooooooooooooooooooogle";
75 wchar_t text_content_2[] = L"Overwrite Me";
76 };
77
78 // Move one directory from source to destination when destination does not
79 // exist.
80 TEST_F(MoveTreeWorkItemTest, MoveDirectory) {
81 // Create two level deep source dir
82 std::wstring from_dir1(test_dir_);
83 file_util::AppendToPath(&from_dir1, L"From_Dir1");
84 CreateDirectory(from_dir1.c_str(), NULL);
85 ASSERT_TRUE(file_util::PathExists(from_dir1));
86
87 std::wstring from_dir2(from_dir1);
88 file_util::AppendToPath(&from_dir2, L"From_Dir2");
89 CreateDirectory(from_dir2.c_str(), NULL);
90 ASSERT_TRUE(file_util::PathExists(from_dir2));
91
92 std::wstring from_file(from_dir2);
93 file_util::AppendToPath(&from_file, L"From_File");
94 CreateTextFile(from_file, text_content_1);
95 ASSERT_TRUE(file_util::PathExists(from_file));
96
97 // Generate destination path
98 std::wstring to_dir(test_dir_);
99 file_util::AppendToPath(&to_dir, L"To_Dir");
100 ASSERT_FALSE(file_util::PathExists(to_dir));
101
102 std::wstring to_file(to_dir);
103 file_util::AppendToPath(&to_file, L"From_Dir2");
104 file_util::AppendToPath(&to_file, L"From_File");
105 ASSERT_FALSE(file_util::PathExists(to_file));
106
107 // test Do()
108 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
109 from_dir1, to_dir, temp_dir_));
110 EXPECT_TRUE(work_item->Do());
111
112 EXPECT_FALSE(file_util::PathExists(from_dir1));
113 EXPECT_TRUE(file_util::PathExists(to_dir));
114 EXPECT_TRUE(file_util::PathExists(to_file));
115
116 // test rollback()
117 work_item->Rollback();
118
119 EXPECT_TRUE(file_util::PathExists(from_dir1));
120 EXPECT_TRUE(file_util::PathExists(from_file));
121 EXPECT_FALSE(file_util::PathExists(to_dir));
122 }
123
124 // Move one directory from source to destination when destination already
125 // exists.
126 TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExists) {
127 // Create two level deep source dir
128 std::wstring from_dir1(test_dir_);
129 file_util::AppendToPath(&from_dir1, L"From_Dir1");
130 CreateDirectory(from_dir1.c_str(), NULL);
131 ASSERT_TRUE(file_util::PathExists(from_dir1));
132
133 std::wstring from_dir2(from_dir1);
134 file_util::AppendToPath(&from_dir2, L"From_Dir2");
135 CreateDirectory(from_dir2.c_str(), NULL);
136 ASSERT_TRUE(file_util::PathExists(from_dir2));
137
138 std::wstring from_file(from_dir2);
139 file_util::AppendToPath(&from_file, L"From_File");
140 CreateTextFile(from_file, text_content_1);
141 ASSERT_TRUE(file_util::PathExists(from_file));
142
143 // Create destination path
144 std::wstring to_dir(test_dir_);
145 file_util::AppendToPath(&to_dir, L"To_Dir");
146 CreateDirectory(to_dir.c_str(), NULL);
147 ASSERT_TRUE(file_util::PathExists(to_dir));
148
149 std::wstring orig_to_file(to_dir);
150 file_util::AppendToPath(&orig_to_file, L"To_File");
151 CreateTextFile(orig_to_file, text_content_2);
152 ASSERT_TRUE(file_util::PathExists(orig_to_file));
153
154 std::wstring new_to_file(to_dir);
155 file_util::AppendToPath(&new_to_file, L"From_Dir2");
156 file_util::AppendToPath(&new_to_file, L"From_File");
157 ASSERT_FALSE(file_util::PathExists(new_to_file));
158
159 // test Do()
160 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
161 from_dir1, to_dir, temp_dir_));
162 EXPECT_TRUE(work_item->Do());
163
164 EXPECT_FALSE(file_util::PathExists(from_dir1));
165 EXPECT_TRUE(file_util::PathExists(to_dir));
166 EXPECT_TRUE(file_util::PathExists(new_to_file));
167 EXPECT_FALSE(file_util::PathExists(orig_to_file));
168
169 // test rollback()
170 work_item->Rollback();
171
172 EXPECT_TRUE(file_util::PathExists(from_dir1));
173 EXPECT_TRUE(file_util::PathExists(to_dir));
174 EXPECT_FALSE(file_util::PathExists(new_to_file));
175 EXPECT_TRUE(file_util::PathExists(orig_to_file));
176 EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(text_content_2));
177 EXPECT_EQ(0, ReadTextFile(from_file).compare(text_content_1));
178 }
179
180 // Move one file from source to destination when destination does not
181 // exist.
182 TEST_F(MoveTreeWorkItemTest, MoveAFile) {
183 // Create a file inside source dir
184 std::wstring from_dir(test_dir_);
185 file_util::AppendToPath(&from_dir, L"From_Dir");
186 CreateDirectory(from_dir.c_str(), NULL);
187 ASSERT_TRUE(file_util::PathExists(from_dir));
188
189 std::wstring from_file(from_dir);
190 file_util::AppendToPath(&from_file, L"From_File");
191 CreateTextFile(from_file, text_content_1);
192 ASSERT_TRUE(file_util::PathExists(from_file));
193
194 // Generate destination file name
195 std::wstring to_file(test_dir_);
196 file_util::AppendToPath(&to_file, L"To_File");
197 ASSERT_FALSE(file_util::PathExists(to_file));
198
199 // test Do()
200 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
201 from_file, to_file, temp_dir_));
202 EXPECT_TRUE(work_item->Do());
203
204 EXPECT_TRUE(file_util::PathExists(from_dir));
205 EXPECT_FALSE(file_util::PathExists(from_file));
206 EXPECT_TRUE(file_util::PathExists(to_file));
207 EXPECT_EQ(0, ReadTextFile(to_file).compare(text_content_1));
208
209 // test rollback()
210 work_item->Rollback();
211
212 EXPECT_TRUE(file_util::PathExists(from_dir));
213 EXPECT_TRUE(file_util::PathExists(from_file));
214 EXPECT_FALSE(file_util::PathExists(to_file));
215 EXPECT_EQ(0, ReadTextFile(from_file).compare(text_content_1));
216 }
217
218 // Move one file from source to destination when destination already
219 // exists.
220 TEST_F(MoveTreeWorkItemTest, MoveFileDestExists) {
221 // Create a file inside source dir
222 std::wstring from_dir(test_dir_);
223 file_util::AppendToPath(&from_dir, L"From_Dir");
224 CreateDirectory(from_dir.c_str(), NULL);
225 ASSERT_TRUE(file_util::PathExists(from_dir));
226
227 std::wstring from_file(from_dir);
228 file_util::AppendToPath(&from_file, L"From_File");
229 CreateTextFile(from_file, text_content_1);
230 ASSERT_TRUE(file_util::PathExists(from_file));
231
232 // Create destination path
233 std::wstring to_dir(test_dir_);
234 file_util::AppendToPath(&to_dir, L"To_Dir");
235 CreateDirectory(to_dir.c_str(), NULL);
236 ASSERT_TRUE(file_util::PathExists(to_dir));
237
238 std::wstring to_file(to_dir);
239 file_util::AppendToPath(&to_file, L"To_File");
240 CreateTextFile(to_file, text_content_2);
241 ASSERT_TRUE(file_util::PathExists(to_file));
242
243 // test Do()
244 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
245 from_file, to_dir, temp_dir_));
246 EXPECT_TRUE(work_item->Do());
247
248 EXPECT_TRUE(file_util::PathExists(from_dir));
249 EXPECT_FALSE(file_util::PathExists(from_file));
250 EXPECT_TRUE(file_util::PathExists(to_dir));
251 EXPECT_FALSE(file_util::PathExists(to_file));
252 EXPECT_EQ(0, ReadTextFile(to_dir).compare(text_content_1));
253
254 // test rollback()
255 work_item->Rollback();
256
257 EXPECT_TRUE(file_util::PathExists(from_dir));
258 EXPECT_EQ(0, ReadTextFile(from_file).compare(text_content_1));
259 EXPECT_TRUE(file_util::PathExists(to_dir));
260 EXPECT_EQ(0, ReadTextFile(to_file).compare(text_content_2));
261 }
262
263 // Move one file from source to destination when destination already
264 // exists and is in use.
265 TEST_F(MoveTreeWorkItemTest, MoveFileDestInUse) {
266 // Create a file inside source dir
267 std::wstring from_dir(test_dir_);
268 file_util::AppendToPath(&from_dir, L"From_Dir");
269 CreateDirectory(from_dir.c_str(), NULL);
270 ASSERT_TRUE(file_util::PathExists(from_dir));
271
272 std::wstring from_file(from_dir);
273 file_util::AppendToPath(&from_file, L"From_File");
274 CreateTextFile(from_file, text_content_1);
275 ASSERT_TRUE(file_util::PathExists(from_file));
276
277 // Create an executable in destination path by copying ourself to it.
278 std::wstring to_dir(test_dir_);
279 file_util::AppendToPath(&to_dir, L"To_Dir");
280 CreateDirectory(to_dir.c_str(), NULL);
281 ASSERT_TRUE(file_util::PathExists(to_dir));
282
283 wchar_t exe_full_path_str[MAX_PATH];
284 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
285 std::wstring exe_full_path(exe_full_path_str);
286 std::wstring to_file(to_dir);
287 file_util::AppendToPath(&to_file, L"To_File");
288 file_util::CopyFile(exe_full_path, to_file);
289 ASSERT_TRUE(file_util::PathExists(to_file));
290
291 // Run the executable in destination path
292 STARTUPINFOW si = {sizeof(si)};
293 PROCESS_INFORMATION pi = {0};
294 ASSERT_TRUE(::CreateProcess(NULL, const_cast<wchar_t*>(to_file.c_str()),
295 NULL, NULL, FALSE,
296 CREATE_NO_WINDOW | CREATE_SUSPENDED,
297 NULL, NULL, &si, &pi));
298
299 // test Do()
300 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
301 from_file, to_file, temp_dir_));
302 EXPECT_TRUE(work_item->Do());
303
304 EXPECT_TRUE(file_util::PathExists(from_dir));
305 EXPECT_FALSE(file_util::PathExists(from_file));
306 EXPECT_TRUE(file_util::PathExists(to_dir));
307 EXPECT_EQ(0, ReadTextFile(to_file).compare(text_content_1));
308
309 // test rollback()
310 work_item->Rollback();
311
312 EXPECT_TRUE(file_util::PathExists(from_dir));
313 EXPECT_EQ(0, ReadTextFile(from_file).compare(text_content_1));
314 EXPECT_TRUE(file_util::PathExists(to_dir));
315 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, to_file));
316
317 TerminateProcess(pi.hProcess, 0);
318 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
319 CloseHandle(pi.hProcess);
320 CloseHandle(pi.hThread);
321 }
322
323 // Move one file that is in use to destination.
324 TEST_F(MoveTreeWorkItemTest, MoveFileInUse) {
325 // Create an executable for source by copying ourself to a new source dir.
326 std::wstring from_dir(test_dir_);
327 file_util::AppendToPath(&from_dir, L"From_Dir");
328 CreateDirectory(from_dir.c_str(), NULL);
329 ASSERT_TRUE(file_util::PathExists(from_dir));
330
331 wchar_t exe_full_path_str[MAX_PATH];
332 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
333 std::wstring exe_full_path(exe_full_path_str);
334 std::wstring from_file(from_dir);
335 file_util::AppendToPath(&from_file, L"From_File");
336 file_util::CopyFile(exe_full_path, from_file);
337 ASSERT_TRUE(file_util::PathExists(from_file));
338
339 // Create a destination source dir and generate destination file name.
340 std::wstring to_dir(test_dir_);
341 file_util::AppendToPath(&to_dir, L"To_Dir");
342 CreateDirectory(to_dir.c_str(), NULL);
343 ASSERT_TRUE(file_util::PathExists(to_dir));
344
345 std::wstring to_file(to_dir);
346 file_util::AppendToPath(&to_file, L"To_File");
347 CreateTextFile(to_file, text_content_1);
348 ASSERT_TRUE(file_util::PathExists(to_file));
349
350 // Run the executable in source path
351 STARTUPINFOW si = {sizeof(si)};
352 PROCESS_INFORMATION pi = {0};
353 ASSERT_TRUE(::CreateProcess(NULL, const_cast<wchar_t*>(from_file.c_str()),
354 NULL, NULL, FALSE,
355 CREATE_NO_WINDOW | CREATE_SUSPENDED,
356 NULL, NULL, &si, &pi));
357
358 // test Do()
359 scoped_ptr<MoveTreeWorkItem> work_item(WorkItem::CreateMoveTreeWorkItem(
360 from_file, to_file, temp_dir_));
361 EXPECT_TRUE(work_item->Do());
362
363 EXPECT_TRUE(file_util::PathExists(from_dir));
364 EXPECT_FALSE(file_util::PathExists(from_file));
365 EXPECT_TRUE(file_util::PathExists(to_dir));
366 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, to_file));
367
368 // Close the process and make sure all the conditions after Do() are
369 // still true.
370 TerminateProcess(pi.hProcess, 0);
371 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
372 CloseHandle(pi.hProcess);
373 CloseHandle(pi.hThread);
374
375 EXPECT_TRUE(file_util::PathExists(from_dir));
376 EXPECT_FALSE(file_util::PathExists(from_file));
377 EXPECT_TRUE(file_util::PathExists(to_dir));
378 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, to_file));
379
380 // test rollback()
381 work_item->Rollback();
382
383 EXPECT_TRUE(file_util::PathExists(from_dir));
384 EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, from_file));
385 EXPECT_TRUE(file_util::PathExists(to_dir));
386 EXPECT_EQ(0, ReadTextFile(to_file).compare(text_content_1));
387 }
OLDNEW
« no previous file with comments | « chrome/installer/util/move_tree_work_item.cc ('k') | chrome/installer/util/util.vcproj » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698