1 // Copyright (c) 2012 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
9 #include "base/base_paths.h"
10 #include "base/file_util.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/threading/platform_thread.h"
17 #include "chrome/installer/util/copy_tree_work_item.h"
18 #include "chrome/installer/util/work_item.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 namespace {
22 class CopyTreeWorkItemTest : public testing::Test {
23 protected:
SetUp()24 virtual void SetUp() {
25 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
26 ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
27 }
28
TearDown()29 virtual void TearDown() {
30 logging::CloseLogFile();
31 }
32
33 // the path to temporary directory used to contain the test operations
34 base::ScopedTempDir test_dir_;
35 base::ScopedTempDir temp_dir_;
36 };
37
38 // Simple function to dump some text into a new file.
CreateTextFile(const std::wstring & filename,const std::wstring & contents)39 void CreateTextFile(const std::wstring& filename,
40 const std::wstring& contents) {
41 std::ofstream file;
42 file.open(filename.c_str());
43 ASSERT_TRUE(file.is_open());
44 file << contents;
45 file.close();
46 }
47
IsFileInUse(const base::FilePath & path)48 bool IsFileInUse(const base::FilePath& path) {
49 if (!base::PathExists(path))
50 return false;
51
52 HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS,
53 NULL, NULL, OPEN_EXISTING, NULL, NULL);
54 if (handle == INVALID_HANDLE_VALUE)
55 return true;
56
57 CloseHandle(handle);
58 return false;
59 }
60
61 // Simple function to read text from a file.
ReadTextFile(const std::wstring & filename)62 std::wstring ReadTextFile(const std::wstring& filename) {
63 WCHAR contents[64];
64 std::wifstream file;
65 file.open(filename.c_str());
66 EXPECT_TRUE(file.is_open());
67 file.getline(contents, 64);
68 file.close();
69 return std::wstring(contents);
70 }
71
72 wchar_t text_content_1[] = L"Gooooooooooooooooooooogle";
73 wchar_t text_content_2[] = L"Overwrite Me";
74 };
75
76 // Copy one file from source to destination.
TEST_F(CopyTreeWorkItemTest,CopyFile)77 TEST_F(CopyTreeWorkItemTest, CopyFile) {
78 // Create source file
79 base::FilePath file_name_from(test_dir_.path());
80 file_name_from = file_name_from.AppendASCII("File_From.txt");
81 CreateTextFile(file_name_from.value(), text_content_1);
82 ASSERT_TRUE(base::PathExists(file_name_from));
83
84 // Create destination path
85 base::FilePath dir_name_to(test_dir_.path());
86 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
87 base::CreateDirectory(dir_name_to);
88 ASSERT_TRUE(base::PathExists(dir_name_to));
89
90 base::FilePath file_name_to(dir_name_to);
91 file_name_to = file_name_to.AppendASCII("File_To.txt");
92
93 // test Do()
94 scoped_ptr<CopyTreeWorkItem> work_item(
95 WorkItem::CreateCopyTreeWorkItem(file_name_from,
96 file_name_to,
97 temp_dir_.path(),
98 WorkItem::ALWAYS,
99 base::FilePath()));
100
101 EXPECT_TRUE(work_item->Do());
102
103 EXPECT_TRUE(base::PathExists(file_name_from));
104 EXPECT_TRUE(base::PathExists(file_name_to));
105 EXPECT_TRUE(base::ContentsEqual(file_name_from, file_name_to));
106
107 // test rollback()
108 work_item->Rollback();
109
110 EXPECT_FALSE(base::PathExists(file_name_to));
111 EXPECT_TRUE(base::PathExists(file_name_from));
112 }
113
114 // Copy one file, overwriting the existing one in destination.
115 // Test with always_overwrite being true or false. The file is overwritten
116 // regardless since the content at destination file is different from source.
TEST_F(CopyTreeWorkItemTest,CopyFileOverwrite)117 TEST_F(CopyTreeWorkItemTest, CopyFileOverwrite) {
118 // Create source file
119 base::FilePath file_name_from(test_dir_.path());
120 file_name_from = file_name_from.AppendASCII("File_From.txt");
121 CreateTextFile(file_name_from.value(), text_content_1);
122 ASSERT_TRUE(base::PathExists(file_name_from));
123
124 // Create destination file
125 base::FilePath dir_name_to(test_dir_.path());
126 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
127 base::CreateDirectory(dir_name_to);
128 ASSERT_TRUE(base::PathExists(dir_name_to));
129
130 base::FilePath file_name_to(dir_name_to);
131 file_name_to = file_name_to.AppendASCII("File_To.txt");
132 CreateTextFile(file_name_to.value(), text_content_2);
133 ASSERT_TRUE(base::PathExists(file_name_to));
134
135 // test Do() with always_overwrite being true.
136 scoped_ptr<CopyTreeWorkItem> work_item(
137 WorkItem::CreateCopyTreeWorkItem(file_name_from,
138 file_name_to,
139 temp_dir_.path(),
140 WorkItem::ALWAYS,
141 base::FilePath()));
142
143 EXPECT_TRUE(work_item->Do());
144
145 EXPECT_TRUE(base::PathExists(file_name_from));
146 EXPECT_TRUE(base::PathExists(file_name_to));
147 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
148 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
149
150 // test rollback()
151 work_item->Rollback();
152
153 EXPECT_TRUE(base::PathExists(file_name_from));
154 EXPECT_TRUE(base::PathExists(file_name_to));
155 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
156 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_2));
157
158 // test Do() with always_overwrite being false.
159 // the file is still overwritten since the content is different.
160 work_item.reset(
161 WorkItem::CreateCopyTreeWorkItem(file_name_from,
162 file_name_to,
163 temp_dir_.path(),
164 WorkItem::IF_DIFFERENT,
165 base::FilePath()));
166
167 EXPECT_TRUE(work_item->Do());
168
169 EXPECT_TRUE(base::PathExists(file_name_from));
170 EXPECT_TRUE(base::PathExists(file_name_to));
171 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
172 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
173
174 // test rollback()
175 work_item->Rollback();
176
177 EXPECT_TRUE(base::PathExists(file_name_from));
178 EXPECT_TRUE(base::PathExists(file_name_to));
179 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
180 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_2));
181 }
182
183 // Copy one file, with the existing one in destination having the same
184 // content.
185 // If always_overwrite being true, the file is overwritten.
186 // If always_overwrite being false, the file is unchanged.
TEST_F(CopyTreeWorkItemTest,CopyFileSameContent)187 TEST_F(CopyTreeWorkItemTest, CopyFileSameContent) {
188 // Create source file
189 base::FilePath file_name_from(test_dir_.path());
190 file_name_from = file_name_from.AppendASCII("File_From.txt");
191 CreateTextFile(file_name_from.value(), text_content_1);
192 ASSERT_TRUE(base::PathExists(file_name_from));
193
194 // Create destination file
195 base::FilePath dir_name_to(test_dir_.path());
196 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
197 base::CreateDirectory(dir_name_to);
198 ASSERT_TRUE(base::PathExists(dir_name_to));
199
200 base::FilePath file_name_to(dir_name_to);
201 file_name_to = file_name_to.AppendASCII("File_To.txt");
202 CreateTextFile(file_name_to.value(), text_content_1);
203 ASSERT_TRUE(base::PathExists(file_name_to));
204
205 // test Do() with always_overwrite being true.
206 scoped_ptr<CopyTreeWorkItem> work_item(
207 WorkItem::CreateCopyTreeWorkItem(file_name_from,
208 file_name_to,
209 temp_dir_.path(),
210 WorkItem::ALWAYS,
211 base::FilePath()));
212
213 EXPECT_TRUE(work_item->Do());
214
215 // Get the path of backup file
216 base::FilePath backup_file(work_item->backup_path_.path());
217 EXPECT_FALSE(backup_file.empty());
218 backup_file = backup_file.AppendASCII("File_To.txt");
219
220 EXPECT_TRUE(base::PathExists(file_name_from));
221 EXPECT_TRUE(base::PathExists(file_name_to));
222 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
223 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
224 // we verify the file is overwritten by checking the existence of backup
225 // file.
226 EXPECT_TRUE(base::PathExists(backup_file));
227 EXPECT_EQ(0, ReadTextFile(backup_file.value()).compare(text_content_1));
228
229 // test rollback()
230 work_item->Rollback();
231
232 EXPECT_TRUE(base::PathExists(file_name_from));
233 EXPECT_TRUE(base::PathExists(file_name_to));
234 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
235 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
236 // the backup file should be gone after rollback
237 EXPECT_FALSE(base::PathExists(backup_file));
238
239 // test Do() with always_overwrite being false. nothing should change.
240 work_item.reset(
241 WorkItem::CreateCopyTreeWorkItem(file_name_from,
242 file_name_to,
243 temp_dir_.path(),
244 WorkItem::IF_DIFFERENT,
245 base::FilePath()));
246
247 EXPECT_TRUE(work_item->Do());
248
249 EXPECT_TRUE(base::PathExists(file_name_from));
250 EXPECT_TRUE(base::PathExists(file_name_to));
251 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
252 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
253 // we verify the file is not overwritten by checking that the backup
254 // file does not exist.
255 EXPECT_FALSE(base::PathExists(backup_file));
256
257 // test rollback(). nothing should happen here.
258 work_item->Rollback();
259
260 EXPECT_TRUE(base::PathExists(file_name_from));
261 EXPECT_TRUE(base::PathExists(file_name_to));
262 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
263 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
264 EXPECT_FALSE(base::PathExists(backup_file));
265 }
266
267 // Copy one file and without rollback. Verify all temporary files are deleted.
TEST_F(CopyTreeWorkItemTest,CopyFileAndCleanup)268 TEST_F(CopyTreeWorkItemTest, CopyFileAndCleanup) {
269 // Create source file
270 base::FilePath file_name_from(test_dir_.path());
271 file_name_from = file_name_from.AppendASCII("File_From.txt");
272 CreateTextFile(file_name_from.value(), text_content_1);
273 ASSERT_TRUE(base::PathExists(file_name_from));
274
275 // Create destination file
276 base::FilePath dir_name_to(test_dir_.path());
277 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
278 base::CreateDirectory(dir_name_to);
279 ASSERT_TRUE(base::PathExists(dir_name_to));
280
281 base::FilePath file_name_to(dir_name_to);
282 file_name_to = file_name_to.AppendASCII("File_To.txt");
283 CreateTextFile(file_name_to.value(), text_content_2);
284 ASSERT_TRUE(base::PathExists(file_name_to));
285
286 base::FilePath backup_file;
287
288 {
289 // test Do().
290 scoped_ptr<CopyTreeWorkItem> work_item(
291 WorkItem::CreateCopyTreeWorkItem(file_name_from,
292 file_name_to,
293 temp_dir_.path(),
294 WorkItem::IF_DIFFERENT,
295 base::FilePath()));
296
297 EXPECT_TRUE(work_item->Do());
298
299 // Get the path of backup file
300 backup_file = work_item->backup_path_.path();
301 EXPECT_FALSE(backup_file.empty());
302 backup_file = backup_file.AppendASCII("File_To.txt");
303
304 EXPECT_TRUE(base::PathExists(file_name_from));
305 EXPECT_TRUE(base::PathExists(file_name_to));
306 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
307 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
308 // verify the file is moved to backup place.
309 EXPECT_TRUE(base::PathExists(backup_file));
310 EXPECT_EQ(0, ReadTextFile(backup_file.value()).compare(text_content_2));
311 }
312
313 // verify the backup file is cleaned up as well.
314 EXPECT_FALSE(base::PathExists(backup_file));
315 }
316
317 // Copy one file, with the existing one in destination being used with
318 // overwrite option as IF_DIFFERENT. This destination-file-in-use should
319 // be moved to backup location after Do() and moved back after Rollback().
TEST_F(CopyTreeWorkItemTest,CopyFileInUse)320 TEST_F(CopyTreeWorkItemTest, CopyFileInUse) {
321 // Create source file
322 base::FilePath file_name_from(test_dir_.path());
323 file_name_from = file_name_from.AppendASCII("File_From");
324 CreateTextFile(file_name_from.value(), text_content_1);
325 ASSERT_TRUE(base::PathExists(file_name_from));
326
327 // Create an executable in destination path by copying ourself to it.
328 wchar_t exe_full_path_str[MAX_PATH];
329 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
330 base::FilePath exe_full_path(exe_full_path_str);
331
332 base::FilePath dir_name_to(test_dir_.path());
333 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
334 base::CreateDirectory(dir_name_to);
335 ASSERT_TRUE(base::PathExists(dir_name_to));
336
337 base::FilePath file_name_to(dir_name_to);
338 file_name_to = file_name_to.AppendASCII("File_To");
339 base::CopyFile(exe_full_path, file_name_to);
340 ASSERT_TRUE(base::PathExists(file_name_to));
341
342 VLOG(1) << "copy ourself from " << exe_full_path.value()
343 << " to " << file_name_to.value();
344
345 // Run the executable in destination path
346 STARTUPINFOW si = {sizeof(si)};
347 PROCESS_INFORMATION pi = {0};
348 ASSERT_TRUE(
349 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
350 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
351 NULL, NULL, &si, &pi));
352
353 // test Do().
354 scoped_ptr<CopyTreeWorkItem> work_item(
355 WorkItem::CreateCopyTreeWorkItem(file_name_from,
356 file_name_to,
357 temp_dir_.path(),
358 WorkItem::IF_DIFFERENT,
359 base::FilePath()));
360
361 EXPECT_TRUE(work_item->Do());
362
363 // Get the path of backup file
364 base::FilePath backup_file(work_item->backup_path_.path());
365 EXPECT_FALSE(backup_file.empty());
366 backup_file = backup_file.AppendASCII("File_To");
367
368 EXPECT_TRUE(base::PathExists(file_name_from));
369 EXPECT_TRUE(base::PathExists(file_name_to));
370 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
371 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
372 // verify the file in used is moved to backup place.
373 EXPECT_TRUE(base::PathExists(backup_file));
374 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file));
375
376 // test rollback()
377 work_item->Rollback();
378
379 EXPECT_TRUE(base::PathExists(file_name_from));
380 EXPECT_TRUE(base::PathExists(file_name_to));
381 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
382 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
383 // the backup file should be gone after rollback
384 EXPECT_FALSE(base::PathExists(backup_file));
385
386 TerminateProcess(pi.hProcess, 0);
387 // make sure the handle is closed.
388 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
389 CloseHandle(pi.hProcess);
390 CloseHandle(pi.hThread);
391 }
392
393 // Test overwrite option NEW_NAME_IF_IN_USE:
394 // 1. If destination file is in use, the source should be copied with the
395 // new name after Do() and this new name file should be deleted
396 // after rollback.
397 // 2. If destination file is not in use, the source should be copied in the
398 // destination folder after Do() and should be rolled back after Rollback().
TEST_F(CopyTreeWorkItemTest,NewNameAndCopyTest)399 TEST_F(CopyTreeWorkItemTest, NewNameAndCopyTest) {
400 // Create source file
401 base::FilePath file_name_from(test_dir_.path());
402 file_name_from = file_name_from.AppendASCII("File_From");
403 CreateTextFile(file_name_from.value(), text_content_1);
404 ASSERT_TRUE(base::PathExists(file_name_from));
405
406 // Create an executable in destination path by copying ourself to it.
407 wchar_t exe_full_path_str[MAX_PATH];
408 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
409 base::FilePath exe_full_path(exe_full_path_str);
410
411 base::FilePath dir_name_to(test_dir_.path());
412 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
413 base::CreateDirectory(dir_name_to);
414 ASSERT_TRUE(base::PathExists(dir_name_to));
415
416 base::FilePath file_name_to(dir_name_to), alternate_to(dir_name_to);
417 file_name_to = file_name_to.AppendASCII("File_To");
418 alternate_to = alternate_to.AppendASCII("Alternate_To");
419 base::CopyFile(exe_full_path, file_name_to);
420 ASSERT_TRUE(base::PathExists(file_name_to));
421
422 VLOG(1) << "copy ourself from " << exe_full_path.value()
423 << " to " << file_name_to.value();
424
425 // Run the executable in destination path
426 STARTUPINFOW si = {sizeof(si)};
427 PROCESS_INFORMATION pi = {0};
428 ASSERT_TRUE(
429 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
430 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
431 NULL, NULL, &si, &pi));
432
433 // test Do().
434 scoped_ptr<CopyTreeWorkItem> work_item(
435 WorkItem::CreateCopyTreeWorkItem(file_name_from,
436 file_name_to,
437 temp_dir_.path(),
438 WorkItem::NEW_NAME_IF_IN_USE,
439 alternate_to));
440
441 EXPECT_TRUE(work_item->Do());
442
443 EXPECT_TRUE(base::PathExists(file_name_from));
444 EXPECT_TRUE(base::PathExists(file_name_to));
445 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
446 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
447 // verify that the backup path does not exist
448 EXPECT_TRUE(work_item->backup_path_.path().empty());
449 EXPECT_TRUE(base::ContentsEqual(file_name_from, alternate_to));
450
451 // test rollback()
452 work_item->Rollback();
453
454 EXPECT_TRUE(base::PathExists(file_name_from));
455 EXPECT_TRUE(base::PathExists(file_name_to));
456 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
457 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
458 EXPECT_TRUE(work_item->backup_path_.path().empty());
459 // the alternate file should be gone after rollback
460 EXPECT_FALSE(base::PathExists(alternate_to));
461
462 TerminateProcess(pi.hProcess, 0);
463 // make sure the handle is closed.
464 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
465 CloseHandle(pi.hProcess);
466 CloseHandle(pi.hThread);
467
468 // Now the process has terminated, lets try overwriting the file again
469 work_item.reset(WorkItem::CreateCopyTreeWorkItem(
470 file_name_from, file_name_to,
471 temp_dir_.path(), WorkItem::NEW_NAME_IF_IN_USE,
472 alternate_to));
473 if (IsFileInUse(file_name_to))
474 base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
475 // If file is still in use, the rest of the test will fail.
476 ASSERT_FALSE(IsFileInUse(file_name_to));
477 EXPECT_TRUE(work_item->Do());
478
479 // Get the path of backup file
480 base::FilePath backup_file(work_item->backup_path_.path());
481 EXPECT_FALSE(backup_file.empty());
482 backup_file = backup_file.AppendASCII("File_To");
483
484 EXPECT_TRUE(base::PathExists(file_name_from));
485 EXPECT_TRUE(base::PathExists(file_name_to));
486 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
487 EXPECT_TRUE(base::ContentsEqual(file_name_from, file_name_to));
488 // verify that the backup path does exist
489 EXPECT_TRUE(base::PathExists(backup_file));
490 EXPECT_FALSE(base::PathExists(alternate_to));
491
492 // test rollback()
493 work_item->Rollback();
494
495 EXPECT_TRUE(base::PathExists(file_name_from));
496 EXPECT_TRUE(base::PathExists(file_name_to));
497 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
498 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
499 // the backup file should be gone after rollback
500 EXPECT_FALSE(base::PathExists(backup_file));
501 EXPECT_FALSE(base::PathExists(alternate_to));
502 }
503
504 // Test overwrite option IF_NOT_PRESENT:
505 // 1. If destination file/directory exist, the source should not be copied
506 // 2. If destination file/directory do not exist, the source should be copied
507 // in the destination folder after Do() and should be rolled back after
508 // Rollback().
509 // Flaky, http://crbug.com/59785.
TEST_F(CopyTreeWorkItemTest,DISABLED_IfNotPresentTest)510 TEST_F(CopyTreeWorkItemTest, DISABLED_IfNotPresentTest) {
511 // Create source file
512 base::FilePath file_name_from(test_dir_.path());
513 file_name_from = file_name_from.AppendASCII("File_From");
514 CreateTextFile(file_name_from.value(), text_content_1);
515 ASSERT_TRUE(base::PathExists(file_name_from));
516
517 // Create an executable in destination path by copying ourself to it.
518 wchar_t exe_full_path_str[MAX_PATH];
519 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
520 base::FilePath exe_full_path(exe_full_path_str);
521
522 base::FilePath dir_name_to(test_dir_.path());
523 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
524 base::CreateDirectory(dir_name_to);
525 ASSERT_TRUE(base::PathExists(dir_name_to));
526 base::FilePath file_name_to(dir_name_to);
527 file_name_to = file_name_to.AppendASCII("File_To");
528 base::CopyFile(exe_full_path, file_name_to);
529 ASSERT_TRUE(base::PathExists(file_name_to));
530
531 // Get the path of backup file
532 base::FilePath backup_file(temp_dir_.path());
533 backup_file = backup_file.AppendASCII("File_To");
534
535 // test Do().
536 scoped_ptr<CopyTreeWorkItem> work_item(
537 WorkItem::CreateCopyTreeWorkItem(
538 file_name_from,
539 file_name_to, temp_dir_.path(),
540 WorkItem::IF_NOT_PRESENT,
541 base::FilePath()));
542 EXPECT_TRUE(work_item->Do());
543
544 // verify that the source, destination have not changed and backup path
545 // does not exist
546 EXPECT_TRUE(base::PathExists(file_name_from));
547 EXPECT_TRUE(base::PathExists(file_name_to));
548 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
549 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
550 EXPECT_FALSE(base::PathExists(backup_file));
551
552 // test rollback()
553 work_item->Rollback();
554
555 // verify that the source, destination have not changed and backup path
556 // does not exist after rollback also
557 EXPECT_TRUE(base::PathExists(file_name_from));
558 EXPECT_TRUE(base::PathExists(file_name_to));
559 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
560 EXPECT_TRUE(base::ContentsEqual(exe_full_path, file_name_to));
561 EXPECT_FALSE(base::PathExists(backup_file));
562
563 // Now delete the destination and try copying the file again.
564 base::DeleteFile(file_name_to, true);
565 work_item.reset(WorkItem::CreateCopyTreeWorkItem(
566 file_name_from, file_name_to,
567 temp_dir_.path(), WorkItem::IF_NOT_PRESENT,
568 base::FilePath()));
569 EXPECT_TRUE(work_item->Do());
570
571 // verify that the source, destination are the same and backup path
572 // does not exist
573 EXPECT_TRUE(base::PathExists(file_name_from));
574 EXPECT_TRUE(base::PathExists(file_name_to));
575 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
576 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
577 EXPECT_FALSE(base::PathExists(backup_file));
578
579 // test rollback()
580 work_item->Rollback();
581
582 // verify that the destination does not exist anymore
583 EXPECT_TRUE(base::PathExists(file_name_from));
584 EXPECT_FALSE(base::PathExists(file_name_to));
585 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
586 EXPECT_FALSE(base::PathExists(backup_file));
587 }
588
589 // Copy one file without rollback. The existing one in destination is in use.
590 // Verify it is moved to backup location and stays there.
591 // Flaky, http://crbug.com/59783.
TEST_F(CopyTreeWorkItemTest,DISABLED_CopyFileInUseAndCleanup)592 TEST_F(CopyTreeWorkItemTest, DISABLED_CopyFileInUseAndCleanup) {
593 // Create source file
594 base::FilePath file_name_from(test_dir_.path());
595 file_name_from = file_name_from.AppendASCII("File_From");
596 CreateTextFile(file_name_from.value(), text_content_1);
597 ASSERT_TRUE(base::PathExists(file_name_from));
598
599 // Create an executable in destination path by copying ourself to it.
600 wchar_t exe_full_path_str[MAX_PATH];
601 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
602 base::FilePath exe_full_path(exe_full_path_str);
603
604 base::FilePath dir_name_to(test_dir_.path());
605 dir_name_to = dir_name_to.AppendASCII("Copy_To_Subdir");
606 base::CreateDirectory(dir_name_to);
607 ASSERT_TRUE(base::PathExists(dir_name_to));
608
609 base::FilePath file_name_to(dir_name_to);
610 file_name_to = file_name_to.AppendASCII("File_To");
611 base::CopyFile(exe_full_path, file_name_to);
612 ASSERT_TRUE(base::PathExists(file_name_to));
613
614 VLOG(1) << "copy ourself from " << exe_full_path.value()
615 << " to " << file_name_to.value();
616
617 // Run the executable in destination path
618 STARTUPINFOW si = {sizeof(si)};
619 PROCESS_INFORMATION pi = {0};
620 ASSERT_TRUE(
621 ::CreateProcess(NULL, const_cast<wchar_t*>(file_name_to.value().c_str()),
622 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
623 NULL, NULL, &si, &pi));
624
625 base::FilePath backup_file;
626
627 // test Do().
628 {
629 scoped_ptr<CopyTreeWorkItem> work_item(
630 WorkItem::CreateCopyTreeWorkItem(file_name_from,
631 file_name_to,
632 temp_dir_.path(),
633 WorkItem::IF_DIFFERENT,
634 base::FilePath()));
635
636 EXPECT_TRUE(work_item->Do());
637
638 // Get the path of backup file
639 backup_file = work_item->backup_path_.path();
640 EXPECT_FALSE(backup_file.empty());
641 backup_file = backup_file.AppendASCII("File_To");
642
643 EXPECT_TRUE(base::PathExists(file_name_from));
644 EXPECT_TRUE(base::PathExists(file_name_to));
645 EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
646 EXPECT_EQ(0, ReadTextFile(file_name_to.value()).compare(text_content_1));
647 // verify the file in used is moved to backup place.
648 EXPECT_TRUE(base::PathExists(backup_file));
649 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file));
650 }
651
652 // verify the file in used should be still at the backup place.
653 EXPECT_TRUE(base::PathExists(backup_file));
654 EXPECT_TRUE(base::ContentsEqual(exe_full_path, backup_file));
655
656 TerminateProcess(pi.hProcess, 0);
657 // make sure the handle is closed.
658 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
659 CloseHandle(pi.hProcess);
660 CloseHandle(pi.hThread);
661 }
662
663 // Copy a tree from source to destination.
664 // Flaky, http://crbug.com/59784.
TEST_F(CopyTreeWorkItemTest,DISABLED_CopyTree)665 TEST_F(CopyTreeWorkItemTest, DISABLED_CopyTree) {
666 // Create source tree
667 base::FilePath dir_name_from(test_dir_.path());
668 dir_name_from = dir_name_from.AppendASCII("from");
669 base::CreateDirectory(dir_name_from);
670 ASSERT_TRUE(base::PathExists(dir_name_from));
671
672 base::FilePath dir_name_from_1(dir_name_from);
673 dir_name_from_1 = dir_name_from_1.AppendASCII("1");
674 base::CreateDirectory(dir_name_from_1);
675 ASSERT_TRUE(base::PathExists(dir_name_from_1));
676
677 base::FilePath dir_name_from_2(dir_name_from);
678 dir_name_from_2 = dir_name_from_2.AppendASCII("2");
679 base::CreateDirectory(dir_name_from_2);
680 ASSERT_TRUE(base::PathExists(dir_name_from_2));
681
682 base::FilePath file_name_from_1(dir_name_from_1);
683 file_name_from_1 = file_name_from_1.AppendASCII("File_1.txt");
684 CreateTextFile(file_name_from_1.value(), text_content_1);
685 ASSERT_TRUE(base::PathExists(file_name_from_1));
686
687 base::FilePath file_name_from_2(dir_name_from_2);
688 file_name_from_2 = file_name_from_2.AppendASCII("File_2.txt");
689 CreateTextFile(file_name_from_2.value(), text_content_1);
690 ASSERT_TRUE(base::PathExists(file_name_from_2));
691
692 base::FilePath dir_name_to(test_dir_.path());
693 dir_name_to = dir_name_to.AppendASCII("to");
694
695 // test Do()
696 {
697 scoped_ptr<CopyTreeWorkItem> work_item(
698 WorkItem::CreateCopyTreeWorkItem(dir_name_from,
699 dir_name_to,
700 temp_dir_.path(),
701 WorkItem::ALWAYS,
702 base::FilePath()));
703
704 EXPECT_TRUE(work_item->Do());
705 }
706
707 base::FilePath file_name_to_1(dir_name_to);
708 file_name_to_1 = file_name_to_1.AppendASCII("1");
709 file_name_to_1 = file_name_to_1.AppendASCII("File_1.txt");
710 EXPECT_TRUE(base::PathExists(file_name_to_1));
711 VLOG(1) << "compare " << file_name_from_1.value()
712 << " and " << file_name_to_1.value();
713 EXPECT_TRUE(base::ContentsEqual(file_name_from_1, file_name_to_1));
714
715 base::FilePath file_name_to_2(dir_name_to);
716 file_name_to_2 = file_name_to_2.AppendASCII("2");
717 file_name_to_2 = file_name_to_2.AppendASCII("File_2.txt");
718 EXPECT_TRUE(base::PathExists(file_name_to_2));
719 VLOG(1) << "compare " << file_name_from_2.value()
720 << " and " << file_name_to_2.value();
721 EXPECT_TRUE(base::ContentsEqual(file_name_from_2, file_name_to_2));
722 }
723