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