Coverage for /Syzygy/grinder/basic_block_util_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%1821820.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/grinder/basic_block_util.h"
  16    :  
  17    :  #include "base/files/scoped_temp_dir.h"
  18    :  #include "base/win/scoped_com_initializer.h"
  19    :  #include "gmock/gmock.h"
  20    :  #include "gtest/gtest.h"
  21    :  #include "syzygy/common/indexed_frequency_data.h"
  22    :  #include "syzygy/core/unittest_util.h"
  23    :  #include "syzygy/grinder/grinder.h"
  24    :  #include "syzygy/grinder/indexed_frequency_data_serializer.h"
  25    :  #include "syzygy/pe/pe_file.h"
  26    :  #include "syzygy/pe/unittest_util.h"
  27    :  
  28    :  namespace grinder {
  29    :  namespace basic_block_util {
  30    :  
  31    :  namespace {
  32    :  
  33    :  using testing::GetExeTestDataRelativePath;
  34    :  using trace::parser::AbsoluteAddress64;
  35    :  using trace::parser::Parser;
  36    :  
  37    :  class TestGrinder : public GrinderInterface {
  38    :   public:
  39  E :    TestGrinder() : parser_(NULL), on_bb_freq_was_called_(false) {
  40    :      // Nothing else to initialize.
  41  E :    }
  42    :  
  43    :    // @name GrinderInterface implementation.
  44    :    // @{
  45  E :    virtual bool ParseCommandLine(const base::CommandLine*) override {
  46  E :      return true;
  47  E :    }
  48  E :    virtual void SetParser(Parser* parser) override {
  49  E :      ASSERT_TRUE(parser != NULL);
  50  E :      parser_ = parser;
  51  E :    }
  52  E :    virtual bool Grind() override { return true; }
  53  E :    virtual bool OutputData(FILE*) override { return true; }
  54    :    // @}
  55    :  
  56    :    // @name ParseEventHandler overrides.
  57    :    // @{
  58    :    virtual void OnIndexedFrequency(
  59    :        base::Time time,
  60    :        DWORD process_id,
  61    :        DWORD thread_id,
  62  E :        const TraceIndexedFrequencyData* data) override {
  63  E :      on_bb_freq_was_called_ = true;
  64  E :      ASSERT_TRUE(data != NULL);
  65    :  
  66  E :      ASSERT_TRUE(
  67    :          data->data_type == common::IndexedFrequencyData::BASIC_BLOCK_ENTRY ||
  68    :          data->data_type == common::IndexedFrequencyData::COVERAGE);
  69    :  
  70    :      // Lookup the module information.
  71    :      const ModuleInformation* module_info = parser_->GetModuleInformation(
  72  E :          process_id, AbsoluteAddress64(data->module_base_addr));
  73  E :      ASSERT_TRUE(module_info != NULL);
  74    :  
  75    :      // Load the PDB information.
  76  E :      PdbInfo* pdb_info = NULL;
  77  E :      ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &pdb_info));
  78  E :      ASSERT_TRUE(pdb_info != NULL);
  79    :  
  80    :      // Validate that the cache works.
  81  E :      PdbInfo* dup_pdb_info = NULL;
  82  E :      ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &dup_pdb_info));
  83  E :      ASSERT_EQ(pdb_info, dup_pdb_info);
  84  E :    }
  85    :  
  86    :    // Ensures that COM is initialized for tests in this fixture.
  87    :    base::win::ScopedCOMInitializer com_initializer_;
  88    :  
  89    :    Parser* parser_;
  90    :    PdbInfoMap pdb_info_cache_;
  91    :    bool on_bb_freq_was_called_;
  92    :  };
  93    :  
  94  E :  void PopulateModuleInformation(ModuleInformation* module_info) {
  95  E :    ASSERT_TRUE(module_info != NULL);
  96  E :    module_info->base_address.set_value(0xDEADBEEF);
  97  E :    module_info->module_checksum = 0xCAFEBABE;
  98  E :    module_info->path = L"image_file_name";
  99  E :    module_info->module_size = 0x12345678;
 100  E :    module_info->module_time_date_stamp = 0x87654321;
 101  E :  }
 102    :  
 103    :  }  // namespace
 104    :  
 105  E :  TEST(GrinderBasicBlockUtilTest, ModuleIdentityComparator) {
 106  E :    ModuleInformation a;
 107  E :    PopulateModuleInformation(&a);
 108    :  
 109  E :    ModuleInformation b(a);
 110    :    ModuleIdentityComparator comp;
 111    :    // The two should compare equal.
 112  E :    EXPECT_FALSE(comp(a, b));
 113  E :    EXPECT_FALSE(comp(b, a));
 114    :  
 115    :    // Jiggle b's base address and checksum.
 116  E :    b.base_address -= 10;
 117  E :    b.module_checksum += 100;
 118    :    // The two should still compare equal.
 119  E :    EXPECT_FALSE(comp(a, b));
 120  E :    EXPECT_FALSE(comp(b, a));
 121    :  
 122  E :    b = a;
 123  E :    b.module_size -= 1;
 124  E :    EXPECT_FALSE(comp(a, b));
 125  E :    EXPECT_TRUE(comp(b, a));
 126    :  
 127  E :    b = a;
 128  E :    b.module_time_date_stamp += 1;
 129  E :    EXPECT_TRUE(comp(a, b));
 130  E :    EXPECT_FALSE(comp(b, a));
 131    :  
 132  E :    b = a;
 133  E :    b.path = L"foo";
 134  E :    EXPECT_FALSE(comp(a, b));
 135  E :    EXPECT_TRUE(comp(b, a));
 136  E :  }
 137    :  
 138  E :  TEST(GrinderBasicBlockUtilTest, FindEntryCountVector) {
 139    :    // Create a prototype module info structure.
 140  E :    ModuleInformation module_info;
 141  E :    EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&module_info));
 142    :  
 143    :    // Initialize a signature matching the module_info.
 144  E :    pe::PEFile::Signature signature(module_info);
 145    :  
 146    :    // Create an empty count map.
 147  E :    ModuleIndexedFrequencyMap module_count_map;
 148  E :    EXPECT_TRUE(module_count_map.empty());
 149    :  
 150    :    // Search the empty map for the module..
 151  E :    const IndexedFrequencyInformation* count_map = NULL;
 152    :    EXPECT_FALSE(
 153  E :        FindIndexedFrequencyInfo(signature, module_count_map, &count_map));
 154  E :    EXPECT_EQ(NULL, count_map);
 155    :  
 156    :    // Insert a matching module and search again.
 157    :    const IndexedFrequencyInformation* count_map_1 =
 158  E :        &module_count_map[module_info];
 159    :    EXPECT_TRUE(
 160  E :        FindIndexedFrequencyInfo(signature, module_count_map, &count_map));
 161  E :    EXPECT_EQ(count_map_1, count_map);
 162    :  
 163    :    // Insert a second matching module and search again. This should fail.
 164  E :    module_info.path = L"Some other file name";
 165    :    const IndexedFrequencyInformation* count_map_2 =
 166  E :        &module_count_map[module_info];
 167  E :    ASSERT_NE(count_map_1, count_map_2);
 168    :    EXPECT_FALSE(
 169  E :        FindIndexedFrequencyInfo(signature, module_count_map, &count_map));
 170  E :    EXPECT_EQ(NULL, count_map);
 171  E :  }
 172    :  
 173  E :  TEST(GrinderBasicBlockUtilTest, LoadBranchStatisticsFromFileFailed) {
 174    :    // A temporary directory into which temp files will be written.
 175  E :    base::ScopedTempDir temp_dir;
 176  E :    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 177    :  
 178    :    // Create a prototype module info structure.
 179  E :    ModuleInformation module_info;
 180  E :    EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&module_info));
 181  E :    pe::PEFile::Signature signature(module_info);
 182    :  
 183    :    // Validate non existing file is reported.
 184  E :    IndexedFrequencyMap frequencies;
 185  E :    base::FilePath invalid_path(L"this_file_doesnt_exists");
 186    :    EXPECT_FALSE(
 187  E :        LoadBranchStatisticsFromFile(invalid_path, signature, &frequencies));
 188    :  
 189    :    // Validate invalid file format is reported.
 190  E :    base::FilePath empty_file;
 191    :    ASSERT_TRUE(
 192  E :        base::CreateTemporaryFileInDir(temp_dir.path(), &empty_file));
 193    :    EXPECT_FALSE(
 194  E :        LoadBranchStatisticsFromFile(empty_file, signature, &frequencies));
 195    :  
 196    :    // Serialize to a file without any module.
 197  E :    base::FilePath temp_file;
 198  E :    ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file));
 199  E :    ModuleIndexedFrequencyMap modules;
 200  E :    IndexedFrequencyDataSerializer serializer;
 201  E :    ASSERT_TRUE(serializer.SaveAsJson(modules, temp_file));
 202    :  
 203    :    // Expect to not find the module with the current signature.
 204    :    EXPECT_FALSE(
 205  E :        LoadBranchStatisticsFromFile(temp_file, signature, &frequencies));
 206  E :  }
 207    :  
 208  E :  TEST(GrinderBasicBlockUtilTest, LoadBranchStatisticsFromFile) {
 209    :    // A temporary directory into which temp files will be written.
 210  E :    base::ScopedTempDir temp_dir;
 211  E :    ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
 212    :  
 213    :    // Create a prototype module info structure.
 214  E :    ModuleInformation module_info;
 215  E :    EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&module_info));
 216  E :    pe::PEFile::Signature signature(module_info);
 217    :  
 218    :    // Populate module information.
 219  E :    ModuleIndexedFrequencyMap modules;
 220  E :    IndexedFrequencyInformation information;
 221  E :    information.data_type = common::IndexedFrequencyData::BRANCH;
 222  E :    information.frequency_size = 4;
 223  E :    information.num_columns = 3;
 224  E :    information.num_entries = 0;
 225  E :    modules[module_info] = information;
 226    :  
 227    :    // Serialize to a file.
 228  E :    base::FilePath temp_file;
 229  E :    ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.path(), &temp_file));
 230  E :    IndexedFrequencyDataSerializer serializer;
 231  E :    ASSERT_TRUE(serializer.SaveAsJson(modules, temp_file));
 232    :  
 233    :    // Expect to find the module with the current signature.
 234  E :    IndexedFrequencyMap frequencies;
 235    :    EXPECT_TRUE(
 236  E :        LoadBranchStatisticsFromFile(temp_file, signature, &frequencies));
 237  E :  }
 238    :  
 239  E :  TEST(GrinderBasicBlockUtilTest, LoadBasicBlockRanges) {
 240  E :    RelativeAddressRangeVector bb_ranges;
 241    :  
 242    :    base::FilePath wrong_file_type(GetExeTestDataRelativePath(
 243  E :        testing::kCoverageTraceFiles[0]));
 244  E :    EXPECT_FALSE(LoadBasicBlockRanges(wrong_file_type, &bb_ranges));
 245    :  
 246    :    base::FilePath wrong_pdb(
 247  E :        GetExeTestDataRelativePath(testing::kTestDllPdbName));
 248  E :    EXPECT_FALSE(LoadBasicBlockRanges(wrong_pdb, &bb_ranges));
 249    :  
 250    :    base::FilePath right_pdb(GetExeTestDataRelativePath(
 251  E :        testing::kBBEntryInstrumentedTestDllPdbName));
 252  E :    EXPECT_TRUE(LoadBasicBlockRanges(right_pdb, &bb_ranges));
 253  E :  }
 254    :  
 255  E :  TEST(GrinderBasicBlockUtilTest, LoadPdbInfo) {
 256    :    // TODO(rogerm): Rewrite me! This test doesn't directly test LoadPdbInfo.
 257  E :    Parser parser;
 258  E :    TestGrinder grinder;
 259  E :    ASSERT_TRUE(parser.Init(&grinder));
 260  E :    ASSERT_NO_FATAL_FAILURE(grinder.SetParser(&parser));
 261  E :    ASSERT_TRUE(grinder.ParseCommandLine(NULL));
 262    :    ASSERT_TRUE(parser.OpenTraceFile(GetExeTestDataRelativePath(
 263  E :        testing::kCoverageTraceFiles[0])));
 264  E :    ASSERT_TRUE(parser.Consume());
 265  E :    ASSERT_TRUE(grinder.on_bb_freq_was_called_);
 266  E :    ASSERT_TRUE(grinder.Grind());
 267  E :    ASSERT_TRUE(grinder.OutputData(NULL));
 268  E :  }
 269    :  
 270  E :  TEST(GrinderBasicBlockUtilTest, IsValidFrequencySize) {
 271  E :    EXPECT_TRUE(IsValidFrequencySize(1));
 272  E :    EXPECT_TRUE(IsValidFrequencySize(2));
 273  E :    EXPECT_TRUE(IsValidFrequencySize(4));
 274    :  
 275  E :    EXPECT_FALSE(IsValidFrequencySize(0));
 276  E :    EXPECT_FALSE(IsValidFrequencySize(3));
 277  E :    EXPECT_FALSE(IsValidFrequencySize(8));
 278  E :    EXPECT_FALSE(IsValidFrequencySize(65536));
 279  E :  }
 280    :  
 281  E :  TEST(GrinderBasicBlockUtilTest, GetFrequency) {
 282    :    // Counter data we'll test against.
 283    :    static const uint8 kData[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
 284    :                                   0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB };
 285    :  
 286    :    // A buffer over which we'll overlay a TraceIndexedFrequencyData struct.
 287  E :    uint8 buffer[sizeof(TraceIndexedFrequencyData) + sizeof(kData) - 1] = {};
 288  E :    ::memset(buffer, 0, sizeof(buffer));
 289    :  
 290    :    // A TraceDataBlockFrequencyData structure with the frequency_data populated
 291    :    // with a copy of kData.
 292    :    TraceIndexedFrequencyData* data =
 293  E :        reinterpret_cast<TraceIndexedFrequencyData*>(buffer);
 294  E :    ::memcpy(data->frequency_data, kData, sizeof(kData));
 295    :  
 296    :    // Set 1 column of basic block entry count.
 297  E :    data->num_columns = 1;
 298  E :    data->data_type = common::IndexedFrequencyData::BASIC_BLOCK_ENTRY;
 299    :  
 300    :    // Validate 1-byte frequency data.
 301  E :    data->frequency_size = 1;
 302  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 303  E :    EXPECT_EQ(0x44, GetFrequency(data, 0x4, 0));
 304  E :    EXPECT_EQ(0xAA, GetFrequency(data, 0xA, 0));
 305    :  
 306    :    // Validate 2-byte frequency data.
 307  E :    data->frequency_size = 2;
 308  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 309  E :    EXPECT_EQ(0x5544, GetFrequency(data, 0x2, 0));
 310  E :    EXPECT_EQ(0x9988, GetFrequency(data, 0x4, 0));
 311    :  
 312    :    // Validate 4-byte frequency data.
 313  E :    data->frequency_size = 4;
 314  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 315  E :    EXPECT_EQ(0x33221100, GetFrequency(data, 0x0, 0));
 316  E :    EXPECT_EQ(0xBBAA9988, GetFrequency(data, 0x2, 0));
 317  E :  }
 318    :  
 319  E :  TEST(GrinderBasicBlockUtilTest, GetFrequencyWithColumns) {
 320    :    // Counter data we'll test against.
 321    :    static const uint8 kData[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
 322    :                                   0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB };
 323    :  
 324    :    // A buffer over which we'll overlay a TraceIndexedFrequencyData struct.
 325  E :    uint8 buffer[sizeof(TraceIndexedFrequencyData) + sizeof(kData) - 1] = {};
 326  E :    ::memset(buffer, 0, sizeof(buffer));
 327    :  
 328    :    // A TraceDataBlockFrequencyData structure with the frequency_data populated
 329    :    // with a copy of kData.
 330    :    TraceIndexedFrequencyData* data =
 331  E :        reinterpret_cast<TraceIndexedFrequencyData*>(buffer);
 332  E :    ::memcpy(data->frequency_data, kData, sizeof(kData));
 333    :  
 334    :    // Set 2 columns of basic block entry count.
 335  E :    data->num_columns = 2;
 336  E :    data->data_type = common::IndexedFrequencyData::BASIC_BLOCK_ENTRY;
 337    :  
 338    :    // Validate 1-byte frequency data.
 339  E :    data->frequency_size = 1;
 340  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 341  E :    EXPECT_EQ(0x88, GetFrequency(data, 0x4, 0));
 342  E :    EXPECT_EQ(0x99, GetFrequency(data, 0x4, 1));
 343    :  
 344    :    // Validate 2-byte frequency data.
 345  E :    data->frequency_size = 2;
 346  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 347  E :    EXPECT_EQ(0x9988, GetFrequency(data, 0x2, 0));
 348  E :    EXPECT_EQ(0xBBAA, GetFrequency(data, 0x2, 1));
 349    :  
 350    :    // Validate 4-byte frequency data.
 351  E :    data->frequency_size = 4;
 352  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 353  E :    EXPECT_EQ(0x33221100, GetFrequency(data, 0x0, 0));
 354  E :    EXPECT_EQ(0x77665544, GetFrequency(data, 0x0, 1));
 355  E :  }
 356    :  
 357    :  }  // namespace basic_block_util
 358    :  }  // namespace grinder

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