Coverage for /Syzygy/grinder/indexed_frequency_data_serializer_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
91.8%89970.C++test

Line-by-line coverage:

   1    :  // Copyright 2013 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/indexed_frequency_data_serializer.h"
  16    :  
  17    :  #include "base/values.h"
  18    :  #include "base/files/file_util.h"
  19    :  #include "base/files/scoped_temp_dir.h"
  20    :  #include "base/json/json_reader.h"
  21    :  #include "gmock/gmock.h"
  22    :  #include "gtest/gtest.h"
  23    :  #include "syzygy/core/unittest_util.h"
  24    :  #include "syzygy/pe/metadata.h"
  25    :  #include "syzygy/pe/unittest_util.h"
  26    :  
  27    :  namespace grinder {
  28    :  
  29    :  namespace {
  30    :  
  31    :  using base::DictionaryValue;
  32    :  using base::FundamentalValue;
  33    :  using base::JSONReader;
  34    :  using base::ListValue;
  35    :  using base::Value;
  36    :  using basic_block_util::IndexedFrequencyInformation;
  37    :  using basic_block_util::IndexedFrequencyMap;
  38    :  using basic_block_util::EntryCountType;
  39    :  using basic_block_util::ModuleIndexedFrequencyMap;
  40    :  using basic_block_util::ModuleInformation;
  41    :  using testing::ContainerEq;
  42    :  
  43    :  const wchar_t kImageFileName[] = L"foo.dll";
  44    :  const uint32 kBaseAddress = 0xDEADBEEF;
  45    :  const uint32 kModuleSize = 0x1000;
  46    :  const uint32 kImageChecksum = 0xCAFEBABE;
  47    :  const uint32 kTimeDateStamp = 0xBABECAFE;
  48    :  
  49    :  class TestIndexedFrequencyDataSerializer
  50    :      : public IndexedFrequencyDataSerializer {
  51    :   public:
  52    :    using IndexedFrequencyDataSerializer::PopulateFromJsonValue;
  53    :    using IndexedFrequencyDataSerializer::pretty_print_;
  54    :  };
  55    :  
  56    :  class IndexedFrequencyDataSerializerTest : public testing::PELibUnitTest {
  57    :   public:
  58    :    typedef testing::PELibUnitTest Super;
  59    :  
  60  E :    virtual void SetUp() override {
  61  E :      Super::SetUp();
  62  E :      ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
  63  E :    }
  64    :  
  65  E :    void InitModuleInfo(ModuleInformation* module_info) {
  66  E :      ASSERT_TRUE(module_info != NULL);
  67  E :      module_info->path = kImageFileName;
  68  E :      module_info->base_address.set_value(kBaseAddress);
  69  E :      module_info->module_size = kModuleSize;
  70  E :      module_info->module_checksum = kImageChecksum;
  71  E :      module_info->module_time_date_stamp = kTimeDateStamp;
  72  E :    }
  73    :   protected:
  74    :    base::ScopedTempDir temp_dir_;
  75    :  };
  76    :  
  77    :  }  // namespace
  78    :  
  79  E :  TEST_F(IndexedFrequencyDataSerializerTest, Accessors) {
  80  E :    TestIndexedFrequencyDataSerializer serializer;
  81  E :    EXPECT_FALSE(serializer.pretty_print_);
  82    :  
  83  E :    serializer.set_pretty_print(true);
  84  E :    EXPECT_TRUE(serializer.pretty_print_);
  85  E :  }
  86    :  
  87  E :  TEST_F(IndexedFrequencyDataSerializerTest, LoadFromJsonFails) {
  88  E :    TestIndexedFrequencyDataSerializer serializer;
  89  E :    ModuleIndexedFrequencyMap frequency_map;
  90    :  
  91    :    base::FilePath does_not_exist(
  92  E :        temp_dir_.path().AppendASCII("does_not_exist.json"));
  93  E :    EXPECT_FALSE(serializer.LoadFromJson(does_not_exist, &frequency_map));
  94    :  
  95    :    base::FilePath some_path(testing::GetExeTestDataRelativePath(
  96  E :        testing::kBranchTraceFiles[0]));
  97  E :    EXPECT_FALSE(serializer.LoadFromJson(some_path, &frequency_map));
  98  E :  }
  99    :  
 100  E :  TEST_F(IndexedFrequencyDataSerializerTest, PopulateFromJsonValueFails) {
 101  E :    ModuleIndexedFrequencyMap frequency_map;
 102  E :    TestIndexedFrequencyDataSerializer serializer;
 103    :  
 104    :    // It should fail if the outermost JSON object is not a list.
 105  E :    scoped_ptr<Value> int_value(new base::FundamentalValue(7));
 106    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(int_value.get(),
 107  E :                                                  &frequency_map));
 108    :  
 109    :    // It should fail if the outermost list does not contain dictionaries.
 110  E :    scoped_ptr<ListValue> list_value(new ListValue());
 111  E :    list_value->Append(new base::FundamentalValue(true));
 112    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 113  E :                                                  &frequency_map));
 114  E :    list_value->Clear();
 115    :  
 116    :    // It should fail if the list entry does not contain a metadata key.
 117  E :    DictionaryValue* dict_value = new DictionaryValue();
 118  E :    list_value->Append(dict_value);
 119    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 120  E :                                                  &frequency_map));
 121    :  
 122    :    // It should fail if the metadata value is not a dictionary.
 123  E :    dict_value->Set("metadata", new base::FundamentalValue("foo"));
 124    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 125  E :                                                  &frequency_map));
 126    :  
 127    :    // After adding the metadata value, it should still fail since there is no
 128    :    // information/frequency_map key.
 129    :    static const char kMetadataStr[] =
 130    :        "{\n"
 131    :        "  \"command_line\": \"foo.exe\",\n"
 132    :        "  \"creation_time\": \"Wed, 19 Sep 2012 17:33:52 GMT\",\n"
 133    :        "  \"toolchain_version\": {\n"
 134    :        "    \"major\": 0,\n"
 135    :        "    \"minor\": 2,\n"
 136    :        "    \"build\": 7,\n"
 137    :        "    \"patch\": 0,\n"
 138    :        "    \"last_change\": \"0\"\n"
 139    :        "  },\n"
 140    :        "  \"module_signature\": {\n"
 141    :        "    \"path\": \"C:\\\\foo\\\\bar.dll\",\n"
 142    :        "    \"base_address\": 1904279552,\n"
 143    :        "    \"module_size\": 180224,\n"
 144    :        "    \"module_time_date_stamp\": \"0x46F7885059FE32\",\n"
 145    :        "    \"module_checksum\": \"0x257AF\"\n"
 146    :        "  },\n"
 147    :        "}\n";
 148    :  
 149  E :    std::string error_msg;
 150    :    scoped_ptr<Value> metadata(JSONReader().ReadAndReturnError(
 151  E :        kMetadataStr, true, NULL, &error_msg));
 152  E :    EXPECT_EQ(std::string(), error_msg);
 153  E :    ASSERT_TRUE(metadata.get() != NULL);
 154  E :    dict_value->Set("metadata", metadata.release());
 155    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 156  E :                                                  &frequency_map));
 157    :  
 158    :    // After adding the description value, it should still fail since there is no
 159    :    // frequency_map key.
 160    :    static const char kDescriptionStr[] =
 161    :        "{\n"
 162    :        "  \"num_entries\": 100,\n"
 163    :        "  \"num_columns\": 3,\n"
 164    :        "  \"data_type\": \"branch\",\n"
 165    :        "  \"frequency_size\": 4\n"
 166    :        "}\n";
 167    :  
 168    :    scoped_ptr<Value> information(JSONReader().ReadAndReturnError(
 169  E :        kDescriptionStr, true, NULL, &error_msg));
 170  E :    EXPECT_EQ(std::string(), error_msg);
 171  E :    ASSERT_TRUE(information.get() != NULL);
 172  E :    dict_value->Set("description", information.release());
 173    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 174  E :                                                  &frequency_map));
 175    :  
 176    :    // It should still fail since the frequencies key has the wrong value type.
 177  E :    dict_value->Set("frequencies", new base::StringValue("foo"));
 178    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 179  E :                                                  &frequency_map));
 180    :  
 181    :    // It should still fail since the frequencies list contains an invalid value.
 182  E :    ListValue* frequencies = new ListValue();
 183  E :    dict_value->Set("frequencies", frequencies);
 184  E :    frequencies->Append(new base::StringValue("foo"));
 185    :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 186  E :                                                  &frequency_map));
 187    :  
 188    :    // It should succeed once we start putting numbers into the entry_counts list.
 189  E :    IndexedFrequencyMap expected_values;
 190  E :    frequencies->Clear();
 191  E :    for (int i = 0; i < static_cast<int>(expected_values.size()); ++i) {
 192  i :      scoped_ptr<ListValue> entry(new ListValue());
 193  i :      entry->Append(new base::FundamentalValue(i * i));
 194  i :      entry->Append(new base::FundamentalValue(100 * i));
 195  i :      entry->Append(new base::FundamentalValue(100 * i + 1));
 196  i :      expected_values[std::make_pair(core::RelativeAddress(i * i), 0)] = 100 * i;
 197    :      expected_values[std::make_pair(core::RelativeAddress(i * i), 1)] =
 198  i :          100 * i + 1;
 199    :  
 200  i :      frequencies->Append(entry.release());
 201  i :    }
 202    :  
 203    :    ASSERT_TRUE(serializer.PopulateFromJsonValue(list_value.get(),
 204  E :                                                 &frequency_map));
 205    :  
 206  E :    EXPECT_EQ(1U, frequency_map.size());
 207    :    EXPECT_THAT(frequency_map.begin()->second.frequency_map,
 208  E :                testing::ContainerEq(expected_values));
 209  E :  }
 210    :  
 211  E :  TEST_F(IndexedFrequencyDataSerializerTest, RoundTrip) {
 212  E :    ModuleInformation module_info;
 213  E :    ASSERT_NO_FATAL_FAILURE(InitModuleInfo(&module_info));
 214    :  
 215  E :    size_t num_basic_blocks = 100;
 216  E :    size_t num_columns = 10;
 217    :  
 218  E :    ModuleIndexedFrequencyMap frequency_map;
 219  E :    IndexedFrequencyInformation& frequency_info = frequency_map[module_info];
 220  E :    frequency_info.num_entries = num_basic_blocks;
 221  E :    frequency_info.num_columns = num_columns;
 222  E :    frequency_info.data_type = common::IndexedFrequencyData::BRANCH;
 223  E :    frequency_info.frequency_size = 4;
 224  E :    frequency_info.frequency_map = IndexedFrequencyMap();
 225    :  
 226  E :    IndexedFrequencyMap& counters = frequency_info.frequency_map;
 227  E :    for (size_t i = 0; i < num_basic_blocks; ++i) {
 228  E :      for (size_t c = 0; c < num_columns; ++c)
 229  E :        counters[std::make_pair(core::RelativeAddress(i * i), c)] = i + c + 1;
 230  E :    }
 231    :  
 232  E :    base::FilePath json_path(temp_dir_.path().AppendASCII("test.json"));
 233    :  
 234  E :    TestIndexedFrequencyDataSerializer serializer;
 235  E :    serializer.set_pretty_print(true);
 236  E :    ASSERT_TRUE(serializer.SaveAsJson(frequency_map, json_path));
 237    :  
 238  E :    ModuleIndexedFrequencyMap new_frequency_map;
 239  E :    serializer.LoadFromJson(json_path, &new_frequency_map);
 240    :  
 241  E :    EXPECT_THAT(new_frequency_map, ContainerEq(frequency_map));
 242  E :  }
 243    :  
 244    :  }  // namespace grinder

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