Coverage for /Syzygy/pe/dia_util_unittest.cc

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

Coverage information generated Thu Jul 04 09:34:53 2013.