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