Coverage for /Syzygy/pdb/pdb_writer_unittest.cc

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

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   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_writer.h"
  16    :  
  17    :  #include "base/file_util.h"
  18    :  #include "gtest/gtest.h"
  19    :  #include "syzygy/pdb/pdb_constants.h"
  20    :  #include "syzygy/pdb/pdb_reader.h"
  21    :  
  22    :  namespace pdb {
  23    :  
  24    :  namespace {
  25    :  
  26  E :  uint32 GetNumPages(uint32 num_bytes) {
  27  E :    return (num_bytes + pdb::kPdbPageSize - 1) / pdb::kPdbPageSize;
  28  E :  }
  29    :  
  30    :  class TestPdbWriter : public PdbWriter {
  31    :   public:
  32  E :    TestPdbWriter() {
  33  E :      FilePath path;
  34  E :      file_.reset(file_util::CreateAndOpenTemporaryFile(&path));
  35  E :      EXPECT_TRUE(file_.get() != NULL);
  36  E :    }
  37    :  
  38  E :    FILE* file() { return file_.get(); }
  39    :  
  40    :    using PdbWriter::StreamInfo;
  41    :    using PdbWriter::StreamInfoList;
  42    :    using PdbWriter::PadToPageBoundary;
  43    :    using PdbWriter::AppendStream;
  44    :    using PdbWriter::WriteDirectory;
  45    :    using PdbWriter::WriteDirectoryPages;
  46    :    using PdbWriter::WriteHeader;
  47    :  };
  48    :  
  49    :  class TestPdbStream : public PdbStream {
  50    :   public:
  51  E :    explicit TestPdbStream(uint32 length) : PdbStream(length) {
  52  E :    }
  53    :  
  54  E :    bool ReadBytes(void* dest, size_t count, size_t* bytes_read) {
  55  E :      DCHECK(bytes_read != NULL);
  56    :  
  57  E :      if (pos() == length()) {
  58  E :        *bytes_read = 0;
  59  E :        return true;
  60    :      }
  61    :  
  62  E :      count = std::min(count, length() - pos());
  63  E :      memset(dest, 0xFF, count);
  64  E :      Seek(pos() + count);
  65  E :      *bytes_read = count;
  66    :  
  67  E :      return true;
  68  E :    }
  69    :  };
  70    :  
  71    :  }  // namespace
  72    :  
  73    :  using pdb::kPdbHeaderMagicString;
  74    :  using pdb::kPdbPageSize;
  75    :  using pdb::PdbHeader;
  76    :  using pdb::PdbReader;
  77    :  
  78  E :  TEST(PdbWriterTest, WritePdbFile) {
  79  E :    PdbFile pdb_file;
  80  E :    for (uint32 i = 0; i < 4; ++i) {
  81  E :      pdb_file.AppendStream(new TestPdbStream(1 << (8 + i)));
  82  E :    }
  83    :  
  84    :    // Test that we can create a pdb file and then read it successfully.
  85  E :    FilePath path;
  86  E :    EXPECT_TRUE(file_util::CreateTemporaryFile(&path));
  87    :    {
  88    :      // Create a scope so that the file gets closed.
  89  E :      TestPdbWriter writer;
  90  E :      EXPECT_TRUE(writer.Write(path, pdb_file));
  91  E :    }
  92    :  
  93  E :    PdbFile pdb_file_read;
  94  E :    PdbReader reader;
  95  E :    EXPECT_TRUE(reader.Read(path, &pdb_file_read));
  96  E :    EXPECT_EQ(pdb_file.StreamCount(), pdb_file_read.StreamCount());
  97    :  
  98  E :    for (size_t i = 0; i < pdb_file.StreamCount(); ++i) {
  99  E :      ASSERT_TRUE(pdb_file.GetStream(i) != NULL);
 100  E :      ASSERT_TRUE(pdb_file_read.GetStream(i) != NULL);
 101    :      EXPECT_EQ(pdb_file.GetStream(i)->length(),
 102  E :                pdb_file_read.GetStream(i)->length());
 103  E :    }
 104  E :  }
 105    :  
 106  E :  TEST(PdbWriterTest, PadToPageBoundary) {
 107    :    // Test that the right amount is padded for the given offset.
 108    :    uint32 test_cases[][2] = {
 109  E :      {0, 0},  // offset, padding.
 110  E :      {1, 1023},
 111  E :      {1023, 1},
 112  E :      {1024, 0},
 113  E :      {1025, 1023},
 114  E :      {2000, 48},
 115  E :      {3000, 72},
 116  E :      {4000, 96}
 117    :    };
 118    :  
 119  E :    TestPdbWriter writer;
 120  E :    uint32 total_bytes = 0;
 121  E :    for (uint32 i = 0; i < arraysize(test_cases); ++i) {
 122  E :      uint32* test_case = test_cases[i];
 123  E :      uint32 padding = 0;
 124  E :      EXPECT_TRUE(writer.PadToPageBoundary("", test_case[0], &padding));
 125  E :      EXPECT_EQ(test_case[1], padding);
 126  E :      total_bytes += padding;
 127  E :    }
 128    :  
 129    :    // Test that zeroes are padded successfully.
 130  E :    FILE* file = writer.file();
 131  E :    for (uint32 i = 0; i < total_bytes; ++i) {
 132  E :      EXPECT_EQ(0, fseek(file, i, SEEK_SET));
 133    :      uint8 buffer;
 134  E :      EXPECT_EQ(1, fread(&buffer, 1, 1, file));
 135  E :      EXPECT_EQ(0, buffer);
 136  E :    }
 137  E :  }
 138    :  
 139  E :  TEST(PdbWriterTest, AppendStream) {
 140    :    // Test that the bytes written corresponds to the stream length and padding.
 141  E :    TestPdbWriter writer;
 142  E :    size_t len = (1 << 17) + 123;
 143  E :    scoped_refptr<TestPdbStream> stream(new TestPdbStream(len));
 144    :    uint32 bytes_written;
 145  E :    EXPECT_TRUE(writer.AppendStream(stream.get(), &bytes_written));
 146  E :    EXPECT_EQ(GetNumPages(len) * kPdbPageSize, bytes_written);
 147    :  
 148    :    // Test that the correct data is written.
 149  E :    FILE* file = writer.file();
 150  E :    for (size_t i = 0; i < len; ++i) {
 151  E :      EXPECT_EQ(0, fseek(file, i, SEEK_SET));
 152    :      uint8 buffer;
 153  E :      EXPECT_EQ(1, fread(&buffer, 1, 1, file));
 154  E :      EXPECT_EQ(0xFF, buffer);
 155  E :    }
 156  E :  }
 157    :  
 158  E :  TEST(PdbWriterTest, WriteDirectory) {
 159    :    uint32 stream_lengths[] = {
 160  E :      kPdbPageSize + 10,
 161  E :      2 * kPdbPageSize + 20,
 162    :      4 * kPdbPageSize + 40
 163  E :    };
 164    :  
 165  E :    TestPdbWriter::StreamInfoList stream_info_list;
 166  E :    uint32 total_bytes = 0;
 167  E :    for (uint32 i = 0; i < arraysize(stream_lengths); ++i) {
 168    :      TestPdbWriter::StreamInfo stream_info;
 169  E :      stream_info.offset = total_bytes;
 170  E :      stream_info.length = stream_lengths[i];
 171  E :      stream_info_list.push_back(stream_info);
 172  E :      total_bytes += GetNumPages(stream_lengths[i]) * kPdbPageSize;
 173  E :    };
 174    :  
 175  E :    TestPdbWriter writer;
 176  E :    uint32 dir_size = 0;
 177  E :    uint32 bytes_written = 0;
 178    :    EXPECT_TRUE(
 179  E :        writer.WriteDirectory(stream_info_list, &dir_size, &bytes_written));
 180    :  
 181    :    // Test the directory size.
 182    :    // The number of streams.
 183  E :    uint32 expected_dir_size = sizeof(uint32);
 184    :    // The length of each stream.
 185  E :    expected_dir_size += stream_info_list.size() * sizeof(uint32);
 186    :    // The page numbers of each stream.
 187  E :    for (uint32 i = 0; i < arraysize(stream_lengths); ++i) {
 188  E :      expected_dir_size += GetNumPages(stream_lengths[i]) * sizeof(uint32);
 189  E :    }
 190  E :    EXPECT_EQ(expected_dir_size, dir_size);
 191  E :    EXPECT_EQ(GetNumPages(dir_size) * kPdbPageSize, bytes_written);
 192    :  
 193    :    // Test the directory contents.
 194  E :    FILE* file = writer.file();
 195  E :    EXPECT_EQ(0, fseek(file, 0, SEEK_SET));
 196    :  
 197    :    uint32 num_streams;
 198  E :    EXPECT_EQ(1, fread(&num_streams, sizeof(uint32), 1, file));
 199  E :    EXPECT_EQ(arraysize(stream_lengths), num_streams);
 200    :  
 201  E :    for (uint32 i = 0; i < arraysize(stream_lengths); ++i) {
 202  E :      uint32 stream_length = 0;
 203  E :      EXPECT_EQ(1, fread(&stream_length, sizeof(uint32), 1, file));
 204  E :      EXPECT_EQ(stream_lengths[i], stream_length);
 205  E :    }
 206    :  
 207  E :    uint32 page_count = 0;
 208  E :    for (uint32 i = 0; i < arraysize(stream_lengths); ++i) {
 209  E :      uint32 num_pages = GetNumPages(stream_lengths[i]);
 210  E :      for (uint32 j = 0; j < num_pages; ++j) {
 211  E :        uint32 page_num = 0;
 212  E :        EXPECT_EQ(1, fread(&page_num, sizeof(uint32), 1, file));
 213  E :        EXPECT_EQ(page_count + j, page_num);
 214  E :      }
 215  E :      page_count += num_pages;
 216  E :    }
 217  E :  }
 218    :  
 219  E :  TEST(PdbWriterTest, WriteDirectoryPages) {
 220  E :    TestPdbWriter writer;
 221  E :    uint32 dir_size = (1 << 12) + 234;
 222  E :    uint32 dir_page = 15;
 223  E :    uint32 dir_pages_size = 0;
 224  E :    uint32 bytes_written = 0;
 225    :    EXPECT_TRUE(writer.WriteDirectoryPages(dir_size, dir_page, &dir_pages_size,
 226  E :                                           &bytes_written));
 227    :  
 228    :    // Test the directory pages size.
 229  E :    uint32 num_dir_pages = GetNumPages(dir_size);
 230  E :    EXPECT_EQ(num_dir_pages * sizeof(uint32), dir_pages_size);
 231  E :    EXPECT_EQ(GetNumPages(dir_pages_size) * kPdbPageSize, bytes_written);
 232    :  
 233    :    // Test the directory pages contents.
 234  E :    FILE* file = writer.file();
 235  E :    EXPECT_EQ(0, fseek(file, 0, SEEK_SET));
 236  E :    for (uint32 i = 0; i < num_dir_pages; ++i) {
 237  E :      uint32 page_num = 0;
 238  E :      EXPECT_EQ(1, fread(&page_num, sizeof(uint32), 1, file));
 239  E :      EXPECT_EQ(dir_page + i, page_num);
 240  E :    }
 241  E :  }
 242    :  
 243  E :  TEST(PdbWriterTest, WriteHeader) {
 244  E :    TestPdbWriter writer;
 245  E :    uint32 file_size = 1 << 20;
 246  E :    uint32 dir_size = (1 << 12) + 234;
 247  E :    uint32 dir_root_size = (1 << 6) + 64;
 248  E :    uint32 dir_root_page = 4;
 249    :    EXPECT_TRUE(writer.WriteHeader(file_size, dir_size, dir_root_size,
 250  E :                                   dir_root_page));
 251    :  
 252    :    // Test the header contents.
 253  E :    FILE* file = writer.file();
 254  E :    EXPECT_EQ(0, fseek(file, 0, SEEK_SET));
 255  E :    PdbHeader header = { 0 };
 256  E :    EXPECT_EQ(1, fread(&header, sizeof(header), 1, file));
 257    :  
 258    :    EXPECT_EQ(0, memcmp(header.magic_string, kPdbHeaderMagicString,
 259  E :                        sizeof(kPdbHeaderMagicString)));
 260  E :    EXPECT_EQ(kPdbPageSize, header.page_size);
 261  E :    EXPECT_EQ(1, header.free_page_map);
 262  E :    EXPECT_EQ(GetNumPages(file_size), header.num_pages);
 263  E :    EXPECT_EQ(dir_size, header.directory_size);
 264  E :    EXPECT_EQ(0, header.reserved);
 265    :  
 266  E :    uint32 num_dir_root_pages = GetNumPages(dir_root_size);
 267  E :    for (uint32 i = 0; i < num_dir_root_pages; ++i) {
 268  E :      EXPECT_EQ(dir_root_page + i, header.root_pages[i]);
 269  E :    }
 270  E :  }
 271    :  
 272    :  }  // namespace pdb

Coverage information generated Thu Sep 06 11:30:46 2012.