Coverage for /Syzygy/trace/parse/parse_engine_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
91.2%2793060.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/trace/parse/parse_engine.h"
  16    :  
  17    :  #include <windows.h>  // NOLINT
  18    :  #include <wmistr.h>  // NOLINT
  19    :  #include <evntrace.h>
  20    :  
  21    :  #include <set>
  22    :  #include <vector>
  23    :  
  24    :  #include "base/logging.h"
  25    :  #include "gmock/gmock.h"
  26    :  #include "gtest/gtest.h"
  27    :  #include "syzygy/common/indexed_frequency_data.h"
  28    :  #include "syzygy/trace/parse/parser.h"
  29    :  
  30    :  namespace {
  31    :  
  32    :  using testing::_;
  33    :  using trace::parser::Parser;
  34    :  using trace::parser::ParseEngine;
  35    :  using trace::parser::ParseEventHandler;
  36    :  using trace::parser::ModuleInformation;
  37    :  
  38    :  typedef std::multiset<FuncAddr> FunctionSet;
  39    :  typedef std::vector<TraceModuleData> ModuleSet;
  40    :  
  41    :  class ParseEngineUnitTest
  42    :      : public testing::Test,
  43    :        public ParseEngine,
  44    :        public ParseEventHandler {
  45    :   public:
  46    :    ParseEngineUnitTest()
  47    :        : ParseEngine("Test", true),
  48    :          basic_block_frequencies(0),
  49  E :          expected_data(NULL) {
  50  E :      ::memset(&event_record_, 0, sizeof(event_record_));
  51  E :      set_event_handler(this);
  52  E :    }
  53    :  
  54  E :    ~ParseEngineUnitTest() {
  55  E :    }
  56    :  
  57  E :    void DispatchEventData(TraceEventType type, const void* data, size_t size) {
  58  E :      ::memset(&event_record_, 0, sizeof(event_record_));
  59  E :      event_record_.Header.ProcessId = kProcessId;
  60  E :      event_record_.Header.ThreadId = kThreadId;
  61  E :      event_record_.Header.Guid = kCallTraceEventClass;
  62  E :      event_record_.Header.Class.Type = type;
  63  E :      event_record_.MofData = const_cast<void*>(data);
  64  E :      event_record_.MofLength = size;
  65    :  
  66  E :      ASSERT_TRUE(DispatchEvent(&event_record_));
  67  E :    }
  68    :  
  69  i :    bool IsRecognizedTraceFile(const base::FilePath& trace_file_path) OVERRIDE {
  70  i :      return true;
  71  i :    }
  72    :  
  73  i :    bool OpenTraceFile(const base::FilePath& trace_file_path) OVERRIDE {
  74  i :      return true;
  75  i :    }
  76    :  
  77  i :    virtual bool ConsumeAllEvents() {
  78  i :      return true;
  79  i :    }
  80    :  
  81  i :    virtual bool CloseAllTraceFiles() {
  82  i :      return true;
  83  i :    }
  84    :  
  85    :    // ParseEventHander methods.
  86    :  
  87    :    virtual void OnProcessStarted(base::Time time,
  88    :                                  DWORD process_id,
  89  i :                                  const TraceSystemInfo* data) OVERRIDE {
  90  i :      ASSERT_EQ(process_id, kProcessId);
  91  i :    }
  92    :  
  93  i :    virtual void OnProcessEnded(base::Time time, DWORD process_id) OVERRIDE {
  94  i :      ASSERT_EQ(process_id, kProcessId);
  95  i :    }
  96    :  
  97    :    virtual void OnFunctionEntry(base::Time time,
  98    :                                 DWORD process_id,
  99    :                                 DWORD thread_id,
 100  E :                                 const TraceEnterExitEventData* data) OVERRIDE {
 101  E :      ASSERT_EQ(process_id, kProcessId);
 102  E :      ASSERT_EQ(thread_id, kThreadId);
 103  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 104  E :      EXPECT_TRUE(data->function != NULL);
 105  E :      function_entries.insert(data->function);
 106  E :    }
 107    :  
 108    :    virtual void OnFunctionExit(base::Time time,
 109    :                                DWORD process_id,
 110    :                                DWORD thread_id,
 111  E :                                const TraceEnterExitEventData* data) OVERRIDE {
 112  E :      ASSERT_EQ(process_id, kProcessId);
 113  E :      ASSERT_EQ(thread_id, kThreadId);
 114  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 115  E :      EXPECT_TRUE(data->function != NULL);
 116  E :      function_exits.insert(data->function);
 117  E :    }
 118    :  
 119    :    virtual void OnBatchFunctionEntry(base::Time time,
 120    :                                      DWORD process_id,
 121    :                                      DWORD thread_id,
 122  E :                                      const TraceBatchEnterData* data) OVERRIDE {
 123  E :      ASSERT_EQ(process_id, kProcessId);
 124  E :      ASSERT_EQ(thread_id, kThreadId);
 125  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 126  E :      for (size_t i = 0; i < data->num_calls; ++i) {
 127  E :        function_entries.insert(data->calls[i].function);
 128  E :      }
 129  E :    }
 130    :  
 131    :    virtual void OnProcessAttach(base::Time time,
 132    :                                 DWORD process_id,
 133    :                                 DWORD thread_id,
 134  E :                                 const TraceModuleData* data) OVERRIDE {
 135  E :      ASSERT_EQ(process_id, kProcessId);
 136  E :      ASSERT_EQ(thread_id, kThreadId);
 137  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 138  E :      process_attaches.push_back(*data);
 139  E :    }
 140    :  
 141    :    virtual void OnProcessDetach(base::Time time,
 142    :                                 DWORD process_id,
 143    :                                 DWORD thread_id,
 144  E :                                 const TraceModuleData* data) OVERRIDE {
 145  E :      ASSERT_EQ(process_id, kProcessId);
 146  E :      ASSERT_EQ(thread_id, kThreadId);
 147  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 148  E :      process_detaches.push_back(*data);
 149  E :    }
 150    :  
 151    :    virtual void OnThreadAttach(base::Time time,
 152    :                                DWORD process_id,
 153    :                                DWORD thread_id,
 154  E :                                const TraceModuleData* data) OVERRIDE {
 155  E :      ASSERT_EQ(process_id, kProcessId);
 156  E :      ASSERT_EQ(thread_id, kThreadId);
 157  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 158  E :      thread_attaches.push_back(*data);
 159  E :    }
 160    :  
 161    :    // Issued for DLL_THREAD_DETACH on an instrumented module.
 162    :    virtual void OnThreadDetach(base::Time time,
 163    :                                DWORD process_id,
 164    :                                DWORD thread_id,
 165  E :                                const TraceModuleData* data) OVERRIDE {
 166  E :      ASSERT_EQ(process_id, kProcessId);
 167  E :      ASSERT_EQ(thread_id, kThreadId);
 168  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 169  E :      thread_detaches.push_back(*data);
 170  E :    }
 171    :  
 172    :    virtual void OnInvocationBatch(
 173    :        base::Time time, DWORD process_id, DWORD thread_id,
 174  i :        size_t num_invocations, const TraceBatchInvocationInfo* data) OVERRIDE {
 175    :      // TODO(anyone): Test this.
 176  i :    }
 177    :  
 178    :    virtual void OnIndexedFrequency(
 179    :        base::Time time,
 180    :        DWORD process_id,
 181    :        DWORD thread_id,
 182  E :        const TraceIndexedFrequencyData* data) OVERRIDE {
 183  E :      ASSERT_EQ(process_id, kProcessId);
 184  E :      ASSERT_EQ(thread_id, kThreadId);
 185  E :      ASSERT_TRUE(reinterpret_cast<const void*>(data) == expected_data);
 186  E :      ++basic_block_frequencies;
 187  E :    }
 188    :  
 189    :    MOCK_METHOD4(OnThreadName,
 190    :        void(base::Time time, DWORD process_id, DWORD thread_id,
 191  i :             const base::StringPiece& thread_name));
 192    :    MOCK_METHOD3(OnDynamicSymbol,
 193    :        void(DWORD process_id, uint32 symbol_id,
 194  E :             const base::StringPiece& symbol_name));
 195    :    MOCK_METHOD3(OnSampleData,
 196    :                 void(base::Time time,
 197    :                      DWORD process_id,
 198  E :                      const TraceSampleData* data));
 199    :  
 200    :    static const DWORD kProcessId;
 201    :    static const DWORD kThreadId;
 202    :    static const ModuleInformation kExeInfo;
 203    :    static const ModuleInformation kDllInfo;
 204    :    static const TraceModuleData kModuleData;
 205    :    static const TraceIndexedFrequencyData kIndexedFrequencyData;
 206    :    static const TraceIndexedFrequencyData kShortIndexedFrequencyData;
 207    :  
 208    :    EVENT_TRACE event_record_;
 209    :  
 210    :    FunctionSet function_entries;
 211    :    FunctionSet function_exits;
 212    :    ModuleSet process_attaches;
 213    :    ModuleSet process_detaches;
 214    :    ModuleSet thread_attaches;
 215    :    ModuleSet thread_detaches;
 216    :    size_t basic_block_frequencies;
 217    :  
 218    :    const void* expected_data;
 219    :  };
 220    :  
 221    :  const DWORD ParseEngineUnitTest::kProcessId = 0xAAAAAAAA;
 222    :  
 223    :  const DWORD ParseEngineUnitTest::kThreadId = 0xBBBBBBBB;
 224    :  
 225  E :  const ModuleInformation ParseEngineUnitTest::kExeInfo = {
 226  E :      0x11111111, 0x22222222, 0x33333333, 0x44444444, L"file_name.exe" };
 227    :  
 228  E :  const ModuleInformation ParseEngineUnitTest::kDllInfo = {
 229  E :      0x55555555, 0x66666666, 0x77777777, 0x88888888, L"file_name.dll" };
 230    :  
 231    :  const TraceModuleData ParseEngineUnitTest::kModuleData = {
 232    :      reinterpret_cast<ModuleAddr>(0x99999999),
 233    :      0x11111111,
 234    :      0x22222222,
 235    :      0x33333333,
 236    :      L"module",
 237    :      L"executable" };
 238    :  
 239    :  const TraceIndexedFrequencyData ParseEngineUnitTest::kIndexedFrequencyData = {
 240    :      reinterpret_cast<ModuleAddr>(0x11111111),
 241    :      0x22222222,
 242    :      0x33333333,
 243    :      0x44444444,
 244    :      1,
 245    :      1,
 246    :      common::IndexedFrequencyData::BASIC_BLOCK_ENTRY,
 247    :      1,
 248    :      0 };
 249    :  
 250    :  // This indexed frequency struct does not contain enough data for its implicitly
 251    :  // encoded length.
 252    :  const TraceIndexedFrequencyData
 253    :      ParseEngineUnitTest::kShortIndexedFrequencyData = {
 254    :          reinterpret_cast<ModuleAddr>(0x11111111),
 255    :          0x22222222,
 256    :          0x33333333,
 257    :          0x44444444,
 258    :          10,
 259    :          1,
 260    :          common::IndexedFrequencyData::BASIC_BLOCK_ENTRY,
 261    :          4,
 262    :          0 };
 263    :  
 264    :  // A test function to show up in the trace events.
 265  i :  void TestFunc1() {
 266  i :    ::Sleep(100);
 267  i :  }
 268    :  
 269    :  // Another test function to show up in the trace events.
 270  i :  void TestFunc2() {
 271  i :    ::time(NULL);
 272  i :  }
 273    :  
 274  E :  TEST_F(ParseEngineUnitTest, ModuleInfo) {
 275  E :    const ModuleInformation* module_info = NULL;
 276    :  
 277    :    // Insert the module information.
 278  E :    ASSERT_TRUE(AddModuleInformation(kProcessId, kExeInfo));
 279  E :    ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
 280  E :    ASSERT_EQ(1, processes_.size());
 281  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 282    :  
 283    :    // Multiple identical insertions should be ok.
 284  E :    ASSERT_TRUE(AddModuleInformation(kProcessId, kDllInfo));
 285  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 286    :  
 287    :    // Intersecting but not identical insertions should fail if disallowed.
 288  E :    ModuleInformation bad_dll_info(kDllInfo);
 289  E :    bad_dll_info.base_address += 100;
 290  E :    ASSERT_TRUE(fail_on_module_conflict_);
 291  E :    ASSERT_FALSE(AddModuleInformation(kProcessId, bad_dll_info));
 292  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 293    :  
 294    :    // If conflicting module info is non-fatal, insertions should appear to
 295    :    // succeed but not actually happen.
 296  E :    fail_on_module_conflict_ = false;
 297  E :    ASSERT_TRUE(AddModuleInformation(kProcessId, bad_dll_info));
 298  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 299  E :    fail_on_module_conflict_ = true;
 300    :  
 301    :    // Search for unknown process.
 302  E :    module_info = GetModuleInformation(kProcessId + 1, kExeInfo.base_address);
 303  E :    ASSERT_TRUE(module_info == NULL);
 304    :  
 305    :    // Search before exe start address
 306  E :    const int kBeforeOffset = -1;
 307    :    module_info = GetModuleInformation(kProcessId,
 308  E :                                       kExeInfo.base_address + kBeforeOffset);
 309  E :    ASSERT_TRUE(module_info == NULL);
 310    :  
 311    :    // Search after exe end address.
 312  E :    const size_t kAfterOffset = kExeInfo.module_size;
 313    :    module_info = GetModuleInformation(kProcessId,
 314  E :                                       kExeInfo.base_address + kAfterOffset);
 315  E :    ASSERT_TRUE(module_info == NULL);
 316    :  
 317    :    // Get exe module by start address.
 318  E :    const size_t kStartOffset = 0;
 319    :    module_info = GetModuleInformation(kProcessId,
 320  E :                                       kExeInfo.base_address + kStartOffset);
 321  E :    ASSERT_TRUE(module_info != NULL);
 322  E :    ASSERT_TRUE(*module_info == kExeInfo);
 323    :  
 324    :    // Get exe module by address somewhere in the middle.
 325  E :    const size_t kMiddleOffset = kExeInfo.module_size / 2;
 326    :    module_info = GetModuleInformation(kProcessId,
 327  E :                                       kExeInfo.base_address + kMiddleOffset);
 328  E :    ASSERT_TRUE(module_info != NULL);
 329  E :    ASSERT_TRUE(*module_info == kExeInfo);
 330    :  
 331    :    // Get exe module by address at the end.
 332  E :    const size_t kEndOffset = kExeInfo.module_size - 1;
 333    :    module_info = GetModuleInformation(kProcessId,
 334  E :                                       kExeInfo.base_address + kEndOffset);
 335  E :    ASSERT_TRUE(module_info != NULL);
 336  E :    ASSERT_TRUE(*module_info == kExeInfo);
 337    :  
 338    :    // We only remove modules from a given process if a conflicting module is
 339    :    // loaded after the module has been marked as dirty. This is because (1) we
 340    :    // don't guarantee temporal order of all events in a process, so you
 341    :    // might parse a function event after seeing the module get unloaded
 342    :    // if the buffers are flushed in that order; and (2) because process ids may
 343    :    // be reused (but not concurrently) so we do want to drop stale module info
 344    :    // when the process has been replaced.
 345    :  
 346    :    // Get dll module by address somewhere in the middle, then remove it and
 347    :    // see that it's STILL found by that address.
 348  E :    const size_t kDllOffset = kDllInfo.module_size / 2;
 349    :    module_info = GetModuleInformation(kProcessId,
 350  E :                                       kDllInfo.base_address + kDllOffset);
 351  E :    ASSERT_TRUE(module_info != NULL);
 352  E :    ASSERT_TRUE(*module_info == kDllInfo);
 353  E :    ASSERT_TRUE(RemoveModuleInformation(kProcessId, kDllInfo));
 354  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 355    :    module_info = GetModuleInformation(kProcessId,
 356  E :                                       kDllInfo.base_address + kDllOffset);
 357  E :    ASSERT_TRUE(module_info != NULL);
 358  E :    ASSERT_TRUE(*module_info == kDllInfo);
 359    :  
 360    :    // Add conflicting module information and see that the old module is gone.
 361  E :    ModuleInformation new_dll_info = kDllInfo;
 362  E :    new_dll_info.base_address += 4;
 363  E :    ASSERT_TRUE(AddModuleInformation(kProcessId, new_dll_info));
 364  E :    ASSERT_EQ(2, processes_[kProcessId].size());
 365  E :    module_info = GetModuleInformation(kProcessId, kDllInfo.base_address);
 366  E :    ASSERT_TRUE(module_info == NULL);
 367  E :    module_info = GetModuleInformation(kProcessId, new_dll_info.base_address);
 368  E :    ASSERT_TRUE(module_info != NULL);
 369  E :    ASSERT_TRUE(*module_info == new_dll_info);
 370  E :  }
 371    :  
 372  E :  TEST_F(ParseEngineUnitTest, UnhandledEvent) {
 373  E :    EVENT_TRACE local_record = {};
 374  E :    ASSERT_FALSE(DispatchEvent(&local_record));
 375    :  
 376  E :    local_record.Header.ProcessId = kProcessId;
 377  E :    local_record.Header.ThreadId = kThreadId;
 378  E :    local_record.Header.Guid = kCallTraceEventClass;
 379  E :    local_record.Header.Class.Type = 0xFF;  // Invalid value.
 380  E :    ASSERT_TRUE(DispatchEvent(&local_record));
 381  E :    ASSERT_TRUE(error_occurred());
 382  E :  }
 383    :  
 384  E :  TEST_F(ParseEngineUnitTest, FunctionEntryEvents) {
 385  E :    TraceEnterEventData event_data = {};
 386  E :    event_data.function = &TestFunc1;
 387  E :    expected_data = &event_data;
 388    :  
 389    :    ASSERT_NO_FATAL_FAILURE(
 390  E :        DispatchEventData(TRACE_ENTER_EVENT, &event_data, sizeof(event_data)));
 391  E :    ASSERT_FALSE(error_occurred());
 392    :    ASSERT_NO_FATAL_FAILURE(
 393  E :        DispatchEventData(TRACE_ENTER_EVENT, &event_data, sizeof(event_data)));
 394  E :    ASSERT_FALSE(error_occurred());
 395  E :    ASSERT_EQ(function_entries.size(), 2);
 396  E :    ASSERT_EQ(function_entries.count(&TestFunc1), 2);
 397    :  
 398    :    // Check for short event data.
 399    :    ASSERT_NO_FATAL_FAILURE(
 400    :        DispatchEventData(TRACE_ENTER_EVENT,
 401    :                          &event_data,
 402  E :                          sizeof(TraceEnterEventData) - 1));
 403  E :    ASSERT_TRUE(error_occurred());
 404  E :  }
 405    :  
 406  E :  TEST_F(ParseEngineUnitTest, FunctionExitEvents) {
 407  E :    TraceExitEventData event_data = {};
 408  E :    event_data.function = &TestFunc2;
 409  E :    expected_data = &event_data;
 410    :  
 411    :    ASSERT_NO_FATAL_FAILURE(
 412  E :        DispatchEventData(TRACE_EXIT_EVENT, &event_data, sizeof(event_data)));
 413  E :    ASSERT_FALSE(error_occurred());
 414    :    ASSERT_NO_FATAL_FAILURE(
 415  E :        DispatchEventData(TRACE_EXIT_EVENT, &event_data, sizeof(event_data)));
 416  E :    ASSERT_FALSE(error_occurred());
 417  E :    ASSERT_EQ(function_exits.size(), 2);
 418  E :    ASSERT_EQ(function_exits.count(&TestFunc2), 2);
 419    :  
 420    :    // Check for short event data.
 421    :   ASSERT_NO_FATAL_FAILURE(
 422    :       DispatchEventData(TRACE_EXIT_EVENT,
 423    :                         &event_data,
 424  E :                         sizeof(TraceEnterEventData) - 1));
 425  E :    ASSERT_TRUE(error_occurred());
 426  E :  }
 427    :  
 428  E :  TEST_F(ParseEngineUnitTest, BatchFunctionEntry) {
 429    :    uint8 raw_data[sizeof(TraceBatchEnterData) +
 430  E :                       4 * sizeof(TraceEnterEventData)] = {};
 431    :    TraceBatchEnterData& event_data =
 432  E :       *reinterpret_cast<TraceBatchEnterData*>(&raw_data);
 433  E :    event_data.thread_id = kThreadId;
 434  E :    event_data.num_calls = 5;
 435  E :    event_data.calls[0].function = &TestFunc1;
 436  E :    event_data.calls[1].function = &TestFunc2;
 437  E :    event_data.calls[2].function = &TestFunc1;
 438  E :    event_data.calls[3].function = &TestFunc2;
 439  E :    event_data.calls[4].function = NULL;
 440  E :    expected_data = &raw_data;
 441    :  
 442    :    ASSERT_NO_FATAL_FAILURE(
 443  E :        DispatchEventData(TRACE_BATCH_ENTER, &raw_data, sizeof(raw_data)));
 444  E :    ASSERT_FALSE(error_occurred());
 445    :    ASSERT_NO_FATAL_FAILURE(
 446  E :        DispatchEventData(TRACE_BATCH_ENTER, &raw_data, sizeof(raw_data)));
 447  E :    ASSERT_FALSE(error_occurred());
 448  E :    ASSERT_EQ(function_entries.size(), 8);
 449  E :    ASSERT_EQ(function_entries.count(&TestFunc1), 4);
 450  E :    ASSERT_EQ(function_entries.count(&TestFunc2), 4);
 451    :  
 452    :    // Check for short event header.
 453    :    ASSERT_NO_FATAL_FAILURE(
 454    :        DispatchEventData(TRACE_BATCH_ENTER,
 455    :                          &raw_data,
 456  E :                          FIELD_OFFSET(TraceBatchEnterData, num_calls)));
 457  E :    ASSERT_TRUE(error_occurred());
 458    :  
 459    :    // Check for short event tail (remove the empty record + one byte).
 460  E :    set_error_occurred(false);
 461    :    ASSERT_NO_FATAL_FAILURE(
 462    :        DispatchEventData(TRACE_BATCH_ENTER,
 463    :                          &raw_data,
 464  E :                           sizeof(raw_data) - sizeof(TraceEnterEventData) - 1));
 465  E :    ASSERT_TRUE(error_occurred());
 466  E :  }
 467    :  
 468  E :  TEST_F(ParseEngineUnitTest, ProcessAttachIncomplete) {
 469  E :    TraceModuleData incomplete(kModuleData);
 470  E :    incomplete.module_base_addr = NULL;
 471    :  
 472    :    // No error should be reported for NULL module addr, instead the record
 473    :    // should be ignored.
 474  E :    expected_data = &kModuleData;
 475    :    ASSERT_NO_FATAL_FAILURE(
 476    :        DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
 477    :                          &incomplete,
 478  E :                          sizeof(incomplete)));
 479    :  
 480  E :    ASSERT_FALSE(error_occurred());
 481  E :    ASSERT_EQ(process_attaches.size(), 0);
 482  E :  }
 483    :  
 484  E :  TEST_F(ParseEngineUnitTest, ProcessAttach) {
 485  E :    expected_data = &kModuleData;
 486    :  
 487    :    ASSERT_NO_FATAL_FAILURE(
 488    :        DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
 489    :                          &kModuleData,
 490  E :                          sizeof(kModuleData)));
 491  E :    ASSERT_FALSE(error_occurred());
 492  E :    ASSERT_EQ(process_attaches.size(), 1);
 493    :  
 494    :    // Check for short module event.
 495    :    ASSERT_NO_FATAL_FAILURE(
 496    :        DispatchEventData(TRACE_PROCESS_ATTACH_EVENT,
 497    :                          &kModuleData,
 498  E :                          sizeof(kModuleData) - 1));
 499  E :    ASSERT_TRUE(error_occurred());
 500  E :  }
 501    :  
 502  E :  TEST_F(ParseEngineUnitTest, ProcessDetach) {
 503  E :    expected_data = &kModuleData;
 504    :  
 505    :    ASSERT_NO_FATAL_FAILURE(
 506    :        DispatchEventData(TRACE_PROCESS_DETACH_EVENT,
 507    :                          &kModuleData,
 508  E :                          sizeof(kModuleData)));
 509  E :    ASSERT_FALSE(error_occurred());
 510  E :    ASSERT_EQ(process_detaches.size(), 1);
 511    :  
 512    :    // Check for short module event.
 513    :    ASSERT_NO_FATAL_FAILURE(
 514    :        DispatchEventData(TRACE_PROCESS_DETACH_EVENT,
 515    :                          &kModuleData,
 516  E :                          sizeof(kModuleData) - 1));
 517  E :    ASSERT_TRUE(error_occurred());
 518  E :  }
 519    :  
 520  E :  TEST_F(ParseEngineUnitTest, ThreadAttach) {
 521  E :    expected_data = &kModuleData;
 522    :  
 523    :    ASSERT_NO_FATAL_FAILURE(
 524    :        DispatchEventData(TRACE_THREAD_ATTACH_EVENT,
 525    :                          &kModuleData,
 526  E :                          sizeof(kModuleData)));
 527  E :    ASSERT_FALSE(error_occurred());
 528  E :    ASSERT_EQ(thread_attaches.size(), 1);
 529    :  
 530    :    // Check for short module event.
 531    :    ASSERT_NO_FATAL_FAILURE(
 532    :        DispatchEventData(TRACE_THREAD_ATTACH_EVENT,
 533    :                          &kModuleData,
 534  E :                          sizeof(kModuleData) - 1));
 535  E :    ASSERT_TRUE(error_occurred());
 536  E :  }
 537    :  
 538  E :  TEST_F(ParseEngineUnitTest, ThreadDetach) {
 539  E :    expected_data = &kModuleData;
 540    :  
 541    :    ASSERT_NO_FATAL_FAILURE(
 542    :        DispatchEventData(TRACE_THREAD_DETACH_EVENT,
 543    :                          &kModuleData,
 544  E :                          sizeof(kModuleData)));
 545  E :    ASSERT_FALSE(error_occurred());
 546  E :    ASSERT_EQ(thread_detaches.size(), 1);
 547    :  
 548    :    // Check for short module event.
 549    :    ASSERT_NO_FATAL_FAILURE(
 550    :        DispatchEventData(TRACE_THREAD_DETACH_EVENT,
 551    :                          &kModuleData,
 552  E :                          sizeof(kModuleData) - 1));
 553  E :    ASSERT_TRUE(error_occurred());
 554  E :  }
 555    :  
 556  E :  TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForHeader) {
 557    :    ASSERT_NO_FATAL_FAILURE(
 558    :        DispatchEventData(TRACE_INDEXED_FREQUENCY,
 559    :                          &kIndexedFrequencyData,
 560  E :                          sizeof(kIndexedFrequencyData) - 1));
 561    :  
 562  E :    ASSERT_TRUE(error_occurred());
 563  E :    ASSERT_EQ(basic_block_frequencies, 0);
 564  E :  }
 565    :  
 566  E :  TEST_F(ParseEngineUnitTest, IndexedFrequencyTooSmallForContents) {
 567    :    ASSERT_NO_FATAL_FAILURE(
 568    :        DispatchEventData(TRACE_INDEXED_FREQUENCY,
 569    :                          &kShortIndexedFrequencyData,
 570  E :                          sizeof(kShortIndexedFrequencyData)));
 571    :  
 572  E :    ASSERT_TRUE(error_occurred());
 573  E :    ASSERT_EQ(basic_block_frequencies, 0);
 574  E :  }
 575    :  
 576  E :  TEST_F(ParseEngineUnitTest, IndexedFrequency) {
 577  E :    expected_data = &kIndexedFrequencyData;
 578    :    ASSERT_NO_FATAL_FAILURE(
 579    :        DispatchEventData(TRACE_INDEXED_FREQUENCY,
 580    :                          &kIndexedFrequencyData,
 581  E :                          sizeof(kIndexedFrequencyData)));
 582  E :    ASSERT_FALSE(error_occurred());
 583  E :    ASSERT_EQ(basic_block_frequencies, 1);
 584  E :  }
 585    :  
 586  E :  TEST_F(ParseEngineUnitTest, DynamicSymbol) {
 587    :    static const char kSymbolName[] = "aDynamicSymbol";
 588  E :    const uint32 kSymbolId = 0x17459A;
 589    :    char data[FIELD_OFFSET(TraceDynamicSymbol, symbol_name) +
 590    :              sizeof(kSymbolName)];
 591  E :    TraceDynamicSymbol* symbol = reinterpret_cast<TraceDynamicSymbol*>(data);
 592  E :    symbol->symbol_id = kSymbolId;
 593  E :    ::memcpy(symbol->symbol_name, kSymbolName, sizeof(kSymbolName));
 594    :  
 595    :    // Dispatch a valid dynamic symbol record.
 596    :    EXPECT_CALL(*this,
 597  E :        OnDynamicSymbol(kProcessId, kSymbolId, base::StringPiece(kSymbolName)));
 598    :    ASSERT_NO_FATAL_FAILURE(
 599  E :        DispatchEventData(TRACE_DYNAMIC_SYMBOL, data, sizeof(data)));
 600  E :    ASSERT_FALSE(error_occurred());
 601    :  
 602    :    // Dispatch a short symbol record, make sure we err out.
 603    :    ASSERT_NO_FATAL_FAILURE(
 604    :        DispatchEventData(TRACE_DYNAMIC_SYMBOL,
 605    :                          data,
 606  E :                          FIELD_OFFSET(TraceDynamicSymbol, symbol_name) - 1));
 607  E :    ASSERT_TRUE(error_occurred());
 608  E :  }
 609    :  
 610  E :  TEST_F(ParseEngineUnitTest, SampleData) {
 611  E :    const uint32 kBucketCount = 42;
 612    :    char buffer[FIELD_OFFSET(TraceSampleData, buckets) +
 613  E :                kBucketCount * sizeof(uint32)] = {};
 614  E :    TraceSampleData* data = reinterpret_cast<TraceSampleData*>(buffer);
 615    :  
 616  E :    data->module_base_addr = reinterpret_cast<ModuleAddr>(0x01000000);
 617  E :    data->module_size = 32 * 1024 * 1024;
 618  E :    data->module_checksum = 0xDEADF00D;
 619  E :    data->module_time_date_stamp = 0x12345678;
 620  E :    data->bucket_size = 4;
 621  E :    data->bucket_start = reinterpret_cast<ModuleAddr>(0x01001000);
 622  E :    data->bucket_count = kBucketCount;
 623  E :    data->sampling_start_time = 0x0102030405060708;
 624  E :    data->sampling_end_time = 0x0203040506070809;
 625  E :    data->sampling_interval = 0x10000;
 626    :  
 627  E :    for (size_t i = 0; i < kBucketCount; ++i)
 628  E :      data->buckets[i] = i;
 629    :  
 630  E :    EXPECT_CALL(*this, OnSampleData(_, kProcessId, data));
 631    :    ASSERT_NO_FATAL_FAILURE(
 632  E :        DispatchEventData(TRACE_SAMPLE_DATA, data, sizeof(buffer)));
 633  E :    ASSERT_FALSE(error_occurred());
 634    :  
 635    :    // Dispatch a malformed record and make sure the parser errors.
 636    :    ASSERT_NO_FATAL_FAILURE(
 637  E :        DispatchEventData(TRACE_SAMPLE_DATA, data, sizeof(buffer) - 1));
 638  E :    ASSERT_TRUE(error_occurred());
 639  E :  }
 640    :  
 641    :  }  // namespace

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