• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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