chromium/chrome/installer/util/delete_reg_value_work_item_unittest.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/installer/util/delete_reg_value_work_item.h"

#include <windows.h>

#include <memory>
#include <string>

#include "base/test/test_reg_util_win.h"
#include "base/win/registry.h"
#include "chrome/installer/util/work_item.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::win::RegKey;

namespace {

const wchar_t kTestKey[] = L"DeleteRegValueWorkItemTest";
const wchar_t kNameStr[] = L"name_str";
const wchar_t kNameDword[] = L"name_dword";

class DeleteRegValueWorkItemTest : public testing::Test {
 public:
  DeleteRegValueWorkItemTest(const DeleteRegValueWorkItemTest&) = delete;
  DeleteRegValueWorkItemTest& operator=(const DeleteRegValueWorkItemTest&) =
      delete;

 protected:
  DeleteRegValueWorkItemTest() {}

  void SetUp() override {
    ASSERT_NO_FATAL_FAILURE(
        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
  }

 private:
  registry_util::RegistryOverrideManager registry_override_manager_;
};

}  // namespace

// Delete a value. The value should get deleted after Do() and should be
// recreated after Rollback().
TEST_F(DeleteRegValueWorkItemTest, DeleteExistingValue) {
  RegKey key;
  ASSERT_EQ(ERROR_SUCCESS,
            key.Create(HKEY_CURRENT_USER, kTestKey, KEY_READ | KEY_WRITE));
  const std::wstring data_str(L"data_111");
  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kNameStr, data_str.c_str()));
  const DWORD data_dword = 100;
  ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kNameDword, data_dword));

  static const wchar_t kNameEmpty[](L"name_empty");
  ASSERT_EQ(ERROR_SUCCESS,
            RegSetValueEx(key.Handle(), kNameEmpty, 0, REG_SZ, nullptr, 0));

  std::unique_ptr<DeleteRegValueWorkItem> work_item1(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameStr));
  std::unique_ptr<DeleteRegValueWorkItem> work_item2(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameDword));
  std::unique_ptr<DeleteRegValueWorkItem> work_item3(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameEmpty));

  EXPECT_TRUE(key.HasValue(kNameStr));
  EXPECT_TRUE(key.HasValue(kNameDword));
  EXPECT_TRUE(key.HasValue(kNameEmpty));

  EXPECT_TRUE(work_item1->Do());
  EXPECT_TRUE(work_item2->Do());
  EXPECT_TRUE(work_item3->Do());

  EXPECT_FALSE(key.HasValue(kNameStr));
  EXPECT_FALSE(key.HasValue(kNameDword));
  EXPECT_FALSE(key.HasValue(kNameEmpty));

  work_item1->Rollback();
  work_item2->Rollback();
  work_item3->Rollback();

  EXPECT_TRUE(key.HasValue(kNameStr));
  EXPECT_TRUE(key.HasValue(kNameDword));
  EXPECT_TRUE(key.HasValue(kNameEmpty));

  std::wstring read_str;
  DWORD read_dword;
  EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(kNameStr, &read_str));
  EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(kNameDword, &read_dword));
  EXPECT_EQ(read_str, data_str);
  EXPECT_EQ(read_dword, data_dword);

  // Verify empty value.
  DWORD type = 0;
  DWORD size = 0;
  EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(kNameEmpty, nullptr, &size, &type));
  EXPECT_EQ(static_cast<DWORD>(REG_SZ), type);
  EXPECT_EQ(0u, size);
}

// Try deleting a value that doesn't exist.
TEST_F(DeleteRegValueWorkItemTest, DeleteNonExistentValue) {
  RegKey key;
  ASSERT_EQ(ERROR_SUCCESS,
            key.Create(HKEY_CURRENT_USER, kTestKey, KEY_READ | KEY_WRITE));
  EXPECT_FALSE(key.HasValue(kNameStr));
  EXPECT_FALSE(key.HasValue(kNameDword));

  std::unique_ptr<DeleteRegValueWorkItem> work_item1(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameStr));
  std::unique_ptr<DeleteRegValueWorkItem> work_item2(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameDword));

  EXPECT_TRUE(work_item1->Do());
  EXPECT_TRUE(work_item2->Do());

  EXPECT_FALSE(key.HasValue(kNameStr));
  EXPECT_FALSE(key.HasValue(kNameDword));

  work_item1->Rollback();
  work_item2->Rollback();

  EXPECT_FALSE(key.HasValue(kNameStr));
  EXPECT_FALSE(key.HasValue(kNameDword));
}

// Try deleting a value whose key doesn't even exist.
TEST_F(DeleteRegValueWorkItemTest, DeleteValueInNonExistentKey) {
  RegKey key;
  // Confirm the key doesn't exist.
  ASSERT_EQ(ERROR_FILE_NOT_FOUND,
            key.Open(HKEY_CURRENT_USER, kTestKey, KEY_READ));

  std::unique_ptr<DeleteRegValueWorkItem> work_item1(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameStr));
  std::unique_ptr<DeleteRegValueWorkItem> work_item2(
      WorkItem::CreateDeleteRegValueWorkItem(
          HKEY_CURRENT_USER, kTestKey, WorkItem::kWow64Default, kNameDword));

  EXPECT_TRUE(work_item1->Do());
  EXPECT_TRUE(work_item2->Do());

  EXPECT_EQ(ERROR_FILE_NOT_FOUND,
            key.Open(HKEY_CURRENT_USER, kTestKey, KEY_READ));

  work_item1->Rollback();
  work_item2->Rollback();

  EXPECT_EQ(ERROR_FILE_NOT_FOUND,
            key.Open(HKEY_CURRENT_USER, kTestKey, KEY_READ));
}