// Copyright (c) 2012 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. // // Main entry point for all unit tests. #include "rlz_test_helpers.h" #include <map> #include <vector> #include "base/strings/string16.h" #include "rlz/lib/rlz_lib.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_WIN) #include <shlwapi.h> #include "base/win/registry.h" #include "base/win/windows_version.h" #elif defined(OS_POSIX) #include "base/files/file_path.h" #include "rlz/lib/rlz_value_store.h" #endif #if defined(OS_WIN) namespace { // Path to recursively copy into the replacemment hives. These are needed // to make sure certain win32 APIs continue to run correctly once the real // hives are replaced. const wchar_t kHKLMAccessProviders[] = L"System\\CurrentControlSet\\Control\\Lsa\\AccessProviders"; struct RegistryValue { base::string16 name; DWORD type; std::vector<uint8> data; }; struct RegistryKeyData { std::vector<RegistryValue> values; std::map<base::string16, RegistryKeyData> keys; }; void ReadRegistryTree(const base::win::RegKey& src, RegistryKeyData* data) { // First read values. { base::win::RegistryValueIterator i(src.Handle(), L""); data->values.clear(); data->values.reserve(i.ValueCount()); for (; i.Valid(); ++i) { RegistryValue& value = *data->values.insert(data->values.end(), RegistryValue()); const uint8* data = reinterpret_cast<const uint8*>(i.Value()); value.name.assign(i.Name()); value.type = i.Type(); value.data.assign(data, data + i.ValueSize()); } } // Next read subkeys recursively. for (base::win::RegistryKeyIterator i(src.Handle(), L""); i.Valid(); ++i) { ReadRegistryTree(base::win::RegKey(src.Handle(), i.Name(), KEY_READ), &data->keys[base::string16(i.Name())]); } } void WriteRegistryTree(const RegistryKeyData& data, base::win::RegKey* dest) { // First write values. for (size_t i = 0; i < data.values.size(); ++i) { const RegistryValue& value = data.values[i]; dest->WriteValue(value.name.c_str(), value.data.size() ? &value.data[0] : NULL, static_cast<DWORD>(value.data.size()), value.type); } // Next write values recursively. for (std::map<base::string16, RegistryKeyData>::const_iterator iter = data.keys.begin(); iter != data.keys.end(); ++iter) { base::win::RegKey key(dest->Handle(), iter->first.c_str(), KEY_ALL_ACCESS); WriteRegistryTree(iter->second, &key); } } // Initialize temporary HKLM/HKCU registry hives used for testing. // Testing RLZ requires reading and writing to the Windows registry. To keep // the tests isolated from the machine's state, as well as to prevent the tests // from causing side effects in the registry, HKCU and HKLM are overridden for // the duration of the tests. RLZ tests don't expect the HKCU and KHLM hives to // be empty though, and this function initializes the minimum value needed so // that the test will run successfully. void InitializeRegistryOverridesForTesting( registry_util::RegistryOverrideManager* override_manager) { // For the moment, the HKCU hive requires no initialization. const bool do_copy = (base::win::GetVersion() >= base::win::VERSION_WIN7); RegistryKeyData data; if (do_copy) { // Copy the following HKLM subtrees to the temporary location so that the // win32 APIs used by the tests continue to work: // // HKLM\System\CurrentControlSet\Control\Lsa\AccessProviders // // This seems to be required since Win7. ReadRegistryTree(base::win::RegKey(HKEY_LOCAL_MACHINE, kHKLMAccessProviders, KEY_READ), &data); } override_manager->OverrideRegistry(HKEY_LOCAL_MACHINE); override_manager->OverrideRegistry(HKEY_CURRENT_USER); if (do_copy) { base::win::RegKey key( HKEY_LOCAL_MACHINE, kHKLMAccessProviders, KEY_ALL_ACCESS); WriteRegistryTree(data, &key); } } } // namespace #endif // defined(OS_WIN) void RlzLibTestNoMachineState::SetUp() { #if defined(OS_WIN) InitializeRegistryOverridesForTesting(&override_manager_); #elif defined(OS_MACOSX) base::mac::ScopedNSAutoreleasePool pool; #endif // defined(OS_WIN) #if defined(OS_POSIX) ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); rlz_lib::testing::SetRlzStoreDirectory(temp_dir_.path()); #endif // defined(OS_POSIX) } void RlzLibTestNoMachineState::TearDown() { #if defined(OS_POSIX) rlz_lib::testing::SetRlzStoreDirectory(base::FilePath()); #endif // defined(OS_POSIX) } void RlzLibTestBase::SetUp() { RlzLibTestNoMachineState::SetUp(); #if defined(OS_WIN) rlz_lib::CreateMachineState(); #endif // defined(OS_WIN) }