Coverage for /Syzygy/agent/basic_block_entry/basic_block_entry_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
90.5%4504970.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    :  // BasicBlockEntry trace agent unit-tests.
  16    :  
  17    :  #include "syzygy/agent/basic_block_entry/basic_block_entry.h"
  18    :  
  19    :  #include "base/bind.h"
  20    :  #include "base/callback.h"
  21    :  #include "base/file_util.h"
  22    :  #include "base/files/file_enumerator.h"
  23    :  #include "base/files/scoped_temp_dir.h"
  24    :  #include "base/strings/stringprintf.h"
  25    :  #include "base/threading/thread.h"
  26    :  #include "gmock/gmock.h"
  27    :  #include "gtest/gtest.h"
  28    :  #include "syzygy/common/indexed_frequency_data.h"
  29    :  #include "syzygy/trace/common/unittest_util.h"
  30    :  #include "syzygy/trace/parse/unittest_util.h"
  31    :  
  32    :  // There's a quick and dirty way to get the HMODULE of this module for MS
  33    :  // linkers. HINSTANCE == HMODULE == &__ImageBase;
  34    :  // See http://blogs.msdn.com/b/oldnewthing/archive/2004/10/25/247180.aspx
  35    :  EXTERN_C IMAGE_DOS_HEADER __ImageBase;
  36    :  
  37    :  namespace agent {
  38    :  namespace basic_block_entry {
  39    :  
  40    :  namespace {
  41    :  
  42    :  using ::common::IndexedFrequencyData;
  43    :  using testing::_;
  44    :  using testing::StrictMockParseEventHandler;
  45    :  using trace::parser::Parser;
  46    :  
  47    :  // This is the name of the agent DLL.
  48    :  const wchar_t kBasicBlockEntryClientDll[] = L"basic_block_entry_client.dll";
  49    :  
  50    :  // The number of columns we'll work with for these tests.
  51    :  const uint32 kNumColumns = 1;
  52    :  const uint32 kNumBranchColumns = 3;
  53    :  
  54    :  // The number of basic blocks we'll work with for these tests.
  55    :  const uint32 kNumBasicBlocks = 2;
  56    :  
  57    :  // The number of threads used for parallel tests.
  58    :  const uint32 kNumThreads = 8;
  59    :  
  60    :  // Number of iterations done by each thread.
  61    :  const uint32 kNumThreadIteration = 4 * BasicBlockEntry::kBufferSize;
  62    :  
  63    :  // The module defining this lib/executable.
  64    :  const HMODULE kThisModule = reinterpret_cast<HMODULE>(&__ImageBase);
  65    :  
  66    :  // A helper to match modules by base address.
  67  E :  MATCHER_P(ModuleAtAddress, module, "") {
  68  E :    return arg->module_base_addr == module;
  69  E :  }
  70    :  
  71    :  // A helper to match basic-block frequency results to expectations.
  72  E :  MATCHER_P3(FrequencyDataMatches, module, values_count, bb_freqs, "") {
  73  E :    if (arg->module_base_addr != module)
  74  i :      return false;
  75    :  
  76  E :    if (arg->frequency_size != sizeof(uint32))
  77  i :      return false;
  78    :  
  79  E :    if (arg->num_entries * arg->num_columns != values_count)
  80  i :      return false;
  81    :  
  82  E :    return ::memcmp(bb_freqs, arg->frequency_data, values_count) == 0;
  83  E :  }
  84    :  
  85    :  // The test fixture for the basic-block entry agent.
  86    :  class BasicBlockEntryTest : public testing::Test {
  87    :   public:
  88    :    enum InstrumentationMode {
  89    :      kBasicBlockEntryInstrumentation,
  90    :      kBranchInstrumentation,
  91    :      kBufferedBranchInstrumentation,
  92    :      kBranchWithSlotInstrumentation,
  93    :      kBufferedBranchWithSlotInstrumentation
  94    :    };
  95    :  
  96    :    enum MainMode {
  97    :      kDllMain,
  98    :      kExeMain
  99    :    };
 100    :  
 101  E :    BasicBlockEntryTest()
 102    :        : agent_module_(NULL) {
 103  E :    }
 104    :  
 105  E :    void ConfigureBasicBlockAgent() {
 106  E :      common_data_->agent_id = ::common::kBasicBlockEntryAgentId;
 107  E :      common_data_->data_type = ::common::IndexedFrequencyData::BASIC_BLOCK_ENTRY;
 108  E :      common_data_->version = ::common::kBasicBlockFrequencyDataVersion;
 109  E :      module_data_.tls_index = TLS_OUT_OF_INDEXES;
 110  E :      module_data_.fs_slot = 0;
 111  E :      common_data_->initialization_attempted = 0U;
 112  E :      common_data_->num_entries = kNumBasicBlocks;
 113  E :      common_data_->num_columns = kNumColumns;
 114  E :      common_data_->frequency_size = sizeof(default_frequency_data_[0]);
 115  E :      common_data_->frequency_data = default_frequency_data_;
 116  E :      ::memset(&default_frequency_data_, 0, sizeof(default_frequency_data_));
 117  E :    }
 118    :  
 119  E :    void ConfigureBranchAgent() {
 120  E :      common_data_->agent_id = ::common::kBasicBlockEntryAgentId;
 121  E :      common_data_->data_type = ::common::IndexedFrequencyData::BRANCH;
 122  E :      common_data_->version = ::common::kBasicBlockFrequencyDataVersion;
 123  E :      module_data_.tls_index = TLS_OUT_OF_INDEXES;
 124  E :      module_data_.fs_slot = 0;
 125  E :      common_data_->initialization_attempted = 0U;
 126  E :      common_data_->num_entries = kNumBasicBlocks;
 127  E :      common_data_->num_columns = kNumBranchColumns;
 128  E :      common_data_->frequency_size = sizeof(default_branch_data_[0]);
 129  E :      common_data_->frequency_data = default_branch_data_;
 130  E :      ::memset(&default_branch_data_, 0, sizeof(default_branch_data_));
 131  E :    }
 132    :  
 133  E :    void ConfigureAgent(InstrumentationMode mode) {
 134  E :      switch (mode) {
 135    :        case kBasicBlockEntryInstrumentation:
 136  E :          ConfigureBasicBlockAgent();
 137  E :          break;
 138    :        case kBranchInstrumentation:
 139    :        case kBufferedBranchInstrumentation:
 140  E :          ConfigureBranchAgent();
 141  E :          break;
 142    :        case kBranchWithSlotInstrumentation:
 143    :        case kBufferedBranchWithSlotInstrumentation:
 144  E :          ConfigureBranchAgent();
 145  E :          module_data_.fs_slot = 1;
 146  E :          break;
 147    :        default:
 148  i :          NOTREACHED();
 149    :          break;
 150    :      }
 151  E :    }
 152    :  
 153  E :    void Startup(MainMode mode) {
 154  E :      switch (mode) {
 155    :        case kDllMain:
 156    :          // Simulate the process attach event.
 157  E :          SimulateModuleEvent(DLL_PROCESS_ATTACH);
 158  E :          break;
 159    :        case kExeMain:
 160    :          // Simulate the call to main.
 161  E :          ExeMainThunk();
 162  E :          break;
 163    :        default:
 164  i :          NOTREACHED();
 165    :          break;
 166    :      }
 167  E :    }
 168    :  
 169  E :    void Shutdown(MainMode mode) {
 170  E :      switch (mode) {
 171    :        case kDllMain:
 172    :          // Simulate the process detach event.
 173  E :          SimulateModuleEvent(DLL_PROCESS_DETACH);
 174  E :          break;
 175    :        case kExeMain:
 176  E :          break;
 177    :        default:
 178  i :          NOTREACHED();
 179    :          break;
 180    :      }
 181  E :    }
 182    :  
 183  E :    virtual void SetUp() OVERRIDE {
 184  E :      testing::Test::SetUp();
 185  E :      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 186  E :      service_.SetEnvironment();
 187  E :      common_data_ = &module_data_.module_data;
 188  E :    }
 189    :  
 190  E :    virtual void TearDown() OVERRIDE {
 191  E :      UnloadDll();
 192  E :      service_.Stop();
 193  E :    }
 194    :  
 195  E :    void StartService() {
 196  E :      service_.Start(temp_dir_.path());
 197  E :    }
 198    :  
 199  E :    void StopService() {
 200  E :      service_.Stop();
 201  E :    }
 202    :  
 203  E :    void ReplayLogs(size_t files_expected) {
 204    :      // Stop the service if it's running.
 205  E :      ASSERT_NO_FATAL_FAILURE(StopService());
 206    :  
 207  E :      Parser parser;
 208  E :      ASSERT_TRUE(parser.Init(&handler_));
 209    :  
 210    :      // Queue up the trace file(s) we engendered.
 211    :      base::FileEnumerator enumerator(temp_dir_.path(),
 212    :                                      false,
 213  E :                                      base::FileEnumerator::FILES);
 214  E :      size_t num_files = 0;
 215  E :      while (true) {
 216  E :        base::FilePath trace_file = enumerator.Next();
 217  E :        if (trace_file.empty())
 218  E :          break;
 219  E :        ASSERT_TRUE(parser.OpenTraceFile(trace_file));
 220  E :        ++num_files;
 221  E :      }
 222    :  
 223  E :      EXPECT_EQ(files_expected, num_files);
 224    :  
 225  E :      if (num_files > 0)
 226  E :        ASSERT_TRUE(parser.Consume());
 227  E :    }
 228    :  
 229  E :    void LoadDll() {
 230  E :      ASSERT_EQ(NULL, agent_module_);
 231  E :      ASSERT_EQ(NULL, basic_block_enter_stub_);
 232  E :      ASSERT_EQ(NULL, ::GetModuleHandle(kBasicBlockEntryClientDll));
 233    :  
 234  E :      agent_module_ = ::LoadLibrary(kBasicBlockEntryClientDll);
 235  E :      ASSERT_TRUE(agent_module_ != NULL);
 236    :  
 237    :      basic_block_enter_stub_ =
 238  E :          ::GetProcAddress(agent_module_, "_branch_enter");
 239  E :      ASSERT_TRUE(basic_block_enter_stub_ != NULL);
 240    :  
 241    :      basic_block_enter_buffered_stub_ =
 242  E :          ::GetProcAddress(agent_module_, "_branch_enter_buffered");
 243  E :      ASSERT_TRUE(basic_block_enter_buffered_stub_ != NULL);
 244    :  
 245    :      basic_block_enter_s1_stub_ =
 246  E :          ::GetProcAddress(agent_module_, "_branch_enter_s1");
 247  E :      ASSERT_TRUE(basic_block_enter_s1_stub_ != NULL);
 248    :  
 249    :      basic_block_enter_buffered_s1_stub_ =
 250  E :          ::GetProcAddress(agent_module_, "_branch_enter_buffered_s1");
 251  E :      ASSERT_TRUE(basic_block_enter_buffered_s1_stub_ != NULL);
 252    :  
 253    :      basic_block_exit_stub_ =
 254  E :          ::GetProcAddress(agent_module_, "_branch_exit");
 255  E :      ASSERT_TRUE(basic_block_exit_stub_ != NULL);
 256    :  
 257    :      basic_block_exit_s1_stub_ =
 258  E :          ::GetProcAddress(agent_module_, "_branch_exit_s1");
 259  E :      ASSERT_TRUE(basic_block_exit_s1_stub_ != NULL);
 260    :  
 261    :      basic_block_function_enter_s1_stub_ =
 262  E :          ::GetProcAddress(agent_module_, "_function_enter_s1");
 263  E :      ASSERT_TRUE(basic_block_function_enter_s1_stub_ != NULL);
 264    :  
 265    :      basic_block_increment_stub_ =
 266  E :          ::GetProcAddress(agent_module_, "_increment_indexed_freq_data");
 267  E :      ASSERT_TRUE(basic_block_increment_stub_ != NULL);
 268    :  
 269    :      indirect_penter_dllmain_stub_ =
 270  E :          ::GetProcAddress(agent_module_, "_indirect_penter_dllmain");
 271  E :      ASSERT_TRUE(indirect_penter_dllmain_stub_ != NULL);
 272    :  
 273    :      indirect_penter_exemain_stub_ =
 274  E :          ::GetProcAddress(agent_module_, "_indirect_penter_exemain");
 275  E :      ASSERT_TRUE(indirect_penter_exemain_stub_ != NULL);
 276  E :    }
 277    :  
 278  E :    void UnloadDll() {
 279  E :      if (agent_module_ != NULL) {
 280  E :        ASSERT_TRUE(::FreeLibrary(agent_module_));
 281  E :        agent_module_ = NULL;
 282  E :        basic_block_enter_stub_ = NULL;
 283  E :        basic_block_enter_buffered_stub_ = NULL;
 284  E :        basic_block_enter_s1_stub_ = NULL;
 285  E :        basic_block_enter_buffered_s1_stub_ = NULL;
 286  E :        basic_block_exit_stub_ = NULL;
 287  E :        basic_block_exit_s1_stub_ = NULL;
 288  E :        basic_block_function_enter_s1_stub_ = NULL;
 289  E :        basic_block_increment_stub_ = NULL;
 290  E :        indirect_penter_dllmain_stub_ = NULL;
 291  E :        indirect_penter_exemain_stub_ = NULL;
 292    :      }
 293  E :    }
 294    :  
 295    :   protected:
 296    :    static BOOL WINAPI DllMain(HMODULE module, DWORD reason, LPVOID reserved);
 297    :    static BOOL WINAPI DllMainThunk(
 298    :        HMODULE module, DWORD reason, LPVOID reserved);
 299    :    static int __cdecl ExeMain();
 300    :    static int __cdecl ExeMainThunk();
 301    :    static int __cdecl GetFrequencyDataThunk();
 302    :  
 303  E :    void SimulateModuleEvent(DWORD reason) {
 304  E :      DllMainThunk(kThisModule, reason, NULL);
 305  E :    }
 306    :  
 307  i :    void SimulateBasicBlockEntry(uint32 basic_block_id) {
 308    :      __asm {
 309  i :        push basic_block_id
 310  i :        push offset module_data_
 311  i :        call basic_block_increment_stub_
 312    :      }
 313  i :    }
 314    :  
 315  i :    void SimulateBranchEnter(uint32 basic_block_id) {
 316    :      __asm {
 317  i :        push basic_block_id
 318  i :        push offset module_data_
 319  i :        call basic_block_enter_stub_
 320    :      }
 321  i :    }
 322    :  
 323  i :    void SimulateBranchEnterBuffered(uint32 basic_block_id) {
 324    :      __asm {
 325  i :        push basic_block_id
 326  i :        push offset module_data_
 327  i :        call basic_block_enter_buffered_stub_
 328    :      }
 329  i :    }
 330    :  
 331  i :    void SimulateFunctionEnter() {
 332    :      __asm {
 333  i :        push offset module_data_
 334  i :        call basic_block_function_enter_s1_stub_
 335    :      }
 336  i :    }
 337    :  
 338  i :    void SimulateBranchEnterSlot(uint32 basic_block_id) {
 339    :      __asm {
 340  i :        push basic_block_id
 341  i :        call basic_block_enter_s1_stub_
 342    :      }
 343  i :    }
 344    :  
 345  i :    void SimulateBranchEnterBufferedSlot(uint32 basic_block_id) {
 346    :      __asm {
 347  i :        push basic_block_id
 348  i :        call basic_block_enter_buffered_s1_stub_
 349    :      }
 350  i :    }
 351    :  
 352  i :    void SimulateBranchExit(uint32 basic_block_id) {
 353    :      __asm {
 354  i :        push basic_block_id
 355  i :        push offset module_data_
 356  i :        call basic_block_exit_stub_
 357    :      }
 358  i :    }
 359    :  
 360    :    void SimulateBranchExitSlot(uint32 basic_block_id) {
 361    :      __asm {
 362    :        push basic_block_id
 363    :        call basic_block_exit_s1_stub_
 364    :      }
 365    :    }
 366    :  
 367  E :    void SimulateThreadFunction(InstrumentationMode mode) {
 368  E :      switch (mode) {
 369    :        case kBranchWithSlotInstrumentation:
 370    :        case kBufferedBranchWithSlotInstrumentation:
 371  E :          SimulateFunctionEnter();
 372    :          break;
 373    :      }
 374  E :    }
 375    :  
 376  E :    void SimulateThreadStep(InstrumentationMode mode, uint32 basic_block_id) {
 377  E :      switch (mode) {
 378    :        case kBasicBlockEntryInstrumentation:
 379  E :          SimulateBasicBlockEntry(basic_block_id);
 380  E :          break;
 381    :        case kBranchInstrumentation:
 382  E :          SimulateBranchEnter(basic_block_id);
 383  E :          SimulateBranchExit(basic_block_id);
 384  E :          break;
 385    :        case kBufferedBranchInstrumentation:
 386  E :          SimulateBranchEnterBuffered(basic_block_id);
 387  E :          SimulateBranchExit(basic_block_id);
 388  E :          break;
 389    :        case kBranchWithSlotInstrumentation:
 390  E :          SimulateBranchEnterSlot(basic_block_id);
 391  E :          SimulateBranchExit(basic_block_id);
 392  E :          break;
 393    :        case kBufferedBranchWithSlotInstrumentation:
 394  E :          SimulateBranchEnterBufferedSlot(basic_block_id);
 395  E :          SimulateBranchExit(basic_block_id);
 396  E :          break;
 397    :        default:
 398  i :          NOTREACHED();
 399    :          break;
 400    :      }
 401  E :    }
 402    :  
 403  E :    void SimulateThreadExecution(MainMode main_mode, InstrumentationMode mode) {
 404    :      // Simulate the thread attach event.
 405  E :      if (main_mode == kDllMain)
 406  E :        SimulateModuleEvent(DLL_THREAD_ATTACH);
 407    :  
 408    :      // Simulate entering a function.
 409  E :      SimulateThreadFunction(mode);
 410    :  
 411    :      // Simulate the thread loop.
 412  E :      for (uint32 i = 0; i < kNumThreadIteration; ++i) {
 413  E :        for (uint32 j = 0; j < kNumBasicBlocks; ++j)
 414  E :          SimulateThreadStep(mode, j);
 415  E :      }
 416    :  
 417    :      // Simulate the thread detach event.
 418  E :      if (main_mode == kDllMain)
 419  E :        SimulateModuleEvent(DLL_THREAD_DETACH);
 420  E :    }
 421    :  
 422  E :    void CheckThreadExecution(MainMode main_mode, InstrumentationMode mode) {
 423    :      // Configure for instrumented mode.
 424  E :      ConfigureAgent(mode);
 425    :  
 426  E :      ASSERT_NO_FATAL_FAILURE(StartService());
 427  E :      ASSERT_NO_FATAL_FAILURE(LoadDll());
 428    :  
 429  E :      Startup(main_mode);
 430    :  
 431  E :      std::vector<base::Thread*> threads;
 432  E :      for (size_t i = 0; i < kNumThreads; ++i) {
 433  E :        std::string thread_name = base::StringPrintf("thread-%d", i);
 434  E :        threads.push_back(new base::Thread(thread_name.c_str()));
 435    :  
 436  E :        threads[i]->Start();
 437    :        threads[i]->message_loop()->PostTask(FROM_HERE,
 438    :            base::Bind(&BasicBlockEntryTest::SimulateThreadExecution,
 439    :                       base::Unretained(this),
 440    :                       main_mode,
 441  E :                       mode));
 442  E :      }
 443    :  
 444    :      // Stop all running tasks.
 445  E :      for (size_t i = 0; i < kNumThreads; ++i) {
 446  E :        threads[i]->Stop();
 447  E :        delete threads[i];
 448  E :      }
 449  E :      threads.clear();
 450    :  
 451  E :      Shutdown(main_mode);
 452    :  
 453    :      // Validate all events have been committed.
 454    :      const uint32* frequency_data =
 455  E :          reinterpret_cast<uint32*>(common_data_->frequency_data);
 456  E :      uint32 num_columns = common_data_->num_columns;
 457    :  
 458  E :      const uint32 expected_frequency = kNumThreads * kNumThreadIteration;
 459  E :      for (size_t i = 0; i < kNumBasicBlocks; ++i) {
 460  E :        EXPECT_EQ(expected_frequency, frequency_data[i * num_columns]);
 461  E :      }
 462    :  
 463    :      // Unload the DLL and stop the service.
 464  E :      ASSERT_NO_FATAL_FAILURE(UnloadDll());
 465  E :      ASSERT_NO_FATAL_FAILURE(StopService());
 466  E :    }
 467    :  
 468  E :    void CheckExecution(MainMode main_mode, InstrumentationMode mode) {
 469    :      // Configure for instrumented mode.
 470  E :      ConfigureAgent(mode);
 471    :  
 472  E :      ASSERT_NO_FATAL_FAILURE(StartService());
 473  E :      ASSERT_NO_FATAL_FAILURE(LoadDll());
 474    :  
 475    :      // Simulate the process attach event.
 476  E :      Startup(main_mode);
 477    :  
 478    :      // Simulate entering a function.
 479  E :      SimulateThreadFunction(mode);
 480    :  
 481    :      // Keep a pointer to raw counters.
 482    :      const uint32* frequency_data =
 483  E :          reinterpret_cast<uint32*>(common_data_->frequency_data);
 484  E :      uint32 num_columns = common_data_->num_columns;
 485    :  
 486    :      // Validate no events have been committed.
 487  E :      for (size_t i = 0; i < num_columns; ++i) {
 488  E :        EXPECT_EQ(0U, frequency_data[i]);
 489  E :      }
 490    :  
 491    :      // Simulate a sequential execution.
 492  E :      for (size_t i = 0; i < kNumThreads; ++i) {
 493  E :        for (uint32 j = 0; j < kNumThreadIteration; ++j) {
 494  E :          for (uint32 k = 0; k < kNumBasicBlocks; ++k)
 495  E :            SimulateThreadStep(mode, k);
 496  E :        }
 497  E :      }
 498    :  
 499    :      // Simulate the process detach event.
 500  E :      Shutdown(main_mode);
 501    :  
 502    :      // Validate all events have been committed.
 503  E :      const uint32 expected_frequency = kNumThreads * kNumThreadIteration;
 504  E :      for (size_t i = 0; i < kNumBasicBlocks; ++i) {
 505  E :        EXPECT_EQ(expected_frequency, frequency_data[i * num_columns]);
 506  E :      }
 507    :  
 508    :      // Unload the DLL and stop the service.
 509  E :      ASSERT_NO_FATAL_FAILURE(UnloadDll());
 510  E :      ASSERT_NO_FATAL_FAILURE(StopService());
 511  E :    }
 512    :  
 513    :    // The directory where trace file output will be written.
 514    :    base::ScopedTempDir temp_dir_;
 515    :  
 516    :    // The handler to which the trace file parser will delegate events.
 517    :    StrictMockParseEventHandler handler_;
 518    :  
 519    :    // Our call trace service process instance.
 520    :    testing::CallTraceService service_;
 521    :  
 522    :    // The basic-block entry client module.
 523    :    HMODULE agent_module_;
 524    :  
 525    :    // This will be a stand-in for the (usually statically allocated) trace
 526    :    // data which would have been referenced by the instrumentation.
 527    :    static BasicBlockEntry::BasicBlockIndexedFrequencyData module_data_;
 528    :    static BasicBlockEntry::IndexedFrequencyData* common_data_;
 529    :  
 530    :    // This will be a stand-in for the (usually statically allocated) fall-back
 531    :    // frequency to which module_data_.frequency_data will point.
 532    :    static uint32 default_frequency_data_[kNumBasicBlocks];
 533    :    static uint32 default_branch_data_[kNumBranchColumns * kNumBasicBlocks];
 534    :  
 535    :    // The basic-block entry entrance hook.
 536    :    static FARPROC basic_block_enter_stub_;
 537    :  
 538    :    // The basic-block entry entrance hook (with buffering).
 539    :    static FARPROC basic_block_enter_buffered_stub_;
 540    :  
 541    :    // The basic-block entry entrance hook (FS-slot 1).
 542    :    static FARPROC basic_block_enter_s1_stub_;
 543    :  
 544    :    // The basic-block entry entrance hook (with buffering and FS-slot 1).
 545    :    static FARPROC basic_block_enter_buffered_s1_stub_;
 546    :  
 547    :    // The basic-block exit hook.
 548    :    static FARPROC basic_block_exit_stub_;
 549    :  
 550    :    // The basic-block exit hook (FS-slot 1).
 551    :    static FARPROC basic_block_exit_s1_stub_;
 552    :  
 553    :    // The function entrance hook (FS-slot 1).
 554    :    static FARPROC basic_block_function_enter_s1_stub_;
 555    :  
 556    :    // The basic-block increment hook.
 557    :    static FARPROC basic_block_increment_stub_;
 558    :  
 559    :    // The DllMain entry stub.
 560    :    static FARPROC indirect_penter_dllmain_stub_;
 561    :  
 562    :    // The ExeMain entry stub.
 563    :    static FARPROC indirect_penter_exemain_stub_;
 564    :  };
 565    :  
 566    :  BOOL WINAPI BasicBlockEntryTest::DllMain(
 567  E :      HMODULE module, DWORD reason, LPVOID reserved) {
 568  E :    return TRUE;
 569  E :  }
 570    :  
 571    :  BOOL __declspec(naked) WINAPI BasicBlockEntryTest::DllMainThunk(
 572  i :      HMODULE module, DWORD reason, LPVOID reserved) {
 573    :    __asm {
 574  i :      push offset module_data_
 575  i :      push DllMain
 576  i :      jmp indirect_penter_dllmain_stub_
 577    :    }
 578    :  }
 579    :  
 580  E :  int __cdecl BasicBlockEntryTest::ExeMain() {
 581  E :    return 0;
 582  E :  }
 583    :  
 584  i :  BOOL __declspec(naked) __cdecl BasicBlockEntryTest::ExeMainThunk() {
 585    :    __asm {
 586  i :      push offset module_data_
 587  i :      push ExeMain
 588  i :      jmp indirect_penter_exemain_stub_
 589    :    }
 590    :  }
 591    :  
 592    :  BasicBlockEntry::BasicBlockIndexedFrequencyData
 593    :      BasicBlockEntryTest::module_data_ = {};
 594    :  BasicBlockEntry::IndexedFrequencyData* BasicBlockEntryTest::common_data_ = NULL;
 595    :  uint32 BasicBlockEntryTest::default_frequency_data_[] = {};
 596    :  uint32 BasicBlockEntryTest::default_branch_data_[] = {};
 597    :  FARPROC BasicBlockEntryTest::basic_block_enter_stub_ = NULL;
 598    :  FARPROC BasicBlockEntryTest::basic_block_enter_buffered_stub_ = NULL;
 599    :  FARPROC BasicBlockEntryTest::basic_block_enter_s1_stub_ = NULL;
 600    :  FARPROC BasicBlockEntryTest::basic_block_enter_buffered_s1_stub_ = NULL;
 601    :  FARPROC BasicBlockEntryTest::basic_block_exit_stub_ = NULL;
 602    :  FARPROC BasicBlockEntryTest::basic_block_exit_s1_stub_ = NULL;
 603    :  FARPROC BasicBlockEntryTest::basic_block_function_enter_s1_stub_ = NULL;
 604    :  FARPROC BasicBlockEntryTest::basic_block_increment_stub_ = NULL;
 605    :  FARPROC BasicBlockEntryTest::indirect_penter_dllmain_stub_ = NULL;
 606    :  FARPROC BasicBlockEntryTest::indirect_penter_exemain_stub_ = NULL;
 607    :  
 608    :  }  // namespace
 609    :  
 610  E :  TEST_F(BasicBlockEntryTest, NoServerNoCrash) {
 611    :    // Configure for BasicBlock mode.
 612  E :    ConfigureBasicBlockAgent();
 613    :  
 614    :    // Load the agent dll.
 615  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 616    :  
 617    :    // Simulate the process attach event.
 618  E :    SimulateModuleEvent(DLL_PROCESS_ATTACH);
 619    :  
 620    :    // Validate that it only modified the tls_index and initialization_attempted
 621    :    // values.
 622  E :    ASSERT_EQ(::common::kBasicBlockEntryAgentId, common_data_->agent_id);
 623  E :    ASSERT_EQ(::common::kBasicBlockFrequencyDataVersion, common_data_->version);
 624  E :    ASSERT_EQ(IndexedFrequencyData::BASIC_BLOCK_ENTRY, common_data_->data_type);
 625  E :    ASSERT_NE(TLS_OUT_OF_INDEXES, module_data_.tls_index);
 626  E :    ASSERT_EQ(0U, module_data_.fs_slot);
 627  E :    ASSERT_NE(0U, common_data_->initialization_attempted);
 628  E :    ASSERT_EQ(kNumColumns, common_data_->num_columns);
 629  E :    ASSERT_EQ(kNumBasicBlocks, common_data_->num_entries);
 630  E :    ASSERT_EQ(default_frequency_data_, common_data_->frequency_data);
 631    :  
 632    :    // Visiting an initial basic-block should not fail. It should increment the
 633    :    // call count in the default array.
 634  E :    SimulateBasicBlockEntry(0);
 635  E :    ASSERT_EQ(1U, default_frequency_data_[0]);
 636  E :    ASSERT_EQ(0U, default_frequency_data_[1]);
 637    :  
 638    :    // Re-visiting the same basic-block should only update the frequency array.
 639  E :    DWORD new_tls_index = module_data_.tls_index;
 640  E :    SimulateBasicBlockEntry(0);
 641  E :    ASSERT_EQ(new_tls_index, module_data_.tls_index);
 642  E :    ASSERT_EQ(2U, default_frequency_data_[0]);
 643  E :    ASSERT_EQ(0U, default_frequency_data_[1]);
 644    :  
 645    :    // Visiting a different basic-block should only update the frequency array.
 646  E :    SimulateBasicBlockEntry(1);
 647  E :    ASSERT_EQ(new_tls_index, module_data_.tls_index);
 648  E :    ASSERT_EQ(2U, default_frequency_data_[0]);
 649  E :    ASSERT_EQ(1U, default_frequency_data_[1]);
 650    :  
 651    :    // FS-Slot must stay unchanged.
 652  E :    ASSERT_EQ(0U, module_data_.fs_slot);
 653    :  
 654    :    // Simulate the process detach event.
 655  E :    SimulateModuleEvent(DLL_PROCESS_DETACH);
 656    :  
 657    :    // Unload the DLL.
 658  E :    ASSERT_NO_FATAL_FAILURE(UnloadDll());
 659    :  
 660    :    // Replay the log. There should be none as we didn't start the service.
 661  E :    ASSERT_NO_FATAL_FAILURE(ReplayLogs(0));
 662  E :  }
 663    :  
 664  E :  TEST_F(BasicBlockEntryTest, SingleThreadedDllBasicBlockEvents) {
 665    :    // Configure for BasicBlock mode.
 666  E :    ConfigureBasicBlockAgent();
 667    :  
 668  E :    ASSERT_NO_FATAL_FAILURE(StartService());
 669  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 670    :  
 671    :    // Simulate the process attach event.
 672  E :    SimulateModuleEvent(DLL_PROCESS_ATTACH);
 673    :  
 674    :    // Validate that it does not modify any of our initialization values.
 675  E :    ASSERT_EQ(::common::kBasicBlockEntryAgentId, common_data_->agent_id);
 676  E :    ASSERT_EQ(::common::kBasicBlockFrequencyDataVersion, common_data_->version);
 677  E :    ASSERT_EQ(IndexedFrequencyData::BASIC_BLOCK_ENTRY, common_data_->data_type);
 678  E :    ASSERT_NE(TLS_OUT_OF_INDEXES, module_data_.tls_index);
 679  E :    ASSERT_EQ(0U, module_data_.fs_slot);
 680  E :    ASSERT_NE(0U, common_data_->initialization_attempted);
 681  E :    ASSERT_EQ(kNumColumns, common_data_->num_columns);
 682  E :    ASSERT_EQ(kNumBasicBlocks, common_data_->num_entries);
 683    :  
 684    :    // The frequency_data must be allocated and frequency_data must point to it.
 685  E :    ASSERT_NE(default_branch_data_, common_data_->frequency_data);
 686    :  
 687    :    // Visiting an initial basic-block should not fail.
 688  E :    SimulateBasicBlockEntry(0);
 689  E :    ASSERT_EQ(0U, default_frequency_data_[0]);
 690    :  
 691    :    // Make a few more calls, just to keep things interesting.
 692  E :    SimulateBasicBlockEntry(0);
 693  E :    SimulateBasicBlockEntry(1);
 694  E :    SimulateBasicBlockEntry(0);
 695    :  
 696    :    // Simulate the process detach event.
 697  E :    SimulateModuleEvent(DLL_PROCESS_DETACH);
 698    :  
 699    :    // Unload the DLL and stop the service.
 700  E :    ASSERT_NO_FATAL_FAILURE(UnloadDll());
 701    :  
 702  E :    HMODULE self = ::GetModuleHandle(NULL);
 703  E :    DWORD process_id = ::GetCurrentProcessId();
 704  E :    DWORD thread_id = ::GetCurrentThreadId();
 705    :  
 706    :    static const uint32 kExpectedFrequencyData[kNumBasicBlocks] = { 3, 1 };
 707    :  
 708    :    // Set up expectations for what should be in the trace.
 709  E :    EXPECT_CALL(handler_, OnProcessStarted(_, process_id, _));
 710    :    EXPECT_CALL(handler_, OnProcessAttach(_,
 711    :                                          process_id,
 712    :                                          thread_id,
 713  E :                                          ModuleAtAddress(self)));
 714    :    EXPECT_CALL(handler_, OnIndexedFrequency(
 715    :        _,
 716    :        process_id,
 717    :        thread_id,
 718  E :        FrequencyDataMatches(self, kNumBasicBlocks, kExpectedFrequencyData)));
 719  E :    EXPECT_CALL(handler_, OnProcessEnded(_, process_id));
 720    :  
 721    :    // Replay the log.
 722  E :    ASSERT_NO_FATAL_FAILURE(ReplayLogs(1));
 723  E :  }
 724    :  
 725  E :  TEST_F(BasicBlockEntryTest, SingleThreadedExeBasicBlockEvents) {
 726    :    // Configure for BasicBlock mode.
 727  E :    ConfigureBasicBlockAgent();
 728    :  
 729  E :    ASSERT_NO_FATAL_FAILURE(StartService());
 730  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 731    :  
 732    :    // Simulate the process attach event.
 733  E :    ExeMainThunk();
 734    :  
 735    :    // Validate that it does not modify any of our initialization values.
 736  E :    ASSERT_EQ(::common::kBasicBlockEntryAgentId, common_data_->agent_id);
 737  E :    ASSERT_EQ(::common::kBasicBlockFrequencyDataVersion, common_data_->version);
 738  E :    ASSERT_EQ(IndexedFrequencyData::BASIC_BLOCK_ENTRY, common_data_->data_type);
 739  E :    ASSERT_NE(TLS_OUT_OF_INDEXES, module_data_.tls_index);
 740  E :    ASSERT_EQ(0U, module_data_.fs_slot);
 741  E :    ASSERT_NE(0U, common_data_->initialization_attempted);
 742  E :    ASSERT_EQ(kNumColumns, common_data_->num_columns);
 743  E :    ASSERT_EQ(kNumBasicBlocks, common_data_->num_entries);
 744    :  
 745    :    // The frequency_data must be allocated and frequency_data must point to it.
 746  E :    ASSERT_NE(default_branch_data_, common_data_->frequency_data);
 747    :  
 748    :    // Visiting an initial basic-block should not fail.
 749  E :    SimulateBasicBlockEntry(0);
 750  E :    ASSERT_EQ(0U, default_frequency_data_[0]);
 751    :  
 752    :    // Make a few more calls, just to keep things interesting.
 753  E :    SimulateBasicBlockEntry(0);
 754  E :    SimulateBasicBlockEntry(1);
 755  E :    SimulateBasicBlockEntry(0);
 756    :  
 757    :    // Simulate the process detach event.
 758  E :    SimulateModuleEvent(DLL_PROCESS_DETACH);
 759    :  
 760    :    // Unload the DLL and stop the service.
 761  E :    ASSERT_NO_FATAL_FAILURE(UnloadDll());
 762    :  
 763  E :    HMODULE self = ::GetModuleHandle(NULL);
 764  E :    DWORD process_id = ::GetCurrentProcessId();
 765  E :    DWORD thread_id = ::GetCurrentThreadId();
 766    :  
 767    :    static const uint32 kExpectedFrequencyData[kNumBasicBlocks] = { 3, 1 };
 768    :  
 769    :    // Set up expectations for what should be in the trace.
 770  E :    EXPECT_CALL(handler_, OnProcessStarted(_, process_id, _));
 771    :    EXPECT_CALL(handler_, OnProcessAttach(_,
 772    :                                          process_id,
 773    :                                          thread_id,
 774  E :                                          ModuleAtAddress(self)));
 775    :    EXPECT_CALL(handler_, OnIndexedFrequency(
 776    :        _,
 777    :        process_id,
 778    :        thread_id,
 779  E :        FrequencyDataMatches(self, kNumBasicBlocks, kExpectedFrequencyData)));
 780  E :    EXPECT_CALL(handler_, OnProcessEnded(_, process_id));
 781    :  
 782    :    // Replay the log.
 783  E :    ASSERT_NO_FATAL_FAILURE(ReplayLogs(1));
 784  E :  }
 785    :  
 786  E :  TEST_F(BasicBlockEntryTest, SingleThreadedExeBranchEvents) {
 787    :    // Configure for Branch mode.
 788  E :    ConfigureBranchAgent();
 789    :  
 790  E :    ASSERT_NO_FATAL_FAILURE(StartService());
 791  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 792    :  
 793    :    // Simulate the process attach event.
 794  E :    ExeMainThunk();
 795    :  
 796    :    // Validate that it does not modify any of our initialization values.
 797  E :    ASSERT_EQ(::common::kBasicBlockEntryAgentId, common_data_->agent_id);
 798  E :    ASSERT_EQ(::common::kBasicBlockFrequencyDataVersion, common_data_->version);
 799  E :    ASSERT_EQ(IndexedFrequencyData::BRANCH, common_data_->data_type);
 800  E :    ASSERT_NE(TLS_OUT_OF_INDEXES, module_data_.tls_index);
 801  E :    ASSERT_EQ(0U, module_data_.fs_slot);
 802  E :    ASSERT_NE(0U, common_data_->initialization_attempted);
 803  E :    ASSERT_EQ(kNumBranchColumns, common_data_->num_columns);
 804  E :    ASSERT_EQ(kNumBasicBlocks, common_data_->num_entries);
 805    :  
 806    :    // The frequency_data must be allocated and frequency_data must point to it.
 807  E :    ASSERT_NE(default_branch_data_, common_data_->frequency_data);
 808    :  
 809    :    // Visiting an initial basic-block should not fail.
 810  E :    SimulateBranchEnter(0);
 811  E :    SimulateBranchExit(0);
 812  E :    ASSERT_NE(default_branch_data_, common_data_->frequency_data);
 813  E :    for (size_t i = 0; i < kNumBranchColumns; ++i) {
 814  E :      ASSERT_EQ(0U, default_branch_data_[i]);
 815  E :    }
 816    :  
 817    :    // Make a few more calls, just to keep things interesting.
 818  E :    SimulateBranchEnter(1);
 819  E :    SimulateBranchExit(1);
 820  E :    SimulateBranchEnter(0);
 821  E :    SimulateBranchExit(0);
 822  E :    SimulateBranchEnter(1);
 823  E :    SimulateBranchExit(1);
 824  E :    SimulateBranchEnter(0);
 825  E :    SimulateBranchExit(0);
 826  E :    for (int i = 0; i < 6; ++i) {
 827  E :      SimulateBranchEnter(1);
 828  E :      SimulateBranchExit(1);
 829  E :    }
 830  E :    for (int i = 0; i < 6; ++i) {
 831  E :      SimulateBranchEnter(0);
 832  E :      SimulateBranchExit(0);
 833  E :    }
 834    :  
 835    :    // Simulate the process detach event.
 836  E :    SimulateModuleEvent(DLL_PROCESS_DETACH);
 837    :  
 838    :    // Unload the DLL and stop the service.
 839  E :    ASSERT_NO_FATAL_FAILURE(UnloadDll());
 840    :  
 841  E :    HMODULE self = ::GetModuleHandle(NULL);
 842  E :    DWORD process_id = ::GetCurrentProcessId();
 843  E :    DWORD thread_id = ::GetCurrentThreadId();
 844    :  
 845    :    static const uint32 kExpectedBranchData[kNumBranchColumns * kNumBasicBlocks] =
 846    :        { 9, 5, 2, 8, 2, 2 };
 847    :  
 848    :    // Set up expectations for what should be in the trace.
 849  E :    EXPECT_CALL(handler_, OnProcessStarted(_, process_id, _));
 850    :    EXPECT_CALL(handler_, OnProcessAttach(_,
 851    :                                          process_id,
 852    :                                          thread_id,
 853  E :                                          ModuleAtAddress(self)));
 854  E :    const uint32 kNumData = kNumBranchColumns * kNumBasicBlocks;
 855    :    EXPECT_CALL(handler_, OnIndexedFrequency(
 856    :        _,
 857    :        process_id,
 858    :        thread_id,
 859  E :        FrequencyDataMatches(self, kNumData, kExpectedBranchData)));
 860  E :    EXPECT_CALL(handler_, OnProcessEnded(_, process_id));
 861    :  
 862    :    // Replay the log.
 863  E :    ASSERT_NO_FATAL_FAILURE(ReplayLogs(1));
 864  E :  }
 865    :  
 866  E :  TEST_F(BasicBlockEntryTest, BranchWithBufferingEvents) {
 867    :    // Configure for Branch mode.
 868  E :    ConfigureBranchAgent();
 869    :  
 870  E :    ASSERT_NO_FATAL_FAILURE(StartService());
 871  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 872    :  
 873    :    // Simulate the process attach event.
 874  E :    ExeMainThunk();
 875    :  
 876    :    // Visiting an initial basic-block should not fail.
 877  E :    SimulateBranchEnterBuffered(0);
 878  E :    SimulateBranchExit(0);
 879  E :    SimulateBranchEnterBuffered(1);
 880  E :    SimulateBranchExit(1);
 881  E :    ASSERT_NE(default_branch_data_, common_data_->frequency_data);
 882    :  
 883    :    // Keep a pointer to raw counters.
 884    :    uint32* frequency_data =
 885  E :        reinterpret_cast<uint32*>(common_data_->frequency_data);
 886    :  
 887    :    // Validate no events have been committed.
 888  E :    for (size_t i = 0; i < kNumBranchColumns; ++i) {
 889  E :      EXPECT_EQ(0U, frequency_data[i]);
 890  E :    }
 891    :  
 892    :    // Force a flush.
 893  E :    const int kBigEnoughToCauseAFlush = BasicBlockEntry::kBufferSize + 1;
 894  E :    for (int i = 0; i < kBigEnoughToCauseAFlush; ++i) {
 895  E :      SimulateBranchEnterBuffered(0);
 896  E :      SimulateBranchExit(0);
 897  E :    }
 898    :  
 899    :    // Validate some events are committed.
 900  E :    EXPECT_NE(0U, frequency_data[0 * kNumBranchColumns]);
 901    :    // Entering basic block 1 must be committed.
 902  E :    EXPECT_EQ(1U, frequency_data[1 * kNumBranchColumns]);
 903    :  
 904    :    // Force a flush.
 905  E :    uint32 old_count = frequency_data[0];
 906  E :    for (int i = 0; i < kBigEnoughToCauseAFlush; ++i) {
 907  E :      SimulateBranchEnterBuffered(0);
 908  E :      SimulateBranchExit(0);
 909  E :    }
 910    :  
 911    :    // Expect to have increasing values.
 912  E :    uint32 new_count = frequency_data[0];
 913  E :    EXPECT_LT(old_count, new_count);
 914    :  
 915  E :    ASSERT_NO_FATAL_FAILURE(StopService());
 916  E :  }
 917    :  
 918  E :  TEST_F(BasicBlockEntryTest, SingleExeBranchEvents) {
 919    :    ASSERT_NO_FATAL_FAILURE(
 920  E :      CheckExecution(kExeMain, kBranchInstrumentation));
 921  E :  }
 922    :  
 923  E :  TEST_F(BasicBlockEntryTest, SingleDllBranchEvents) {
 924    :    ASSERT_NO_FATAL_FAILURE(
 925  E :      CheckExecution(kDllMain, kBranchInstrumentation));
 926  E :  }
 927    :  
 928  E :  TEST_F(BasicBlockEntryTest, SingleExeBranchWithSlotEvents) {
 929    :    ASSERT_NO_FATAL_FAILURE(
 930  E :      CheckExecution(kExeMain, kBranchWithSlotInstrumentation));
 931  E :  }
 932    :  
 933  E :  TEST_F(BasicBlockEntryTest, SingleDllBranchWithSlotEvents) {
 934    :    ASSERT_NO_FATAL_FAILURE(
 935  E :      CheckExecution(kDllMain, kBranchWithSlotInstrumentation));
 936  E :  }
 937    :  
 938  E :  TEST_F(BasicBlockEntryTest, SingleExeBranchBufferedEvents) {
 939    :    ASSERT_NO_FATAL_FAILURE(
 940  E :      CheckExecution(kExeMain, kBufferedBranchInstrumentation));
 941  E :  }
 942    :  
 943  E :  TEST_F(BasicBlockEntryTest, SingleDllBranchBufferedEvents) {
 944    :    ASSERT_NO_FATAL_FAILURE(
 945  E :      CheckExecution(kDllMain, kBufferedBranchInstrumentation));
 946  E :  }
 947    :  
 948  E :  TEST_F(BasicBlockEntryTest, SingleExeBranchBufferedWithSlotEvents) {
 949    :    ASSERT_NO_FATAL_FAILURE(
 950  E :      CheckExecution(kExeMain, kBufferedBranchWithSlotInstrumentation));
 951  E :  }
 952    :  
 953  E :  TEST_F(BasicBlockEntryTest, SingleDllBranchBufferedWithSlotEvents) {
 954    :    ASSERT_NO_FATAL_FAILURE(
 955  E :      CheckExecution(kDllMain, kBufferedBranchWithSlotInstrumentation));
 956  E :  }
 957    :  
 958  E :  TEST_F(BasicBlockEntryTest, MultiThreadedDllBasicBlockEvents) {
 959    :    ASSERT_NO_FATAL_FAILURE(
 960  E :        CheckThreadExecution(kDllMain, kBasicBlockEntryInstrumentation));
 961  E :  }
 962    :  
 963  E :  TEST_F(BasicBlockEntryTest, MultiThreadedExeBasicBlockEvents) {
 964    :    ASSERT_NO_FATAL_FAILURE(
 965  E :        CheckThreadExecution(kExeMain, kBasicBlockEntryInstrumentation));
 966  E :  }
 967    :  
 968  E :  TEST_F(BasicBlockEntryTest, MultiThreadedDllBranchEvents) {
 969    :    ASSERT_NO_FATAL_FAILURE(
 970  E :        CheckThreadExecution(kDllMain, kBranchInstrumentation));
 971  E :  }
 972    :  
 973  E :  TEST_F(BasicBlockEntryTest, MultiThreadedExeBranchEvents) {
 974    :    ASSERT_NO_FATAL_FAILURE(
 975  E :        CheckThreadExecution(kExeMain, kBranchInstrumentation));
 976  E :  }
 977    :  
 978  E :  TEST_F(BasicBlockEntryTest, MultiThreadedDllBranchWithSlotEvents) {
 979    :    ASSERT_NO_FATAL_FAILURE(
 980  E :        CheckThreadExecution(kDllMain, kBranchWithSlotInstrumentation));
 981  E :  }
 982    :  
 983  E :  TEST_F(BasicBlockEntryTest, MultiThreadedExeBranchWithSlotEvents) {
 984    :    ASSERT_NO_FATAL_FAILURE(
 985  E :        CheckThreadExecution(kExeMain, kBranchWithSlotInstrumentation));
 986  E :  }
 987    :  
 988  E :  TEST_F(BasicBlockEntryTest, MultiThreadedDllBufferedBranchEvents) {
 989    :    ASSERT_NO_FATAL_FAILURE(
 990  E :        CheckThreadExecution(kDllMain, kBufferedBranchInstrumentation));
 991  E :  }
 992    :  
 993  E :  TEST_F(BasicBlockEntryTest, MultiThreadedExeBufferedBranchEvents) {
 994    :    ASSERT_NO_FATAL_FAILURE(
 995  E :        CheckThreadExecution(kExeMain, kBufferedBranchInstrumentation));
 996  E :  }
 997    :  
 998  E :  TEST_F(BasicBlockEntryTest, MultiThreadedDllBufferedBranchWithSlotEvents) {
 999    :    ASSERT_NO_FATAL_FAILURE(
1000  E :        CheckThreadExecution(kDllMain, kBufferedBranchWithSlotInstrumentation));
1001  E :  }
1002    :  
1003  E :  TEST_F(BasicBlockEntryTest, MultiThreadedExeBufferedBranchWithSlotEvents) {
1004    :    ASSERT_NO_FATAL_FAILURE(
1005  E :        CheckThreadExecution(kExeMain, kBufferedBranchWithSlotInstrumentation));
1006  E :  }
1007    :  
1008    :  }  // namespace basic_block_entry
1009    :  }  // namespace agent

Coverage information generated Thu Mar 26 16:15:41 2015.