Coverage for /Syzygy/pe/dia_util_unittest.cc

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

Line-by-line coverage:

   1    :  // Copyright 2011 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/pe/dia_util.h"
  16    :  
  17    :  #include <map>
  18    :  #include <set>
  19    :  #include <vector>
  20    :  
  21    :  #include "base/bind.h"
  22    :  #include "base/files/file_path.h"
  23    :  #include "base/files/file_util.h"
  24    :  #include "base/win/scoped_bstr.h"
  25    :  #include "base/win/scoped_comptr.h"
  26    :  #include "gmock/gmock.h"
  27    :  #include "syzygy/core/file_util.h"
  28    :  #include "syzygy/core/unittest_util.h"
  29    :  #include "syzygy/pdb/pdb_data.h"
  30    :  #include "syzygy/pe/unittest_util.h"
  31    :  
  32    :  namespace pe {
  33    :  
  34    :  namespace {
  35    :  
  36    :  using base::win::ScopedBstr;
  37    :  using base::win::ScopedComPtr;
  38    :  
  39    :  static const wchar_t kNonsenseStreamName[] =
  40    :      L"ThisStreamNameCertainlyDoesNotExist";
  41    :  
  42    :  // The test_dll output file name configured by the build system.
  43    :  static const char kTestDllObjPath[] = TEST_DLL_OBJECT_FILE;
  44    :  
  45    :  struct FilePathLess {
  46  E :    bool operator()(const std::wstring& lhs, const std::wstring& rhs) {
  47  E :      return base::FilePath::CompareLessIgnoreCase(lhs, rhs);
  48  E :    }
  49    :  };
  50    :  
  51    :  class DiaUtilTest : public testing::PELibUnitTest {
  52    :  };
  53    :  
  54  E :  MATCHER_P(IsSameFile, value, "") {
  55  E :    base::FilePath path1(arg);
  56  E :    base::FilePath path2(value);
  57  E :    core::FilePathCompareResult result = core::CompareFilePaths(path1, path2);
  58  E :    return result == core::kEquivalentFilePaths;
  59  E :  }
  60    :  
  61    :  }  // namespace
  62    :  
  63  E :  TEST_F(DiaUtilTest, CreateDiaSource) {
  64  E :    ScopedComPtr<IDiaDataSource> dia_source;
  65  E :    EXPECT_TRUE(CreateDiaSource(dia_source.Receive()));
  66  E :  }
  67    :  
  68  E :  TEST_F(DiaUtilTest, CreateDiaSesssionDll) {
  69  E :    ScopedComPtr<IDiaDataSource> dia_source;
  70  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
  71    :  
  72  E :    ScopedComPtr<IDiaSession> dia_session;
  73    :    EXPECT_TRUE(CreateDiaSession(
  74    :        testing::GetExeRelativePath(testing::kTestDllName),
  75    :        dia_source.get(),
  76  E :        dia_session.Receive()));
  77  E :  }
  78    :  
  79  E :  TEST_F(DiaUtilTest, CreateDiaSesssionPdb) {
  80  E :    ScopedComPtr<IDiaDataSource> dia_source;
  81  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
  82    :  
  83  E :    ScopedComPtr<IDiaSession> dia_session;
  84    :    EXPECT_TRUE(CreateDiaSession(
  85    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
  86    :        dia_source.get(),
  87  E :        dia_session.Receive()));
  88  E :  }
  89    :  
  90  E :  TEST_F(DiaUtilTest, FindDiaTableByIid) {
  91  E :    ScopedComPtr<IDiaDataSource> dia_source;
  92  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
  93    :  
  94  E :    ScopedComPtr<IDiaSession> dia_session;
  95    :    ASSERT_TRUE(CreateDiaSession(
  96    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
  97    :        dia_source.get(),
  98  E :        dia_session.Receive()));
  99    :  
 100  E :    ScopedComPtr<IDiaEnumSectionContribs> section_contribs;
 101    :    EXPECT_EQ(kSearchSucceeded,
 102    :              FindDiaTable(section_contribs.iid(),
 103    :                           dia_session.get(),
 104  E :                           reinterpret_cast<void**>(section_contribs.Receive())));
 105  E :  }
 106    :  
 107  E :  TEST_F(DiaUtilTest, FindDiaTableByType) {
 108  E :    ScopedComPtr<IDiaDataSource> dia_source;
 109  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
 110    :  
 111  E :    ScopedComPtr<IDiaSession> dia_session;
 112    :    ASSERT_TRUE(CreateDiaSession(
 113    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
 114    :        dia_source.get(),
 115  E :        dia_session.Receive()));
 116    :  
 117  E :    ScopedComPtr<IDiaEnumSectionContribs> section_contribs;
 118    :    EXPECT_EQ(kSearchSucceeded,
 119  E :              FindDiaTable(dia_session.get(), section_contribs.Receive()));
 120  E :  }
 121    :  
 122  E :  TEST_F(DiaUtilTest, FindDiaDebugStream) {
 123  E :    ScopedComPtr<IDiaDataSource> dia_source;
 124  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
 125    :  
 126  E :    ScopedComPtr<IDiaSession> dia_session;
 127    :    ASSERT_TRUE(CreateDiaSession(
 128    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
 129    :        dia_source.get(),
 130  E :        dia_session.Receive()));
 131    :  
 132  E :    ScopedComPtr<IDiaEnumDebugStreamData> debug_stream;
 133    :  
 134    :    EXPECT_EQ(kSearchFailed,
 135    :              FindDiaDebugStream(kNonsenseStreamName,
 136    :                                 dia_session.get(),
 137  E :                                 debug_stream.Receive()));
 138    :  
 139    :    EXPECT_EQ(kSearchSucceeded,
 140    :              FindDiaDebugStream(kFixupDiaDebugStreamName,
 141    :                                 dia_session.get(),
 142  E :                                 debug_stream.Receive()));
 143  E :  }
 144    :  
 145  E :  TEST_F(DiaUtilTest, LoadDiaDebugStream) {
 146  E :    ScopedComPtr<IDiaDataSource> dia_source;
 147  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
 148    :  
 149  E :    ScopedComPtr<IDiaSession> dia_session;
 150    :    ASSERT_TRUE(CreateDiaSession(
 151    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
 152    :        dia_source.get(),
 153  E :        dia_session.Receive()));
 154    :  
 155  E :    ScopedComPtr<IDiaEnumDebugStreamData> debug_stream;
 156    :    ASSERT_EQ(kSearchSucceeded,
 157    :              FindDiaDebugStream(kFixupDiaDebugStreamName,
 158    :                                 dia_session.get(),
 159  E :                                 debug_stream.Receive()));
 160    :  
 161  E :    std::vector<pdb::PdbFixup> fixups;
 162  E :    EXPECT_TRUE(LoadDiaDebugStream(debug_stream.get(), &fixups));
 163  E :    EXPECT_FALSE(fixups.empty());
 164  E :  }
 165    :  
 166  E :  TEST_F(DiaUtilTest, FindAndLoadDiaDebugStreamByName) {
 167  E :    ScopedComPtr<IDiaDataSource> dia_source;
 168  E :    ASSERT_TRUE(CreateDiaSource(dia_source.Receive()));
 169    :  
 170  E :    ScopedComPtr<IDiaSession> dia_session;
 171    :    ASSERT_TRUE(CreateDiaSession(
 172    :        testing::GetExeRelativePath(testing::kTestDllPdbName),
 173    :        dia_source.get(),
 174  E :        dia_session.Receive()));
 175    :  
 176  E :    std::vector<pdb::PdbFixup> fixups;
 177    :  
 178    :    EXPECT_EQ(kSearchFailed,
 179    :              FindAndLoadDiaDebugStreamByName(kNonsenseStreamName,
 180    :                                              dia_session.get(),
 181  E :                                              &fixups));
 182  E :    EXPECT_TRUE(fixups.empty());
 183    :  
 184    :    EXPECT_EQ(kSearchSucceeded,
 185    :              FindAndLoadDiaDebugStreamByName(kFixupDiaDebugStreamName,
 186    :                                              dia_session.get(),
 187  E :                                              &fixups));
 188  E :    EXPECT_FALSE(fixups.empty());
 189  E :  }
 190    :  
 191    :  class DiaUtilVisitorTest : public DiaUtilTest {
 192    :   public:
 193  E :    virtual void SetUp() override {
 194  E :      ASSERT_TRUE(CreateDiaSource(dia_source_.Receive()));
 195  E :      ASSERT_TRUE(CreateDiaSession(
 196    :          testing::GetExeRelativePath(testing::kTestDllName),
 197    :          dia_source_.get(),
 198    :          dia_session_.Receive()));
 199  E :      ASSERT_EQ(S_OK, dia_session_->get_globalScope(dia_globals_.Receive()));
 200  E :    }
 201    :  
 202    :    typedef std::vector<std::wstring> StringVector;
 203  E :    bool OnFunction(StringVector* names, IDiaSymbol* function) {
 204  E :      EXPECT_TRUE(IsSymTag(function, SymTagFunction));
 205  E :      ScopedBstr name;
 206  E :      EXPECT_EQ(S_OK, function->get_name(name.Receive()));
 207  E :      names->push_back(common::ToString(name));
 208  E :      return true;
 209  E :    }
 210    :  
 211  E :    bool OnCompiland(StringVector* names, IDiaSymbol* compiland) {
 212  E :      EXPECT_TRUE(IsSymTag(compiland, SymTagCompiland));
 213  E :      ScopedBstr name;
 214  E :      EXPECT_EQ(S_OK, compiland->get_name(name.Receive()));
 215  E :      names->push_back(common::ToString(name));
 216  E :      return true;
 217  E :    }
 218    :  
 219    :    bool OnCompilandFind(const std::wstring& compiland_path,
 220    :                         ScopedComPtr<IDiaSymbol>* compiland_out,
 221  E :                         IDiaSymbol* compiland) {
 222  E :      EXPECT_TRUE(IsSymTag(compiland, SymTagCompiland));
 223  E :      ScopedBstr name;
 224  E :      EXPECT_EQ(S_OK, compiland->get_name(name.Receive()));
 225  E :      if (testing::Value(common::ToString(name), IsSameFile(compiland_path))) {
 226  E :        *compiland_out = compiland;
 227  E :        return false;
 228    :      }
 229  E :      return true;
 230  E :    }
 231    :  
 232    :    typedef std::set<std::pair<DWORD, DWORD>> LineSet;
 233    :    typedef std::map<std::wstring, LineSet, FilePathLess> LineMap;
 234  E :    bool OnLine(LineMap* line_map, IDiaLineNumber* line) {
 235  E :      DCHECK_NE(reinterpret_cast<LineMap*>(NULL), line_map);
 236  E :      DCHECK_NE(reinterpret_cast<IDiaLineNumber*>(NULL), line);
 237    :  
 238  E :      ScopedComPtr<IDiaSourceFile> source_file;
 239  E :      EXPECT_HRESULT_SUCCEEDED(line->get_sourceFile(source_file.Receive()));
 240    :  
 241  E :      ScopedBstr source_name;
 242  E :      EXPECT_HRESULT_SUCCEEDED(source_file->get_fileName(source_name.Receive()));
 243    :  
 244  E :      ScopedComPtr<IDiaSymbol> compiland;
 245  E :      EXPECT_HRESULT_SUCCEEDED(line->get_compiland(compiland.Receive()));
 246    :  
 247  E :      DWORD line_number = 0;
 248  E :      EXPECT_HRESULT_SUCCEEDED(line->get_lineNumber(&line_number));
 249  E :      DWORD line_number_end = 0;
 250  E :      EXPECT_HRESULT_SUCCEEDED(line->get_lineNumberEnd(&line_number_end));
 251    :  
 252    :      // This doesn't necessarily have to hold, but so far it seems to do so.
 253  E :      EXPECT_EQ(line_number, line_number_end);
 254    :  
 255    :      (*line_map)[common::ToString(source_name)].insert(
 256  E :          std::make_pair(line_number, line_number_end));
 257    :  
 258  E :      return true;
 259  E :    }
 260    :  
 261    :    ScopedComPtr<IDiaDataSource> dia_source_;
 262    :    ScopedComPtr<IDiaSession> dia_session_;
 263    :    ScopedComPtr<IDiaSymbol> dia_globals_;
 264    :  };
 265    :  
 266  E :  TEST_F(DiaUtilVisitorTest, ChildVisitorTest) {
 267  E :    ChildVisitor visitor(dia_globals_.get(), SymTagFunction);
 268    :  
 269  E :    StringVector function_names;
 270    :    ASSERT_TRUE(visitor.VisitChildren(
 271    :        base::Bind(&DiaUtilVisitorTest::OnFunction,
 272    :                   base::Unretained(this),
 273  E :                   &function_names)));
 274    :  
 275    :    // Expect that we found a bunch of functions.
 276  E :    ASSERT_LT(1U, function_names.size());
 277    :    // One of them should be "DllMain".
 278  E :    ASSERT_THAT(function_names, testing::Contains(L"DllMain"));
 279  E :  }
 280    :  
 281  E :  TEST_F(DiaUtilVisitorTest, CompilandVisitorTest) {
 282  E :    CompilandVisitor visitor(dia_session_.get());
 283    :  
 284  E :    StringVector compiland_names;
 285    :    ASSERT_TRUE(visitor.VisitAllCompilands(
 286    :        base::Bind(&DiaUtilVisitorTest::OnCompiland,
 287    :                   base::Unretained(this),
 288  E :                   &compiland_names)));
 289    :  
 290    :    // We expect to have seen some compiland_names.
 291  E :    ASSERT_LT(0U, compiland_names.size());
 292    :  
 293    :    // One of the compiland_names should be the test_dll.obj file.
 294  E :    std::string test_dll_path(kTestDllObjPath);
 295  E :    std::wstring test_dll_wide_path(test_dll_path.begin(), test_dll_path.end());
 296    :    base::FilePath test_dll_obj =
 297    :        base::MakeAbsoluteFilePath(
 298  E :            testing::GetOutputRelativePath(test_dll_wide_path.c_str()));
 299    :    ASSERT_THAT(compiland_names,
 300  E :                testing::Contains(IsSameFile(test_dll_obj.value())));
 301  E :  }
 302    :  
 303  E :  TEST_F(DiaUtilVisitorTest, LineVisitorTest) {
 304  E :    CompilandVisitor compiland_visitor(dia_session_.get());
 305    :  
 306    :    // Start by finding the test dll compiland.
 307  E :    ScopedComPtr<IDiaSymbol> compiland;
 308  E :    std::string test_dll_path(kTestDllObjPath);
 309  E :    std::wstring test_dll_wide_path(test_dll_path.begin(), test_dll_path.end());
 310    :    base::FilePath test_dll_obj =
 311    :        base::MakeAbsoluteFilePath(
 312  E :            testing::GetOutputRelativePath(test_dll_wide_path.c_str()));
 313    :    ASSERT_FALSE(compiland_visitor.VisitAllCompilands(
 314    :        base::Bind(&DiaUtilVisitorTest::OnCompilandFind,
 315    :                   base::Unretained(this),
 316    :                   test_dll_obj.value(),
 317  E :                   &compiland)));
 318    :  
 319  E :    ASSERT_TRUE(compiland != NULL);
 320    :  
 321    :    // Now enumerate all line entries in that compiland.
 322  E :    LineVisitor line_visitor(dia_session_.get(), compiland.get());
 323    :  
 324  E :    LineMap line_map;
 325    :    ASSERT_TRUE(line_visitor.VisitLines(
 326    :        base::Bind(&DiaUtilVisitorTest::OnLine,
 327    :                   base::Unretained(this),
 328  E :                   &line_map)));
 329    :  
 330    :    // We expect to have at least one file.
 331  E :    ASSERT_LE(1U, line_map.size());
 332    :  
 333    :    base::FilePath test_dll_cc =
 334  E :        testing::GetSrcRelativePath(L"syzygy\\pe\\test_dll.cc");
 335  E :    ASSERT_TRUE(line_map.find(test_dll_cc.value()) != line_map.end());
 336    :  
 337  E :    ASSERT_LT(1U, line_map[test_dll_cc.value()].size());
 338  E :  }
 339    :  
 340    :  }  // namespace pe

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