Coverage for /Syzygy/pdb/pdb_util_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
99.8%5295300.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/pdb/pdb_util.h"
  16    :  
  17    :  #include <objbase.h>
  18    :  #include <vector>
  19    :  
  20    :  #include "base/command_line.h"
  21    :  #include "base/path_service.h"
  22    :  #include "base/scoped_native_library.h"
  23    :  #include "base/files/scoped_temp_dir.h"
  24    :  #include "base/process/launch.h"
  25    :  #include "base/strings/utf_string_conversions.h"
  26    :  #include "base/win/pe_image.h"
  27    :  #include "gmock/gmock.h"
  28    :  #include "gtest/gtest.h"
  29    :  #include "syzygy/common/dbghelp_util.h"
  30    :  #include "syzygy/core/unittest_util.h"
  31    :  #include "syzygy/pdb/pdb_byte_stream.h"
  32    :  #include "syzygy/pdb/pdb_reader.h"
  33    :  #include "syzygy/pdb/pdb_stream_reader.h"
  34    :  #include "syzygy/pdb/pdb_writer.h"
  35    :  #include "syzygy/pdb/unittest_util.h"
  36    :  #include "syzygy/pe/pe_data.h"
  37    :  #include "syzygy/pe/unittest_util.h"
  38    :  
  39    :  namespace pdb {
  40    :  
  41    :  namespace {
  42    :  
  43    :  const wchar_t* kTempPdbFileName = L"temp.pdb";
  44    :  const wchar_t* kTempPdbFileName2 = L"temp2.pdb";
  45    :  
  46    :  const GUID kSampleGuid = {0xACDC900D, 0x9009, 0xFEED, {7, 6, 5, 4, 3, 2, 1, 0}};
  47    :  
  48    :  const PdbInfoHeader70 kSamplePdbHeader = {
  49    :    kPdbCurrentVersion,
  50    :    1336402486,  // 7 May 2012, 14:54:00 GMT.
  51    :    999,
  52    :    {0xDEADBEEF, 0x900D, 0xF00D, {0, 1, 2, 3, 4, 5, 6, 7}}
  53    :  };
  54    :  
  55    :  const DbiHeader kSampleDbiHeader = {
  56    :    -1,   // signature.
  57    :    19990903,  // version.
  58    :    999,  // age.
  59    :  };
  60    :  
  61    :  const OMAP kOmapToData[] = {
  62    :    {4096, 4096},
  63    :    {5012, 5012},
  64    :    {6064, 6064},
  65    :    {7048, 240504}
  66    :  };
  67    :  
  68    :  const OMAP kOmapFromData[] = {
  69    :    {4096, 4096},
  70    :    {5012, 5012},
  71    :    {240504, 7048}
  72    :  };
  73    :  
  74    :  class PdbUtilTest : public testing::Test {
  75    :   public:
  76  E :    PdbUtilTest() : process_(this) {
  77  E :    }
  78    :  
  79  E :    void SetUp() {
  80  E :      ASSERT_TRUE(common::SymInitialize(process_, NULL, false));
  81    :  
  82  E :      ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&new_guid_));
  83  E :      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  84    :  
  85  E :      temp_pdb_file_path_ = temp_dir_.path().Append(kTempPdbFileName);
  86  E :      temp_pdb_file_path2_ = temp_dir_.path().Append(kTempPdbFileName2);
  87  E :    }
  88    :  
  89  E :    void TearDown() {
  90  E :      ASSERT_TRUE(::SymCleanup(process_));
  91  E :    }
  92    :  
  93    :    void VerifyGuidData(const base::FilePath& pdb_path,
  94    :                        const GUID& guid) {
  95    :      DWORD64 base_address =
  96    :          ::SymLoadModuleExW(process_,
  97    :                             NULL,
  98    :                             pdb_path.value().c_str(),
  99    :                             NULL,
 100    :                             1,
 101    :                             1,
 102    :                             NULL,
 103    :                             0);
 104    :      EXPECT_NE(0, base_address);
 105    :  
 106    :      // Get the module info to verify that the new PDB has the GUID we specified.
 107    :      IMAGEHLP_MODULEW64 module_info = { sizeof(module_info) };
 108    :      EXPECT_TRUE(::SymGetModuleInfoW64(process_, base_address, &module_info));
 109    :      EXPECT_EQ(new_guid_, module_info.PdbSig70);
 110    :  
 111    :      EXPECT_TRUE(::SymUnloadModule64(process_, base_address));
 112    :    }
 113    :  
 114    :    void VerifyOmapData(const base::FilePath& pdb_path,
 115    :                        const std::vector<OMAP>& omap_to_list,
 116  E :                        const std::vector<OMAP>& omap_from_list) {
 117    :      DWORD64 base_address =
 118  E :          ::SymLoadModuleExW(process_,
 119    :                             NULL,
 120    :                             pdb_path.value().c_str(),
 121    :                             NULL,
 122    :                             1,
 123    :                             1,
 124    :                             NULL,
 125    :                             0);
 126  E :      ASSERT_NE(0, base_address);
 127    :  
 128  E :      OMAP* omap_to = NULL;
 129  E :      DWORD64 omap_to_length = 0;
 130  E :      OMAP* omap_from = NULL;
 131  E :      DWORD64 omap_from_length = 0;
 132  E :      ASSERT_TRUE(::SymGetOmaps(process_,
 133    :                                base_address,
 134    :                                &omap_to,
 135    :                                &omap_to_length,
 136    :                                &omap_from,
 137    :                                &omap_from_length));
 138    :  
 139  E :      ASSERT_EQ(omap_to_list.size(), omap_to_length);
 140  E :      EXPECT_EQ(0, memcmp(&omap_to_list[0], omap_to,
 141    :                          omap_to_list.size() * sizeof(OMAP)));
 142  E :      ASSERT_EQ(omap_from_list.size(), omap_from_length);
 143  E :      EXPECT_EQ(0, memcmp(&omap_from_list[0], omap_from,
 144    :                          omap_from_list.size() * sizeof(OMAP)));
 145    :  
 146  E :      EXPECT_TRUE(::SymUnloadModule64(process_, base_address));
 147  E :    }
 148    :  
 149    :   protected:
 150    :    HANDLE process_;
 151    :    GUID new_guid_;
 152    :    base::ScopedTempDir temp_dir_;
 153    :    base::FilePath temp_pdb_file_path_;
 154    :    base::FilePath temp_pdb_file_path2_;
 155    :  };
 156    :  
 157    :  class TestPdbStream : public PdbStream {
 158    :   public:
 159  E :    TestPdbStream() : PdbStream(0), bytes_(NULL) {
 160  E :    }
 161    :  
 162    :    template <typename T>
 163    :    explicit TestPdbStream(const T& t)
 164  E :        : PdbStream(sizeof(T)), bytes_(reinterpret_cast<const uint8_t*>(&t)) {}
 165    :  
 166    :    explicit TestPdbStream(const std::vector<char>& data)
 167    :        : PdbStream(data.size()),
 168    :          bytes_(reinterpret_cast<const uint8_t*>(&data.at(0))) {}
 169    :  
 170  E :    bool ReadBytesAt(size_t pos, size_t count, void* dest) override {
 171  E :      if (count > length() - pos)
 172  i :        return false;
 173  E :      ::memcpy(dest, bytes_ + pos, count);
 174  E :      return true;
 175  E :    }
 176    :  
 177    :   private:
 178    :    const uint8_t* const bytes_;
 179    :  };
 180    :  
 181    :  // Comparison operator for PdbInfoHeader70 objects.
 182    :  bool AreEqual(const PdbInfoHeader70& header1,
 183  E :                const PdbInfoHeader70& header2) {
 184  E :    return ::memcmp(&header1, &header2, sizeof(header1)) == 0;
 185  E :  }
 186    :  
 187    :  }  // namespace
 188    :  
 189  E :  TEST(PdbBitSetTest, ReadEmptyStream) {
 190  E :    scoped_refptr<PdbStream> stream(new TestPdbStream());
 191  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 192    :  
 193  E :    PdbBitSet bs;
 194  E :    EXPECT_FALSE(bs.Read(&reader));
 195  E :  }
 196    :  
 197  E :  TEST(PdbBitSetTest, SimpleMutators) {
 198  E :    PdbBitSet bs;
 199  E :    EXPECT_TRUE(bs.IsEmpty());
 200  E :    EXPECT_EQ(bs.size(), 0u);
 201  E :    bs.Resize(43);
 202  E :    EXPECT_EQ(bs.size(), 64u);
 203    :  
 204  E :    for (size_t i = 0; i < 64; ++i)
 205  E :      EXPECT_FALSE(bs.IsSet(i));
 206    :  
 207  E :    bs.Toggle(15);
 208  E :    EXPECT_TRUE(bs.IsSet(15));
 209  E :    bs.Toggle(15);
 210  E :    EXPECT_FALSE(bs.IsSet(15));
 211    :  
 212  E :    bs.Set(25);
 213  E :    EXPECT_TRUE(bs.IsSet(25));
 214  E :    bs.Clear(25);
 215  E :    EXPECT_FALSE(bs.IsSet(25));
 216    :  
 217  E :    for (size_t i = 0; i < 64; i += 10)
 218  E :      bs.Set(i);
 219    :  
 220  E :    for (size_t i = 0; i < 64; ++i)
 221  E :      EXPECT_EQ((i % 10) == 0, bs.IsSet(i));
 222  E :  }
 223    :  
 224  E :  TEST(PdbBitSetTest, ReadEmptyBitSet) {
 225  E :    const uint32_t kSize = 0;
 226  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kSize));
 227  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 228  E :    PdbBitSet bs;
 229  E :    EXPECT_TRUE(bs.Read(&reader));
 230  E :    EXPECT_TRUE(bs.IsEmpty());
 231  E :    EXPECT_EQ(bs.size(), 0u);
 232  E :  }
 233    :  
 234  E :  TEST(PdbBitSetTest, ReadSingleDwordBitSet) {
 235  E :    const uint32_t kData[] = {1, (1 << 0) | (1 << 5) | (1 << 13)};
 236  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kData));
 237  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 238  E :    PdbBitSet bs;
 239  E :    EXPECT_TRUE(bs.Read(&reader));
 240  E :    EXPECT_FALSE(bs.IsEmpty());
 241  E :    EXPECT_EQ(bs.size(), 32u);
 242  E :    for (size_t i = 0; i < bs.size(); ++i)
 243  E :      EXPECT_EQ(i == 0 || i == 5 || i == 13, bs.IsSet(i));
 244  E :  }
 245    :  
 246  E :  TEST(PdbBitSetTest, ReadMultiDwordBitSet) {
 247  E :    const uint32_t kData[] = {2, (1 << 0) | (1 << 5) | (1 << 13), (1 << 5)};
 248  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kData));
 249  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 250  E :    PdbBitSet bs;
 251  E :    EXPECT_TRUE(bs.Read(&reader));
 252  E :    EXPECT_FALSE(bs.IsEmpty());
 253  E :    EXPECT_EQ(bs.size(), 64u);
 254  E :    for (size_t i = 0; i < bs.size(); ++i)
 255  E :      EXPECT_EQ(i == 0 || i == 5 || i == 13 || i == (32 + 5), bs.IsSet(i));
 256  E :  }
 257    :  
 258  E :  TEST(PdbBitSetTest, WriteEmptyBitSet) {
 259  E :    const uint32_t kData[] = {0};
 260  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kData));
 261  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 262  E :    PdbBitSet bs;
 263  E :    EXPECT_TRUE(bs.Read(&reader));
 264    :  
 265  E :    scoped_refptr<PdbByteStream> new_stream(new PdbByteStream());
 266  E :    scoped_refptr<WritablePdbStream> writer(new_stream->GetWritableStream());
 267  E :    EXPECT_TRUE(bs.Write(writer.get(), true));
 268  E :    EXPECT_EQ(sizeof(kData), new_stream->length());
 269    :  
 270  E :    uint32_t data[arraysize(kData)] = {};
 271  E :    EXPECT_TRUE(new_stream->ReadBytesAt(0, sizeof(data), data));
 272  E :    EXPECT_THAT(data, testing::ElementsAreArray(kData));
 273  E :  }
 274    :  
 275  E :  TEST(PdbBitSetTest, WriteEmptyBitSetWithoutSize) {
 276  E :    const uint32_t kData[] = {0};
 277  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kData));
 278  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 279  E :    PdbBitSet bs;
 280  E :    EXPECT_TRUE(bs.Read(&reader));
 281    :  
 282  E :    scoped_refptr<PdbByteStream> new_stream(new PdbByteStream());
 283  E :    scoped_refptr<WritablePdbStream> writer(new_stream->GetWritableStream());
 284  E :    EXPECT_TRUE(bs.Write(writer.get(), false));
 285    :  
 286  E :    EXPECT_EQ(0, new_stream->length());
 287  E :  }
 288    :  
 289  E :  TEST(PdbBitSetTest, WriteBitSet) {
 290  E :    const uint32_t kData[] = {2, (1 << 0) | (1 << 5) | (1 << 13), (1 << 5)};
 291  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kData));
 292  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 293  E :    PdbBitSet bs;
 294  E :    EXPECT_TRUE(bs.Read(&reader));
 295    :  
 296  E :    scoped_refptr<PdbByteStream> new_stream(new PdbByteStream());
 297  E :    scoped_refptr<WritablePdbStream> writer(new_stream->GetWritableStream());
 298  E :    EXPECT_TRUE(bs.Write(writer.get(), true));
 299  E :    EXPECT_EQ(sizeof(kData), new_stream->length());
 300    :  
 301  E :    uint32_t data[arraysize(kData)] = {};
 302  E :    EXPECT_TRUE(new_stream->ReadBytesAt(0, sizeof(data), data));
 303  E :    EXPECT_THAT(data, testing::ElementsAreArray(kData));
 304  E :  }
 305    :  
 306  E :  TEST(PdbBitSetTest, WriteBitSetWithoutSize) {
 307  E :    const uint32_t kInputData[] = {2, (1 << 0) | (1 << 5) | (1 << 13), (1 << 5)};
 308  E :    const uint32_t kExpectedData[] = {(1 << 0) | (1 << 5) | (1 << 13), (1 << 5)};
 309  E :    scoped_refptr<PdbStream> stream(new TestPdbStream(kInputData));
 310  E :    pdb::PdbStreamReaderWithPosition reader(stream.get());
 311  E :    PdbBitSet bs;
 312  E :    EXPECT_TRUE(bs.Read(&reader));
 313    :  
 314  E :    scoped_refptr<PdbByteStream> new_stream(new PdbByteStream());
 315  E :    scoped_refptr<WritablePdbStream> writer(new_stream->GetWritableStream());
 316  E :    EXPECT_TRUE(bs.Write(writer.get(), false));
 317  E :    EXPECT_EQ(sizeof(kExpectedData), new_stream->length());
 318    :  
 319  E :    uint32_t data[arraysize(kExpectedData)] = {};
 320  E :    EXPECT_TRUE(new_stream->ReadBytesAt(0, sizeof(data), data));
 321  E :    EXPECT_THAT(data, testing::ElementsAreArray(kExpectedData));
 322  E :  }
 323    :  
 324  E :  TEST_F(PdbUtilTest, HashString) {
 325  E :    EXPECT_EQ(1024, HashString(""));
 326  E :    EXPECT_EQ(20527, HashString("___onexitend"));
 327  E :    EXPECT_EQ(24736, HashString("__imp____getmainargs"));
 328  E :    EXPECT_EQ(61647, HashString("___security_cookie"));
 329  E :  }
 330    :  
 331  E :  TEST_F(PdbUtilTest, GetDbiDbgHeaderOffsetTestDll) {
 332    :    // Test the test_dll.dll.pdb doesn't have Omap information.
 333  E :    PdbReader reader;
 334  E :    PdbFile pdb_file;
 335  E :    EXPECT_TRUE(reader.Read(
 336    :        testing::GetSrcRelativePath(testing::kTestPdbFilePath),
 337  E :        &pdb_file));
 338    :  
 339  E :    PdbStream* dbi_stream = pdb_file.GetStream(kDbiStream).get();
 340    :    DbiHeader dbi_header;
 341  E :    EXPECT_TRUE(dbi_stream->ReadBytesAt(0, sizeof(dbi_header), &dbi_header));
 342    :  
 343  E :    uint32_t offset = GetDbiDbgHeaderOffset(dbi_header);
 344  E :    EXPECT_LE(offset, dbi_stream->length() - sizeof(DbiDbgHeader));
 345    :  
 346    :    DbiDbgHeader dbi_dbg_header;
 347  E :    EXPECT_TRUE(
 348  E :        dbi_stream->ReadBytesAt(offset, sizeof(dbi_dbg_header), &dbi_dbg_header));
 349    :  
 350  E :    EXPECT_EQ(-1, dbi_dbg_header.omap_to_src);
 351  E :    EXPECT_EQ(-1, dbi_dbg_header.omap_from_src);
 352  E :  }
 353    :  
 354  E :  TEST_F(PdbUtilTest, GetDbiDbgHeaderOffsetOmappedTestDll) {
 355    :    // Test that omapped_test_dll.dll.pdb does have Omap information.
 356  E :    PdbReader reader;
 357  E :    PdbFile pdb_file;
 358  E :    EXPECT_TRUE(reader.Read(
 359    :        testing::GetSrcRelativePath(testing::kOmappedTestPdbFilePath),
 360  E :        &pdb_file));
 361    :  
 362  E :    PdbStream* dbi_stream = pdb_file.GetStream(kDbiStream).get();
 363    :    DbiHeader dbi_header;
 364  E :    EXPECT_TRUE(dbi_stream->ReadBytesAt(0, sizeof(dbi_header), &dbi_header));
 365    :  
 366  E :    uint32_t offset = GetDbiDbgHeaderOffset(dbi_header);
 367  E :    EXPECT_LE(offset, dbi_stream->length() - sizeof(DbiDbgHeader));
 368    :  
 369    :    DbiDbgHeader dbi_dbg_header;
 370  E :    EXPECT_TRUE(
 371  E :        dbi_stream->ReadBytesAt(offset, sizeof(dbi_dbg_header), &dbi_dbg_header));
 372    :  
 373  E :    EXPECT_NE(-1, dbi_dbg_header.omap_to_src);
 374  E :    EXPECT_NE(-1, dbi_dbg_header.omap_from_src);
 375  E :  }
 376    :  
 377  E :  TEST_F(PdbUtilTest, TestDllHasNoOmap) {
 378    :    // Test that test_dll.dll.pdb has no Omap information.
 379  E :    base::FilePath test_pdb_file_path = testing::GetSrcRelativePath(
 380    :        testing::kTestPdbFilePath);
 381    :    DWORD64 base_address =
 382  E :        ::SymLoadModuleExW(process_,
 383    :                           NULL,
 384    :                           test_pdb_file_path.value().c_str(),
 385    :                           NULL,
 386    :                           1,
 387    :                           1,
 388    :                           NULL,
 389    :                           0);
 390  E :    EXPECT_NE(0, base_address);
 391    :  
 392  E :    OMAP* omap_to = NULL;
 393  E :    DWORD64 omap_to_length = 0;
 394  E :    OMAP* omap_from = NULL;
 395  E :    DWORD64 omap_from_length = 0;
 396  E :    EXPECT_FALSE(::SymGetOmaps(process_,
 397    :                               base_address,
 398    :                               &omap_to,
 399    :                               &omap_to_length,
 400    :                               &omap_from,
 401  E :                               &omap_from_length));
 402    :  
 403  E :    EXPECT_TRUE(::SymUnloadModule64(process_, base_address));
 404  E :  }
 405    :  
 406  E :  TEST_F(PdbUtilTest, SetOmapToAndFromStream) {
 407    :    // Add Omap information to test_dll.pdb and test that the output file
 408    :    // has Omap information.
 409  E :    std::vector<OMAP> omap_to_list(kOmapToData,
 410    :                                   kOmapToData + arraysize(kOmapToData));
 411  E :    std::vector<OMAP> omap_from_list(kOmapFromData,
 412    :                                     kOmapFromData + arraysize(kOmapFromData));
 413    :  
 414  E :    base::FilePath test_pdb_file_path = testing::GetSrcRelativePath(
 415    :        testing::kTestPdbFilePath);
 416  E :    PdbReader pdb_reader;
 417  E :    PdbFile pdb_file;
 418  E :    ASSERT_TRUE(pdb_reader.Read(test_pdb_file_path, &pdb_file));
 419    :  
 420  E :    EXPECT_TRUE(SetOmapToStream(omap_to_list, &pdb_file));
 421  E :    EXPECT_TRUE(SetOmapFromStream(omap_from_list, &pdb_file));
 422    :  
 423  E :    PdbWriter pdb_writer;
 424  E :    ASSERT_TRUE(pdb_writer.Write(temp_pdb_file_path_, pdb_file));
 425    :  
 426  E :    VerifyOmapData(temp_pdb_file_path_,
 427    :                   omap_to_list,
 428    :                   omap_from_list);
 429  E :  }
 430    :  
 431  E :  TEST_F(PdbUtilTest, PdbHeaderMatchesImageDebugDirectory) {
 432  E :    PdbReader reader;
 433  E :    PdbFile pdb_file;
 434  E :    EXPECT_TRUE(reader.Read(
 435    :        testing::GetSrcRelativePath(testing::kTestPdbFilePath),
 436  E :        &pdb_file));
 437    :  
 438  E :    PdbInfoHeader70 header = { 0 };
 439  E :    ASSERT_GE(pdb_file.StreamCount(), kPdbHeaderInfoStream);
 440  E :    ASSERT_TRUE(pdb_file.GetStream(kPdbHeaderInfoStream) != NULL);
 441  E :    EXPECT_TRUE(pdb_file.GetStream(kPdbHeaderInfoStream)
 442  E :                    ->ReadBytesAt(0, sizeof(header), &header));
 443  E :    EXPECT_EQ(header.version, kPdbCurrentVersion);
 444    :  
 445  E :    base::NativeLibraryLoadError error;
 446    :    base::NativeLibrary test_dll =
 447  E :        base::LoadNativeLibrary(
 448    :            testing::GetSrcRelativePath(testing::kTestDllFilePath),
 449    :            &error);
 450  E :    ASSERT_TRUE(test_dll != NULL);
 451    :  
 452    :    // Make sure the DLL is unloaded on exit.
 453  E :    base::ScopedNativeLibrary test_dll_keeper(test_dll);
 454  E :    base::win::PEImage image(test_dll);
 455    :  
 456  E :    ASSERT_EQ(sizeof(IMAGE_DEBUG_DIRECTORY),
 457  E :              image.GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG));
 458    :    const IMAGE_DEBUG_DIRECTORY* debug_directory =
 459    :        reinterpret_cast<const IMAGE_DEBUG_DIRECTORY*>(
 460  E :            image.GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG));
 461    :  
 462  E :    ASSERT_EQ(IMAGE_DEBUG_TYPE_CODEVIEW, debug_directory->Type);
 463  E :    ASSERT_GE(debug_directory->SizeOfData, sizeof(pe::CvInfoPdb70));
 464    :  
 465    :    const pe::CvInfoPdb70* cv_info =
 466    :        reinterpret_cast<const pe::CvInfoPdb70*>(
 467  E :            image.RVAToAddr(debug_directory->AddressOfRawData));
 468    :  
 469  E :    ASSERT_EQ(pe::kPdb70Signature, cv_info->cv_signature);
 470  E :    ASSERT_EQ(header.signature, cv_info->signature);
 471  E :    ASSERT_EQ(header.pdb_age, cv_info->pdb_age);
 472  E :  }
 473    :  
 474  E :  TEST_F(PdbUtilTest, ReadPdbHeader) {
 475  E :    const base::FilePath pdb_path = testing::GetSrcRelativePath(
 476    :        testing::kTestPdbFilePath);
 477  E :    PdbInfoHeader70 pdb_header = {};
 478  E :    EXPECT_TRUE(ReadPdbHeader(pdb_path, &pdb_header));
 479  E :  }
 480    :  
 481  E :  TEST(EnsureStreamWritableTest, DoesNothingWhenAlreadyWritable) {
 482  E :    PdbFile pdb_file;
 483  E :    scoped_refptr<PdbStream> stream = new PdbByteStream();
 484  E :    size_t index = pdb_file.AppendStream(stream.get());
 485  E :    EXPECT_TRUE(EnsureStreamWritable(index, &pdb_file));
 486  E :    scoped_refptr<PdbStream> stream2 = pdb_file.GetStream(index);
 487  E :    EXPECT_EQ(stream.get(), stream2.get());
 488  E :  }
 489    :  
 490  E :  TEST(EnsureStreamWritableTest, WorksWhenReadOnly) {
 491  E :    PdbFile pdb_file;
 492  E :    scoped_refptr<PdbStream> stream = new TestPdbStream();
 493  E :    size_t index = pdb_file.AppendStream(stream.get());
 494  E :    EXPECT_TRUE(EnsureStreamWritable(index, &pdb_file));
 495  E :    scoped_refptr<PdbStream> stream2 = pdb_file.GetStream(index);
 496  E :    EXPECT_TRUE(stream2.get() != NULL);
 497  E :    EXPECT_NE(stream.get(), stream2.get());
 498  E :    EXPECT_TRUE(stream2->GetWritableStream() != NULL);
 499  E :  }
 500    :  
 501  E :  TEST(EnsureStreamWritableTest, FailsWhenNonExistent) {
 502  E :    PdbFile pdb_file;
 503  E :    EXPECT_FALSE(EnsureStreamWritable(45, &pdb_file));
 504  E :  }
 505    :  
 506  E :  TEST(SetGuidTest, FailsWhenStreamsDoNotExist) {
 507  E :    PdbFile pdb_file;
 508    :  
 509    :    // Leave the Pdb header missing.
 510  E :    pdb_file.SetStream(kPdbHeaderInfoStream, NULL);
 511  E :    pdb_file.SetStream(kDbiStream, new TestPdbStream(kSampleDbiHeader));
 512  E :    EXPECT_FALSE(SetGuid(kSampleGuid, &pdb_file));
 513    :  
 514    :    // Add the header stream, but leave the Dbi header missing.
 515  E :    pdb_file.SetStream(kPdbHeaderInfoStream, new TestPdbStream(kSamplePdbHeader));
 516  E :    pdb_file.SetStream(kDbiStream, NULL);
 517  E :    EXPECT_FALSE(SetGuid(kSampleGuid, &pdb_file));
 518  E :  }
 519    :  
 520  E :  TEST(SetGuidTest, FailsWhenStreamsAreTooShort) {
 521  E :    PdbFile pdb_file;
 522    :  
 523  E :    const uint8_t kByte = 6;
 524  E :    pdb_file.SetStream(kPdbHeaderInfoStream, new TestPdbStream(kByte));
 525  E :    pdb_file.SetStream(kDbiStream, new TestPdbStream(kSampleDbiHeader));
 526  E :    EXPECT_FALSE(SetGuid(kSampleGuid, &pdb_file));
 527    :  
 528  E :    pdb_file.SetStream(kPdbHeaderInfoStream, new TestPdbStream(kSamplePdbHeader));
 529  E :    pdb_file.SetStream(kDbiStream, new TestPdbStream(kByte));
 530  E :    EXPECT_FALSE(SetGuid(kSampleGuid, &pdb_file));
 531  E :  }
 532    :  
 533  E :  TEST(SetGuidTest, Succeeds) {
 534  E :    PdbFile pdb_file;
 535    :  
 536  E :    pdb_file.SetStream(kPdbHeaderInfoStream, new TestPdbStream(kSamplePdbHeader));
 537  E :    pdb_file.SetStream(kDbiStream, new TestPdbStream(kSampleDbiHeader));
 538    :  
 539    :    scoped_refptr<PdbStream> stream =
 540  E :        pdb_file.GetStream(kPdbHeaderInfoStream);
 541  E :    ASSERT_TRUE(stream.get() != NULL);
 542  E :    ASSERT_EQ(stream->length(), sizeof(PdbInfoHeader70));
 543    :  
 544  E :    uint32_t time1 = static_cast<uint32_t>(time(NULL));
 545  E :    EXPECT_TRUE(SetGuid(kSampleGuid, &pdb_file));
 546  E :    uint32_t time2 = static_cast<uint32_t>(time(NULL));
 547    :  
 548    :    // Read the new header.
 549  E :    PdbInfoHeader70 pdb_header = {};
 550  E :    stream = pdb_file.GetStream(kPdbHeaderInfoStream);
 551  E :    EXPECT_TRUE(stream->ReadBytesAt(0, sizeof(pdb_header), &pdb_header));
 552    :  
 553    :    // Validate that the fields are as expected.
 554  E :    EXPECT_LE(time1, pdb_header.timestamp);
 555  E :    EXPECT_LE(pdb_header.timestamp, time2);
 556  E :    EXPECT_EQ(1u, pdb_header.pdb_age);
 557  E :    EXPECT_EQ(kSampleGuid, pdb_header.signature);
 558    :  
 559  E :    DbiHeader dbi_header = {};
 560  E :    stream = pdb_file.GetStream(kDbiStream);
 561  E :    ASSERT_TRUE(stream.get() != NULL);
 562  E :    ASSERT_EQ(stream->length(), sizeof(dbi_header));
 563    :  
 564  E :    EXPECT_TRUE(stream->ReadBytesAt(0, sizeof(dbi_header), &dbi_header));
 565  E :    EXPECT_EQ(1u, dbi_header.age);
 566  E :  }
 567    :  
 568  E :  TEST(ReadHeaderInfoStreamTest, ReadFromPdbFile) {
 569  E :    const base::FilePath pdb_path = testing::GetSrcRelativePath(
 570    :        testing::kTestPdbFilePath);
 571    :  
 572  E :    PdbFile pdb_file;
 573  E :    PdbReader pdb_reader;
 574  E :    ASSERT_TRUE(pdb_reader.Read(pdb_path, &pdb_file));
 575    :  
 576  E :    PdbInfoHeader70 pdb_header = {};
 577  E :    NameStreamMap name_stream_map;
 578  E :    EXPECT_TRUE(ReadHeaderInfoStream(pdb_file, &pdb_header, &name_stream_map));
 579  E :  }
 580    :  
 581  E :  TEST(ReadHeaderInfoStreamTest, ReadEmptyStream) {
 582  E :    scoped_refptr<PdbStream> stream(new TestPdbStream());
 583  E :    PdbInfoHeader70 pdb_header = {};
 584  E :    NameStreamMap name_stream_map;
 585  E :    EXPECT_FALSE(
 586  E :        ReadHeaderInfoStream(stream.get(), &pdb_header, &name_stream_map));
 587  E :  }
 588    :  
 589  E :  TEST(ReadHeaderInfoStreamTest, ReadStreamWithOnlyHeader) {
 590  E :    scoped_refptr<PdbStream> reader(new PdbByteStream());
 591  E :    scoped_refptr<WritablePdbStream> writer(reader->GetWritableStream());
 592    :  
 593  E :    PdbInfoHeader70 pdb_header = {};
 594  E :    ASSERT_TRUE(writer->Write(pdb_header));
 595    :  
 596  E :    NameStreamMap name_stream_map;
 597  E :    EXPECT_FALSE(
 598  E :        ReadHeaderInfoStream(reader.get(), &pdb_header, &name_stream_map));
 599  E :  }
 600    :  
 601  E :  TEST(ReadHeaderInfoStreamTest, ReadStreamWithEmptyNameStreamMap) {
 602  E :    scoped_refptr<PdbStream> reader(new PdbByteStream());
 603  E :    scoped_refptr<WritablePdbStream> writer(reader->GetWritableStream());
 604    :  
 605  E :    PdbInfoHeader70 pdb_header = {};
 606  E :    ASSERT_TRUE(writer->Write(pdb_header));
 607  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // total string length.
 608  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // number of names.
 609  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // size of bitsets.
 610  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // first bitset.
 611  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // second bitset.
 612    :  
 613  E :    NameStreamMap name_stream_map;
 614  E :    EXPECT_TRUE(
 615  E :        ReadHeaderInfoStream(reader.get(), &pdb_header, &name_stream_map));
 616  E :    EXPECT_EQ(name_stream_map.size(), 0u);
 617  E :  }
 618    :  
 619  E :  TEST(ReadHeaderInfoStreamTest, ReadStreamWithNameStreamMap) {
 620  E :    scoped_refptr<PdbStream> reader(new PdbByteStream());
 621  E :    scoped_refptr<WritablePdbStream> writer(reader->GetWritableStream());
 622    :  
 623  E :    PdbInfoHeader70 pdb_header = {};
 624  E :    ASSERT_TRUE(writer->Write(pdb_header));
 625  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(9)));  // total string length.
 626  E :    uint32_t offset1 = writer->pos();
 627  E :    ASSERT_TRUE(writer->Write(3, "/a"));  // name 1.
 628  E :    uint32_t offset2 = writer->pos();
 629  E :    ASSERT_TRUE(writer->Write(3, "/b"));  // name 2.
 630  E :    uint32_t offset3 = writer->pos();
 631  E :    ASSERT_TRUE(writer->Write(3, "/c"));  // name 3.
 632  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(3)));  // number of names.
 633  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(3)));  // size of bitsets.
 634    :  
 635  E :    PdbBitSet present;
 636  E :    present.Resize(3);
 637  E :    present.Set(0);
 638  E :    present.Set(1);
 639  E :    present.Set(2);
 640  E :    ASSERT_TRUE(present.Write(writer.get(), true));
 641    :  
 642  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(0)));  // second bitset.
 643    :  
 644  E :    ASSERT_TRUE(writer->Write(0));
 645  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(42)));
 646  E :    ASSERT_TRUE(writer->Write(offset2 - offset1));
 647  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(7)));
 648  E :    ASSERT_TRUE(writer->Write(offset3 - offset1));
 649  E :    ASSERT_TRUE(writer->Write(static_cast<uint32_t>(95)));
 650    :  
 651  E :    NameStreamMap name_stream_map;
 652  E :    EXPECT_TRUE(
 653  E :        ReadHeaderInfoStream(reader.get(), &pdb_header, &name_stream_map));
 654    :  
 655  E :    NameStreamMap expected;
 656  E :    expected["/a"] = 42;
 657  E :    expected["/b"] = 7;
 658  E :    expected["/c"] = 95;
 659  E :    EXPECT_THAT(name_stream_map, testing::ContainerEq(expected));
 660  E :  }
 661    :  
 662  E :  TEST(ReadHeaderInfoStreamTest, ReadFromPdb) {
 663  E :    const base::FilePath pdb_path = testing::GetSrcRelativePath(
 664    :        testing::kTestPdbFilePath);
 665  E :    PdbFile pdb_file;
 666  E :    PdbReader pdb_reader;
 667  E :    EXPECT_TRUE(pdb_reader.Read(pdb_path, &pdb_file));
 668    :  
 669  E :    PdbInfoHeader70 pdb_header = {};
 670  E :    NameStreamMap name_stream_map;
 671  E :    EXPECT_TRUE(
 672    :        ReadHeaderInfoStream(pdb_file.GetStream(kPdbHeaderInfoStream).get(),
 673  E :                             &pdb_header, &name_stream_map));
 674  E :  }
 675    :  
 676  E :  TEST(WriteHeaderInfoStreamTest, WriteToPdbFile) {
 677  E :    const base::FilePath pdb_path = testing::GetSrcRelativePath(
 678    :        testing::kTestPdbFilePath);
 679    :  
 680  E :    PdbFile pdb_file;
 681  E :    PdbReader pdb_reader;
 682  E :    ASSERT_TRUE(pdb_reader.Read(pdb_path, &pdb_file));
 683    :  
 684  E :    PdbInfoHeader70 pdb_header = {};
 685  E :    NameStreamMap name_stream_map;
 686  E :    ASSERT_TRUE(ReadHeaderInfoStream(pdb_file, &pdb_header, &name_stream_map));
 687    :  
 688  E :    pdb_header.pdb_age++;
 689  E :    name_stream_map["NewStream!"] = 999;
 690    :  
 691  E :    EXPECT_TRUE(WriteHeaderInfoStream(pdb_header, name_stream_map, &pdb_file));
 692    :  
 693  E :    PdbInfoHeader70 pdb_header2 = {};
 694  E :    NameStreamMap name_stream_map2;
 695  E :    ASSERT_TRUE(ReadHeaderInfoStream(pdb_file, &pdb_header2, &name_stream_map2));
 696    :  
 697  E :    EXPECT_TRUE(AreEqual(pdb_header, pdb_header2));
 698  E :    EXPECT_EQ(name_stream_map, name_stream_map2);
 699  E :  }
 700    :  
 701  E :  TEST(WriteHeaderInfoStreamTest, WriteEmpty) {
 702  E :    scoped_refptr<PdbStream> reader(new PdbByteStream());
 703  E :    scoped_refptr<WritablePdbStream> writer(reader->GetWritableStream());
 704    :  
 705  E :    NameStreamMap name_stream_map;
 706  E :    EXPECT_TRUE(WriteHeaderInfoStream(kSamplePdbHeader,
 707    :                                      name_stream_map,
 708  E :                                      writer.get()));
 709    :  
 710  E :    PdbInfoHeader70 read_pdb_header = {};
 711  E :    NameStreamMap read_name_stream_map;
 712  E :    EXPECT_TRUE(ReadHeaderInfoStream(reader.get(),
 713    :                                     &read_pdb_header,
 714  E :                                     &read_name_stream_map));
 715    :  
 716  E :    EXPECT_EQ(0, ::memcmp(&kSamplePdbHeader,
 717    :                          &read_pdb_header,
 718  E :                          sizeof(kSamplePdbHeader)));
 719  E :    EXPECT_THAT(name_stream_map, testing::ContainerEq(read_name_stream_map));
 720  E :  }
 721    :  
 722  E :  TEST(WriteHeaderInfoStreamTest, WriteNonEmpty) {
 723  E :    scoped_refptr<PdbStream> reader(new PdbByteStream());
 724  E :    scoped_refptr<WritablePdbStream> writer(reader->GetWritableStream());
 725    :  
 726  E :    NameStreamMap name_stream_map;
 727  E :    name_stream_map["/StreamFoo"] = 9;
 728  E :    name_stream_map["/StreamBar"] = 42;
 729  E :    name_stream_map["/Stream/With/A/Path"] = 19;
 730  E :    EXPECT_TRUE(WriteHeaderInfoStream(kSamplePdbHeader,
 731    :                                      name_stream_map,
 732  E :                                      writer.get()));
 733    :  
 734  E :    PdbInfoHeader70 read_pdb_header = {};
 735  E :    NameStreamMap read_name_stream_map;
 736  E :    EXPECT_TRUE(ReadHeaderInfoStream(reader.get(),
 737    :                                     &read_pdb_header,
 738  E :                                     &read_name_stream_map));
 739    :  
 740  E :    EXPECT_EQ(0, ::memcmp(&kSamplePdbHeader,
 741    :                          &read_pdb_header,
 742  E :                          sizeof(kSamplePdbHeader)));
 743  E :    EXPECT_THAT(name_stream_map, testing::ContainerEq(read_name_stream_map));
 744  E :  }
 745    :  
 746  E :  TEST_F(PdbUtilTest, NamedStreamsWorkWithPdbStr) {
 747    :    // We start by creating a PDB file (a copy of a checked in sample one) and
 748    :    // adding a new stream to it using our named-stream implementation.
 749    :    {
 750  E :      base::FilePath orig_pdb_path = testing::GetSrcRelativePath(
 751    :          testing::kTestPdbFilePath);
 752    :  
 753    :      // Read the sample PDB.
 754  E :      PdbReader pdb_reader;
 755  E :      PdbFile pdb_file;
 756  E :      ASSERT_TRUE(pdb_reader.Read(orig_pdb_path, &pdb_file));
 757    :  
 758    :      // Add a new stream to it.
 759  E :      scoped_refptr<PdbStream> foo_reader(new PdbByteStream());
 760  E :      scoped_refptr<WritablePdbStream> foo_writer(
 761    :          foo_reader->GetWritableStream());
 762  E :      size_t foo_index = pdb_file.AppendStream(foo_reader.get());
 763  E :      foo_writer->WriteString("foo");
 764    :  
 765    :      // Get the PDB header stream.
 766  E :      scoped_refptr<PdbStream> header_stream(pdb_file.GetStream(
 767    :          kPdbHeaderInfoStream));
 768  E :      ASSERT_TRUE(header_stream.get() != NULL);
 769    :  
 770    :      // Read the existing name-stream map.
 771  E :      PdbInfoHeader70 pdb_header = {};
 772  E :      NameStreamMap name_stream_map;
 773  E :      ASSERT_TRUE(ReadHeaderInfoStream(header_stream.get(), &pdb_header,
 774  E :                                       &name_stream_map));
 775    :  
 776    :      // Add an entry for the new stream.
 777  E :      name_stream_map["foo"] = foo_index;
 778    :  
 779    :      // Write the new header stream to it.
 780  E :      scoped_refptr<PdbStream> new_header_reader(new PdbByteStream());
 781  E :      scoped_refptr<WritablePdbStream> new_header_writer(
 782    :          new_header_reader->GetWritableStream());
 783  E :      ASSERT_TRUE(pdb::WriteHeaderInfoStream(pdb_header, name_stream_map,
 784  E :                                             new_header_writer.get()));
 785  E :      pdb_file.ReplaceStream(kPdbHeaderInfoStream, new_header_reader.get());
 786    :  
 787    :      // Write the PDB.
 788  E :      PdbWriter pdb_writer;
 789  E :      ASSERT_TRUE(pdb_writer.Write(temp_pdb_file_path_, pdb_file));
 790  E :    }
 791    :  
 792    :    // We've now created a new PDB file. We want to make sure that pdbstr.exe
 793    :    // plays nicely with our named streams by doing a few things:
 794    :    // (1) If we try to read a non-existing stream, we should get empty output.
 795    :    // (2) We should be able to read an existing stream and get non-empty output.
 796    :    // (3) We should be able to add a new stream, and then read it using our
 797    :    //     mechanisms.
 798    :  
 799    :    // Get the path to pdbstr.exe, which we redistribute in third_party.
 800    :    base::FilePath pdbstr_path =
 801  E :        testing::GetSrcRelativePath(testing::kPdbStrPath);
 802    :  
 803    :    // Create the argument specifying the PDB path.
 804  E :    std::string pdb_arg = base::WideToUTF8(temp_pdb_file_path_.value());
 805  E :    pdb_arg.insert(0, "-p:");
 806    :  
 807    :    // First test: try to read a non-existing stream. Should produce no output.
 808    :    {
 809  E :      base::CommandLine cmd(pdbstr_path);
 810  E :      cmd.AppendArg(pdb_arg);
 811  E :      cmd.AppendArg("-r");
 812  E :      cmd.AppendArg("-s:nonexistent-stream-name");
 813  E :      base::LaunchOptions options;
 814  E :      options.inherit_handles = true;
 815  E :      base::Process process = base::LaunchProcess(cmd, options);
 816    :  
 817  E :      int exit_code = 0;
 818  E :      ASSERT_TRUE(process.WaitForExit(&exit_code));
 819  E :      ASSERT_EQ(-1, exit_code);
 820  E :    }
 821    :  
 822    :    // Second test: read an existing stream (the one we just added). Should
 823    :    // exit without error and return the expected contents (with a trailing
 824    :    // newline).
 825    :    {
 826  E :      base::CommandLine cmd(pdbstr_path);
 827  E :      cmd.AppendArg(pdb_arg);
 828  E :      cmd.AppendArg("-r");
 829  E :      cmd.AppendArg("-s:foo");
 830  E :      std::string output;
 831  E :      ASSERT_TRUE(base::GetAppOutput(cmd, &output));
 832  E :      ASSERT_EQ(std::string("foo\r\n"), output);
 833  E :    }
 834    :  
 835    :    // Third test: Add another new stream. This should return without error, and
 836    :    // we should then be able to read the stream using our mechanisms.
 837    :    {
 838  E :      base::FilePath bar_txt = temp_dir_.path().Append(L"bar.txt");
 839  E :      base::ScopedFILE bar_file(base::OpenFile(
 840    :          bar_txt, "wb"));
 841  E :      fprintf(bar_file.get(), "bar");
 842  E :      bar_file.reset();
 843    :  
 844  E :      std::string bar_arg = base::WideToUTF8(bar_txt.value());
 845  E :      bar_arg.insert(0, "-i:");
 846    :  
 847  E :      base::CommandLine cmd(pdbstr_path);
 848  E :      cmd.AppendArg(pdb_arg);
 849  E :      cmd.AppendArg("-w");
 850  E :      cmd.AppendArg("-s:bar");
 851  E :      cmd.AppendArg(bar_arg);
 852  E :      std::string output;
 853  E :      ASSERT_TRUE(base::GetAppOutput(cmd, &output));
 854  E :      ASSERT_TRUE(output.empty());
 855    :  
 856  E :      PdbFile pdb_file;
 857  E :      PdbReader pdb_reader;
 858  E :      ASSERT_TRUE(pdb_reader.Read(temp_pdb_file_path_, &pdb_file));
 859    :  
 860    :      // Get the PDB header stream.
 861  E :      scoped_refptr<PdbStream> header_stream(pdb_file.GetStream(
 862    :          kPdbHeaderInfoStream));
 863  E :      ASSERT_TRUE(header_stream.get() != NULL);
 864    :  
 865    :      // Read the existing name-stream map.
 866  E :      PdbInfoHeader70 pdb_header = {};
 867  E :      NameStreamMap name_stream_map;
 868  E :      ASSERT_TRUE(ReadHeaderInfoStream(header_stream.get(), &pdb_header,
 869  E :                                       &name_stream_map));
 870    :  
 871    :      // There should be a 'bar' stream.
 872  E :      ASSERT_TRUE(name_stream_map.count("bar"));
 873    :  
 874    :      // Get the bar stream.
 875  E :      scoped_refptr<PdbStream> bar_stream(pdb_file.GetStream(
 876    :          name_stream_map["bar"]));
 877  E :      ASSERT_TRUE(bar_stream.get() != NULL);
 878    :  
 879    :      // Read all of the data and ensure it is as expected.
 880  E :      std::string bar_data;
 881  E :      bar_data.resize(bar_stream->length());
 882  E :      ASSERT_TRUE(bar_stream->ReadBytesAt(0, bar_data.size(), &bar_data.at(0)));
 883  E :      ASSERT_EQ("bar", bar_data);
 884  E :    }
 885  E :  }
 886    :  
 887  E :  TEST_F(PdbUtilTest, LoadNamedStreamFromPdbFile) {
 888  E :    PdbReader reader;
 889  E :    PdbFile pdb_file;
 890  E :    EXPECT_TRUE(reader.Read(
 891    :        testing::GetOutputRelativePath(testing::kTestDllPdbName),
 892  E :        &pdb_file));
 893    :  
 894  E :    scoped_refptr<PdbStream> stream;
 895  E :    EXPECT_TRUE(LoadNamedStreamFromPdbFile(
 896  E :        "StreamThatDoesNotExist", &pdb_file, &stream));
 897  E :    EXPECT_TRUE(stream.get() == NULL);
 898    :  
 899    :    // The MSVC toolchain produces a handful of named streams whose existence we
 900    :    // can rely on.
 901  E :    EXPECT_TRUE(LoadNamedStreamFromPdbFile("/LinkInfo", &pdb_file, &stream));
 902  E :    ASSERT_TRUE(stream.get() != NULL);
 903  E :  }
 904    :  
 905    :  }  // namespace pdb

Coverage information generated Fri Jul 29 11:00:21 2016.