Coverage for /Syzygy/playback/playback_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%82820.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/playback/playback.h"
  16    :  
  17    :  #include <string>
  18    :  
  19    :  #include "gmock/gmock.h"
  20    :  #include "gtest/gtest.h"
  21    :  #include "syzygy/core/unittest_util.h"
  22    :  #include "syzygy/pdb/omap.h"
  23    :  #include "syzygy/pe/pe_file.h"
  24    :  #include "syzygy/pe/unittest_util.h"
  25    :  #include "syzygy/trace/parse/parse_engine.h"
  26    :  #include "syzygy/trace/parse/unittest_util.h"
  27    :  #include "syzygy/version/syzygy_version.h"
  28    :  
  29    :  namespace playback {
  30    :  
  31    :  namespace {
  32    :  
  33    :  using testing::_;
  34    :  using testing::GetSrcRelativePath;
  35    :  using testing::GetExeRelativePath;
  36    :  using testing::GetExeTestDataRelativePath;
  37    :  using testing::MockParseEventHandler;
  38    :  using testing::Return;
  39    :  
  40    :  // A test parse engine that exposes some internals so we can simulate some
  41    :  // events.
  42    :  class TestParseEngine : public trace::parser::ParseEngine {
  43    :   public:
  44    :    using trace::parser::ParseEngine::AddModuleInformation;
  45    :    using trace::parser::ParseEngine::RemoveModuleInformation;
  46    :  };
  47    :  
  48    :  // A test parser that exposes the parse engine, so we can feed it simulated
  49    :  // events.
  50    :  class TestParser : public trace::parser::Parser {
  51    :   public:
  52  E :    TestParseEngine* active_parse_engine() const {
  53  E :      return reinterpret_cast<TestParseEngine*>(active_parse_engine_);
  54  E :    }
  55    :  };
  56    :  
  57    :  class PlaybackTest : public testing::PELibUnitTest {
  58    :   public:
  59  E :    PlaybackTest() : image_layout_(&block_graph_) {
  60  E :    }
  61    :  
  62  E :    void SetUp() {
  63    :      module_path_ =
  64  E :          GetExeTestDataRelativePath(testing::kTestDllName);
  65    :  
  66    :      instrumented_path_ =
  67  E :          GetExeTestDataRelativePath(testing::kCallTraceInstrumentedTestDllName);
  68    :  
  69    :      const base::FilePath kTraceFiles[] = {
  70    :          GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[0]),
  71    :          GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[1]),
  72    :          GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[2]),
  73    :          GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[3]),
  74  E :      };
  75    :      trace_files_ = Playback::TraceFileList(kTraceFiles,
  76  E :          kTraceFiles + arraysize(kTraceFiles));
  77  E :    }
  78    :  
  79  E :    bool Init() {
  80    :      playback_.reset(
  81  E :          new Playback(module_path_, instrumented_path_, trace_files_));
  82    :  
  83  E :      parse_event_handler_.reset(new MockParseEventHandler);
  84  E :      parser_.reset(new TestParser);
  85  E :      return parser_->Init(parse_event_handler_.get());
  86  E :    }
  87    :  
  88    :    scoped_ptr<Playback> playback_;
  89    :  
  90    :    base::FilePath module_path_;
  91    :    base::FilePath instrumented_path_;
  92    :    Playback::TraceFileList trace_files_;
  93    :  
  94    :    pe::PEFile input_dll_;
  95    :    block_graph::BlockGraph block_graph_;
  96    :    pe::ImageLayout image_layout_;
  97    :  
  98    :    scoped_ptr<MockParseEventHandler> parse_event_handler_;
  99    :    scoped_ptr<TestParser> parser_;
 100    :  };
 101    :  
 102    :  }  // namespace
 103    :  
 104  E :  TEST_F(PlaybackTest, MismatchedDLLTest) {
 105  E :    module_path_ = GetExeTestDataRelativePath(L"randomized_test_dll.dll");
 106    :  
 107  E :    EXPECT_TRUE(Init());
 108  E :    EXPECT_FALSE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
 109  E :  }
 110    :  
 111  E :  TEST_F(PlaybackTest, BadTraceFile) {
 112    :    const base::FilePath kTraceFile = GetSrcRelativePath(
 113  E :        L"syzygy/playback/test_data/bad-trace.bin");
 114  E :    trace_files_ = Playback::TraceFileList(&kTraceFile, &kTraceFile + 1);
 115    :  
 116  E :    EXPECT_TRUE(Init());
 117  E :    EXPECT_FALSE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
 118  E :  }
 119    :  
 120  E :  TEST_F(PlaybackTest, SuccessfulInit) {
 121  E :    EXPECT_TRUE(Init());
 122  E :    EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
 123  E :  }
 124    :  
 125  E :  TEST_F(PlaybackTest, ConsumeCallTraceEvents) {
 126  E :    EXPECT_TRUE(Init());
 127  E :    EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
 128    :  
 129    :  #ifdef OFFICIAL_BUILD
 130    :    static const size_t kProcessAttachCount = 4;
 131    :    static const size_t kBatchFunctionEntryCount = 4;
 132    :  #else
 133    :    static const size_t kProcessAttachCount = 12;
 134    :    static const size_t kBatchFunctionEntryCount = 12;
 135    :  #endif
 136    :  
 137  E :    EXPECT_CALL(*parse_event_handler_, OnProcessStarted(_, _, _)).Times(4);
 138  E :    EXPECT_CALL(*parse_event_handler_, OnProcessEnded(_, _)).Times(4);
 139  E :    EXPECT_CALL(*parse_event_handler_, OnFunctionEntry(_, _, _, _)).Times(0);
 140  E :    EXPECT_CALL(*parse_event_handler_, OnFunctionExit(_, _, _, _)).Times(0);
 141    :    EXPECT_CALL(*parse_event_handler_, OnBatchFunctionEntry(_, _, _, _)).
 142  E :                    Times(kBatchFunctionEntryCount);
 143    :    EXPECT_CALL(*parse_event_handler_, OnProcessAttach(_, _, _, _)).
 144  E :                    Times(kProcessAttachCount);
 145  E :    EXPECT_CALL(*parse_event_handler_, OnThreadAttach(_, _, _, _)).Times(0);
 146  E :    EXPECT_CALL(*parse_event_handler_, OnThreadDetach(_, _, _, _)).Times(0);
 147    :    EXPECT_CALL(*parse_event_handler_,
 148  E :                OnInvocationBatch(_, _, _, _, _)).Times(0);
 149    :  
 150  E :    EXPECT_TRUE(parser_->Consume());
 151  E :  }
 152    :  
 153  E :  TEST_F(PlaybackTest, FindFunctionBlock) {
 154  E :    EXPECT_TRUE(Init());
 155  E :    EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
 156    :  
 157    :    // Get the instrumented module's signature. We need this so we can inject
 158    :    // modules into the parse engine.
 159  E :    pe::PEFile pe_file;
 160  E :    trace::parser::ModuleInformation module_info;
 161  E :    ASSERT_TRUE(pe_file.Init(instrumented_path_));
 162  E :    pe_file.GetSignature(&module_info);
 163    :  
 164  E :    const DWORD kPid = 0x1234;
 165    :  
 166    :    // Get pointers to text and data.
 167  E :    const IMAGE_SECTION_HEADER* text = input_dll_.GetSectionHeader(".text");
 168  E :    const IMAGE_SECTION_HEADER* data = input_dll_.GetSectionHeader(".data");
 169  E :    ASSERT_TRUE(text != NULL);
 170  E :    ASSERT_TRUE(data != NULL);
 171    :    FuncAddr text_addr = reinterpret_cast<FuncAddr>(
 172  E :        module_info.base_address.value() + text->VirtualAddress);
 173    :    FuncAddr data_addr = reinterpret_cast<FuncAddr>(
 174  E :        module_info.base_address.value() + data->VirtualAddress);
 175    :  
 176  E :    trace::parser::ModuleInformation other_module_info;
 177  E :    other_module_info.base_address.set_value(0x3F000000);
 178  E :    other_module_info.module_size = 0x00010000;
 179  E :    other_module_info.module_checksum = 0xF000BA55;
 180  E :    other_module_info.module_time_date_stamp = 0xDEADBEEF;
 181  E :    other_module_info.path = L"other_module.dll";
 182    :    FuncAddr other_text_addr = reinterpret_cast<FuncAddr>(
 183  E :        other_module_info.base_address.value() + 0x1000);
 184    :  
 185    :    ASSERT_TRUE(parser_->active_parse_engine()->AddModuleInformation(
 186  E :        kPid, module_info));
 187    :  
 188    :    // We should be able to find text.
 189  E :    bool error = false;
 190  E :    EXPECT_TRUE(playback_->FindFunctionBlock(kPid, text_addr, &error) != NULL);
 191  E :    EXPECT_FALSE(error);
 192    :  
 193    :    // We should get an error looking up data.
 194  E :    error = false;
 195  E :    EXPECT_TRUE(playback_->FindFunctionBlock(kPid, data_addr, &error) == NULL);
 196  E :    EXPECT_TRUE(error);
 197    :  
 198    :    // We should get an error looking up an address outside of the module.
 199  E :    error = false;
 200    :    EXPECT_TRUE(
 201  E :        playback_->FindFunctionBlock(kPid, other_text_addr, &error) == NULL);
 202  E :    EXPECT_TRUE(error);
 203    :  
 204    :    // Now add the dummy module. Another lookup should succeed but return NULL.
 205    :    ASSERT_TRUE(parser_->active_parse_engine()->AddModuleInformation(
 206  E :        kPid, other_module_info));
 207  E :    error = false;
 208    :    EXPECT_TRUE(
 209  E :        playback_->FindFunctionBlock(kPid, other_text_addr, &error) == NULL);
 210  E :    EXPECT_FALSE(error);
 211  E :  }
 212    :  
 213    :  }  // namespace playback

Coverage information generated Thu Jan 14 17:40:38 2016.