Coverage for /Syzygy/grinder/basic_block_util_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%1271270.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 "gmock/gmock.h"
  18    :  #include "gtest/gtest.h"
  19    :  #include "syzygy/common/indexed_frequency_data.h"
  20    :  #include "syzygy/core/unittest_util.h"
  21    :  #include "syzygy/grinder/grinder.h"
  22    :  #include "syzygy/pe/pe_file.h"
  23    :  #include "syzygy/pe/unittest_util.h"
  24    :  
  25    :  namespace grinder {
  26    :  namespace basic_block_util {
  27    :  
  28    :  namespace {
  29    :  
  30    :  using testing::GetExeTestDataRelativePath;
  31    :  using trace::parser::AbsoluteAddress64;
  32    :  using trace::parser::Parser;
  33    :  
  34    :  class TestGrinder : public GrinderInterface {
  35    :   public:
  36  E :    TestGrinder() : parser_(NULL), on_bb_freq_was_called_(false) {
  37    :      // Nothing else to initialize.
  38  E :    }
  39    :  
  40    :    // @name GrinderInterface implementation.
  41    :    // @{
  42  E :    virtual bool ParseCommandLine(const CommandLine*) OVERRIDE { return true; }
  43  E :    virtual void SetParser(Parser* parser) OVERRIDE {
  44  E :      ASSERT_TRUE(parser != NULL);
  45  E :      parser_ = parser;
  46  E :    }
  47  E :    virtual bool Grind() OVERRIDE { return true; };
  48  E :    virtual bool OutputData(FILE*) OVERRIDE { return true; }
  49    :    // @}
  50    :  
  51    :    // @name ParseEventHandler overrides.
  52    :    // @{
  53    :    virtual void OnIndexedFrequency(
  54    :        base::Time time,
  55    :        DWORD process_id,
  56    :        DWORD thread_id,
  57  E :        const TraceIndexedFrequencyData* data) OVERRIDE {
  58  E :      on_bb_freq_was_called_ = true;
  59  E :      ASSERT_TRUE(data != NULL);
  60    :  
  61  E :      ASSERT_TRUE(
  62    :          data->data_type == common::IndexedFrequencyData::BASIC_BLOCK_ENTRY ||
  63    :          data->data_type == common::IndexedFrequencyData::COVERAGE);
  64    :  
  65    :      // Lookup the module information.
  66    :      const ModuleInformation* module_info = parser_->GetModuleInformation(
  67  E :          process_id, AbsoluteAddress64(data->module_base_addr));
  68  E :      ASSERT_TRUE(module_info != NULL);
  69    :  
  70    :      // Load the PDB information.
  71  E :      PdbInfo* pdb_info = NULL;
  72  E :      ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &pdb_info));
  73  E :      ASSERT_TRUE(pdb_info != NULL);
  74    :  
  75    :      // Validate that the cache works.
  76  E :      PdbInfo* dup_pdb_info = NULL;
  77  E :      ASSERT_TRUE(LoadPdbInfo(&pdb_info_cache_, *module_info, &dup_pdb_info));
  78  E :      ASSERT_EQ(pdb_info, dup_pdb_info);
  79  E :    }
  80    :  
  81    :    Parser* parser_;
  82    :    PdbInfoMap pdb_info_cache_;
  83    :    bool on_bb_freq_was_called_;
  84    :  };
  85    :  
  86  E :  void PopulateModuleInformation(ModuleInformation* module_info) {
  87  E :    ASSERT_TRUE(module_info != NULL);
  88  E :    module_info->base_address = 0xDEADBEEF;
  89  E :    module_info->image_checksum = 0xCAFEBABE;
  90  E :    module_info->image_file_name = L"image_file_name";
  91  E :    module_info->module_size = 0x12345678;
  92  E :    module_info->time_date_stamp = 0x87654321;
  93  E :  }
  94    :  
  95    :  }  // namespace
  96    :  
  97  E :  TEST(GrinderBasicBlockUtilTest, ModuleIdentityComparator) {
  98  E :    ModuleInformation a;
  99  E :    PopulateModuleInformation(&a);
 100    :  
 101  E :    ModuleInformation b = a;
 102    :    ModuleIdentityComparator comp;
 103    :    // The two should compare equal.
 104  E :    EXPECT_FALSE(comp(a, b));
 105  E :    EXPECT_FALSE(comp(b, a));
 106    :  
 107    :    // Jiggle b's base address and checksum.
 108  E :    b.base_address -= 10;
 109  E :    b.image_checksum += 100;
 110    :    // The two should still compare equal.
 111  E :    EXPECT_FALSE(comp(a, b));
 112  E :    EXPECT_FALSE(comp(b, a));
 113    :  
 114  E :    b = a;
 115  E :    b.module_size -= 1;
 116  E :    EXPECT_FALSE(comp(a, b));
 117  E :    EXPECT_TRUE(comp(b, a));
 118    :  
 119  E :    b = a;
 120  E :    b.time_date_stamp += 1;
 121  E :    EXPECT_TRUE(comp(a, b));
 122  E :    EXPECT_FALSE(comp(b, a));
 123    :  
 124  E :    b = a;
 125  E :    b.image_file_name = L"foo";
 126  E :    EXPECT_FALSE(comp(a, b));
 127  E :    EXPECT_TRUE(comp(b, a));
 128  E :  }
 129    :  
 130  E :  TEST(GrinderBasicBlockUtilTest, InitModuleInfo) {
 131    :    // Create a prototype module info structure.
 132  E :    ModuleInformation orig_module_info;
 133  E :    EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&orig_module_info));
 134    :  
 135    :    // Initialize a signature matching the prototype.
 136  E :    pe::PEFile::Signature signature(orig_module_info);
 137    :  
 138    :    // Extract the module information from the signature. It should match the
 139    :    // prototype.
 140  E :    ModuleInformation new_module_info;
 141  E :    InitModuleInfo(signature, &new_module_info);
 142  E :    EXPECT_EQ(orig_module_info, new_module_info);
 143  E :  }
 144    :  
 145  E :  TEST(GrinderBasicBlockUtilTest, FindEntryCountVector) {
 146    :    // Create a prototype module info structure.
 147  E :    ModuleInformation module_info;
 148  E :    EXPECT_NO_FATAL_FAILURE(PopulateModuleInformation(&module_info));
 149    :  
 150    :    // Initialize a signature matching the module_info.
 151  E :    pe::PEFile::Signature signature(module_info);
 152    :  
 153    :    // Create an empty entry count map.
 154  E :    ModuleEntryCountMap module_entry_count_map;
 155  E :    EXPECT_TRUE(module_entry_count_map.empty());
 156    :  
 157    :    // Search the empty map for the module..
 158  E :    const EntryCountMap* entry_count_map = NULL;
 159    :    EXPECT_FALSE(
 160  E :        FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
 161  E :    EXPECT_EQ(NULL, entry_count_map);
 162    :  
 163    :    // Insert a matching module and search again.
 164  E :    const EntryCountMap* entry_count_map_1 = &module_entry_count_map[module_info];
 165    :    EXPECT_TRUE(
 166  E :        FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
 167  E :    EXPECT_EQ(entry_count_map_1, entry_count_map);
 168    :  
 169    :    // Insert a second matching module and search again. This should fail.
 170  E :    module_info.image_file_name = L"Some other file name";
 171  E :    const EntryCountMap* entry_count_map_2 = &module_entry_count_map[module_info];
 172  E :    ASSERT_NE(entry_count_map_1, entry_count_map_2);
 173    :    EXPECT_FALSE(
 174  E :        FindEntryCountMap(signature, module_entry_count_map, &entry_count_map));
 175  E :    EXPECT_EQ(NULL, entry_count_map);
 176  E :  }
 177    :  
 178  E :  TEST(GrinderBasicBlockUtilTest, LoadBasicBlockRanges) {
 179  E :    RelativeAddressRangeVector bb_ranges;
 180    :  
 181    :    base::FilePath wrong_file_type(GetExeTestDataRelativePath(
 182  E :        testing::kCoverageTraceFiles[0]));
 183  E :    EXPECT_FALSE(LoadBasicBlockRanges(wrong_file_type, &bb_ranges));
 184    :  
 185    :    base::FilePath wrong_pdb(
 186  E :        GetExeTestDataRelativePath(testing::kTestDllPdbName));
 187  E :    EXPECT_FALSE(LoadBasicBlockRanges(wrong_pdb, &bb_ranges));
 188    :  
 189    :    base::FilePath right_pdb(GetExeTestDataRelativePath(
 190  E :        testing::kBBEntryInstrumentedTestDllPdbName));
 191  E :    EXPECT_TRUE(LoadBasicBlockRanges(right_pdb, &bb_ranges));
 192  E :  }
 193    :  
 194  E :  TEST(GrinderBasicBlockUtilTest, LoadPdbInfo) {
 195    :    // TODO(rogerm): Rewrite me! This test doesn't directly test LoadPdbInfo.
 196  E :    Parser parser;
 197  E :    TestGrinder grinder;
 198  E :    ASSERT_TRUE(parser.Init(&grinder));
 199  E :    ASSERT_NO_FATAL_FAILURE(grinder.SetParser(&parser));
 200  E :    ASSERT_TRUE(grinder.ParseCommandLine(NULL));
 201    :    ASSERT_TRUE(parser.OpenTraceFile(GetExeTestDataRelativePath(
 202  E :        testing::kCoverageTraceFiles[0])));
 203  E :    ASSERT_TRUE(parser.Consume());
 204  E :    ASSERT_TRUE(grinder.on_bb_freq_was_called_);
 205  E :    ASSERT_TRUE(grinder.Grind());
 206  E :    ASSERT_TRUE(grinder.OutputData(NULL));
 207  E :  }
 208    :  
 209  E :  TEST(GrinderBasicBlockUtilTest, IsValidFrequencySize) {
 210  E :    EXPECT_TRUE(IsValidFrequencySize(1));
 211  E :    EXPECT_TRUE(IsValidFrequencySize(2));
 212  E :    EXPECT_TRUE(IsValidFrequencySize(4));
 213    :  
 214  E :    EXPECT_FALSE(IsValidFrequencySize(0));
 215  E :    EXPECT_FALSE(IsValidFrequencySize(3));
 216  E :    EXPECT_FALSE(IsValidFrequencySize(8));
 217  E :    EXPECT_FALSE(IsValidFrequencySize(65536));
 218  E :  }
 219    :  
 220  E :  TEST(GrinderBasicBlockUtilTest, GetFrequency) {
 221    :    // Counter data we'll test against.
 222    :    static const uint8 kData[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
 223    :                                   0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB };
 224    :  
 225    :    // A buffer over which we'll overlay a TraceIndexedFrequencyData struct.
 226  E :    uint8 buffer[sizeof(TraceIndexedFrequencyData) + sizeof(kData) - 1] = {};
 227  E :    ::memset(buffer, 0, sizeof(buffer));
 228    :  
 229    :    // A TraceDataBlockFrequencyData structure with the frequency_data populated
 230    :    // with a copy of kData.
 231    :    TraceIndexedFrequencyData* data =
 232  E :        reinterpret_cast<TraceIndexedFrequencyData*>(buffer);
 233  E :    ::memcpy(data->frequency_data, kData, sizeof(kData));
 234    :  
 235    :    // Validate 1-byte frequency data.
 236  E :    data->frequency_size = 1;
 237  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 238  E :    EXPECT_EQ(0x44, GetFrequency(data, 0x4));
 239  E :    EXPECT_EQ(0xAA, GetFrequency(data, 0xA));
 240    :  
 241    :    // Validate 2-byte frequency data.
 242  E :    data->frequency_size = 2;
 243  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 244  E :    EXPECT_EQ(0x5544, GetFrequency(data, 0x2));
 245  E :    EXPECT_EQ(0x9988, GetFrequency(data, 0x4));
 246    :  
 247    :    // Validate 4-byte frequency data.
 248  E :    data->frequency_size = 4;
 249  E :    data->num_entries = sizeof(kData) / data->frequency_size;
 250  E :    EXPECT_EQ(0x33221100, GetFrequency(data, 0x0));
 251  E :    EXPECT_EQ(0xBBAA9988, GetFrequency(data, 0x2));
 252  E :  }
 253    :  
 254    :  }  // namespace basic_block_util
 255    :  }  // namespace grinder

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