Coverage for /Syzygy/agent/memprof/memprof_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%95950.C++test

Line-by-line coverage:

   1    :  // Copyright 2014 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    :  // Memory Profiler unittests.
  16    :  
  17    :  #include "syzygy/agent/memprof/memprof.h"
  18    :  
  19    :  #include <windows.h>
  20    :  
  21    :  #include "base/file_util.h"
  22    :  #include "base/scoped_native_library.h"
  23    :  #include "base/files/file_enumerator.h"
  24    :  #include "base/files/scoped_temp_dir.h"
  25    :  #include "base/message_loop/message_loop.h"
  26    :  #include "base/threading/platform_thread.h"
  27    :  #include "base/threading/thread.h"
  28    :  #include "gmock/gmock.h"
  29    :  #include "gtest/gtest.h"
  30    :  #include "syzygy/agent/common/process_utils.h"
  31    :  #include "syzygy/core/unittest_util.h"
  32    :  #include "syzygy/pe/unittest_util.h"
  33    :  #include "syzygy/trace/common/unittest_util.h"
  34    :  #include "syzygy/trace/parse/parser.h"
  35    :  #include "syzygy/trace/parse/unittest_util.h"
  36    :  #include "syzygy/trace/protocol/call_trace_defs.h"
  37    :  #include "syzygy/trace/service/service.h"
  38    :  #include "syzygy/trace/service/service_rpc_impl.h"
  39    :  
  40    :  namespace agent {
  41    :  namespace memprof {
  42    :  
  43    :  namespace {
  44    :  
  45    :  using agent::common::GetProcessModules;
  46    :  using agent::common::ModuleVector;
  47    :  using testing::_;
  48    :  using testing::AllOf;
  49    :  using testing::Return;
  50    :  using testing::StrictMockParseEventHandler;
  51    :  using trace::service::RpcServiceInstanceManager;
  52    :  using trace::service::Service;
  53    :  using trace::parser::Parser;
  54    :  using trace::parser::ParseEventHandler;
  55    :  
  56    :  // Function pointers for various Heap API functions.
  57    :  typedef HANDLE (WINAPI *HeapCreatePtr)(DWORD, SIZE_T, SIZE_T);
  58    :  typedef BOOL (WINAPI *HeapDestroyPtr)(HANDLE);
  59    :  typedef LPVOID (WINAPI *HeapAllocPtr)(HANDLE, DWORD, SIZE_T);
  60    :  typedef BOOL (WINAPI *HeapFreePtr)(HANDLE, DWORD, LPVOID);
  61    :  
  62    :  class MemoryProfilerTest : public testing::Test {
  63    :   public:
  64    :    MemoryProfilerTest()
  65    :        : module_(nullptr),
  66    :          heap_create_(nullptr),
  67    :          heap_destroy_(nullptr),
  68    :          heap_alloc_(nullptr),
  69  E :          heap_free_(nullptr) {
  70  E :    }
  71    :  
  72  E :    virtual void SetUp() OVERRIDE {
  73  E :      testing::Test::SetUp();
  74    :  
  75    :      // Create a temporary directory for the call trace files.
  76  E :      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  77    :  
  78  E :      service_.SetEnvironment();
  79  E :    }
  80    :  
  81  E :    virtual void TearDown() OVERRIDE {
  82  E :      UnloadDll();
  83    :  
  84    :      // Stop the call trace service.
  85  E :      service_.Stop();
  86  E :    }
  87    :  
  88  E :    void StartService() {
  89  E :      service_.Start(temp_dir_.path());
  90  E :    }
  91    :  
  92  E :    void StopService() {
  93  E :      service_.Stop();
  94  E :    }
  95    :  
  96  E :    void ReplayLogs() {
  97    :      // Stop the service if it's running.
  98  E :      ASSERT_NO_FATAL_FAILURE(StopService());
  99    :  
 100  E :      Parser parser;
 101  E :      ASSERT_TRUE(parser.Init(&handler_));
 102    :  
 103    :      // Queue up the trace file(s) we engendered.
 104    :      base::FileEnumerator enumerator(temp_dir_.path(),
 105    :                                      false,
 106  E :                                      base::FileEnumerator::FILES);
 107  E :      size_t num_files = 0;
 108  E :      while (true) {
 109  E :        base::FilePath trace_file = enumerator.Next();
 110  E :        if (trace_file.empty())
 111  E :          break;
 112  E :        ASSERT_TRUE(parser.OpenTraceFile(trace_file));
 113  E :        ++num_files;
 114  E :      }
 115  E :      EXPECT_GT(num_files, 0U);
 116  E :      ASSERT_TRUE(parser.Consume());
 117  E :    }
 118    :  
 119  E :    void LoadDll() {
 120  E :      ASSERT_TRUE(module_ == NULL);
 121    :      static const wchar_t kClientDll[] = L"memprof.dll";
 122  E :      ASSERT_EQ(NULL, ::GetModuleHandle(kClientDll));
 123  E :      module_ = ::LoadLibrary(kClientDll);
 124  E :      ASSERT_TRUE(module_ != nullptr);
 125    :  
 126    :      heap_create_ = reinterpret_cast<HeapCreatePtr>(
 127  E :          ::GetProcAddress(module_, "asan_HeapCreate"));
 128  E :      ASSERT_TRUE(heap_create_ != nullptr);
 129    :      heap_destroy_ = reinterpret_cast<HeapDestroyPtr>(
 130  E :          ::GetProcAddress(module_, "asan_HeapDestroy"));
 131  E :      ASSERT_TRUE(heap_destroy_ != nullptr);
 132    :      heap_alloc_ = reinterpret_cast<HeapAllocPtr>(
 133  E :          ::GetProcAddress(module_, "asan_HeapAlloc"));
 134  E :      ASSERT_TRUE(heap_alloc_ != nullptr);
 135    :      heap_free_ = reinterpret_cast<HeapFreePtr>(
 136  E :          ::GetProcAddress(module_, "asan_HeapFree"));
 137  E :      ASSERT_TRUE(heap_free_ != nullptr);
 138  E :    }
 139    :  
 140  E :    void UnloadDll() {
 141  E :      if (module_ != NULL) {
 142  E :        ASSERT_TRUE(::FreeLibrary(module_));
 143  E :        module_ = nullptr;
 144  E :        heap_create_ = nullptr;
 145  E :        heap_destroy_ = nullptr;
 146  E :        heap_alloc_ = nullptr;
 147  E :        heap_free_ = nullptr;
 148    :      }
 149  E :    }
 150    :  
 151  E :    void ExpectedRecordsSeenTest(bool emit_stack_traces) {
 152  E :      scoped_ptr<base::Environment> env(base::Environment::Create());
 153  E :      DCHECK_NE(static_cast<base::Environment*>(nullptr), env.get());
 154  E :      if (emit_stack_traces) {
 155    :        env->SetVar(kParametersEnvVar,
 156  E :                    "--stack-trace-tracking=emit --serialize-timestamps");
 157  E :      } else {
 158  E :        env->SetVar(kParametersEnvVar, "--stack-trace-tracking=none");
 159    :      }
 160    :  
 161  E :      ASSERT_NO_FATAL_FAILURE(StartService());
 162  E :      ASSERT_NO_FATAL_FAILURE(LoadDll());
 163    :  
 164  E :      DWORD process_id = ::GetCurrentProcessId();
 165  E :      DWORD thread_id = ::GetCurrentThreadId();
 166    :  
 167    :      // Make some calls to the instrumented heap API.
 168  E :      HANDLE heap = (*heap_create_)(0, 0, 0);
 169  E :      ASSERT_TRUE(heap != nullptr);
 170  E :      void* alloc = (*heap_alloc_)(heap, 0, 1024);
 171  E :      ASSERT_TRUE(alloc != nullptr);
 172  E :      (*heap_free_)(heap, 0, alloc);
 173    :      // Deliberately keep around the value of |alloc| for checking expectation,
 174    :      // even though the memory it points to is no longer valid.
 175  E :      (*heap_destroy_)(heap);
 176    :      // Ditto for the value of |heap|.
 177    :  
 178  E :      ASSERT_NO_FATAL_FAILURE(UnloadDll());
 179  E :      ASSERT_NO_FATAL_FAILURE(StopService());
 180    :  
 181  E :      env->UnSetVar(kParametersEnvVar);
 182    :  
 183  E :      EXPECT_CALL(handler_, OnProcessStarted(_, process_id, _));
 184    :      EXPECT_CALL(handler_, OnProcessAttach(_, process_id, _, _))
 185  E :          .Times(testing::AnyNumber());
 186    :  
 187  E :      EXPECT_CALL(handler_,
 188    :                  OnFunctionNameTableEntry(_, process_id, _)).Times(4);
 189  E :      EXPECT_CALL(handler_,
 190    :                  OnDetailedFunctionCall(_, process_id, thread_id, _)).Times(4);
 191    :  
 192  E :      if (emit_stack_traces) {
 193  E :        EXPECT_CALL(handler_,
 194    :                    OnStackTrace(_, process_id, _)).Times(4);
 195    :      }
 196    :  
 197  E :      EXPECT_CALL(handler_, OnProcessEnded(_, process_id));
 198    :  
 199    :      // Replay the log.
 200  E :      ASSERT_NO_FATAL_FAILURE(ReplayLogs());
 201  E :    }
 202    :  
 203    :   protected:
 204    :    // The directory where trace file output will be written.
 205    :    base::ScopedTempDir temp_dir_;
 206    :  
 207    :    // The handler to which the trace file parser will delegate events.
 208    :    StrictMockParseEventHandler handler_;
 209    :  
 210    :    // Functions exported from the memory profiler client dll.
 211    :    HeapCreatePtr heap_create_;
 212    :    HeapDestroyPtr heap_destroy_;
 213    :    HeapAllocPtr heap_alloc_;
 214    :    HeapFreePtr heap_free_;
 215    :  
 216    :    // Our call trace service process instance.
 217    :    testing::CallTraceService service_;
 218    :  
 219    :   private:
 220    :    HMODULE module_;
 221    :  };
 222    :  
 223    :  }  // namespace
 224    :  
 225  E :  TEST_F(MemoryProfilerTest, NoServerNoCrash) {
 226  E :    ASSERT_NO_FATAL_FAILURE(LoadDll());
 227  E :    ASSERT_NO_FATAL_FAILURE(UnloadDll());
 228  E :  }
 229    :  
 230  E :  TEST_F(MemoryProfilerTest, ExpectedRecordsSeenTestNoStackTraces) {
 231  E :    ASSERT_NO_FATAL_FAILURE(ExpectedRecordsSeenTest(false));
 232  E :  }
 233    :  
 234  E :  TEST_F(MemoryProfilerTest, ExpectedRecordsSeenTestWithStackTraces) {
 235  E :    ASSERT_NO_FATAL_FAILURE(ExpectedRecordsSeenTest(true));
 236  E :  }
 237    :  
 238    :  }  // namespace memprof
 239    :  }  // namespace agent

Coverage information generated Thu Mar 26 16:15:41 2015.