• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SetLogText(const std::string & log_text,MetricsLogManager::SerializedLog * log)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.
TEST(MetricsLogSerializerTest,EmptyLogList)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.
TEST(MetricsLogSerializerTest,SingleElementLogList)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.
TEST(MetricsLogSerializerTest,LongButTinyLogList)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.
TEST(MetricsLogSerializerTest,LongButSmallLogList)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.
TEST(MetricsLogSerializerTest,ShortButLargeLogList)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.
TEST(MetricsLogSerializerTest,LongAndLargeLogList)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
TEST(MetricsLogSerializerTest,SmallRecoveredListSize)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.
TEST(MetricsLogSerializerTest,RemoveSizeFromLogList)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.
TEST(MetricsLogSerializerTest,CorruptSizeOfLogList)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.
TEST(MetricsLogSerializerTest,CorruptChecksumOfLogList)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