15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Unit tests for event trace consumer base class.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/event_trace_consumer.h"
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <objbase.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1758e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process.h"
18868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/event_trace_controller.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/event_trace_provider.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <initguid.h>  // NOLINT - has to be last
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace win {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef std::list<EVENT_TRACE> EventQueue;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestConsumer: public EtwTraceConsumerBase<TestConsumer> {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConsumer() {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sank_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearQueue();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~TestConsumer() {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearQueue();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sank_event_.Close();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearQueue() {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EventQueue::const_iterator it(events_.begin()), end(events_.end());
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (; it != end; ++it) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] it->MofData;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.clear();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void EnqueueEvent(EVENT_TRACE* event) {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.push_back(*event);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EVENT_TRACE& back = events_.back();
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL != event->MofData && 0 != event->MofLength) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      back.MofData = new char[event->MofLength];
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(back.MofData, event->MofData, event->MofLength);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void ProcessEvent(EVENT_TRACE* event) {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnqueueEvent(event);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SetEvent(sank_event_.Get());
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static ScopedHandle sank_event_;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static EventQueue events_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TestConsumer);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScopedHandle TestConsumer::sank_event_;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EventQueue TestConsumer::events_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EtwTraceConsumerBaseTest: public testing::Test {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceConsumerBaseTest()
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : session_name_(StringPrintf(L"TestSession-%d",
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   Process::Current().pid())) {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cleanup any potentially dangling sessions.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties ignore;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceController::Stop(session_name_.c_str(), &ignore);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Allocate a new GUID for each provider test.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cleanup any potentially danging sessions.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties ignore;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceController::Stop(session_name_.c_str(), &ignore);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GUID test_provider_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::wstring session_name_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerBaseTest, Initialize) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConsumer consumer_;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerBaseTest, OpenRealtimeSucceedsWhenNoSession) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConsumer consumer_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      consumer_.OpenRealtimeSession(session_name_.c_str()));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerBaseTest, ConsumerImmediateFailureWhenNoSession) {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConsumer consumer_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      consumer_.OpenRealtimeSession(session_name_.c_str()));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_FAILED(consumer_.Consume());
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EtwTraceConsumerRealtimeTest: public EtwTraceConsumerBaseTest {
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceConsumerBaseTest::SetUp();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_HRESULT_SUCCEEDED(
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        consumer_.OpenRealtimeSession(session_name_.c_str()));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumer_.Close();
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceConsumerBaseTest::TearDown();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD ConsumerThread() {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::SetEvent(consumer_ready_.Get());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = consumer_.Consume();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static DWORD WINAPI ConsumerThreadMainProc(void* arg) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<EtwTraceConsumerRealtimeTest*>(arg)->
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ConsumerThread();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT StartConsumerThread() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumer_ready_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(consumer_ready_ != NULL);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumer_thread_.Set(::CreateThread(NULL, 0, ConsumerThreadMainProc,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        this, 0, NULL));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == consumer_thread_.Get())
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return HRESULT_FROM_WIN32(::GetLastError());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = S_OK;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE events[] = { consumer_ready_, consumer_thread_ };
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD result = ::WaitForMultipleObjects(arraysize(events), events,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            FALSE, INFINITE);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (result) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WAIT_OBJECT_0:
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The event was set, the consumer_ is ready.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return S_OK;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case WAIT_OBJECT_0 + 1: {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // The thread finished. This may race with the event, so check
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // explicitly for the event here, before concluding there's trouble.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (WAIT_OBJECT_0 == ::WaitForSingleObject(consumer_ready_, 0))
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return S_OK;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DWORD exit_code = 0;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (::GetExitCodeThread(consumer_thread_, &exit_code))
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return exit_code;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          else
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return HRESULT_FROM_WIN32(::GetLastError());
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return E_UNEXPECTED;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Waits for consumer_ thread to exit, and returns its exit code.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT JoinConsumerThread() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (WAIT_OBJECT_0 != ::WaitForSingleObject(consumer_thread_, INFINITE))
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return HRESULT_FROM_WIN32(::GetLastError());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD exit_code = 0;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (::GetExitCodeThread(consumer_thread_, &exit_code))
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return exit_code;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HRESULT_FROM_WIN32(::GetLastError());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestConsumer consumer_;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedHandle consumer_ready_;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedHandle consumer_thread_;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerRealtimeTest, ConsumerReturnsWhenSessionClosed) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceController controller;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               100 * 1024);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hr == E_ACCESSDENIED) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "You must be an administrator to run this test on Vista";
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the consumer_.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait around for the consumer_ thread a bit.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(WAIT_TIMEOUT, ::WaitForSingleObject(consumer_thread_, 50));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The consumer_ returns success on session stop.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// {57E47923-A549-476f-86CA-503D57F59E62}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_GUID(kTestEventType,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0x57e47923, 0xa549, 0x476f, 0x86, 0xca, 0x50, 0x3d, 0x57, 0xf5, 0x9e, 0x62);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerRealtimeTest, ConsumeEvent) {
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceController controller;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               100 * 1024);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hr == E_ACCESSDENIED) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "You must be an administrator to run this test on Vista";
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceProvider provider(test_provider_);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERROR_SUCCESS, provider.Register());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the consumer_.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(0, TestConsumer::events_.size());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERROR_SUCCESS, provider.Log(&event.header));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(TestConsumer::sank_event_,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 INFINITE));
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_NE(0u, TestConsumer::events_.size());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We run events through a file session to assert that
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the content comes through.
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class EtwTraceConsumerDataTest: public EtwTraceConsumerBaseTest {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwTraceConsumerDataTest() {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceConsumerBaseTest::SetUp();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProperties prop;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceController::Stop(session_name_.c_str(), &prop);
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a temp dir for this test.
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Construct a temp file name in our dir.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    temp_file_ = temp_dir_.path().Append(L"test.etl");
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::DeleteFile(temp_file_, false));
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceConsumerBaseTest::TearDown();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT LogEventToTempSession(PEVENT_TRACE_HEADER header) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceController controller;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set up a file session.
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = controller.StartFileSession(session_name_.c_str(),
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             temp_file_.value().c_str());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr))
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Enable our provider.
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EtwTraceProvider provider(test_provider_);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Then register our provider, means we get a session handle immediately.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERROR_SUCCESS, provider.Register());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Trace the event, it goes to the temp file.
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERROR_SUCCESS, provider.Log(header));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(test_provider_));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_HRESULT_SUCCEEDED(provider.Unregister());
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_HRESULT_SUCCEEDED(controller.Flush(NULL));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return S_OK;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT ConsumeEventFromTempSession() {
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now consume the event(s).
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestConsumer consumer_;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = consumer_.OpenFileSession(temp_file_.value().c_str());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SUCCEEDED(hr))
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = consumer_.Consume();
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    consumer_.Close();
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // And nab the result.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    events_.swap(TestConsumer::events_);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return hr;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT RoundTripEvent(PEVENT_TRACE_HEADER header, PEVENT_TRACE* trace) {
3387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    base::DeleteFile(temp_file_, false);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HRESULT hr = LogEventToTempSession(header);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SUCCEEDED(hr))
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      hr = ConsumeEventFromTempSession();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FAILED(hr))
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return hr;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should now have the event in the queue.
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (events_.empty())
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return E_FAIL;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *trace = &events_.back();
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return S_OK;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EventQueue events_;
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedTempDir temp_dir_;
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FilePath temp_file_;
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(EtwTraceConsumerDataTest, RoundTrip) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kData[] = "This is but test data";
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.fields[0].DataPtr = reinterpret_cast<ULONG64>(kData);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event.fields[0].Length = sizeof(kData);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PEVENT_TRACE trace = NULL;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HRESULT hr = RoundTripEvent(&event.header, &trace);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (hr == E_ACCESSDENIED) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "You must be an administrator to run this test on Vista";
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_HRESULT_SUCCEEDED(hr) << "RoundTripEvent failed";
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(NULL != trace);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(sizeof(kData), trace->MofLength);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_STREQ(kData, reinterpret_cast<const char*>(trace->MofData));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace win
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace base
384