Home | History | Annotate | Download | only in util
      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