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

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.2%1281290.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 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/asan_runtime.h"
  16    :  
  17    :  #include "base/bind.h"
  18    :  #include "base/command_line.h"
  19    :  #include "base/environment.h"
  20    :  #include "base/string_number_conversions.h"
  21    :  #include "base/utf_string_conversions.h"
  22    :  #include "base/memory/scoped_ptr.h"
  23    :  #include "gtest/gtest.h"
  24    :  #include "syzygy/agent/asan/asan_heap.h"
  25    :  #include "syzygy/agent/asan/asan_logger.h"
  26    :  #include "syzygy/agent/asan/unittest_util.h"
  27    :  
  28    :  namespace agent {
  29    :  namespace asan {
  30    :  
  31    :  namespace {
  32    :  
  33    :  using agent::asan::AsanErrorInfo;
  34    :  using agent::asan::HeapProxy;
  35    :  
  36    :  // A derived class to expose protected members for unit-testing.
  37    :  class TestAsanRuntime : public AsanRuntime {
  38    :   public:
  39    :    using AsanRuntime::AsanFlags;
  40    :    using AsanRuntime::kBottomFramesToSkip;
  41    :    using AsanRuntime::kCompressionReportingPeriod;
  42    :    using AsanRuntime::kExitOnFailure;
  43    :    using AsanRuntime::kIgnoredStackIds;
  44    :    using AsanRuntime::kQuarantineSize;
  45    :    using AsanRuntime::kTrailerPaddingSize;
  46    :    using AsanRuntime::PropagateFlagsValues;
  47    :    using AsanRuntime::flags;
  48    :    using AsanRuntime::set_flags;
  49    :  };
  50    :  
  51    :  class TestHeapProxy : public HeapProxy {
  52    :   public:
  53    :    using HeapProxy::kDefaultQuarantineMaxSize;
  54    :  };
  55    :  
  56    :  class AsanRuntimeTest : public testing::TestWithAsanLogger {
  57    :   public:
  58    :    typedef testing::TestWithAsanLogger Super;
  59    :  
  60    :    AsanRuntimeTest()
  61    :        : current_command_line_(CommandLine::NO_PROGRAM),
  62  E :          stack_cache_(&logger_) {
  63  E :    }
  64    :  
  65  E :    void SetUp() OVERRIDE {
  66  E :      Super::SetUp();
  67    :  
  68  E :      env_.reset(base::Environment::Create());
  69  E :      ASSERT_TRUE(env_.get() != NULL);
  70  E :      env_->UnSetVar(TestAsanRuntime::kSyzygyAsanOptionsEnvVar);
  71  E :      env_->UnSetVar(TestAsanRuntime::kSyzygyAsanCoinTossEnvVar);
  72    :  
  73    :      // Setup the "global" state.
  74  E :      StackCapture::Init();
  75  E :      StackCaptureCache::Init();
  76  E :      HeapProxy::Init(&stack_cache_);
  77  E :    }
  78    :  
  79  E :    void TearDown() OVERRIDE {
  80    :      // Clear the environment so other tests aren't affected.
  81  E :      env_->UnSetVar(TestAsanRuntime::kSyzygyAsanOptionsEnvVar);
  82  E :      env_->UnSetVar(TestAsanRuntime::kSyzygyAsanCoinTossEnvVar);
  83    :  
  84  E :      Super::TearDown();
  85  E :    }
  86    :  
  87    :    AsanLogger logger_;
  88    :    StackCaptureCache stack_cache_;
  89    :  
  90    :    // The test runtime instance.
  91    :    TestAsanRuntime asan_runtime_;
  92    :  
  93    :    // The value of the command-line that we want to test.
  94    :    CommandLine current_command_line_;
  95    :  
  96    :    // The process environment.
  97    :    scoped_ptr<base::Environment> env_;
  98    :  };
  99    :  
 100    :  bool callback_called = false;
 101    :  
 102    :  // A simple callback that change the value of a boolean to indicate that it has
 103    :  // been called.
 104  E :  void TestCallback(AsanErrorInfo* error_info) {
 105  E :    callback_called = true;
 106  E :  }
 107    :  
 108    :  }  // namespace
 109    :  
 110  E :  TEST_F(AsanRuntimeTest, SetUpAndTearDown) {
 111    :    ASSERT_NO_FATAL_FAILURE(
 112  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 113  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 114  E :  }
 115    :  
 116  E :  TEST_F(AsanRuntimeTest, OnError) {
 117    :    ASSERT_NO_FATAL_FAILURE(
 118  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 119  E :    asan_runtime_.SetErrorCallBack(base::Bind(&TestCallback));
 120  E :    callback_called = false;
 121  E :    AsanErrorInfo bad_access_info = {};
 122  E :    RtlCaptureContext(&bad_access_info.context);
 123  E :    asan_runtime_.OnError(&bad_access_info);
 124  E :    ASSERT_TRUE(callback_called);
 125  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 126  E :  }
 127    :  
 128  E :  TEST_F(AsanRuntimeTest, SetDefaultQuarantineMaxSize) {
 129    :    // Initialize the flags with the original command line.
 130    :    ASSERT_NO_FATAL_FAILURE(
 131  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 132    :  
 133    :    // Double the max size of the quarantine.
 134    :    unsigned int quarantine_max_size =
 135  E :        HeapProxy::default_quarantine_max_size() * 2;
 136    :    // Increments the quarantine max size if it was set to 0.
 137  E :    if (quarantine_max_size == 0)
 138  i :      quarantine_max_size++;
 139  E :    DCHECK_GT(quarantine_max_size, 0U);
 140  E :    std::string quarantine_max_size_str = base::UintToString(quarantine_max_size);
 141    :    current_command_line_.AppendSwitchASCII(TestAsanRuntime::kQuarantineSize,
 142  E :                                            quarantine_max_size_str);
 143    :  
 144    :    // Tear down the runtime and restart it with a different command line.
 145  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.TearDown());
 146    :    ASSERT_NO_FATAL_FAILURE(
 147  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 148    :  
 149    :    // Ensure that the quarantine max size has been modified.
 150  E :    EXPECT_EQ(quarantine_max_size, HeapProxy::default_quarantine_max_size());
 151    :  
 152    :    // Ensure that the heap proxies use the new quarantine max size.
 153  E :    HeapProxy heap_proxy;
 154  E :    ASSERT_TRUE(heap_proxy.Create(0, 0, 0));
 155  E :    EXPECT_EQ(quarantine_max_size, heap_proxy.quarantine_max_size());
 156  E :    ASSERT_TRUE(heap_proxy.Destroy());
 157  E :  }
 158    :  
 159  E :  TEST_F(AsanRuntimeTest, SetCompressionReportingPeriod) {
 160    :    ASSERT_EQ(StackCaptureCache::GetDefaultCompressionReportingPeriod(),
 161  E :              StackCaptureCache::compression_reporting_period());
 162    :  
 163    :    size_t new_period =
 164  E :        StackCaptureCache::GetDefaultCompressionReportingPeriod() + 1024;
 165  E :    std::string new_period_str = base::UintToString(new_period);
 166    :    current_command_line_.AppendSwitchASCII(
 167  E :        TestAsanRuntime::kCompressionReportingPeriod, new_period_str);
 168    :  
 169    :    ASSERT_NO_FATAL_FAILURE(
 170  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 171    :  
 172    :    // Ensure that the compression reporting period has been modified.
 173  E :    EXPECT_EQ(new_period, StackCaptureCache::compression_reporting_period());
 174  E :  }
 175    :  
 176  E :  TEST_F(AsanRuntimeTest, SetBottomFramesToSkip) {
 177  E :    size_t frames_to_skip = StackCapture::bottom_frames_to_skip() + 1;
 178  E :    std::string new_frames_to_skip_str = base::UintToString(frames_to_skip);
 179    :    current_command_line_.AppendSwitchASCII(
 180  E :        TestAsanRuntime::kBottomFramesToSkip, new_frames_to_skip_str);
 181    :  
 182    :    ASSERT_NO_FATAL_FAILURE(
 183  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 184    :  
 185  E :    EXPECT_EQ(frames_to_skip, StackCapture::bottom_frames_to_skip());
 186  E :  }
 187    :  
 188  E :  TEST_F(AsanRuntimeTest, SetTrailerPaddingSize) {
 189  E :    size_t trailer_padding_size = HeapProxy::trailer_padding_size() + 1;
 190    :    std::string new_trailer_padding_size_str =
 191  E :        base::UintToString(trailer_padding_size);
 192    :    current_command_line_.AppendSwitchASCII(
 193  E :        TestAsanRuntime::kTrailerPaddingSize, new_trailer_padding_size_str);
 194    :  
 195    :    ASSERT_NO_FATAL_FAILURE(
 196  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 197    :  
 198  E :    EXPECT_EQ(trailer_padding_size, HeapProxy::trailer_padding_size());
 199  E :  }
 200    :  
 201  E :  TEST_F(AsanRuntimeTest, SetExitOnFailure) {
 202  E :    current_command_line_.AppendSwitch(TestAsanRuntime::kExitOnFailure);
 203    :  
 204    :    ASSERT_NO_FATAL_FAILURE(
 205  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 206  E :    EXPECT_TRUE(asan_runtime_.flags()->exit_on_failure);
 207  E :  }
 208    :  
 209  E :  TEST_F(AsanRuntimeTest, ExitOnFailure) {
 210  E :    current_command_line_.AppendSwitch(TestAsanRuntime::kExitOnFailure);
 211    :  
 212    :    ASSERT_NO_FATAL_FAILURE(
 213  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 214    :  
 215  E :    EXPECT_TRUE(asan_runtime_.flags()->exit_on_failure);
 216  E :    AsanErrorInfo bad_access_info = {};
 217  E :    RtlCaptureContext(&bad_access_info.context);
 218    :  
 219    :    // We need to delete the files and directory created by this unittest because
 220    :    // the EXPECT_EXIT macro will clone the process and this new process will exit
 221    :    // after the call to OnError, without calling the destructor of this class
 222    :    // (who takes care of deleting the temporary files/directories).
 223  E :    DeleteTempFileAndDirectory();
 224    :    EXPECT_EXIT(asan_runtime_.OnError(&bad_access_info),
 225  E :                ::testing::ExitedWithCode(EXIT_FAILURE), "");
 226  E :  }
 227    :  
 228  E :  TEST_F(AsanRuntimeTest, IgnoredStackIds) {
 229  E :    std::string ignored_stack_ids = "0x1;0X7E577E57;0xCAFEBABE;0xffffffff";
 230    :    current_command_line_.AppendSwitchASCII(
 231  E :        TestAsanRuntime::kIgnoredStackIds, ignored_stack_ids);
 232    :  
 233    :    ASSERT_NO_FATAL_FAILURE(
 234  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 235    :  
 236    :    EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0x1) !=
 237  E :                asan_runtime_.flags()->ignored_stack_ids.end());
 238    :    EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0x7E577E57) !=
 239  E :                asan_runtime_.flags()->ignored_stack_ids.end());
 240    :    EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0xCAFEBABE) !=
 241  E :                asan_runtime_.flags()->ignored_stack_ids.end());
 242    :    EXPECT_TRUE(asan_runtime_.flags()->ignored_stack_ids.find(0xFFFFFFFF) !=
 243  E :                asan_runtime_.flags()->ignored_stack_ids.end());
 244  E :  }
 245    :  
 246  E :  TEST_F(AsanRuntimeTest, SetFlags) {
 247    :    ASSERT_NO_FATAL_FAILURE(
 248  E :        asan_runtime_.SetUp(current_command_line_.GetCommandLineString()));
 249    :  
 250  E :    TestAsanRuntime::AsanFlags flags;
 251  E :    flags.quarantine_size = HeapProxy::default_quarantine_max_size() - 1;
 252  E :    ASSERT_LT(0U, flags.quarantine_size);
 253    :    flags.reporting_period =
 254  E :        StackCaptureCache::GetDefaultCompressionReportingPeriod() - 1;
 255  E :    ASSERT_LT(0U, flags.reporting_period);
 256    :    flags.bottom_frames_to_skip =
 257  E :        StackCapture::bottom_frames_to_skip() + 1;
 258  E :    ASSERT_LT(0U, flags.bottom_frames_to_skip);
 259    :    flags.max_num_frames =
 260  E :        asan_runtime_.stack_cache()->max_num_frames() - 1;
 261  E :    ASSERT_LT(0U, flags.max_num_frames);
 262  E :    asan_runtime_.set_flags(&flags);
 263  E :    asan_runtime_.PropagateFlagsValues();
 264    :  
 265  E :    ASSERT_EQ(flags.quarantine_size, HeapProxy::default_quarantine_max_size());
 266    :    ASSERT_EQ(flags.reporting_period,
 267  E :              StackCaptureCache::compression_reporting_period());
 268  E :    ASSERT_EQ(flags.bottom_frames_to_skip, StackCapture::bottom_frames_to_skip());
 269    :    ASSERT_EQ(flags.max_num_frames,
 270  E :              asan_runtime_.stack_cache()->max_num_frames());
 271  E :  }
 272    :  
 273  E :  TEST_F(AsanRuntimeTest, NotOptedInWithNoCoinToss) {
 274  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.SetUp(std::wstring()));
 275  E :    ASSERT_FALSE(asan_runtime_.flags()->opted_in);
 276  E :  }
 277    :  
 278  E :  TEST_F(AsanRuntimeTest, NotOptedInWithInvalidCoinToss) {
 279    :    env_->SetVar(TestAsanRuntime::kSyzygyAsanCoinTossEnvVar,
 280  E :                 "This is not a numeric value.");
 281  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.SetUp(std::wstring()));
 282  E :    ASSERT_FALSE(asan_runtime_.flags()->opted_in);
 283  E :  }
 284    :  
 285  E :  TEST_F(AsanRuntimeTest, OptedInWithCoinToss) {
 286  E :    env_->SetVar(TestAsanRuntime::kSyzygyAsanCoinTossEnvVar, "0xF");
 287  E :    ASSERT_NO_FATAL_FAILURE(asan_runtime_.SetUp(std::wstring()));
 288  E :    ASSERT_TRUE(asan_runtime_.flags()->opted_in);
 289    :    ASSERT_NE(TestHeapProxy::kDefaultQuarantineMaxSize,
 290  E :              asan_runtime_.flags()->quarantine_size);
 291  E :    ASSERT_NE(0u, asan_runtime_.flags()->trailer_padding_size);
 292  E :  }
 293    :  
 294    :  }  // namespace asan
 295    :  }  // namespace agent

Coverage information generated Wed Dec 11 11:34:16 2013.