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