Home | History | Annotate | Download | only in metrics
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/base64.h"
      6 #include "base/md5.h"
      7 #include "base/values.h"
      8 #include "chrome/browser/metrics/metrics_log_serializer.h"
      9 #include "testing/gtest/include/gtest/gtest.h"
     10 
     11 namespace {
     12 
     13 const size_t kListLengthLimit = 3;
     14 const size_t kLogByteLimit = 1000;
     15 
     16 void SetLogText(const std::string& log_text,
     17                 MetricsLogManager::SerializedLog* log) {
     18   std::string log_text_copy = log_text;
     19   log->SwapLogText(&log_text_copy);
     20 }
     21 
     22 }  // namespace
     23 
     24 // Store and retrieve empty list.
     25 TEST(MetricsLogSerializerTest, EmptyLogList) {
     26   ListValue list;
     27   std::vector<MetricsLogManager::SerializedLog> local_list;
     28 
     29   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
     30                                             kLogByteLimit, &list);
     31   EXPECT_EQ(0U, list.GetSize());
     32 
     33   local_list.clear();  // ReadLogsFromPrefList() expects empty |local_list|.
     34   EXPECT_EQ(
     35       MetricsLogSerializer::LIST_EMPTY,
     36       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
     37   EXPECT_EQ(0U, local_list.size());
     38 }
     39 
     40 // Store and retrieve a single log value.
     41 TEST(MetricsLogSerializerTest, SingleElementLogList) {
     42   ListValue list;
     43 
     44   std::vector<MetricsLogManager::SerializedLog> local_list(1);
     45   SetLogText("Hello world!", &local_list[0]);
     46 
     47   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
     48                                             kLogByteLimit, &list);
     49 
     50   // |list| will now contain the following:
     51   // [1, Base64Encode("Hello world!"), MD5("Hello world!")].
     52   ASSERT_EQ(3U, list.GetSize());
     53 
     54   // Examine each element.
     55   ListValue::const_iterator it = list.begin();
     56   int size = 0;
     57   (*it)->GetAsInteger(&size);
     58   EXPECT_EQ(1, size);
     59 
     60   ++it;
     61   std::string str;
     62   (*it)->GetAsString(&str);  // Base64 encoded "Hello world!" string.
     63   std::string encoded;
     64   base::Base64Encode("Hello world!", &encoded);
     65   EXPECT_TRUE(encoded == str);
     66 
     67   ++it;
     68   (*it)->GetAsString(&str);  // MD5 for encoded "Hello world!" string.
     69   EXPECT_TRUE(base::MD5String(encoded) == str);
     70 
     71   ++it;
     72   EXPECT_TRUE(it == list.end());  // Reached end of list.
     73 
     74   local_list.clear();
     75   EXPECT_EQ(
     76       MetricsLogSerializer::RECALL_SUCCESS,
     77       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
     78   EXPECT_EQ(1U, local_list.size());
     79 }
     80 
     81 // Store a set of logs over the length limit, but smaller than the min number of
     82 // bytes.
     83 TEST(MetricsLogSerializerTest, LongButTinyLogList) {
     84   ListValue list;
     85 
     86   size_t log_count = kListLengthLimit * 5;
     87   std::vector<MetricsLogManager::SerializedLog> local_list(log_count);
     88   for (size_t i = 0; i < local_list.size(); ++i)
     89     SetLogText("x", &local_list[i]);
     90 
     91   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
     92                                             kLogByteLimit, &list);
     93   std::vector<MetricsLogManager::SerializedLog> result_list;
     94   EXPECT_EQ(
     95       MetricsLogSerializer::RECALL_SUCCESS,
     96       MetricsLogSerializer::ReadLogsFromPrefList(list, &result_list));
     97   EXPECT_EQ(local_list.size(), result_list.size());
     98 
     99   EXPECT_TRUE(result_list.front().log_text().find("x") == 0);
    100 }
    101 
    102 // Store a set of logs over the length limit, but that doesn't reach the minimum
    103 // number of bytes until after passing the length limit.
    104 TEST(MetricsLogSerializerTest, LongButSmallLogList) {
    105   ListValue list;
    106 
    107   size_t log_count = kListLengthLimit * 5;
    108   // Make log_count logs each slightly larger than
    109   // kLogByteLimit / (log_count - 2)
    110   // so that the minimum is reached before the oldest (first) two logs.
    111   std::vector<MetricsLogManager::SerializedLog> local_list(log_count);
    112   size_t log_size = (kLogByteLimit / (log_count - 2)) + 2;
    113   SetLogText("one", &local_list[0]);
    114   SetLogText("two", &local_list[1]);
    115   SetLogText("three", &local_list[2]);
    116   SetLogText("last", &local_list[log_count - 1]);
    117   for (size_t i = 0; i < local_list.size(); ++i) {
    118     std::string log_text = local_list[i].log_text();
    119     log_text.resize(log_size, ' ');
    120     local_list[i].SwapLogText(&log_text);
    121   }
    122 
    123   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    124                                             kLogByteLimit, &list);
    125   std::vector<MetricsLogManager::SerializedLog> result_list;
    126   EXPECT_EQ(
    127       MetricsLogSerializer::RECALL_SUCCESS,
    128       MetricsLogSerializer::ReadLogsFromPrefList(list, &result_list));
    129   EXPECT_EQ(local_list.size() - 2, result_list.size());
    130 
    131   EXPECT_TRUE(result_list.front().log_text().find("three") == 0);
    132   EXPECT_TRUE(result_list.back().log_text().find("last") == 0);
    133 }
    134 
    135 // Store a set of logs within the length limit, but well over the minimum
    136 // number of bytes.
    137 TEST(MetricsLogSerializerTest, ShortButLargeLogList) {
    138   ListValue list;
    139 
    140   std::vector<MetricsLogManager::SerializedLog> local_list(kListLengthLimit);
    141   // Make the total byte count about twice the minimum.
    142   size_t log_size = (kLogByteLimit / local_list.size()) * 2;
    143   for (size_t i = 0; i < local_list.size(); ++i) {
    144     std::string log_text = local_list[i].log_text();
    145     log_text.resize(log_size, ' ');
    146     local_list[i].SwapLogText(&log_text);
    147   }
    148 
    149   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    150                                             kLogByteLimit, &list);
    151   std::vector<MetricsLogManager::SerializedLog> result_list;
    152   EXPECT_EQ(
    153       MetricsLogSerializer::RECALL_SUCCESS,
    154       MetricsLogSerializer::ReadLogsFromPrefList(list, &result_list));
    155   EXPECT_EQ(local_list.size(), result_list.size());
    156 }
    157 
    158 // Store a set of logs over the length limit, and over the minimum number of
    159 // bytes.
    160 TEST(MetricsLogSerializerTest, LongAndLargeLogList) {
    161   ListValue list;
    162 
    163   // Include twice the max number of logs.
    164   std::vector<MetricsLogManager::SerializedLog>
    165       local_list(kListLengthLimit * 2);
    166   // Make the total byte count about four times the minimum.
    167   size_t log_size = (kLogByteLimit / local_list.size()) * 4;
    168   SetLogText("First to keep",
    169              &local_list[local_list.size() - kListLengthLimit]);
    170   for (size_t i = 0; i < local_list.size(); ++i) {
    171     std::string log_text = local_list[i].log_text();
    172     log_text.resize(log_size, ' ');
    173     local_list[i].SwapLogText(&log_text);
    174   }
    175 
    176   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    177                                             kLogByteLimit, &list);
    178   std::vector<MetricsLogManager::SerializedLog> result_list;
    179   EXPECT_EQ(
    180       MetricsLogSerializer::RECALL_SUCCESS,
    181       MetricsLogSerializer::ReadLogsFromPrefList(list, &result_list));
    182   // The max length should control the resulting size.
    183   EXPECT_EQ(kListLengthLimit, result_list.size());
    184   EXPECT_TRUE(result_list.front().log_text().find("First to keep") == 0);
    185 }
    186 
    187 // Induce LIST_SIZE_TOO_SMALL corruption
    188 TEST(MetricsLogSerializerTest, SmallRecoveredListSize) {
    189   ListValue list;
    190 
    191   std::vector<MetricsLogManager::SerializedLog> local_list(1);
    192   SetLogText("Hello world!", &local_list[0]);
    193 
    194   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    195                                             kLogByteLimit, &list);
    196   EXPECT_EQ(3U, list.GetSize());
    197 
    198   // Remove last element.
    199   list.Remove(list.GetSize() - 1, NULL);
    200   EXPECT_EQ(2U, list.GetSize());
    201 
    202   local_list.clear();
    203   EXPECT_EQ(
    204       MetricsLogSerializer::LIST_SIZE_TOO_SMALL,
    205       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
    206 }
    207 
    208 // Remove size from the stored list.
    209 TEST(MetricsLogSerializerTest, RemoveSizeFromLogList) {
    210   ListValue list;
    211 
    212   std::vector<MetricsLogManager::SerializedLog> local_list(2);
    213   SetLogText("one", &local_list[0]);
    214   SetLogText("two", &local_list[1]);
    215   EXPECT_EQ(2U, local_list.size());
    216   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    217                                             kLogByteLimit, &list);
    218   EXPECT_EQ(4U, list.GetSize());
    219 
    220   list.Remove(0, NULL);  // Delete size (1st element).
    221   EXPECT_EQ(3U, list.GetSize());
    222 
    223   local_list.clear();
    224   EXPECT_EQ(
    225       MetricsLogSerializer::LIST_SIZE_MISSING,
    226       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
    227 }
    228 
    229 // Corrupt size of stored list.
    230 TEST(MetricsLogSerializerTest, CorruptSizeOfLogList) {
    231   ListValue list;
    232 
    233   std::vector<MetricsLogManager::SerializedLog> local_list(1);
    234   SetLogText("Hello world!", &local_list[0]);
    235 
    236   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    237                                             kLogByteLimit, &list);
    238   EXPECT_EQ(3U, list.GetSize());
    239 
    240   // Change list size from 1 to 2.
    241   EXPECT_TRUE(list.Set(0, Value::CreateIntegerValue(2)));
    242   EXPECT_EQ(3U, list.GetSize());
    243 
    244   local_list.clear();
    245   EXPECT_EQ(
    246       MetricsLogSerializer::LIST_SIZE_CORRUPTION,
    247       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
    248 }
    249 
    250 // Corrupt checksum of stored list.
    251 TEST(MetricsLogSerializerTest, CorruptChecksumOfLogList) {
    252   ListValue list;
    253 
    254   std::vector<MetricsLogManager::SerializedLog> local_list(1);
    255   SetLogText("Hello world!", &local_list[0]);
    256 
    257   MetricsLogSerializer::WriteLogsToPrefList(local_list, kListLengthLimit,
    258                                             kLogByteLimit, &list);
    259   EXPECT_EQ(3U, list.GetSize());
    260 
    261   // Fetch checksum (last element) and change it.
    262   std::string checksum;
    263   EXPECT_TRUE((*(list.end() - 1))->GetAsString(&checksum));
    264   checksum[0] = (checksum[0] == 'a') ? 'b' : 'a';
    265   EXPECT_TRUE(list.Set(2, Value::CreateStringValue(checksum)));
    266   EXPECT_EQ(3U, list.GetSize());
    267 
    268   local_list.clear();
    269   EXPECT_EQ(
    270       MetricsLogSerializer::CHECKSUM_CORRUPTION,
    271       MetricsLogSerializer::ReadLogsFromPrefList(list, &local_list));
    272 }
    273