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); |
+} |