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

Coverage information generated Tue Jun 25 13:56:24 2013.