Coverage for /Syzygy/grinder/indexed_frequency_data_serializer_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
92.6%1001080.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_t kBaseAddress = 0xDEADBEEF;
  45    :  const uint32_t kModuleSize = 0x1000;
  46    :  const uint32_t kImageChecksum = 0xCAFEBABE;
  47    :  const uint32_t 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  E :    base::FilePath does_not_exist(
  92    :        temp_dir_.path().AppendASCII("does_not_exist.json"));
  93  E :    EXPECT_FALSE(serializer.LoadFromJson(does_not_exist, &frequency_map));
  94    :  
  95  E :    base::FilePath some_path(testing::GetExeTestDataRelativePath(
  96    :        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 :    std::unique_ptr<Value> int_value(new base::FundamentalValue(7));
 106  E :    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 :    std::unique_ptr<ListValue> list_value(new ListValue());
 111  E :    list_value->Append(new base::FundamentalValue(true));
 112  E :    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  E :    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  E :    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  E :    std::unique_ptr<Value> metadata(
 151    :        JSONReader()
 152    :            .ReadAndReturnError(kMetadataStr, true, NULL, &error_msg)
 153    :            .release());
 154  E :    EXPECT_EQ(std::string(), error_msg);
 155  E :    ASSERT_TRUE(metadata.get() != NULL);
 156  E :    dict_value->Set("metadata", metadata.release());
 157  E :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 158  E :                                                  &frequency_map));
 159    :  
 160    :    // After adding the description value, it should still fail since there is no
 161    :    // frequency_map key.
 162    :    static const char kDescriptionStr[] =
 163    :        "{\n"
 164    :        "  \"num_entries\": 100,\n"
 165    :        "  \"num_columns\": 3,\n"
 166    :        "  \"data_type\": \"branch\",\n"
 167    :        "  \"frequency_size\": 4\n"
 168    :        "}\n";
 169    :  
 170  E :    std::unique_ptr<Value> information(
 171    :        JSONReader()
 172    :            .ReadAndReturnError(kDescriptionStr, true, NULL, &error_msg)
 173    :            .release());
 174  E :    EXPECT_EQ(std::string(), error_msg);
 175  E :    ASSERT_TRUE(information.get() != NULL);
 176  E :    dict_value->Set("description", information.release());
 177  E :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 178  E :                                                  &frequency_map));
 179    :  
 180    :    // It should still fail since the frequencies key has the wrong value type.
 181  E :    dict_value->Set("frequencies", new base::StringValue("foo"));
 182  E :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 183  E :                                                  &frequency_map));
 184    :  
 185    :    // It should still fail since the frequencies list contains an invalid value.
 186  E :    ListValue* frequencies = new ListValue();
 187  E :    dict_value->Set("frequencies", frequencies);
 188  E :    frequencies->Append(new base::StringValue("foo"));
 189  E :    ASSERT_FALSE(serializer.PopulateFromJsonValue(list_value.get(),
 190  E :                                                  &frequency_map));
 191    :  
 192    :    // It should succeed once we start putting numbers into the entry_counts list.
 193  E :    IndexedFrequencyMap expected_values;
 194  E :    frequencies->Clear();
 195  E :    for (int i = 0; i < static_cast<int>(expected_values.size()); ++i) {
 196  i :      std::unique_ptr<ListValue> entry(new ListValue());
 197  i :      entry->Append(new base::FundamentalValue(i * i));
 198  i :      entry->Append(new base::FundamentalValue(100 * i));
 199  i :      entry->Append(new base::FundamentalValue(100 * i + 1));
 200  i :      expected_values[std::make_pair(core::RelativeAddress(i * i), 0)] = 100 * i;
 201  i :      expected_values[std::make_pair(core::RelativeAddress(i * i), 1)] =
 202    :          100 * i + 1;
 203    :  
 204  i :      frequencies->Append(entry.release());
 205  i :    }
 206    :  
 207  E :    ASSERT_TRUE(serializer.PopulateFromJsonValue(list_value.get(),
 208  E :                                                 &frequency_map));
 209    :  
 210  E :    EXPECT_EQ(1U, frequency_map.size());
 211  E :    EXPECT_THAT(frequency_map.begin()->second.frequency_map,
 212  E :                testing::ContainerEq(expected_values));
 213  E :  }
 214    :  
 215  E :  TEST_F(IndexedFrequencyDataSerializerTest, RoundTrip) {
 216  E :    ModuleInformation module_info;
 217  E :    ASSERT_NO_FATAL_FAILURE(InitModuleInfo(&module_info));
 218    :  
 219  E :    size_t num_basic_blocks = 100;
 220  E :    size_t num_columns = 10;
 221    :  
 222  E :    ModuleIndexedFrequencyMap frequency_map;
 223  E :    IndexedFrequencyInformation& frequency_info = frequency_map[module_info];
 224  E :    frequency_info.num_entries = num_basic_blocks;
 225  E :    frequency_info.num_columns = num_columns;
 226  E :    frequency_info.data_type = common::IndexedFrequencyData::BRANCH;
 227  E :    frequency_info.frequency_size = 4;
 228  E :    frequency_info.frequency_map = IndexedFrequencyMap();
 229    :  
 230  E :    IndexedFrequencyMap& counters = frequency_info.frequency_map;
 231  E :    for (size_t i = 0; i < num_basic_blocks; ++i) {
 232  E :      for (size_t c = 0; c < num_columns; ++c)
 233  E :        counters[std::make_pair(core::RelativeAddress(i * i), c)] = i + c + 1;
 234  E :    }
 235    :  
 236  E :    base::FilePath json_path(temp_dir_.path().AppendASCII("test.json"));
 237    :  
 238  E :    TestIndexedFrequencyDataSerializer serializer;
 239  E :    serializer.set_pretty_print(true);
 240  E :    ASSERT_TRUE(serializer.SaveAsJson(frequency_map, json_path));
 241    :  
 242  E :    ModuleIndexedFrequencyMap new_frequency_map;
 243  E :    serializer.LoadFromJson(json_path, &new_frequency_map);
 244    :  
 245  E :    EXPECT_THAT(new_frequency_map, ContainerEq(frequency_map));
 246  E :  }
 247    :  
 248    :  }  // namespace grinder

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