// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

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

#include "base/logging.h"
#include "base/win/registry.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::win::RegKey;

RegistryTestData::RegistryTestData()
    : root_key_(NULL) {
}

RegistryTestData::~RegistryTestData() {
  Reset();
}

// static
bool RegistryTestData::DeleteKey(HKEY root_key, const wchar_t* path) {
  LONG result = ERROR_SUCCESS;
  if (root_key != NULL && path != NULL && *path != L'\0') {
    result = RegKey(root_key, L"", KEY_QUERY_VALUE).DeleteKey(path);
    if (result == ERROR_FILE_NOT_FOUND) {
      result = ERROR_SUCCESS;
    } else {
      DLOG_IF(DFATAL, result != ERROR_SUCCESS)
          << "Failed to delete registry key " << path << ", result: " << result;
    }
  }
  return result == ERROR_SUCCESS;
}

void RegistryTestData::Reset() {
  // Clean up behind a previous use (ignore failures).
  DeleteKey(root_key_, base_path_.c_str());

  // Forget state.
  root_key_ = NULL;
  base_path_.clear();
  empty_key_path_.clear();
  non_empty_key_path_.clear();
}

bool RegistryTestData::Initialize(HKEY root_key, const wchar_t* base_path) {
  LONG result = ERROR_SUCCESS;

  Reset();

  // Take over the new registry location.
  if (DeleteKey(root_key, base_path)) {
    // Take on the new values.
    root_key_ = root_key;
    base_path_.assign(base_path);

    // Create our data.
    empty_key_path_.assign(base_path_).append(L"\\EmptyKey");
    non_empty_key_path_.assign(base_path_).append(L"\\NonEmptyKey");

    RegKey key;

    result = key.Create(root_key_, empty_key_path_.c_str(), KEY_QUERY_VALUE);
    if (result == ERROR_SUCCESS)
      result = key.Create(root_key_, non_empty_key_path_.c_str(), KEY_WRITE);
    if (result == ERROR_SUCCESS)
      result = key.WriteValue(NULL, non_empty_key_path_.c_str());
    if (result == ERROR_SUCCESS)
      result = key.CreateKey(L"SubKey", KEY_WRITE);
    if (result == ERROR_SUCCESS)
      result = key.WriteValue(L"SomeValue", 1UL);
    DLOG_IF(DFATAL, result != ERROR_SUCCESS)
        << "Failed to create test registry data based at " << base_path_
        << ", result: " << result;
  } else {
    result = ERROR_INVALID_PARAMETER;
  }

  return result == ERROR_SUCCESS;
}

void RegistryTestData::ExpectMatchesNonEmptyKey(HKEY root_key,
                                                const wchar_t* path) {
  RegKey key;

  EXPECT_EQ(ERROR_SUCCESS, key.Open(root_key, path, KEY_READ));
  std::wstring str_value;
  EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(NULL, &str_value));
  EXPECT_EQ(non_empty_key_path_, str_value);
  EXPECT_EQ(ERROR_SUCCESS, key.OpenKey(L"Subkey", KEY_READ));
  DWORD dw_value = 0;
  EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(L"SomeValue", &dw_value));
  EXPECT_EQ(1UL, dw_value);
}

// static
void RegistryTestData::ExpectEmptyKey(HKEY root_key, const wchar_t* path) {
  DWORD num_subkeys = 0;
  DWORD num_values = 0;
  RegKey key;
  EXPECT_EQ(ERROR_SUCCESS, key.Open(root_key, path, KEY_READ));
  EXPECT_EQ(ERROR_SUCCESS,
            RegQueryInfoKey(key.Handle(), NULL, NULL, NULL, &num_subkeys,
                            NULL, NULL, &num_values, NULL, NULL, NULL, NULL));
  EXPECT_EQ(0UL, num_subkeys);
  EXPECT_EQ(0UL, num_values);
}