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

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