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