MacViews: Get c/b/ui/views/tabs to build on Mac
[chromium-blink-merge.git] / chrome / installer / util / move_tree_work_item_unittest.cc
blob2165cd79853610540d1fe027fbef94d28599c654
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.
5 #include <windows.h>
7 #include <fstream>
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"
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());
29 base::ScopedTempDir temp_from_dir_;
30 base::ScopedTempDir temp_to_dir_;
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();
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);
54 const wchar_t kTextContent1[] = L"Gooooooooooooooooooooogle";
55 const wchar_t kTextContent2[] = L"Overwrite Me";
56 }; // namespace
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));
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));
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));
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));
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));
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());
95 EXPECT_FALSE(base::PathExists(from_dir1));
96 EXPECT_TRUE(base::PathExists(to_dir));
97 EXPECT_TRUE(base::PathExists(to_file));
99 // test rollback()
100 work_item->Rollback();
102 EXPECT_TRUE(base::PathExists(from_dir1));
103 EXPECT_TRUE(base::PathExists(from_file));
104 EXPECT_FALSE(base::PathExists(to_dir));
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));
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));
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));
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));
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));
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));
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());
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));
155 // test rollback()
156 work_item->Rollback();
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));
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));
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));
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));
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());
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));
198 // test rollback()
199 work_item->Rollback();
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));
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));
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));
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));
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));
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());
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));
246 // test rollback()
247 work_item->Rollback();
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));
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));
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));
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));
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));
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));
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());
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));
305 // test rollback()
306 work_item->Rollback();
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));
313 TerminateProcess(pi.hProcess, 0);
314 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0);
315 CloseHandle(pi.hProcess);
316 CloseHandle(pi.hThread);
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));
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));
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));
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));
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));
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());
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));
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);
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));
380 // test rollback()
381 work_item->Rollback();
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));
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));
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));
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));
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));
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));
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();
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());
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()));
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_);
450 // test rollback()
451 work_item->Rollback();
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));
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));
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));
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));
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));
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));
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));
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));
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());
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));
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_);
530 // test rollback()
531 work_item->Rollback();
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));
541 // Also, after rollback the new "to" file should be gone.
542 EXPECT_FALSE(base::PathExists(new_to_file2));