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 "base/base_paths.h" 8 #include "base/files/file_util.h" 9 #include "base/files/scoped_temp_dir.h" 10 #include "base/memory/scoped_ptr.h" 11 #include "base/path_service.h" 12 #include "base/strings/string_util.h" 13 #include "base/test/test_reg_util_win.h" 14 #include "base/win/registry.h" 15 #include "chrome/installer/util/conditional_work_item_list.h" 16 #include "chrome/installer/util/work_item.h" 17 #include "chrome/installer/util/work_item_list.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 using base::win::RegKey; 21 22 namespace { 23 24 const wchar_t kTestRoot[] = L"ListList"; 25 const wchar_t kDataStr[] = L"data_111"; 26 const wchar_t kName[] = L"name"; 27 28 class WorkItemListTest : public testing::Test { 29 protected: 30 virtual void SetUp() { 31 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 32 registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER); 33 } 34 35 virtual void TearDown() { 36 logging::CloseLogFile(); 37 } 38 39 base::ScopedTempDir temp_dir_; 40 registry_util::RegistryOverrideManager registry_override_manager_; 41 }; 42 43 } // namespace 44 45 // Execute a WorkItem list successfully and then rollback. 46 TEST_F(WorkItemListTest, ExecutionSuccess) { 47 scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); 48 scoped_ptr<WorkItem> work_item; 49 50 base::FilePath top_dir_to_create(temp_dir_.path()); 51 top_dir_to_create = top_dir_to_create.AppendASCII("a"); 52 base::FilePath dir_to_create(top_dir_to_create); 53 dir_to_create = dir_to_create.AppendASCII("b"); 54 ASSERT_FALSE(base::PathExists(dir_to_create)); 55 56 work_item.reset(reinterpret_cast<WorkItem*>( 57 WorkItem::CreateCreateDirWorkItem(dir_to_create))); 58 work_item_list->AddWorkItem(work_item.release()); 59 60 std::wstring key_to_create(kTestRoot); 61 key_to_create.push_back(base::FilePath::kSeparators[0]); 62 key_to_create.append(L"ExecutionSuccess"); 63 64 work_item.reset( 65 reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem( 66 HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default))); 67 work_item_list->AddWorkItem(work_item.release()); 68 69 std::wstring name(kName); 70 std::wstring data(kDataStr); 71 work_item.reset(reinterpret_cast<WorkItem*>( 72 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 73 key_to_create, 74 WorkItem::kWow64Default, 75 name, 76 data, 77 false))); 78 work_item_list->AddWorkItem(work_item.release()); 79 80 EXPECT_TRUE(work_item_list->Do()); 81 82 // Verify all WorkItems have been executed. 83 RegKey key; 84 EXPECT_EQ(ERROR_SUCCESS, 85 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 86 std::wstring read_out; 87 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 88 EXPECT_EQ(0, read_out.compare(kDataStr)); 89 key.Close(); 90 EXPECT_TRUE(base::PathExists(dir_to_create)); 91 92 work_item_list->Rollback(); 93 94 // Verify everything is rolled back. 95 // The value must have been deleted first in roll back otherwise the key 96 // can not be deleted. 97 EXPECT_NE(ERROR_SUCCESS, 98 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 99 EXPECT_FALSE(base::PathExists(top_dir_to_create)); 100 } 101 102 // Execute a WorkItem list. Fail in the middle. Rollback what has been done. 103 TEST_F(WorkItemListTest, ExecutionFailAndRollback) { 104 scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); 105 scoped_ptr<WorkItem> work_item; 106 107 base::FilePath top_dir_to_create(temp_dir_.path()); 108 top_dir_to_create = top_dir_to_create.AppendASCII("a"); 109 base::FilePath dir_to_create(top_dir_to_create); 110 dir_to_create = dir_to_create.AppendASCII("b"); 111 ASSERT_FALSE(base::PathExists(dir_to_create)); 112 113 work_item.reset(reinterpret_cast<WorkItem*>( 114 WorkItem::CreateCreateDirWorkItem(dir_to_create))); 115 work_item_list->AddWorkItem(work_item.release()); 116 117 std::wstring key_to_create(kTestRoot); 118 key_to_create.push_back(base::FilePath::kSeparators[0]); 119 key_to_create.append(L"ExecutionFail"); 120 121 work_item.reset( 122 reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem( 123 HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default))); 124 work_item_list->AddWorkItem(work_item.release()); 125 126 std::wstring not_created_key(kTestRoot); 127 not_created_key.push_back(base::FilePath::kSeparators[0]); 128 not_created_key.append(L"NotCreated"); 129 std::wstring name(kName); 130 std::wstring data(kDataStr); 131 work_item.reset(reinterpret_cast<WorkItem*>( 132 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 133 not_created_key, 134 WorkItem::kWow64Default, 135 name, 136 data, 137 false))); 138 work_item_list->AddWorkItem(work_item.release()); 139 140 // This one will not be executed because we will fail early. 141 work_item.reset( 142 reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem( 143 HKEY_CURRENT_USER, not_created_key, WorkItem::kWow64Default))); 144 work_item_list->AddWorkItem(work_item.release()); 145 146 EXPECT_FALSE(work_item_list->Do()); 147 148 // Verify the first 2 WorkItems have been executed. 149 RegKey key; 150 EXPECT_EQ(ERROR_SUCCESS, 151 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 152 key.Close(); 153 EXPECT_TRUE(base::PathExists(dir_to_create)); 154 // The last one should not be there. 155 EXPECT_NE(ERROR_SUCCESS, 156 key.Open(HKEY_CURRENT_USER, not_created_key.c_str(), KEY_READ)); 157 158 work_item_list->Rollback(); 159 160 // Verify everything is rolled back. 161 EXPECT_NE(ERROR_SUCCESS, 162 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 163 EXPECT_FALSE(base::PathExists(top_dir_to_create)); 164 } 165 166 TEST_F(WorkItemListTest, ConditionalExecutionSuccess) { 167 scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); 168 scoped_ptr<WorkItem> work_item; 169 170 base::FilePath top_dir_to_create(temp_dir_.path()); 171 top_dir_to_create = top_dir_to_create.AppendASCII("a"); 172 base::FilePath dir_to_create(top_dir_to_create); 173 dir_to_create = dir_to_create.AppendASCII("b"); 174 ASSERT_FALSE(base::PathExists(dir_to_create)); 175 176 work_item.reset(reinterpret_cast<WorkItem*>( 177 WorkItem::CreateCreateDirWorkItem(dir_to_create))); 178 work_item_list->AddWorkItem(work_item.release()); 179 180 scoped_ptr<WorkItemList> conditional_work_item_list( 181 WorkItem::CreateConditionalWorkItemList( 182 new ConditionRunIfFileExists(dir_to_create))); 183 184 std::wstring key_to_create(kTestRoot); 185 key_to_create.push_back(base::FilePath::kSeparators[0]); 186 key_to_create.append(L"ExecutionSuccess"); 187 work_item.reset( 188 reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem( 189 HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default))); 190 conditional_work_item_list->AddWorkItem(work_item.release()); 191 192 std::wstring name(kName); 193 std::wstring data(kDataStr); 194 work_item.reset(reinterpret_cast<WorkItem*>( 195 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 196 key_to_create, 197 WorkItem::kWow64Default, 198 name, 199 data, 200 false))); 201 conditional_work_item_list->AddWorkItem(work_item.release()); 202 203 work_item_list->AddWorkItem(conditional_work_item_list.release()); 204 205 EXPECT_TRUE(work_item_list->Do()); 206 207 // Verify all WorkItems have been executed. 208 RegKey key; 209 EXPECT_EQ(ERROR_SUCCESS, 210 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 211 std::wstring read_out; 212 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 213 EXPECT_EQ(0, read_out.compare(kDataStr)); 214 key.Close(); 215 EXPECT_TRUE(base::PathExists(dir_to_create)); 216 217 work_item_list->Rollback(); 218 219 // Verify everything is rolled back. 220 // The value must have been deleted first in roll back otherwise the key 221 // can not be deleted. 222 EXPECT_NE(ERROR_SUCCESS, 223 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 224 EXPECT_FALSE(base::PathExists(top_dir_to_create)); 225 } 226 227 TEST_F(WorkItemListTest, ConditionalExecutionConditionFailure) { 228 scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList()); 229 scoped_ptr<WorkItem> work_item; 230 231 base::FilePath top_dir_to_create(temp_dir_.path()); 232 top_dir_to_create = top_dir_to_create.AppendASCII("a"); 233 base::FilePath dir_to_create(top_dir_to_create); 234 dir_to_create = dir_to_create.AppendASCII("b"); 235 ASSERT_FALSE(base::PathExists(dir_to_create)); 236 237 work_item.reset(reinterpret_cast<WorkItem*>( 238 WorkItem::CreateCreateDirWorkItem(dir_to_create))); 239 work_item_list->AddWorkItem(work_item.release()); 240 241 scoped_ptr<WorkItemList> conditional_work_item_list( 242 WorkItem::CreateConditionalWorkItemList( 243 new ConditionRunIfFileExists(dir_to_create.AppendASCII("c")))); 244 245 std::wstring key_to_create(kTestRoot); 246 key_to_create.push_back(base::FilePath::kSeparators[0]); 247 key_to_create.append(L"ExecutionSuccess"); 248 work_item.reset( 249 reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem( 250 HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default))); 251 conditional_work_item_list->AddWorkItem(work_item.release()); 252 253 std::wstring name(kName); 254 std::wstring data(kDataStr); 255 work_item.reset(reinterpret_cast<WorkItem*>( 256 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 257 key_to_create, 258 WorkItem::kWow64Default, 259 name, 260 data, 261 false))); 262 conditional_work_item_list->AddWorkItem(work_item.release()); 263 264 work_item_list->AddWorkItem(conditional_work_item_list.release()); 265 266 EXPECT_TRUE(work_item_list->Do()); 267 268 // Verify that the WorkItems added as part of the conditional list have NOT 269 // been executed. 270 RegKey key; 271 EXPECT_NE(ERROR_SUCCESS, 272 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 273 std::wstring read_out; 274 EXPECT_NE(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 275 key.Close(); 276 277 // Verify that the other work item was executed. 278 EXPECT_TRUE(base::PathExists(dir_to_create)); 279 280 work_item_list->Rollback(); 281 282 // Verify everything is rolled back. 283 // The value must have been deleted first in roll back otherwise the key 284 // can not be deleted. 285 EXPECT_NE(ERROR_SUCCESS, 286 key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ)); 287 EXPECT_FALSE(base::PathExists(top_dir_to_create)); 288 } 289