Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / move_tree_work_item_unittest.cc
1 // Copyright (c) 2011 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/memory_mapped_file.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/path_service.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/installer/util/installer_util_test_common.h"
17 #include "chrome/installer/util/move_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 MoveTreeWorkItemTest : public testing::Test {
23  protected:
24   virtual void SetUp() {
25     ASSERT_TRUE(temp_from_dir_.CreateUniqueTempDir());
26     ASSERT_TRUE(temp_to_dir_.CreateUniqueTempDir());
27   }
28
29   base::ScopedTempDir temp_from_dir_;
30   base::ScopedTempDir temp_to_dir_;
31 };
32
33 // Simple function to dump some text into a new file.
34 void CreateTextFile(const std::wstring& filename,
35                     const std::wstring& contents) {
36   std::wofstream file;
37   file.open(base::UTF16ToASCII(filename).c_str());
38   ASSERT_TRUE(file.is_open());
39   file << contents;
40   file.close();
41 }
42
43 // Simple function to read text from a file.
44 std::wstring ReadTextFile(const base::FilePath& path) {
45   WCHAR contents[64];
46   std::wifstream file;
47   file.open(base::UTF16ToASCII(path.value()).c_str());
48   EXPECT_TRUE(file.is_open());
49   file.getline(contents, arraysize(contents));
50   file.close();
51   return std::wstring(contents);
52 }
53
54 const wchar_t kTextContent1[] = L"Gooooooooooooooooooooogle";
55 const wchar_t kTextContent2[] = L"Overwrite Me";
56 };  // namespace
57
58 // Move one directory from source to destination when destination does not
59 // exist.
60 TEST_F(MoveTreeWorkItemTest, MoveDirectory) {
61   // Create two level deep source dir
62   base::FilePath from_dir1(temp_from_dir_.path());
63   from_dir1 = from_dir1.AppendASCII("From_Dir1");
64   base::CreateDirectory(from_dir1);
65   ASSERT_TRUE(base::PathExists(from_dir1));
66
67   base::FilePath from_dir2(from_dir1);
68   from_dir2 = from_dir2.AppendASCII("From_Dir2");
69   base::CreateDirectory(from_dir2);
70   ASSERT_TRUE(base::PathExists(from_dir2));
71
72   base::FilePath from_file(from_dir2);
73   from_file = from_file.AppendASCII("From_File");
74   CreateTextFile(from_file.value(), kTextContent1);
75   ASSERT_TRUE(base::PathExists(from_file));
76
77   // Generate destination path
78   base::FilePath to_dir(temp_from_dir_.path());
79   to_dir = to_dir.AppendASCII("To_Dir");
80   ASSERT_FALSE(base::PathExists(to_dir));
81
82   base::FilePath to_file(to_dir);
83   to_file = to_file.AppendASCII("From_Dir2");
84   to_file = to_file.AppendASCII("From_File");
85   ASSERT_FALSE(base::PathExists(to_file));
86
87   // test Do()
88   scoped_ptr<MoveTreeWorkItem> work_item(
89       WorkItem::CreateMoveTreeWorkItem(from_dir1,
90                                        to_dir,
91                                        temp_to_dir_.path(),
92                                        WorkItem::ALWAYS_MOVE));
93   EXPECT_TRUE(work_item->Do());
94
95   EXPECT_FALSE(base::PathExists(from_dir1));
96   EXPECT_TRUE(base::PathExists(to_dir));
97   EXPECT_TRUE(base::PathExists(to_file));
98
99   // test rollback()
100   work_item->Rollback();
101
102   EXPECT_TRUE(base::PathExists(from_dir1));
103   EXPECT_TRUE(base::PathExists(from_file));
104   EXPECT_FALSE(base::PathExists(to_dir));
105 }
106
107 // Move one directory from source to destination when destination already
108 // exists.
109 TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExists) {
110   // Create two level deep source dir
111   base::FilePath from_dir1(temp_from_dir_.path());
112   from_dir1 = from_dir1.AppendASCII("From_Dir1");
113   base::CreateDirectory(from_dir1);
114   ASSERT_TRUE(base::PathExists(from_dir1));
115
116   base::FilePath from_dir2(from_dir1);
117   from_dir2 = from_dir2.AppendASCII("From_Dir2");
118   base::CreateDirectory(from_dir2);
119   ASSERT_TRUE(base::PathExists(from_dir2));
120
121   base::FilePath from_file(from_dir2);
122   from_file = from_file.AppendASCII("From_File");
123   CreateTextFile(from_file.value(), kTextContent1);
124   ASSERT_TRUE(base::PathExists(from_file));
125
126   // Create destination path
127   base::FilePath to_dir(temp_from_dir_.path());
128   to_dir = to_dir.AppendASCII("To_Dir");
129   base::CreateDirectory(to_dir);
130   ASSERT_TRUE(base::PathExists(to_dir));
131
132   base::FilePath orig_to_file(to_dir);
133   orig_to_file = orig_to_file.AppendASCII("To_File");
134   CreateTextFile(orig_to_file.value(), kTextContent2);
135   ASSERT_TRUE(base::PathExists(orig_to_file));
136
137   base::FilePath new_to_file(to_dir);
138   new_to_file = new_to_file.AppendASCII("From_Dir2");
139   new_to_file = new_to_file.AppendASCII("From_File");
140   ASSERT_FALSE(base::PathExists(new_to_file));
141
142   // test Do(), don't check for duplicates.
143   scoped_ptr<MoveTreeWorkItem> work_item(
144       WorkItem::CreateMoveTreeWorkItem(from_dir1,
145                                        to_dir,
146                                        temp_to_dir_.path(),
147                                        WorkItem::ALWAYS_MOVE));
148   EXPECT_TRUE(work_item->Do());
149
150   EXPECT_FALSE(base::PathExists(from_dir1));
151   EXPECT_TRUE(base::PathExists(to_dir));
152   EXPECT_TRUE(base::PathExists(new_to_file));
153   EXPECT_FALSE(base::PathExists(orig_to_file));
154
155   // test rollback()
156   work_item->Rollback();
157
158   EXPECT_TRUE(base::PathExists(from_dir1));
159   EXPECT_TRUE(base::PathExists(to_dir));
160   EXPECT_FALSE(base::PathExists(new_to_file));
161   EXPECT_TRUE(base::PathExists(orig_to_file));
162   EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent2));
163   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
164 }
165
166 // Move one file from source to destination when destination does not
167 // exist.
168 TEST_F(MoveTreeWorkItemTest, MoveAFile) {
169   // Create a file inside source dir
170   base::FilePath from_dir(temp_from_dir_.path());
171   from_dir = from_dir.AppendASCII("From_Dir");
172   base::CreateDirectory(from_dir);
173   ASSERT_TRUE(base::PathExists(from_dir));
174
175   base::FilePath from_file(from_dir);
176   from_file = from_file.AppendASCII("From_File");
177   CreateTextFile(from_file.value(), kTextContent1);
178   ASSERT_TRUE(base::PathExists(from_file));
179
180   // Generate destination file name
181   base::FilePath to_file(temp_from_dir_.path());
182   to_file = to_file.AppendASCII("To_File");
183   ASSERT_FALSE(base::PathExists(to_file));
184
185   // test Do()
186   scoped_ptr<MoveTreeWorkItem> work_item(
187       WorkItem::CreateMoveTreeWorkItem(from_file,
188                                        to_file,
189                                        temp_to_dir_.path(),
190                                        WorkItem::ALWAYS_MOVE));
191   EXPECT_TRUE(work_item->Do());
192
193   EXPECT_TRUE(base::PathExists(from_dir));
194   EXPECT_FALSE(base::PathExists(from_file));
195   EXPECT_TRUE(base::PathExists(to_file));
196   EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1));
197
198   // test rollback()
199   work_item->Rollback();
200
201   EXPECT_TRUE(base::PathExists(from_dir));
202   EXPECT_TRUE(base::PathExists(from_file));
203   EXPECT_FALSE(base::PathExists(to_file));
204   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
205 }
206
207 // Move one file from source to destination when destination already
208 // exists.
209 TEST_F(MoveTreeWorkItemTest, MoveFileDestExists) {
210   // Create a file inside source dir
211   base::FilePath from_dir(temp_from_dir_.path());
212   from_dir = from_dir.AppendASCII("From_Dir");
213   base::CreateDirectory(from_dir);
214   ASSERT_TRUE(base::PathExists(from_dir));
215
216   base::FilePath from_file(from_dir);
217   from_file = from_file.AppendASCII("From_File");
218   CreateTextFile(from_file.value(), kTextContent1);
219   ASSERT_TRUE(base::PathExists(from_file));
220
221   // Create destination path
222   base::FilePath to_dir(temp_from_dir_.path());
223   to_dir = to_dir.AppendASCII("To_Dir");
224   base::CreateDirectory(to_dir);
225   ASSERT_TRUE(base::PathExists(to_dir));
226
227   base::FilePath to_file(to_dir);
228   to_file = to_file.AppendASCII("To_File");
229   CreateTextFile(to_file.value(), kTextContent2);
230   ASSERT_TRUE(base::PathExists(to_file));
231
232   // test Do()
233   scoped_ptr<MoveTreeWorkItem> work_item(
234       WorkItem::CreateMoveTreeWorkItem(from_file,
235                                        to_dir,
236                                        temp_to_dir_.path(),
237                                        WorkItem::ALWAYS_MOVE));
238   EXPECT_TRUE(work_item->Do());
239
240   EXPECT_TRUE(base::PathExists(from_dir));
241   EXPECT_FALSE(base::PathExists(from_file));
242   EXPECT_TRUE(base::PathExists(to_dir));
243   EXPECT_FALSE(base::PathExists(to_file));
244   EXPECT_EQ(0, ReadTextFile(to_dir).compare(kTextContent1));
245
246   // test rollback()
247   work_item->Rollback();
248
249   EXPECT_TRUE(base::PathExists(from_dir));
250   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
251   EXPECT_TRUE(base::PathExists(to_dir));
252   EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent2));
253 }
254
255 // Move one file from source to destination when destination already
256 // exists and is in use.
257 TEST_F(MoveTreeWorkItemTest, MoveFileDestInUse) {
258   // Create a file inside source dir
259   base::FilePath from_dir(temp_from_dir_.path());
260   from_dir = from_dir.AppendASCII("From_Dir");
261   base::CreateDirectory(from_dir);
262   ASSERT_TRUE(base::PathExists(from_dir));
263
264   base::FilePath from_file(from_dir);
265   from_file = from_file.AppendASCII("From_File");
266   CreateTextFile(from_file.value(), kTextContent1);
267   ASSERT_TRUE(base::PathExists(from_file));
268
269   // Create an executable in destination path by copying ourself to it.
270   base::FilePath to_dir(temp_from_dir_.path());
271   to_dir = to_dir.AppendASCII("To_Dir");
272   base::CreateDirectory(to_dir);
273   ASSERT_TRUE(base::PathExists(to_dir));
274
275   wchar_t exe_full_path_str[MAX_PATH];
276   ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
277   base::FilePath exe_full_path(exe_full_path_str);
278   base::FilePath to_file(to_dir);
279   to_file = to_file.AppendASCII("To_File");
280   base::CopyFile(exe_full_path, to_file);
281   ASSERT_TRUE(base::PathExists(to_file));
282
283   // Run the executable in destination path
284   STARTUPINFOW si = {sizeof(si)};
285   PROCESS_INFORMATION pi = {0};
286   ASSERT_TRUE(::CreateProcess(NULL,
287                               const_cast<wchar_t*>(to_file.value().c_str()),
288                               NULL, NULL, FALSE,
289                               CREATE_NO_WINDOW | CREATE_SUSPENDED,
290                               NULL, NULL, &si, &pi));
291
292   // test Do()
293   scoped_ptr<MoveTreeWorkItem> work_item(
294       WorkItem::CreateMoveTreeWorkItem(from_file,
295                                        to_file,
296                                        temp_to_dir_.path(),
297                                        WorkItem::ALWAYS_MOVE));
298   EXPECT_TRUE(work_item->Do());
299
300   EXPECT_TRUE(base::PathExists(from_dir));
301   EXPECT_FALSE(base::PathExists(from_file));
302   EXPECT_TRUE(base::PathExists(to_dir));
303   EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1));
304
305   // test rollback()
306   work_item->Rollback();
307
308   EXPECT_TRUE(base::PathExists(from_dir));
309   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
310   EXPECT_TRUE(base::PathExists(to_dir));
311   EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file));
312
313   TerminateProcess(pi.hProcess, 0);
314   EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
315   CloseHandle(pi.hProcess);
316   CloseHandle(pi.hThread);
317 }
318
319 // Move one file that is in use to destination.
320 TEST_F(MoveTreeWorkItemTest, MoveFileInUse) {
321   // Create an executable for source by copying ourself to a new source dir.
322   base::FilePath from_dir(temp_from_dir_.path());
323   from_dir = from_dir.AppendASCII("From_Dir");
324   base::CreateDirectory(from_dir);
325   ASSERT_TRUE(base::PathExists(from_dir));
326
327   wchar_t exe_full_path_str[MAX_PATH];
328   ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH);
329   base::FilePath exe_full_path(exe_full_path_str);
330   base::FilePath from_file(from_dir);
331   from_file = from_file.AppendASCII("From_File");
332   base::CopyFile(exe_full_path, from_file);
333   ASSERT_TRUE(base::PathExists(from_file));
334
335   // Create a destination source dir and generate destination file name.
336   base::FilePath to_dir(temp_from_dir_.path());
337   to_dir = to_dir.AppendASCII("To_Dir");
338   base::CreateDirectory(to_dir);
339   ASSERT_TRUE(base::PathExists(to_dir));
340
341   base::FilePath to_file(to_dir);
342   to_file = to_file.AppendASCII("To_File");
343   CreateTextFile(to_file.value(), kTextContent1);
344   ASSERT_TRUE(base::PathExists(to_file));
345
346   // Run the executable in source path
347   STARTUPINFOW si = {sizeof(si)};
348   PROCESS_INFORMATION pi = {0};
349   ASSERT_TRUE(::CreateProcess(NULL,
350                               const_cast<wchar_t*>(from_file.value().c_str()),
351                               NULL, NULL, FALSE,
352                               CREATE_NO_WINDOW | CREATE_SUSPENDED,
353                               NULL, NULL, &si, &pi));
354
355   // test Do()
356   scoped_ptr<MoveTreeWorkItem> work_item(
357       WorkItem::CreateMoveTreeWorkItem(from_file,
358                                        to_file,
359                                        temp_to_dir_.path(),
360                                        WorkItem::ALWAYS_MOVE));
361   EXPECT_TRUE(work_item->Do());
362
363   EXPECT_TRUE(base::PathExists(from_dir));
364   EXPECT_FALSE(base::PathExists(from_file));
365   EXPECT_TRUE(base::PathExists(to_dir));
366   EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file));
367
368   // Close the process and make sure all the conditions after Do() are
369   // still true.
370   TerminateProcess(pi.hProcess, 0);
371   EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
372   CloseHandle(pi.hProcess);
373   CloseHandle(pi.hThread);
374
375   EXPECT_TRUE(base::PathExists(from_dir));
376   EXPECT_FALSE(base::PathExists(from_file));
377   EXPECT_TRUE(base::PathExists(to_dir));
378   EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file));
379
380   // test rollback()
381   work_item->Rollback();
382
383   EXPECT_TRUE(base::PathExists(from_dir));
384   EXPECT_TRUE(base::ContentsEqual(exe_full_path, from_file));
385   EXPECT_TRUE(base::PathExists(to_dir));
386   EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1));
387 }
388
389 // Move one directory from source to destination when destination already
390 // exists.
391 TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExistsCheckForDuplicatesFull) {
392   // Create two level deep source dir
393   base::FilePath from_dir1(temp_from_dir_.path());
394   from_dir1 = from_dir1.AppendASCII("From_Dir1");
395   base::CreateDirectory(from_dir1);
396   ASSERT_TRUE(base::PathExists(from_dir1));
397
398   base::FilePath from_dir2(from_dir1);
399   from_dir2 = from_dir2.AppendASCII("From_Dir2");
400   base::CreateDirectory(from_dir2);
401   ASSERT_TRUE(base::PathExists(from_dir2));
402
403   base::FilePath from_file(from_dir2);
404   from_file = from_file.AppendASCII("From_File");
405   CreateTextFile(from_file.value(), kTextContent1);
406   ASSERT_TRUE(base::PathExists(from_file));
407
408   // // Create a file hierarchy identical to the one in the source directory.
409   base::FilePath to_dir(temp_from_dir_.path());
410   to_dir = to_dir.AppendASCII("To_Dir");
411   ASSERT_TRUE(installer::test::CopyFileHierarchy(from_dir1, to_dir));
412
413   // Lock one of the files in the to destination directory to prevent moves.
414   base::FilePath orig_to_file(
415       to_dir.AppendASCII("From_Dir2").AppendASCII("From_File"));
416   base::MemoryMappedFile mapped_file;
417   EXPECT_TRUE(mapped_file.Initialize(orig_to_file));
418
419   // First check that we can't do the regular Move().
420   scoped_ptr<MoveTreeWorkItem> work_item(
421       WorkItem::CreateMoveTreeWorkItem(from_dir1,
422                                        to_dir,
423                                        temp_to_dir_.path(),
424                                        WorkItem::ALWAYS_MOVE));
425   EXPECT_FALSE(work_item->Do());
426   work_item->Rollback();
427
428   // Now test Do() with the check for duplicates. This should pass.
429   work_item.reset(
430       WorkItem::CreateMoveTreeWorkItem(from_dir1,
431                                        to_dir,
432                                        temp_to_dir_.path(),
433                                        WorkItem::CHECK_DUPLICATES));
434   EXPECT_TRUE(work_item->Do());
435
436   // Make sure that we "moved" the files, i.e. that the source directory isn't
437   // there anymore,
438   EXPECT_FALSE(base::PathExists(from_dir1));
439   // Make sure that the original directory structure and file are still present.
440   EXPECT_TRUE(base::PathExists(to_dir));
441   EXPECT_TRUE(base::PathExists(orig_to_file));
442   // Make sure that the backup path is not empty.
443   EXPECT_FALSE(base::IsDirectoryEmpty(temp_to_dir_.path()));
444
445   // Check that the work item believes the source to have been moved.
446   EXPECT_TRUE(work_item->source_moved_to_backup_);
447   EXPECT_FALSE(work_item->moved_to_dest_path_);
448   EXPECT_FALSE(work_item->moved_to_backup_);
449
450   // test rollback()
451   work_item->Rollback();
452
453   // Once we rollback all the original files should still be there, as should
454   // the source files.
455   EXPECT_TRUE(base::PathExists(from_dir1));
456   EXPECT_TRUE(base::PathExists(to_dir));
457   EXPECT_TRUE(base::PathExists(orig_to_file));
458   EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent1));
459   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
460 }
461
462 // Move one directory from source to destination when destination already
463 // exists but contains only a subset of the files in source.
464 TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExistsCheckForDuplicatesPartial) {
465   // Create two level deep source dir
466   base::FilePath from_dir1(temp_from_dir_.path());
467   from_dir1 = from_dir1.AppendASCII("From_Dir1");
468   base::CreateDirectory(from_dir1);
469   ASSERT_TRUE(base::PathExists(from_dir1));
470
471   base::FilePath from_dir2(from_dir1);
472   from_dir2 = from_dir2.AppendASCII("From_Dir2");
473   base::CreateDirectory(from_dir2);
474   ASSERT_TRUE(base::PathExists(from_dir2));
475
476   base::FilePath from_file(from_dir2);
477   from_file = from_file.AppendASCII("From_File");
478   CreateTextFile(from_file.value(), kTextContent1);
479   ASSERT_TRUE(base::PathExists(from_file));
480
481   base::FilePath from_file2(from_dir2);
482   from_file2 = from_file2.AppendASCII("From_File2");
483   CreateTextFile(from_file2.value(), kTextContent2);
484   ASSERT_TRUE(base::PathExists(from_file2));
485
486   // Create destination path
487   base::FilePath to_dir(temp_from_dir_.path());
488   to_dir = to_dir.AppendASCII("To_Dir");
489   base::CreateDirectory(to_dir);
490   ASSERT_TRUE(base::PathExists(to_dir));
491
492   // Create a sub-directory of the same name as in the source directory.
493   base::FilePath to_dir2(to_dir);
494   to_dir2 = to_dir2.AppendASCII("From_Dir2");
495   base::CreateDirectory(to_dir2);
496   ASSERT_TRUE(base::PathExists(to_dir2));
497
498   // Create one of the files in the to sub-directory, but not the other.
499   base::FilePath orig_to_file(to_dir2);
500   orig_to_file = orig_to_file.AppendASCII("From_File");
501   CreateTextFile(orig_to_file.value(), kTextContent1);
502   ASSERT_TRUE(base::PathExists(orig_to_file));
503
504   // test Do(), check for duplicates.
505   scoped_ptr<MoveTreeWorkItem> work_item(
506       WorkItem::CreateMoveTreeWorkItem(from_dir1,
507                                        to_dir,
508                                        temp_to_dir_.path(),
509                                        WorkItem::CHECK_DUPLICATES));
510   EXPECT_TRUE(work_item->Do());
511
512   // Make sure that we "moved" the files, i.e. that the source directory isn't
513   // there anymore,
514   EXPECT_FALSE(base::PathExists(from_dir1));
515   // Make sure that the original directory structure and file are still present.
516   EXPECT_TRUE(base::PathExists(to_dir));
517   EXPECT_TRUE(base::PathExists(orig_to_file));
518   // Make sure that the backup path is not empty.
519   EXPECT_FALSE(base::IsDirectoryEmpty(temp_to_dir_.path()));
520   // Make sure that the "new" file is also present.
521   base::FilePath new_to_file2(to_dir2);
522   new_to_file2 = new_to_file2.AppendASCII("From_File2");
523   EXPECT_TRUE(base::PathExists(new_to_file2));
524
525   // Check that the work item believes that this was a regular move.
526   EXPECT_FALSE(work_item->source_moved_to_backup_);
527   EXPECT_TRUE(work_item->moved_to_dest_path_);
528   EXPECT_TRUE(work_item->moved_to_backup_);
529
530   // test rollback()
531   work_item->Rollback();
532
533   // Once we rollback all the original files should still be there, as should
534   // the source files.
535   EXPECT_TRUE(base::PathExists(from_dir1));
536   EXPECT_TRUE(base::PathExists(to_dir));
537   EXPECT_TRUE(base::PathExists(orig_to_file));
538   EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent1));
539   EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1));
540
541   // Also, after rollback the new "to" file should be gone.
542   EXPECT_FALSE(base::PathExists(new_to_file2));
543 }