copy_tree_work_item_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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/process_util.h"
16#include "base/strings/string_util.h"
17#include "base/threading/platform_thread.h"
18#include "chrome/installer/util/copy_tree_work_item.h"
19#include "chrome/installer/util/work_item.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22namespace {
23  class CopyTreeWorkItemTest : public testing::Test {
24   protected:
25    virtual void SetUp() {
26      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
27      ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
28    }
29
30    virtual void TearDown() {
31      logging::CloseLogFile();
32    }
33
34    // the path to temporary directory used to contain the test operations
35    base::ScopedTempDir test_dir_;
36    base::ScopedTempDir temp_dir_;
37  };
38
39  // Simple function to dump some text into a new file.
40  void CreateTextFile(const std::wstring& filename,
41                      const std::wstring& contents) {
42    std::ofstream file;
43    file.open(filename.c_str());
44    ASSERT_TRUE(file.is_open());
45    file << contents;
46    file.close();
47  }
48
49  bool IsFileInUse(const base::FilePath& path) {
50    if (!file_util::PathExists(path))
51      return false;
52
53    HANDLE handle = ::CreateFile(path.value().c_str(), FILE_ALL_ACCESS,
54                                 NULL, NULL, OPEN_EXISTING, NULL, NULL);
55    if (handle  == INVALID_HANDLE_VALUE)
56      return true;
57
58    CloseHandle(handle);
59    return false;
60  }
61
62  // Simple function to read text from a file.
63  std::wstring ReadTextFile(const std::wstring& filename) {
64    WCHAR contents[64];
65    std::wifstream file;
66    file.open(filename.c_str());
67    EXPECT_TRUE(file.is_open());
68    file.getline(contents, 64);
69    file.close();
70    return std::wstring(contents);
71  }
72
73  wchar_t text_content_1[] = L"Gooooooooooooooooooooogle";
74  wchar_t text_content_2[] = L"Overwrite Me";
75};
76
77// Copy one file from source to destination.
78TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
89  ASSERT_TRUE(file_util::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(file_util::PathExists(file_name_from));
105  EXPECT_TRUE(file_util::PathExists(file_name_to));
106  EXPECT_TRUE(file_util::ContentsEqual(file_name_from, file_name_to));
107
108  // test rollback()
109  work_item->Rollback();
110
111  EXPECT_FALSE(file_util::PathExists(file_name_to));
112  EXPECT_TRUE(file_util::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.
118TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
129  ASSERT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
147  EXPECT_TRUE(file_util::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(file_util::PathExists(file_name_from));
155  EXPECT_TRUE(file_util::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(file_util::PathExists(file_name_from));
171  EXPECT_TRUE(file_util::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(file_util::PathExists(file_name_from));
179  EXPECT_TRUE(file_util::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.
188TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
199  ASSERT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
222  EXPECT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
234  EXPECT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
251  EXPECT_TRUE(file_util::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(file_util::PathExists(backup_file));
257
258  // test rollback(). nothing should happen here.
259  work_item->Rollback();
260
261  EXPECT_TRUE(file_util::PathExists(file_name_from));
262  EXPECT_TRUE(file_util::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(file_util::PathExists(backup_file));
266}
267
268// Copy one file and without rollback. Verify all temporary files are deleted.
269TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
280  ASSERT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
306    EXPECT_TRUE(file_util::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(file_util::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(file_util::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().
321TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
336  ASSERT_TRUE(file_util::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  file_util::CopyFile(exe_full_path, file_name_to);
341  ASSERT_TRUE(file_util::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(file_util::PathExists(file_name_from));
370  EXPECT_TRUE(file_util::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(file_util::PathExists(backup_file));
375  EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file));
376
377  // test rollback()
378  work_item->Rollback();
379
380  EXPECT_TRUE(file_util::PathExists(file_name_from));
381  EXPECT_TRUE(file_util::PathExists(file_name_to));
382  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
383  EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
384  // the backup file should be gone after rollback
385  EXPECT_FALSE(file_util::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().
400TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
415  ASSERT_TRUE(file_util::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  file_util::CopyFile(exe_full_path, file_name_to);
421  ASSERT_TRUE(file_util::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(file_util::PathExists(file_name_from));
445  EXPECT_TRUE(file_util::PathExists(file_name_to));
446  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
447  EXPECT_TRUE(file_util::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(file_util::ContentsEqual(file_name_from, alternate_to));
451
452  // test rollback()
453  work_item->Rollback();
454
455  EXPECT_TRUE(file_util::PathExists(file_name_from));
456  EXPECT_TRUE(file_util::PathExists(file_name_to));
457  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
458  EXPECT_TRUE(file_util::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(file_util::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(file_util::PathExists(file_name_from));
486  EXPECT_TRUE(file_util::PathExists(file_name_to));
487  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
488  EXPECT_TRUE(file_util::ContentsEqual(file_name_from, file_name_to));
489  // verify that the backup path does exist
490  EXPECT_TRUE(file_util::PathExists(backup_file));
491  EXPECT_FALSE(file_util::PathExists(alternate_to));
492
493  // test rollback()
494  work_item->Rollback();
495
496  EXPECT_TRUE(file_util::PathExists(file_name_from));
497  EXPECT_TRUE(file_util::PathExists(file_name_to));
498  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
499  EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
500  // the backup file should be gone after rollback
501  EXPECT_FALSE(file_util::PathExists(backup_file));
502  EXPECT_FALSE(file_util::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.
511TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
526  ASSERT_TRUE(file_util::PathExists(dir_name_to));
527  base::FilePath file_name_to(dir_name_to);
528  file_name_to = file_name_to.AppendASCII("File_To");
529  file_util::CopyFile(exe_full_path, file_name_to);
530  ASSERT_TRUE(file_util::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(file_util::PathExists(file_name_from));
548  EXPECT_TRUE(file_util::PathExists(file_name_to));
549  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
550  EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
551  EXPECT_FALSE(file_util::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(file_util::PathExists(file_name_from));
559  EXPECT_TRUE(file_util::PathExists(file_name_to));
560  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
561  EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, file_name_to));
562  EXPECT_FALSE(file_util::PathExists(backup_file));
563
564  // Now delete the destination and try copying the file again.
565  file_util::Delete(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(file_util::PathExists(file_name_from));
575  EXPECT_TRUE(file_util::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(file_util::PathExists(backup_file));
579
580  // test rollback()
581  work_item->Rollback();
582
583  // verify that the destination does not exist anymore
584  EXPECT_TRUE(file_util::PathExists(file_name_from));
585  EXPECT_FALSE(file_util::PathExists(file_name_to));
586  EXPECT_EQ(0, ReadTextFile(file_name_from.value()).compare(text_content_1));
587  EXPECT_FALSE(file_util::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.
593TEST_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(file_util::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  file_util::CreateDirectory(dir_name_to);
608  ASSERT_TRUE(file_util::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  file_util::CopyFile(exe_full_path, file_name_to);
613  ASSERT_TRUE(file_util::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(file_util::PathExists(file_name_from));
645    EXPECT_TRUE(file_util::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(file_util::PathExists(backup_file));
650    EXPECT_TRUE(file_util::ContentsEqual(exe_full_path, backup_file));
651  }
652
653  // verify the file in used should be still at the backup place.
654  EXPECT_TRUE(file_util::PathExists(backup_file));
655  EXPECT_TRUE(file_util::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.
666TEST_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  file_util::CreateDirectory(dir_name_from);
671  ASSERT_TRUE(file_util::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  file_util::CreateDirectory(dir_name_from_1);
676  ASSERT_TRUE(file_util::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  file_util::CreateDirectory(dir_name_from_2);
681  ASSERT_TRUE(file_util::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(file_util::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(file_util::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(file_util::PathExists(file_name_to_1));
712  VLOG(1) << "compare " << file_name_from_1.value()
713          << " and " << file_name_to_1.value();
714  EXPECT_TRUE(file_util::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(file_util::PathExists(file_name_to_2));
720  VLOG(1) << "compare " << file_name_from_2.value()
721          << " and " << file_name_to_2.value();
722  EXPECT_TRUE(file_util::ContentsEqual(file_name_from_2, file_name_to_2));
723}
724