| Index: chrome/installer/util/delete_tree_work_item_unittest.cc
|
| diff --git a/chrome/installer/util/delete_tree_work_item_unittest.cc b/chrome/installer/util/delete_tree_work_item_unittest.cc
|
| index 43a456d65829b96d8cd3f5f89c4b449cc3eb54a8..cc7ae2d1a2a78e53a334bf4051381108ec61b800 100644
|
| --- a/chrome/installer/util/delete_tree_work_item_unittest.cc
|
| +++ b/chrome/installer/util/delete_tree_work_item_unittest.cc
|
| @@ -4,108 +4,230 @@
|
|
|
| #include "chrome/installer/util/delete_tree_work_item.h"
|
|
|
| +#include <windows.h>
|
| +
|
| +#include <fstream>
|
| #include <memory>
|
|
|
| -#include "base/files/file_path.h"
|
| +#include "base/base_paths.h"
|
| #include "base/files/file_util.h"
|
| #include "base/files/scoped_temp_dir.h"
|
| -#include "base/macros.h"
|
| +#include "base/logging.h"
|
| +#include "base/strings/string_util.h"
|
| #include "chrome/installer/util/work_item.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| namespace {
|
|
|
| -constexpr char kTextContent[] = "delete me";
|
| -
|
| class DeleteTreeWorkItemTest : public testing::Test {
|
| protected:
|
| - DeleteTreeWorkItemTest() = default;
|
| -
|
| - void SetUp() override {
|
| - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
|
| -
|
| - dir_name_ = temp_dir_.path().Append(FILE_PATH_LITERAL("to_be_deleted"));
|
| - ASSERT_TRUE(base::CreateDirectory(dir_name_));
|
| - ASSERT_TRUE(base::PathExists(dir_name_));
|
| -
|
| - dir_name_1_ = dir_name_.Append(FILE_PATH_LITERAL("1"));
|
| - ASSERT_TRUE(base::CreateDirectory(dir_name_1_));
|
| - ASSERT_TRUE(base::PathExists(dir_name_1_));
|
| -
|
| - dir_name_2_ = dir_name_.Append(FILE_PATH_LITERAL("2"));
|
| - ASSERT_TRUE(base::CreateDirectory(dir_name_2_));
|
| - ASSERT_TRUE(base::PathExists(dir_name_2_));
|
| -
|
| - file_name_1_ = dir_name_1_.Append(FILE_PATH_LITERAL("File_1.txt"));
|
| - ASSERT_TRUE(
|
| - base::WriteFile(file_name_1_, kTextContent, sizeof(kTextContent)));
|
| - ASSERT_TRUE(base::PathExists(file_name_1_));
|
| -
|
| - file_name_2_ = dir_name_2_.Append(FILE_PATH_LITERAL("File_2.txt"));
|
| - ASSERT_TRUE(
|
| - base::WriteFile(file_name_2_, kTextContent, sizeof(kTextContent)));
|
| - ASSERT_TRUE(base::PathExists(file_name_2_));
|
| - }
|
| -
|
| - void ExpectAllFilesExist() {
|
| - EXPECT_TRUE(base::PathExists(dir_name_));
|
| - EXPECT_TRUE(base::PathExists(dir_name_1_));
|
| - EXPECT_TRUE(base::PathExists(dir_name_2_));
|
| - EXPECT_TRUE(base::PathExists(file_name_1_));
|
| - EXPECT_TRUE(base::PathExists(file_name_2_));
|
| - }
|
| -
|
| - void ExpectAllFilesDeleted() {
|
| - EXPECT_FALSE(base::PathExists(dir_name_));
|
| - EXPECT_FALSE(base::PathExists(dir_name_1_));
|
| - EXPECT_FALSE(base::PathExists(dir_name_2_));
|
| - EXPECT_FALSE(base::PathExists(file_name_1_));
|
| - EXPECT_FALSE(base::PathExists(file_name_2_));
|
| - }
|
| + void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
|
|
|
| // The temporary directory used to contain the test operations.
|
| base::ScopedTempDir temp_dir_;
|
| -
|
| - base::FilePath dir_name_;
|
| - base::FilePath dir_name_1_;
|
| - base::FilePath dir_name_2_;
|
| - base::FilePath file_name_1_;
|
| - base::FilePath file_name_2_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(DeleteTreeWorkItemTest);
|
| };
|
|
|
| +// Simple function to dump some text into a new file.
|
| +void CreateTextFile(const std::wstring& filename,
|
| + const std::wstring& contents) {
|
| + std::ofstream file;
|
| + file.open(filename.c_str());
|
| + ASSERT_TRUE(file.is_open());
|
| + file << contents;
|
| + file.close();
|
| +}
|
| +
|
| +const wchar_t text_content_1[] = L"delete me";
|
| +
|
| } // namespace
|
|
|
| -// Delete a tree with rollback enabled and no file in use. Do() should delete
|
| -// everything and Rollback() should bring back everything.
|
| -TEST_F(DeleteTreeWorkItemTest, Delete) {
|
| +// Delete a tree without key path. Everything should be deleted.
|
| +TEST_F(DeleteTreeWorkItemTest, DeleteTreeNoKeyPath) {
|
| + // Create tree to be deleted.
|
| + base::FilePath dir_name_delete(temp_dir_.path());
|
| + dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
|
| + base::CreateDirectory(dir_name_delete);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete));
|
| +
|
| + base::FilePath dir_name_delete_1(dir_name_delete);
|
| + dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
|
| + base::CreateDirectory(dir_name_delete_1);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_1));
|
| +
|
| + base::FilePath dir_name_delete_2(dir_name_delete);
|
| + dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
|
| + base::CreateDirectory(dir_name_delete_2);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_2));
|
| +
|
| + base::FilePath file_name_delete_1(dir_name_delete_1);
|
| + file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
|
| + CreateTextFile(file_name_delete_1.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_1));
|
| +
|
| + base::FilePath file_name_delete_2(dir_name_delete_2);
|
| + file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
|
| + CreateTextFile(file_name_delete_2.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_2));
|
| +
|
| + // Test Do().
|
| base::ScopedTempDir temp_dir;
|
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
|
|
| + std::vector<base::FilePath> key_files;
|
| std::unique_ptr<DeleteTreeWorkItem> work_item(
|
| - WorkItem::CreateDeleteTreeWorkItem(dir_name_, temp_dir.path()));
|
| -
|
| + WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
|
| + key_files));
|
| EXPECT_TRUE(work_item->Do());
|
| - ExpectAllFilesDeleted();
|
| +
|
| + // everything should be gone
|
| + EXPECT_FALSE(base::PathExists(file_name_delete_1));
|
| + EXPECT_FALSE(base::PathExists(file_name_delete_2));
|
| + EXPECT_FALSE(base::PathExists(dir_name_delete));
|
|
|
| work_item->Rollback();
|
| - ExpectAllFilesExist();
|
| -}
|
| -
|
| -// Delete a tree with rollback disabled and no file in use. Do() should delete
|
| -// everything and Rollback() shouldn't bring back anything.
|
| -TEST_F(DeleteTreeWorkItemTest, DeleteRollbackDisabled) {
|
| + // everything should come back
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_1));
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_2));
|
| + EXPECT_TRUE(base::PathExists(dir_name_delete));
|
| +}
|
| +
|
| +
|
| +// Delete a tree with keypath but not in use. Everything should be gone.
|
| +// Rollback should bring back everything
|
| +TEST_F(DeleteTreeWorkItemTest, DeleteTree) {
|
| + // Create tree to be deleted
|
| + base::FilePath dir_name_delete(temp_dir_.path());
|
| + dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
|
| + base::CreateDirectory(dir_name_delete);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete));
|
| +
|
| + base::FilePath dir_name_delete_1(dir_name_delete);
|
| + dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
|
| + base::CreateDirectory(dir_name_delete_1);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_1));
|
| +
|
| + base::FilePath dir_name_delete_2(dir_name_delete);
|
| + dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
|
| + base::CreateDirectory(dir_name_delete_2);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_2));
|
| +
|
| + base::FilePath file_name_delete_1(dir_name_delete_1);
|
| + file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
|
| + CreateTextFile(file_name_delete_1.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_1));
|
| +
|
| + base::FilePath file_name_delete_2(dir_name_delete_2);
|
| + file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
|
| + CreateTextFile(file_name_delete_2.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_2));
|
| +
|
| + // test Do()
|
| base::ScopedTempDir temp_dir;
|
| ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
|
|
| + std::vector<base::FilePath> key_files(1, file_name_delete_1);
|
| std::unique_ptr<DeleteTreeWorkItem> work_item(
|
| - WorkItem::CreateDeleteTreeWorkItem(dir_name_, temp_dir.path()));
|
| - work_item->set_rollback_enabled(false);
|
| -
|
| + WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
|
| + key_files));
|
| EXPECT_TRUE(work_item->Do());
|
| - ExpectAllFilesDeleted();
|
| +
|
| + // everything should be gone
|
| + EXPECT_FALSE(base::PathExists(file_name_delete_1));
|
| + EXPECT_FALSE(base::PathExists(file_name_delete_2));
|
| + EXPECT_FALSE(base::PathExists(dir_name_delete));
|
|
|
| work_item->Rollback();
|
| - ExpectAllFilesDeleted();
|
| -}
|
| + // everything should come back
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_1));
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_2));
|
| + EXPECT_TRUE(base::PathExists(dir_name_delete));
|
| +}
|
| +
|
| +// Delete a tree with key_path in use. Everything should still be there.
|
| +TEST_F(DeleteTreeWorkItemTest, DeleteTreeInUse) {
|
| + // Create tree to be deleted
|
| + base::FilePath dir_name_delete(temp_dir_.path());
|
| + dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
|
| + base::CreateDirectory(dir_name_delete);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete));
|
| +
|
| + base::FilePath dir_name_delete_1(dir_name_delete);
|
| + dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
|
| + base::CreateDirectory(dir_name_delete_1);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_1));
|
| +
|
| + base::FilePath dir_name_delete_2(dir_name_delete);
|
| + dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
|
| + base::CreateDirectory(dir_name_delete_2);
|
| + ASSERT_TRUE(base::PathExists(dir_name_delete_2));
|
| +
|
| + base::FilePath file_name_delete_1(dir_name_delete_1);
|
| + file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
|
| + CreateTextFile(file_name_delete_1.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_1));
|
| +
|
| + base::FilePath file_name_delete_2(dir_name_delete_2);
|
| + file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
|
| + CreateTextFile(file_name_delete_2.value(), text_content_1);
|
| + ASSERT_TRUE(base::PathExists(file_name_delete_2));
|
| +
|
| + // Create a key path file.
|
| + base::FilePath key_path(dir_name_delete);
|
| + key_path = key_path.AppendASCII("key_file.exe");
|
| +
|
| + wchar_t exe_full_path_str[MAX_PATH];
|
| + ::GetModuleFileNameW(NULL, exe_full_path_str, MAX_PATH);
|
| + base::FilePath exe_full_path(exe_full_path_str);
|
| +
|
| + base::CopyFile(exe_full_path, key_path);
|
| + ASSERT_TRUE(base::PathExists(key_path));
|
| +
|
| + VLOG(1) << "copy ourself from " << exe_full_path.value()
|
| + << " to " << key_path.value();
|
| +
|
| + // Run the key path file to keep it in use.
|
| + STARTUPINFOW si = {sizeof(si)};
|
| + PROCESS_INFORMATION pi = {0};
|
| + base::FilePath::StringType writable_key_path = key_path.value();
|
| + ASSERT_TRUE(
|
| + ::CreateProcessW(NULL, &writable_key_path[0],
|
| + NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
|
| + NULL, NULL, &si, &pi));
|
| +
|
| + // test Do().
|
| + {
|
| + base::ScopedTempDir temp_dir;
|
| + ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
| +
|
| + std::vector<base::FilePath> key_paths(1, key_path);
|
| + std::unique_ptr<DeleteTreeWorkItem> work_item(
|
| + WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
|
| + key_paths));
|
| +
|
| + // delete should fail as file in use.
|
| + EXPECT_FALSE(work_item->Do());
|
| + }
|
| +
|
| + {
|
| + base::ScopedTempDir temp_dir;
|
| + ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
|
| +
|
| + // No key paths, the deletion should succeed.
|
| + std::vector<base::FilePath> key_paths;
|
| + std::unique_ptr<DeleteTreeWorkItem> work_item(
|
| + WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
|
| + key_paths));
|
| +
|
| + EXPECT_TRUE(work_item->Do());
|
| + work_item->Rollback();
|
| + }
|
| +
|
| + // verify everything is still there.
|
| + EXPECT_TRUE(base::PathExists(key_path));
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_1));
|
| + EXPECT_TRUE(base::PathExists(file_name_delete_2));
|
| +
|
| + TerminateProcess(pi.hProcess, 0);
|
| + // make sure the handle is closed.
|
| + WaitForSingleObject(pi.hProcess, INFINITE);
|
| +}
|
|
|