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