summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/base.gyp3
-rw-r--r--base/test/test_reg_util_win.cc100
-rw-r--r--base/test/test_reg_util_win.h55
-rw-r--r--base/test/test_reg_util_win_unittest.cc130
-rw-r--r--chrome/installer/gcapi/gcapi_test_registry_overrider.cc8
-rw-r--r--chrome/installer/setup/setup_util_unittest.cc4
-rw-r--r--chrome/installer/util/product_state_unittest.cc20
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.cc4
-rw-r--r--chrome_frame/test/chrome_frame_test_utils.h4
-rw-r--r--chrome_frame/test/util_unittests.cc4
10 files changed, 240 insertions, 92 deletions
diff --git a/base/base.gyp b/base/base.gyp
index 551aa712..fb096b9 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -638,6 +638,7 @@
'template_util_unittest.cc',
'test/expectations/expectation_unittest.cc',
'test/expectations/parser_unittest.cc',
+ 'test/test_reg_util_win_unittest.cc',
'test/trace_event_analyzer_unittest.cc',
'threading/non_thread_safe_unittest.cc',
'threading/platform_thread_unittest.cc',
@@ -825,8 +826,6 @@
['exclude', '^win/'],
],
'sources!': [
- 'debug/trace_event_win_unittest.cc',
- 'time/time_win_unittest.cc',
'win/win_util_unittest.cc',
],
}],
diff --git a/base/test/test_reg_util_win.cc b/base/test/test_reg_util_win.cc
index e23c6e9..f33fa61 100644
--- a/base/test/test_reg_util_win.cc
+++ b/base/test/test_reg_util_win.cc
@@ -4,23 +4,67 @@
#include "base/test/test_reg_util_win.h"
+#include "base/guid.h"
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace registry_util {
-const wchar_t RegistryOverrideManager::kTempTestKeyPath[] =
- L"Software\\Chromium\\TempTestKeys";
+namespace {
+
+const wchar_t kTimestampDelimiter[] = L"$";
+const wchar_t kTempTestKeyPath[] = L"Software\\Chromium\\TempTestKeys";
+
+void DeleteStaleTestKeys(const base::Time& now, const string16& test_key_root) {
+ base::win::RegKey test_root_key;
+ if (test_root_key.Open(HKEY_CURRENT_USER,
+ test_key_root.c_str(),
+ KEY_ALL_ACCESS) != ERROR_SUCCESS) {
+ // This will occur on first-run, but is harmless.
+ return;
+ }
+
+ base::win::RegistryKeyIterator iterator_test_root_key(HKEY_CURRENT_USER,
+ test_key_root.c_str());
+ for (; iterator_test_root_key.Valid(); ++iterator_test_root_key) {
+ string16 key_name = iterator_test_root_key.Name();
+ std::vector<string16> tokens;
+ Tokenize(key_name, string16(kTimestampDelimiter), &tokens);
+ int64 key_name_as_number = 0;
+
+ if (!base::StringToInt64(tokens[0], &key_name_as_number)) {
+ test_root_key.DeleteKey(key_name.c_str());
+ continue;
+ }
+
+ base::Time key_time = base::Time::FromInternalValue(key_name_as_number);
+ base::TimeDelta age = now - key_time;
+
+ if (age > base::TimeDelta::FromHours(24))
+ test_root_key.DeleteKey(key_name.c_str());
+ }
+}
+
+string16 GenerateTempKeyPath(const string16& test_key_root,
+ const base::Time& timestamp) {
+ string16 key_path = test_key_root;
+ key_path += L"\\" + base::Int64ToString16(timestamp.ToInternalValue());
+ key_path += kTimestampDelimiter + base::ASCIIToWide(base::GenerateGUID());
+
+ return key_path;
+}
+
+} // namespace
RegistryOverrideManager::ScopedRegistryKeyOverride::ScopedRegistryKeyOverride(
HKEY override,
- const std::wstring& temp_name)
- : override_(override),
- temp_name_(temp_name) {
- DCHECK(!temp_name_.empty());
- std::wstring key_path(RegistryOverrideManager::kTempTestKeyPath);
- key_path += L"\\" + temp_name_;
- EXPECT_EQ(ERROR_SUCCESS,
+ const string16& key_path)
+ : override_(override) {
+ EXPECT_EQ(
+ ERROR_SUCCESS,
temp_key_.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS));
EXPECT_EQ(ERROR_SUCCESS,
::RegOverridePredefKey(override_, temp_key_.Handle()));
@@ -29,37 +73,31 @@ RegistryOverrideManager::ScopedRegistryKeyOverride::ScopedRegistryKeyOverride(
RegistryOverrideManager::
ScopedRegistryKeyOverride::~ScopedRegistryKeyOverride() {
::RegOverridePredefKey(override_, NULL);
- // The temp key will be deleted via a call to DeleteAllTempKeys().
+ temp_key_.DeleteKey(L"");
}
-RegistryOverrideManager::RegistryOverrideManager() {
- DeleteAllTempKeys();
+RegistryOverrideManager::RegistryOverrideManager()
+ : timestamp_(base::Time::Now()), test_key_root_(kTempTestKeyPath) {
+ DeleteStaleTestKeys(timestamp_, test_key_root_);
}
-RegistryOverrideManager::~RegistryOverrideManager() {
- RemoveAllOverrides();
+RegistryOverrideManager::RegistryOverrideManager(const base::Time& timestamp,
+ const string16& test_key_root)
+ : timestamp_(timestamp), test_key_root_(test_key_root) {
+ DeleteStaleTestKeys(timestamp_, test_key_root_);
}
-void RegistryOverrideManager::OverrideRegistry(HKEY override,
- const std::wstring& temp_name) {
- overrides_.push_back(new ScopedRegistryKeyOverride(override, temp_name));
-}
+RegistryOverrideManager::~RegistryOverrideManager() {}
-void RegistryOverrideManager::RemoveAllOverrides() {
- while (!overrides_.empty()) {
- delete overrides_.back();
- overrides_.pop_back();
- }
-
- DeleteAllTempKeys();
+void RegistryOverrideManager::OverrideRegistry(
+ HKEY override,
+ const string16& /*override_name*/) {
+ string16 key_path = GenerateTempKeyPath(test_key_root_, timestamp_);
+ overrides_.push_back(new ScopedRegistryKeyOverride(override, key_path));
}
-// static
-void RegistryOverrideManager::DeleteAllTempKeys() {
- base::win::RegKey key;
- if (key.Open(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS) == ERROR_SUCCESS) {
- key.DeleteKey(kTempTestKeyPath);
- }
+string16 GenerateTempKeyPath() {
+ return GenerateTempKeyPath(string16(kTempTestKeyPath), base::Time::Now());
}
} // namespace registry_util
diff --git a/base/test/test_reg_util_win.h b/base/test/test_reg_util_win.h
index b71831f..5315b66 100644
--- a/base/test/test_reg_util_win.h
+++ b/base/test/test_reg_util_win.h
@@ -7,57 +7,72 @@
// Registry utility functions used only by tests.
-#include <string>
-#include <vector>
-
#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "base/strings/string16.h"
+#include "base/time/time.h"
#include "base/win/registry.h"
namespace registry_util {
// Allows a test to easily override registry hives so that it can start from a
// known good state, or make sure to not leave any side effects once the test
-// completes.
+// completes. This supports parallel tests. All the overrides are scoped to the
+// lifetime of the override manager. Destroy the manager to undo the overrides.
+//
+// Overridden hives use keys stored at, for instance:
+// HKCU\Software\Chromium\TempTestKeys\
+// 13028145911617809$02AB211C-CF73-478D-8D91-618E11998AED
+// The key path are comprises of:
+// - The test key root, HKCU\Software\Chromium\TempTestKeys\
+// - The base::Time::ToInternalValue of the creation time. This is used to
+// delete stale keys left over from crashed tests.
+// - A GUID used for preventing name collisions (although unlikely) between
+// two RegistryOverrideManagers created with the same timestamp.
class RegistryOverrideManager {
public:
- // All overridden hives will be descendents of this registry path under the
- // main HKCU hive.
- static const wchar_t kTempTestKeyPath[];
-
RegistryOverrideManager();
~RegistryOverrideManager();
// Override the given registry hive using a temporary key named by temp_name
- // under the temporary test key path.
- void OverrideRegistry(HKEY override, const std::wstring& temp_name);
-
- // Deletes all temporary test keys used by the overrides.
- static void DeleteAllTempKeys();
-
- // Removes all overrides and deletes all temporary test keys used by the
- // overrides.
- void RemoveAllOverrides();
+ // under the temporary test key path. There is no need to randomize
+ // |override_name|, as a random parent key is generated. Multiple overrides to
+ // the same hive are not supported and lead to undefined behavior.
+ void OverrideRegistry(HKEY override, const string16& override_name);
private:
+ friend class RegistryOverrideManagerTest;
+
// Keeps track of one override.
class ScopedRegistryKeyOverride {
public:
- ScopedRegistryKeyOverride(HKEY override, const std::wstring& temp_name);
+ ScopedRegistryKeyOverride(HKEY override, const string16& key_path);
~ScopedRegistryKeyOverride();
private:
HKEY override_;
base::win::RegKey temp_key_;
- std::wstring temp_name_;
DISALLOW_COPY_AND_ASSIGN(ScopedRegistryKeyOverride);
};
- std::vector<ScopedRegistryKeyOverride*> overrides_;
+ // Used for testing only.
+ RegistryOverrideManager(const base::Time& timestamp,
+ const string16& test_key_root);
+
+ base::Time timestamp_;
+ string16 guid_;
+
+ string16 test_key_root_;
+ ScopedVector<ScopedRegistryKeyOverride> overrides_;
DISALLOW_COPY_AND_ASSIGN(RegistryOverrideManager);
};
+// Generates a temporary key path that will be eventually deleted
+// automatically if the process crashes.
+string16 GenerateTempKeyPath();
+
} // namespace registry_util
#endif // BASE_TEST_TEST_REG_UTIL_H_
diff --git a/base/test/test_reg_util_win_unittest.cc b/base/test/test_reg_util_win_unittest.cc
new file mode 100644
index 0000000..25f341f
--- /dev/null
+++ b/base/test/test_reg_util_win_unittest.cc
@@ -0,0 +1,130 @@
+// Copyright 2013 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 "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/test_reg_util_win.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace registry_util {
+
+namespace {
+const wchar_t kTestKeyPath[] = L"Software\\Chromium\\Foo\\Baz\\TestKey";
+const wchar_t kTestValueName[] = L"TestValue";
+} // namespace
+
+class RegistryOverrideManagerTest : public testing::Test {
+ protected:
+ RegistryOverrideManagerTest() {
+ // We assign a fake test key path to our test RegistryOverrideManager
+ // so we don't interfere with any actual RegistryOverrideManagers running
+ // on the system. This fake path will be auto-deleted by other
+ // RegistryOverrideManagers in case we crash.
+ fake_test_key_root_ = registry_util::GenerateTempKeyPath();
+
+ // Ensure a clean test environment.
+ base::win::RegKey key(HKEY_CURRENT_USER);
+ key.DeleteKey(fake_test_key_root_.c_str());
+ key.DeleteKey(kTestKeyPath);
+ }
+
+ virtual ~RegistryOverrideManagerTest() {
+ base::win::RegKey key(HKEY_CURRENT_USER);
+ key.DeleteKey(fake_test_key_root_.c_str());
+ }
+
+ void AssertKeyExists(const string16& key_path) {
+ base::win::RegKey key;
+ ASSERT_EQ(ERROR_SUCCESS,
+ key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
+ << key_path << " does not exist.";
+ }
+
+ void AssertKeyAbsent(const string16& key_path) {
+ base::win::RegKey key;
+ ASSERT_NE(ERROR_SUCCESS,
+ key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
+ << key_path << " exists but it should not.";
+ }
+
+ void CreateKey(const string16& key_path) {
+ base::win::RegKey key;
+ EXPECT_EQ(ERROR_SUCCESS,
+ key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS));
+ }
+
+ string16 FakeOverrideManagerPath(const base::Time& time) {
+ return fake_test_key_root_ + L"\\" +
+ base::Int64ToString16(time.ToInternalValue());
+ }
+
+ void CreateManager(const base::Time& timestamp) {
+ manager_.reset(new RegistryOverrideManager(timestamp, fake_test_key_root_));
+ manager_->OverrideRegistry(HKEY_CURRENT_USER, L"override_manager_unittest");
+ }
+
+ string16 fake_test_key_root_;
+ scoped_ptr<RegistryOverrideManager> manager_;
+};
+
+TEST_F(RegistryOverrideManagerTest, Basic) {
+ CreateManager(base::Time::Now());
+
+ base::win::RegKey create_key;
+ EXPECT_EQ(ERROR_SUCCESS,
+ create_key.Create(HKEY_CURRENT_USER, kTestKeyPath, KEY_ALL_ACCESS));
+ EXPECT_TRUE(create_key.Valid());
+ EXPECT_EQ(ERROR_SUCCESS, create_key.WriteValue(kTestValueName, 42));
+ create_key.Close();
+
+ AssertKeyExists(kTestKeyPath);
+
+ DWORD value;
+ base::win::RegKey read_key;
+ EXPECT_EQ(ERROR_SUCCESS,
+ read_key.Open(HKEY_CURRENT_USER, kTestKeyPath, KEY_READ));
+ EXPECT_TRUE(read_key.Valid());
+ EXPECT_EQ(ERROR_SUCCESS, read_key.ReadValueDW(kTestValueName, &value));
+ EXPECT_EQ(42, value);
+ read_key.Close();
+
+ manager_.reset();
+
+ AssertKeyAbsent(kTestKeyPath);
+}
+
+TEST_F(RegistryOverrideManagerTest, DeleteStaleKeys) {
+ base::Time::Exploded kTestTimeExploded = {2013, 11, 1, 4, 0, 0, 0, 0};
+ base::Time kTestTime = base::Time::FromUTCExploded(kTestTimeExploded);
+
+ string16 path_garbage = fake_test_key_root_ + L"\\Blah";
+ string16 path_very_stale =
+ FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(100));
+ string16 path_stale =
+ FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(5));
+ string16 path_current =
+ FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromMinutes(1));
+ string16 path_future =
+ FakeOverrideManagerPath(kTestTime + base::TimeDelta::FromMinutes(1));
+
+ CreateKey(path_garbage);
+ CreateKey(path_very_stale);
+ CreateKey(path_stale);
+ CreateKey(path_current);
+ CreateKey(path_future);
+
+ CreateManager(kTestTime);
+ manager_.reset();
+
+ AssertKeyAbsent(path_garbage);
+ AssertKeyAbsent(path_very_stale);
+ AssertKeyAbsent(path_stale);
+ AssertKeyExists(path_current);
+ AssertKeyExists(path_future);
+}
+
+} // namespace registry_util
diff --git a/chrome/installer/gcapi/gcapi_test_registry_overrider.cc b/chrome/installer/gcapi/gcapi_test_registry_overrider.cc
index 2df337f..be678a2 100644
--- a/chrome/installer/gcapi/gcapi_test_registry_overrider.cc
+++ b/chrome/installer/gcapi/gcapi_test_registry_overrider.cc
@@ -11,12 +11,8 @@
GCAPITestRegistryOverrider::GCAPITestRegistryOverrider() {
// Override keys - this is undone during destruction.
- string16 hkcu_override = base::StringPrintf(
- L"hkcu_override\\%ls", ASCIIToWide(base::GenerateGUID()));
- override_manager_.OverrideRegistry(HKEY_CURRENT_USER, hkcu_override);
- string16 hklm_override = base::StringPrintf(
- L"hklm_override\\%ls", ASCIIToWide(base::GenerateGUID()));
- override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, hklm_override);
+ override_manager_.OverrideRegistry(HKEY_CURRENT_USER, L"hkcu_override");
+ override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, L"hklm_override");
}
GCAPITestRegistryOverrider::~GCAPITestRegistryOverrider() {
diff --git a/chrome/installer/setup/setup_util_unittest.cc b/chrome/installer/setup/setup_util_unittest.cc
index 0391e3a..647d90f 100644
--- a/chrome/installer/setup/setup_util_unittest.cc
+++ b/chrome/installer/setup/setup_util_unittest.cc
@@ -410,10 +410,6 @@ class MigrateMultiToSingleTest : public testing::Test {
L"MigrateMultiToSingleTest");
}
- virtual void TearDown() OVERRIDE {
- registry_override_manager_.RemoveAllOverrides();
- }
-
static const bool kSystemLevel = false;
static const HKEY kRootKey;
static const wchar_t kVersionString[];
diff --git a/chrome/installer/util/product_state_unittest.cc b/chrome/installer/util/product_state_unittest.cc
index 4946f0a..42c4a99 100644
--- a/chrome/installer/util/product_state_unittest.cc
+++ b/chrome/installer/util/product_state_unittest.cc
@@ -31,15 +31,14 @@ class ProductStateTest : public testing::Test {
void MinimallyInstallProduct(const wchar_t* version);
static BrowserDistribution* dist_;
- static std::wstring temp_key_path_;
bool system_install_;
HKEY overridden_;
+ registry_util::RegistryOverrideManager registry_override_manager_;
RegKey clients_;
RegKey client_state_;
};
BrowserDistribution* ProductStateTest::dist_;
-std::wstring ProductStateTest::temp_key_path_;
// static
void ProductStateTest::SetUpTestCase() {
@@ -48,16 +47,10 @@ void ProductStateTest::SetUpTestCase() {
// We'll use Chrome as our test subject.
dist_ = BrowserDistribution::GetSpecificDistribution(
BrowserDistribution::CHROME_BROWSER);
-
- // And we'll play in HKCU here:
- temp_key_path_.assign(RegistryOverrideManager::kTempTestKeyPath)
- .append(1, L'\\')
- .append(L"ProductStateTest");
}
// static
void ProductStateTest::TearDownTestCase() {
- temp_key_path_.clear();
dist_ = NULL;
testing::Test::TearDownTestCase();
@@ -73,11 +66,8 @@ void ProductStateTest::SetUp() {
// Override for test purposes. We don't use ScopedRegistryKeyOverride
// directly because it doesn't suit itself to our use here.
RegKey temp_key;
- EXPECT_EQ(ERROR_SUCCESS,
- temp_key.Create(HKEY_CURRENT_USER, temp_key_path_.c_str(),
- KEY_ALL_ACCESS));
- EXPECT_EQ(ERROR_SUCCESS,
- ::RegOverridePredefKey(overridden_, temp_key.Handle()));
+
+ registry_override_manager_.OverrideRegistry(overridden_, L"ProductStateTest");
EXPECT_EQ(ERROR_SUCCESS,
clients_.Create(overridden_, dist_->GetVersionKey().c_str(),
@@ -91,13 +81,9 @@ void ProductStateTest::TearDown() {
// Done with the keys.
client_state_.Close();
clients_.Close();
- EXPECT_EQ(ERROR_SUCCESS, ::RegOverridePredefKey(overridden_, NULL));
overridden_ = NULL;
system_install_ = false;
- // Shotgun approach to clearing out data we may have written.
- RegistryOverrideManager::DeleteAllTempKeys();
-
testing::Test::TearDown();
}
diff --git a/chrome_frame/test/chrome_frame_test_utils.cc b/chrome_frame/test/chrome_frame_test_utils.cc
index 298a7c2..6c7fb48 100644
--- a/chrome_frame/test/chrome_frame_test_utils.cc
+++ b/chrome_frame/test/chrome_frame_test_utils.cc
@@ -679,10 +679,6 @@ ScopedVirtualizeHklmAndHkcu::ScopedVirtualizeHklmAndHkcu() {
ScopedVirtualizeHklmAndHkcu::~ScopedVirtualizeHklmAndHkcu() {
}
-void ScopedVirtualizeHklmAndHkcu::RemoveAllOverrides() {
- override_manager_.RemoveAllOverrides();
-}
-
bool KillProcesses(const std::wstring& executable_name, int exit_code,
bool wait) {
bool result = true;
diff --git a/chrome_frame/test/chrome_frame_test_utils.h b/chrome_frame/test/chrome_frame_test_utils.h
index f9c08e2..316d57c 100644
--- a/chrome_frame/test/chrome_frame_test_utils.h
+++ b/chrome_frame/test/chrome_frame_test_utils.h
@@ -338,10 +338,6 @@ class ScopedVirtualizeHklmAndHkcu {
ScopedVirtualizeHklmAndHkcu();
~ScopedVirtualizeHklmAndHkcu();
- // Removes all overrides and deletes all temporary test keys used by the
- // overrides.
- void RemoveAllOverrides();
-
protected:
registry_util::RegistryOverrideManager override_manager_;
};
diff --git a/chrome_frame/test/util_unittests.cc b/chrome_frame/test/util_unittests.cc
index e6dbd65..74e41f9 100644
--- a/chrome_frame/test/util_unittests.cc
+++ b/chrome_frame/test/util_unittests.cc
@@ -34,10 +34,6 @@ class UtilTests : public testing::Test {
DeleteAllSingletons();
}
- void TearDown() {
- registry_virtualization_.RemoveAllOverrides();
- }
-
// This is used to manage life cycle of PolicySettings singleton.
// base::ShadowingAtExitManager at_exit_manager_;
chrome_frame_test::ScopedVirtualizeHklmAndHkcu registry_virtualization_;