Coverage for /Syzygy/agent/asan/registry_cache_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%1921920.C++test

Line-by-line coverage:

   1    :  // Copyright 2015 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #include "syzygy/agent/asan/registry_cache.h"
  16    :  
  17    :  #include "base/base_paths.h"
  18    :  #include "base/file_version_info_win.h"
  19    :  #include "base/path_service.h"
  20    :  #include "base/rand_util.h"
  21    :  #include "base/files/file_path.h"
  22    :  #include "base/test/test_reg_util_win.h"
  23    :  #include "base/win/registry.h"
  24    :  #include "gtest/gtest.h"
  25    :  #include "syzygy/agent/asan/block.h"
  26    :  #include "syzygy/agent/asan/heap_checker.h"
  27    :  #include "syzygy/agent/common/stack_capture.h"
  28    :  
  29    :  namespace agent {
  30    :  namespace asan {
  31    :  
  32    :  namespace {
  33    :  
  34    :  using registry_util::RegistryOverrideManager;
  35    :  
  36    :  // A derived class to expose protected members for unit-testing.
  37    :  class TestRegistryCache : public RegistryCache {
  38    :   public:
  39    :    using RegistryCache::max_days_in_registry_;
  40    :    using RegistryCache::max_entries_per_version_;
  41    :    using RegistryCache::max_modules_;
  42    :    using RegistryCache::max_versions_;
  43    :    using RegistryCache::registry_cache_key_;
  44    :    using RegistryCache::module_key_name_;
  45    :    using RegistryCache::AddOrUpdateStackId;
  46    :    using RegistryCache::RegValueIter;
  47    :    using RegistryCache::RegKeyIter;
  48    :    using RegistryCache::StackId;
  49    :    static const wchar_t kTestRegistryName[];
  50    :  
  51  E :    TestRegistryCache() : RegistryCache(kTestRegistryName) {}
  52    :    TestRegistryCache(const wchar_t registry_name[],
  53    :                      size_t max_days_in_registry,
  54    :                      size_t max_entries_per_version,
  55    :                      size_t max_modules,
  56    :                      size_t max_versions)
  57    :        : RegistryCache(registry_name,
  58    :                        max_days_in_registry,
  59    :                        max_entries_per_version,
  60    :                        max_modules,
  61  E :                        max_versions) {}
  62    :  };
  63    :  
  64    :  const wchar_t TestRegistryCache::kTestRegistryName[] = L"TEST";
  65    :  
  66    :  class RegistryCacheTest : public testing::Test {
  67    :   public:
  68  E :    void SetUp() override {
  69    :      // Setup the "global" state.
  70  E :      registry_key_ = TestRegistryCache::kRegistryBaseKey;
  71  E :      registry_key_ += TestRegistryCache::kTestRegistryName;
  72  E :      override_manager_.OverrideRegistry(TestRegistryCache::kRegistryRootKey);
  73  E :    }
  74    :  
  75  E :    base::Time RecentTime() const {
  76    :      return base::Time::Now() -
  77  E :          base::TimeDelta::FromDays(registry_cache_.max_days_in_registry_ / 2);
  78  E :    }
  79    :  
  80  E :    base::Time OldTime() const {
  81    :      return base::Time::Now() -
  82  E :          base::TimeDelta::FromDays(registry_cache_.max_days_in_registry_ + 9);
  83  E :    }
  84    :  
  85    :    // Returns the number of keys that exist in a registry location.
  86    :    // @param root The root key of the registry.
  87    :    // @param location The location in the registry.
  88    :    // @return Number of keys.
  89  E :    int GetKeyCount(const HKEY root, const std::wstring& location) const {
  90  E :      int count = 0;
  91  E :      TestRegistryCache::RegKeyIter iter(root, location.c_str());
  92  E :      while (iter.Valid()) {
  93  E :        ++count;
  94  E :        ++iter;
  95  E :      }
  96  E :      return count;
  97  E :    }
  98    :  
  99    :   protected:
 100    :    TestRegistryCache registry_cache_;
 101    :    RegistryOverrideManager override_manager_;
 102    :    base::win::RegKey key_;
 103    :    base::string16 registry_key_;
 104    :  };
 105    :  
 106    :  }  // namespace
 107    :  
 108  E :  TEST_F(RegistryCacheTest, Constructors) {
 109    :    // Default constructor.
 110    :    EXPECT_EQ(RegistryCache::kDefaultMaxDaysInRegistry,
 111  E :              registry_cache_.max_days_in_registry_);
 112    :    EXPECT_EQ(RegistryCache::kDefaultMaxEntriesPerVersion,
 113  E :              registry_cache_.max_entries_per_version_);
 114    :    EXPECT_EQ(RegistryCache::kDefaultMaxModules,
 115  E :              registry_cache_.max_modules_);
 116    :    EXPECT_EQ(RegistryCache::kDefaultMaxVersions,
 117  E :              registry_cache_.max_versions_);
 118    :  
 119  E :    TestRegistryCache registry_cache2(L"TESTING", 10, 20, 30, 40);
 120  E :    EXPECT_EQ(10, registry_cache2.max_days_in_registry_);
 121  E :    EXPECT_EQ(20, registry_cache2.max_entries_per_version_);
 122  E :    EXPECT_EQ(30, registry_cache2.max_modules_);
 123  E :    EXPECT_EQ(40, registry_cache2.max_versions_);
 124    :    EXPECT_EQ(L"TESTING", registry_cache2.registry_cache_key_.substr(
 125  E :        registry_cache2.registry_cache_key_.size() - 7));
 126  E :  }
 127    :  
 128  E :  TEST_F(RegistryCacheTest, RemoveOldEntries) {
 129  E :    base::Time recent_time = RecentTime();
 130  E :    base::Time old_time = OldTime();
 131    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 132  E :                (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
 133  E :    ASSERT_TRUE(key_.Valid());
 134    :  
 135  E :    TestRegistryCache::StackId stack_id_old = 4567890;
 136    :    key_.WriteValue(base::Int64ToString16(old_time.ToInternalValue()).c_str(),
 137  E :                    &stack_id_old, sizeof(stack_id_old), REG_BINARY);
 138  E :    TestRegistryCache::StackId stack_id_recent = 9876543;
 139    :    key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
 140  E :                    &stack_id_recent, sizeof(stack_id_recent), REG_BINARY);
 141    :  
 142  E :    registry_cache_.Init();
 143    :  
 144    :    // Only the recent entry should be left.
 145  E :    EXPECT_EQ(1, key_.GetValueCount());
 146    :    TestRegistryCache::StackId value;
 147  E :    DWORD dsize = sizeof(value);
 148  E :    DWORD dtype = 0;
 149    :    key_.ReadValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
 150  E :                   &value, &dsize, &dtype);
 151  E :    EXPECT_EQ(sizeof(stack_id_recent), dsize);
 152  E :    EXPECT_EQ(stack_id_recent, value);
 153  E :  }
 154    :  
 155  E :  TEST_F(RegistryCacheTest, RemoveEmptyKeys) {
 156  E :    base::Time recent_time = RecentTime();
 157    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 158  E :                (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
 159  E :    ASSERT_TRUE(key_.Valid());
 160    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 161  E :                (registry_key_ + L"\\Application 2\\v1").c_str(), KEY_ALL_ACCESS);
 162  E :    ASSERT_TRUE(key_.Valid());
 163  E :    const TestRegistryCache::StackId stack_id = 4567890;
 164    :    key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
 165  E :                    &stack_id, sizeof(stack_id), REG_BINARY);
 166  E :    key_.Close();
 167    :  
 168  E :    registry_cache_.Init();
 169    :  
 170    :    key_.Open(TestRegistryCache::kRegistryRootKey,
 171  E :              (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
 172  E :    EXPECT_FALSE(key_.Valid());
 173    :    key_.Open(TestRegistryCache::kRegistryRootKey,
 174  E :              (registry_key_ + L"\\Application 1").c_str(), KEY_ALL_ACCESS);
 175  E :    EXPECT_FALSE(key_.Valid());
 176    :    key_.Open(TestRegistryCache::kRegistryRootKey,
 177  E :              (registry_key_ + L"\\Application 2\\v1").c_str(), KEY_ALL_ACCESS);
 178  E :    EXPECT_TRUE(key_.Valid());
 179  E :  }
 180    :  
 181  E :  TEST_F(RegistryCacheTest, MaximumNbKeys) {
 182  E :    const int delta = 42;
 183    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 184  E :                (registry_key_ + L"\\Application 1\\v1").c_str(), KEY_ALL_ACCESS);
 185  E :    ASSERT_TRUE(key_.Valid());
 186    :    TestRegistryCache::StackId stack_id;
 187    :    // Start with current time and add increment for each iteration of the loop,
 188    :    // instead of using Time::now() each time. Avoids having possible duplicates
 189    :    // if the iteration runs too fast.
 190  E :    base::Time start_time = base::Time::Now();
 191  E :    for (int i = 0; i < TestRegistryCache::kDefaultMaxEntriesPerVersion + delta;
 192  E :         i++) {
 193  E :      stack_id = base::RandUint64();
 194  E :      base::Time time = start_time + base::TimeDelta::FromMilliseconds(i);
 195    :      key_.WriteValue(base::Int64ToString16(time.ToInternalValue()).c_str(),
 196  E :                      &stack_id, sizeof(stack_id), REG_BINARY);
 197  E :    }
 198    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxEntriesPerVersion + delta,
 199  E :              key_.GetValueCount());
 200  E :    registry_cache_.Init();
 201    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxEntriesPerVersion,
 202  E :              key_.GetValueCount());
 203  E :  }
 204    :  
 205  E :  TEST_F(RegistryCacheTest, MaximumNbVersions) {
 206  E :    const int delta = 42;
 207  E :    const std::wstring app_base_key(registry_key_ + L"\\App");
 208    :    TestRegistryCache::StackId stack_id;
 209    :    key_.Create(TestRegistryCache::kRegistryRootKey, app_base_key.c_str(),
 210  E :                KEY_ALL_ACCESS);
 211  E :    ASSERT_TRUE(key_.Valid());
 212  E :    key_.Close();
 213    :    // Create a lot of version numbers under a single module (more than
 214    :    // |kMaxVersions|). The number of keys should be brought down to
 215    :    // |kMaxVersions| after the cleaning process.
 216  E :    for (int i = 0; i < TestRegistryCache::kDefaultMaxVersions + delta; i++) {
 217    :      key_.Create(TestRegistryCache::kRegistryRootKey,
 218    :                  (app_base_key + L"\\v" + base::IntToString16(i)).c_str(),
 219  E :                  KEY_ALL_ACCESS);
 220  E :      ASSERT_TRUE(key_.Valid());
 221  E :      stack_id = base::RandUint64();
 222    :      key_.WriteValue(
 223    :          base::Int64ToString16(base::Time::Now().ToInternalValue()).c_str(),
 224  E :          &stack_id, sizeof(stack_id), REG_BINARY);
 225  E :      ASSERT_EQ(1, key_.GetValueCount());
 226  E :      key_.Close();
 227  E :    }
 228    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxVersions + delta,
 229  E :              GetKeyCount(TestRegistryCache::kRegistryRootKey, app_base_key));
 230  E :    registry_cache_.Init();
 231    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxVersions,
 232  E :              GetKeyCount(TestRegistryCache::kRegistryRootKey, app_base_key));
 233  E :  }
 234    :  
 235  E :  TEST_F(RegistryCacheTest, MaximumNbModules) {
 236  E :    const int delta = 42;
 237    :    TestRegistryCache::StackId stack_id;
 238    :    key_.Create(TestRegistryCache::kRegistryRootKey, (registry_key_).c_str(),
 239  E :                KEY_ALL_ACCESS);
 240  E :    ASSERT_TRUE(key_.Valid());
 241  E :    key_.Close();
 242    :    // Create a lot of modules (more than |kMaxModules|). The number of keys
 243    :    // should be brought down to |kMaxModules| after the cleaning process.
 244  E :    for (int i = 0; i < TestRegistryCache::kDefaultMaxModules + delta; i++) {
 245    :      key_.Create(
 246    :          TestRegistryCache::kRegistryRootKey,
 247    :          (registry_key_ + L"\\App" + base::IntToString16(i) + L"\\v1").c_str(),
 248  E :          KEY_ALL_ACCESS);
 249  E :      ASSERT_TRUE(key_.Valid());
 250  E :      stack_id = base::RandUint64();
 251    :      key_.WriteValue(
 252    :          base::Int64ToString16(base::Time::Now().ToInternalValue()).c_str(),
 253  E :          &stack_id, sizeof(stack_id), REG_BINARY);
 254  E :      ASSERT_EQ(1, key_.GetValueCount());
 255  E :      key_.Close();
 256  E :    }
 257    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxModules + delta,
 258  E :              GetKeyCount(TestRegistryCache::kRegistryRootKey, registry_key_));
 259  E :    registry_cache_.Init();
 260    :    EXPECT_EQ(TestRegistryCache::kDefaultMaxModules,
 261  E :              GetKeyCount(TestRegistryCache::kRegistryRootKey, registry_key_));
 262  E :  }
 263    :  
 264  E :  TEST_F(RegistryCacheTest, DoesIdExist) {
 265    :    // Called a 1st time to initialize |module_key_name_|.
 266  E :    registry_cache_.Init();
 267    :  
 268  E :    base::Time recent_time = RecentTime();
 269    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 270  E :                registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
 271  E :    ASSERT_TRUE(key_.Valid());
 272    :  
 273  E :    const TestRegistryCache::StackId stack_id = 4567890;
 274    :    key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
 275  E :                    &stack_id, sizeof(stack_id), REG_BINARY);
 276    :  
 277    :    // Called a 2nd time to force the loading of the new value from registry.
 278  E :    registry_cache_.Init();
 279    :  
 280  E :    EXPECT_TRUE(registry_cache_.DoesIdExist(stack_id));
 281  E :  }
 282    :  
 283  E :  TEST_F(RegistryCacheTest, AddOrUpdateStackId) {
 284  E :    const TestRegistryCache::StackId stack_id_1 = 123456;
 285  E :    const TestRegistryCache::StackId stack_id_2 = 3456236;
 286    :  
 287  E :    registry_cache_.Init();
 288    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 289  E :                registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
 290  E :    ASSERT_TRUE(key_.Valid());
 291  E :    ASSERT_EQ(0, key_.GetValueCount());
 292  E :    registry_cache_.AddOrUpdateStackId(stack_id_1);
 293    :    TestRegistryCache::RegValueIter iter(
 294    :        TestRegistryCache::kRegistryRootKey,
 295  E :        registry_cache_.module_key_name_.c_str());
 296  E :    ASSERT_TRUE(iter.Valid());
 297  E :    std::wstring original_name = iter.Name();
 298  E :    ASSERT_EQ(1, key_.GetValueCount());
 299  E :    registry_cache_.AddOrUpdateStackId(stack_id_2);
 300  E :    ASSERT_EQ(2, key_.GetValueCount());
 301  E :    registry_cache_.AddOrUpdateStackId(stack_id_1);
 302  E :    ASSERT_EQ(2, key_.GetValueCount());
 303    :  
 304    :    // Validate that the original value corresponding to |stack_id_1| doesn't
 305    :    // exist anymore (meaning that it was updated), while validating that the two
 306    :    // existing values correspond to both stack_ids.
 307    :    TestRegistryCache::RegValueIter iter2(
 308    :        TestRegistryCache::kRegistryRootKey,
 309  E :        registry_cache_.module_key_name_.c_str());
 310  E :    ASSERT_TRUE(iter2.Valid());
 311  E :    bool stack_id_1_exists = false;
 312  E :    bool stack_id_2_exists = false;
 313  E :    for (; iter2.Valid(); ++iter2) {
 314  E :      ASSERT_EQ(sizeof(TestRegistryCache::StackId), iter2.ValueSize());
 315  E :      ASSERT_NE(original_name, iter2.Name());
 316    :      const TestRegistryCache::StackId* ptr_value =
 317  E :          reinterpret_cast<const TestRegistryCache::StackId*>(iter2.Value());
 318  E :      if (*ptr_value == stack_id_1) {
 319  E :        EXPECT_FALSE(stack_id_1_exists);
 320  E :        stack_id_1_exists = true;
 321  E :      } else if (*ptr_value == stack_id_2) {
 322  E :        EXPECT_FALSE(stack_id_2_exists);
 323  E :        stack_id_2_exists = true;
 324    :      }
 325  E :    }
 326  E :    EXPECT_TRUE(stack_id_1_exists);
 327  E :    EXPECT_TRUE(stack_id_2_exists);
 328  E :  }
 329    :  
 330  E :  TEST_F(RegistryCacheTest, RemoveStackId) {
 331    :    // Called a 1st time to initialize |module_key_name_|.
 332  E :    registry_cache_.Init();
 333    :  
 334  E :    base::Time recent_time = RecentTime();
 335    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 336  E :      registry_cache_.module_key_name_.c_str(), KEY_ALL_ACCESS);
 337  E :    ASSERT_TRUE(key_.Valid());
 338    :  
 339  E :    const TestRegistryCache::StackId stack_id = 4567890;
 340    :    key_.WriteValue(base::Int64ToString16(recent_time.ToInternalValue()).c_str(),
 341  E :      &stack_id, sizeof(stack_id), REG_BINARY);
 342    :  
 343    :    // Called a 2nd time to force the loading of the new value from registry.
 344  E :    registry_cache_.Init();
 345    :  
 346  E :    EXPECT_FALSE(registry_cache_.RemoveStackId(123456));
 347  E :    EXPECT_TRUE(registry_cache_.RemoveStackId(stack_id));
 348  E :    EXPECT_FALSE(registry_cache_.RemoveStackId(stack_id));
 349  E :  }
 350    :  
 351  E :  TEST_F(RegistryCacheTest, DeleteRegistryTree) {
 352  E :    RegistryCache registry_cache2(L"AnotherRegistry");
 353  E :    RegistryCache registry_cache3(L"YetAnotherName");
 354  E :    registry_cache_.Init();
 355  E :    registry_cache2.Init();
 356  E :    registry_cache3.Init();
 357    :  
 358    :    key_.Create(TestRegistryCache::kRegistryRootKey,
 359    :                TestRegistryCache::kRegistryBaseKey,
 360  E :                KEY_ALL_ACCESS);
 361    :  
 362  E :    ASSERT_TRUE(key_.Valid());
 363    :    ASSERT_EQ(3U, GetKeyCount(TestRegistryCache::kRegistryRootKey,
 364  E :                              TestRegistryCache::kRegistryBaseKey));
 365  E :    RegistryCache::DeleteRegistryTree(L"AnotherRegistry");
 366    :    ASSERT_EQ(2U, GetKeyCount(TestRegistryCache::kRegistryRootKey,
 367  E :                              TestRegistryCache::kRegistryBaseKey));
 368    :  
 369    :    TestRegistryCache::RegKeyIter iter(TestRegistryCache::kRegistryRootKey,
 370  E :                                       TestRegistryCache::kRegistryBaseKey);
 371  E :    ASSERT_TRUE(iter.Valid());
 372  E :    EXPECT_EQ(L"YetAnotherName", std::wstring(iter.Name()));
 373  E :    ++iter;
 374  E :    ASSERT_TRUE(iter.Valid());
 375  E :    EXPECT_EQ(L"TEST", std::wstring(iter.Name()));
 376  E :  }
 377    :  
 378    :  }  // namespace asan
 379    :  }  // namespace agent

Coverage information generated Thu Jan 14 17:40:38 2016.