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

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

Coverage information generated Fri Jul 29 11:00:21 2016.