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. 4 5#include <windows.h> 6 7#include "base/files/file_path.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/strings/string_util.h" 10#include "base/win/registry.h" 11#include "chrome/installer/util/create_reg_key_work_item.h" 12#include "chrome/installer/util/work_item.h" 13#include "testing/gtest/include/gtest/gtest.h" 14 15using base::win::RegKey; 16 17namespace { 18 19wchar_t test_root[] = L"TmpTmp"; 20 21class CreateRegKeyWorkItemTest : public testing::Test { 22 protected: 23 virtual void SetUp() { 24 // Create a temporary key for testing 25 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); 26 key.DeleteKey(test_root); 27 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, test_root, KEY_READ)); 28 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, test_root, 29 KEY_READ)); 30 } 31 virtual void TearDown() { 32 logging::CloseLogFile(); 33 // Clean up the temporary key 34 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); 35 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(test_root)); 36 } 37}; 38 39} // namespace 40 41TEST_F(CreateRegKeyWorkItemTest, CreateKey) { 42 RegKey key; 43 44 base::FilePath parent_key(test_root); 45 parent_key = parent_key.AppendASCII("a"); 46 ASSERT_EQ(ERROR_SUCCESS, 47 key.Create(HKEY_CURRENT_USER, parent_key.value().c_str(), KEY_READ)); 48 49 base::FilePath top_key_to_create(parent_key); 50 top_key_to_create = top_key_to_create.AppendASCII("b"); 51 52 base::FilePath key_to_create(top_key_to_create); 53 key_to_create = key_to_create.AppendASCII("c"); 54 key_to_create = key_to_create.AppendASCII("d"); 55 56 scoped_ptr<CreateRegKeyWorkItem> work_item( 57 WorkItem::CreateCreateRegKeyWorkItem( 58 HKEY_CURRENT_USER, key_to_create.value(), WorkItem::kWow64Default)); 59 60 EXPECT_TRUE(work_item->Do()); 61 62 EXPECT_EQ(ERROR_SUCCESS, 63 key.Open(HKEY_CURRENT_USER, key_to_create.value().c_str(), KEY_READ)); 64 65 work_item->Rollback(); 66 67 // Rollback should delete all the keys up to top_key_to_create. 68 EXPECT_NE(ERROR_SUCCESS, 69 key.Open(HKEY_CURRENT_USER, top_key_to_create.value().c_str(), KEY_READ)); 70 EXPECT_EQ(ERROR_SUCCESS, 71 key.Open(HKEY_CURRENT_USER, parent_key.value().c_str(), KEY_READ)); 72} 73 74TEST_F(CreateRegKeyWorkItemTest, CreateExistingKey) { 75 RegKey key; 76 77 base::FilePath key_to_create(test_root); 78 key_to_create = key_to_create.AppendASCII("aa"); 79 ASSERT_EQ(ERROR_SUCCESS, 80 key.Create(HKEY_CURRENT_USER, key_to_create.value().c_str(), KEY_READ)); 81 82 scoped_ptr<CreateRegKeyWorkItem> work_item( 83 WorkItem::CreateCreateRegKeyWorkItem( 84 HKEY_CURRENT_USER, key_to_create.value(), WorkItem::kWow64Default)); 85 86 EXPECT_TRUE(work_item->Do()); 87 88 EXPECT_EQ(ERROR_SUCCESS, 89 key.Open(HKEY_CURRENT_USER, key_to_create.value().c_str(), KEY_READ)); 90 91 work_item->Rollback(); 92 93 // Rollback should not remove the key since it exists before 94 // the CreateRegKeyWorkItem is called. 95 EXPECT_EQ(ERROR_SUCCESS, 96 key.Open(HKEY_CURRENT_USER, key_to_create.value().c_str(), KEY_READ)); 97} 98 99TEST_F(CreateRegKeyWorkItemTest, CreateSharedKey) { 100 RegKey key; 101 base::FilePath key_to_create_1(test_root); 102 key_to_create_1 = key_to_create_1.AppendASCII("aaa"); 103 104 base::FilePath key_to_create_2(key_to_create_1); 105 key_to_create_2 = key_to_create_2.AppendASCII("bbb"); 106 107 base::FilePath key_to_create_3(key_to_create_2); 108 key_to_create_3 = key_to_create_3.AppendASCII("ccc"); 109 110 scoped_ptr<CreateRegKeyWorkItem> work_item( 111 WorkItem::CreateCreateRegKeyWorkItem( 112 HKEY_CURRENT_USER, key_to_create_3.value(), WorkItem::kWow64Default)); 113 114 EXPECT_TRUE(work_item->Do()); 115 116 EXPECT_EQ(ERROR_SUCCESS, 117 key.Open(HKEY_CURRENT_USER, key_to_create_3.value().c_str(), KEY_READ)); 118 119 // Create another key under key_to_create_2 120 base::FilePath key_to_create_4(key_to_create_2); 121 key_to_create_4 = key_to_create_4.AppendASCII("ddd"); 122 ASSERT_EQ(ERROR_SUCCESS, 123 key.Create(HKEY_CURRENT_USER, key_to_create_4.value().c_str(), KEY_READ)); 124 125 work_item->Rollback(); 126 127 // Rollback should delete key_to_create_3. 128 EXPECT_NE(ERROR_SUCCESS, 129 key.Open(HKEY_CURRENT_USER, key_to_create_3.value().c_str(), KEY_READ)); 130 131 // Rollback should not delete key_to_create_2 as it is shared. 132 EXPECT_EQ(ERROR_SUCCESS, 133 key.Open(HKEY_CURRENT_USER, key_to_create_2.value().c_str(), KEY_READ)); 134 EXPECT_EQ(ERROR_SUCCESS, 135 key.Open(HKEY_CURRENT_USER, key_to_create_4.value().c_str(), KEY_READ)); 136} 137 138TEST_F(CreateRegKeyWorkItemTest, RollbackWithMissingKey) { 139 RegKey key; 140 base::FilePath key_to_create_1(test_root); 141 key_to_create_1 = key_to_create_1.AppendASCII("aaaa"); 142 143 base::FilePath key_to_create_2(key_to_create_1); 144 key_to_create_2 = key_to_create_2.AppendASCII("bbbb"); 145 146 base::FilePath key_to_create_3(key_to_create_2); 147 key_to_create_3 = key_to_create_3.AppendASCII("cccc"); 148 149 scoped_ptr<CreateRegKeyWorkItem> work_item( 150 WorkItem::CreateCreateRegKeyWorkItem( 151 HKEY_CURRENT_USER, key_to_create_3.value(), WorkItem::kWow64Default)); 152 153 EXPECT_TRUE(work_item->Do()); 154 155 EXPECT_EQ(ERROR_SUCCESS, 156 key.Open(HKEY_CURRENT_USER, key_to_create_3.value().c_str(), KEY_READ)); 157 key.Close(); 158 159 // now delete key_to_create_3 160 ASSERT_EQ(ERROR_SUCCESS, 161 RegDeleteKey(HKEY_CURRENT_USER, key_to_create_3.value().c_str())); 162 ASSERT_NE(ERROR_SUCCESS, 163 key.Open(HKEY_CURRENT_USER, key_to_create_3.value().c_str(), KEY_READ)); 164 165 work_item->Rollback(); 166 167 // key_to_create_3 has already been deleted, Rollback should delete 168 // the rest. 169 ASSERT_NE(ERROR_SUCCESS, 170 key.Open(HKEY_CURRENT_USER, key_to_create_1.value().c_str(), KEY_READ)); 171} 172 173TEST_F(CreateRegKeyWorkItemTest, RollbackWithSetValue) { 174 RegKey key; 175 176 base::FilePath key_to_create(test_root); 177 key_to_create = key_to_create.AppendASCII("aaaaa"); 178 179 scoped_ptr<CreateRegKeyWorkItem> work_item( 180 WorkItem::CreateCreateRegKeyWorkItem( 181 HKEY_CURRENT_USER, key_to_create.value(), WorkItem::kWow64Default)); 182 183 EXPECT_TRUE(work_item->Do()); 184 185 // Write a value under the key we just created. 186 EXPECT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, 187 key_to_create.value().c_str(), KEY_READ | KEY_SET_VALUE)); 188 EXPECT_EQ(ERROR_SUCCESS, key.WriteValue(L"name", L"value")); 189 key.Close(); 190 191 work_item->Rollback(); 192 193 // Rollback should not remove the key. 194 EXPECT_EQ(ERROR_SUCCESS, 195 key.Open(HKEY_CURRENT_USER, key_to_create.value().c_str(), KEY_READ)); 196} 197