Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / metrics / persisted_logs_unittest.cc
1 // Copyright 2014 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 "components/metrics/persisted_logs.h"
6
7 #include "base/base64.h"
8 #include "base/prefs/pref_registry_simple.h"
9 #include "base/prefs/scoped_user_pref_update.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/rand_util.h"
12 #include "base/sha1.h"
13 #include "base/values.h"
14 #include "components/metrics/compression_utils.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace metrics {
18
19 namespace {
20
21 const char kTestPrefName[] = "TestPref";
22 const char kTestOldPrefName[] = "TestPrefOld";
23 const size_t kLogCountLimit = 3;
24 const size_t kLogByteLimit = 1000;
25
26 // Compresses |log_data| and returns the result.
27 std::string Compress(const std::string& log_data) {
28   std::string compressed_log_data;
29   EXPECT_TRUE(GzipCompress(log_data, &compressed_log_data));
30   return compressed_log_data;
31 }
32
33 // Generates and returns log data such that its size after compression is at
34 // least |min_compressed_size|.
35 std::string GenerateLogWithMinCompressedSize(size_t min_compressed_size) {
36   // Since the size check is done against a compressed log, generate enough
37   // data that compresses to larger than |log_size|.
38   std::string rand_bytes = base::RandBytesAsString(min_compressed_size);
39   while (Compress(rand_bytes).size() < min_compressed_size)
40     rand_bytes.append(base::RandBytesAsString(min_compressed_size));
41   std::string base64_data_for_logging;
42   base::Base64Encode(rand_bytes, &base64_data_for_logging);
43   SCOPED_TRACE(testing::Message() << "Using random data "
44                                   << base64_data_for_logging);
45   return rand_bytes;
46 }
47
48 class PersistedLogsTest : public testing::Test {
49  public:
50   PersistedLogsTest() {
51     prefs_.registry()->RegisterListPref(kTestPrefName);
52     prefs_.registry()->RegisterListPref(kTestOldPrefName);
53   }
54
55  protected:
56   TestingPrefServiceSimple prefs_;
57
58  private:
59   DISALLOW_COPY_AND_ASSIGN(PersistedLogsTest);
60 };
61
62 class TestPersistedLogs : public PersistedLogs {
63  public:
64   TestPersistedLogs(PrefService* service, size_t min_log_bytes)
65       : PersistedLogs(service, kTestPrefName, kTestOldPrefName, kLogCountLimit,
66                       min_log_bytes, 0) {
67   }
68
69   // Stages and removes the next log, while testing it's value.
70   void ExpectNextLog(const std::string& expected_log) {
71     StageLog();
72     EXPECT_EQ(staged_log(), Compress(expected_log));
73     DiscardStagedLog();
74   }
75
76  private:
77   DISALLOW_COPY_AND_ASSIGN(TestPersistedLogs);
78 };
79
80 }  // namespace
81
82 // Store and retrieve empty list_value.
83 TEST_F(PersistedLogsTest, EmptyLogList) {
84   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
85
86   persisted_logs.SerializeLogs();
87   const base::ListValue* list_value = prefs_.GetList(kTestPrefName);
88   EXPECT_EQ(0U, list_value->GetSize());
89
90   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
91   EXPECT_EQ(PersistedLogs::LIST_EMPTY, result_persisted_logs.DeserializeLogs());
92   EXPECT_EQ(0U, result_persisted_logs.size());
93 }
94
95 // Store and retrieve a single log value.
96 TEST_F(PersistedLogsTest, SingleElementLogList) {
97   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
98
99   persisted_logs.StoreLog("Hello world!");
100   persisted_logs.SerializeLogs();
101
102   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
103   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
104             result_persisted_logs.DeserializeLogs());
105   EXPECT_EQ(1U, result_persisted_logs.size());
106
107   // Verify that the result log matches the initial log.
108   persisted_logs.StageLog();
109   result_persisted_logs.StageLog();
110   EXPECT_EQ(persisted_logs.staged_log(), result_persisted_logs.staged_log());
111   EXPECT_EQ(persisted_logs.staged_log_hash(),
112             result_persisted_logs.staged_log_hash());
113 }
114
115 // Store a set of logs over the length limit, but smaller than the min number of
116 // bytes.
117 TEST_F(PersistedLogsTest, LongButTinyLogList) {
118   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
119
120   size_t log_count = kLogCountLimit * 5;
121   for (size_t i = 0; i < log_count; ++i)
122     persisted_logs.StoreLog("x");
123
124   persisted_logs.SerializeLogs();
125
126   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
127   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
128             result_persisted_logs.DeserializeLogs());
129   EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size());
130
131   result_persisted_logs.ExpectNextLog("x");
132 }
133
134 // Store a set of logs over the length limit, but that doesn't reach the minimum
135 // number of bytes until after passing the length limit.
136 TEST_F(PersistedLogsTest, LongButSmallLogList) {
137   size_t log_count = kLogCountLimit * 5;
138   size_t log_size = 50;
139
140   std::string first_kept = "First to keep";
141   first_kept.resize(log_size, ' ');
142
143   std::string blank_log = std::string(log_size, ' ');
144
145   std::string last_kept = "Last to keep";
146   last_kept.resize(log_size, ' ');
147
148   // Set the byte limit enough to keep everything but the first two logs.
149   const size_t min_log_bytes =
150       Compress(first_kept).length() + Compress(last_kept).length() +
151       (log_count - 4) * Compress(blank_log).length();
152   TestPersistedLogs persisted_logs(&prefs_, min_log_bytes);
153
154   persisted_logs.StoreLog("one");
155   persisted_logs.StoreLog("two");
156   persisted_logs.StoreLog(first_kept);
157   for (size_t i = persisted_logs.size(); i < log_count - 1; ++i) {
158     persisted_logs.StoreLog(blank_log);
159   }
160   persisted_logs.StoreLog(last_kept);
161   persisted_logs.SerializeLogs();
162
163   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
164   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
165             result_persisted_logs.DeserializeLogs());
166   EXPECT_EQ(persisted_logs.size() - 2, result_persisted_logs.size());
167
168   result_persisted_logs.ExpectNextLog(last_kept);
169   while (result_persisted_logs.size() > 1) {
170     result_persisted_logs.ExpectNextLog(blank_log);
171   }
172   result_persisted_logs.ExpectNextLog(first_kept);
173 }
174
175 // Store a set of logs within the length limit, but well over the minimum
176 // number of bytes.
177 TEST_F(PersistedLogsTest, ShortButLargeLogList) {
178   // Make the total byte count about twice the minimum.
179   size_t log_count = kLogCountLimit;
180   size_t log_size = (kLogByteLimit / log_count) * 2;
181   std::string log_data = GenerateLogWithMinCompressedSize(log_size);
182
183   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
184   for (size_t i = 0; i < log_count; ++i) {
185     persisted_logs.StoreLog(log_data);
186   }
187   persisted_logs.SerializeLogs();
188
189   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
190   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
191             result_persisted_logs.DeserializeLogs());
192   EXPECT_EQ(persisted_logs.size(), result_persisted_logs.size());
193 }
194
195 // Store a set of logs over the length limit, and over the minimum number of
196 // bytes.
197 TEST_F(PersistedLogsTest, LongAndLargeLogList) {
198   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
199
200   // Include twice the max number of logs.
201   size_t log_count = kLogCountLimit * 2;
202   // Make the total byte count about four times the minimum.
203   size_t log_size = (kLogByteLimit / log_count) * 4;
204
205   std::string target_log = "First to keep";
206   target_log += GenerateLogWithMinCompressedSize(log_size);
207
208   std::string log_data = GenerateLogWithMinCompressedSize(log_size);
209   for (size_t i = 0; i < log_count; ++i) {
210     if (i == log_count - kLogCountLimit)
211       persisted_logs.StoreLog(target_log);
212     else
213       persisted_logs.StoreLog(log_data);
214   }
215
216   persisted_logs.SerializeLogs();
217
218   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
219   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
220             result_persisted_logs.DeserializeLogs());
221   EXPECT_EQ(kLogCountLimit, result_persisted_logs.size());
222
223   while (result_persisted_logs.size() > 1) {
224     result_persisted_logs.ExpectNextLog(log_data);
225   }
226   result_persisted_logs.ExpectNextLog(target_log);
227 }
228
229 // Check that the store/stage/discard functions work as expected.
230 TEST_F(PersistedLogsTest, Staging) {
231   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
232   std::string tmp;
233
234   EXPECT_FALSE(persisted_logs.has_staged_log());
235   persisted_logs.StoreLog("one");
236   EXPECT_FALSE(persisted_logs.has_staged_log());
237   persisted_logs.StoreLog("two");
238   persisted_logs.StageLog();
239   EXPECT_TRUE(persisted_logs.has_staged_log());
240   EXPECT_EQ(persisted_logs.staged_log(), Compress("two"));
241   persisted_logs.StoreLog("three");
242   EXPECT_EQ(persisted_logs.staged_log(), Compress("two"));
243   EXPECT_EQ(persisted_logs.size(), 3U);
244   persisted_logs.DiscardStagedLog();
245   EXPECT_FALSE(persisted_logs.has_staged_log());
246   EXPECT_EQ(persisted_logs.size(), 2U);
247   persisted_logs.StageLog();
248   EXPECT_EQ(persisted_logs.staged_log(), Compress("three"));
249   persisted_logs.DiscardStagedLog();
250   persisted_logs.StageLog();
251   EXPECT_EQ(persisted_logs.staged_log(), Compress("one"));
252   persisted_logs.DiscardStagedLog();
253   EXPECT_FALSE(persisted_logs.has_staged_log());
254   EXPECT_EQ(persisted_logs.size(), 0U);
255 }
256
257 TEST_F(PersistedLogsTest, DiscardOrder) {
258   // Ensure that the correct log is discarded if new logs are pushed while
259   // a log is staged.
260   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
261
262   persisted_logs.StoreLog("one");
263   persisted_logs.StageLog();
264   persisted_logs.StoreLog("two");
265   persisted_logs.DiscardStagedLog();
266   persisted_logs.SerializeLogs();
267
268   TestPersistedLogs result_persisted_logs(&prefs_, kLogByteLimit);
269   EXPECT_EQ(PersistedLogs::RECALL_SUCCESS,
270             result_persisted_logs.DeserializeLogs());
271   EXPECT_EQ(1U, result_persisted_logs.size());
272   result_persisted_logs.ExpectNextLog("two");
273 }
274
275
276 TEST_F(PersistedLogsTest, Hashes) {
277   const char kFooText[] = "foo";
278   const std::string foo_hash = base::SHA1HashString(kFooText);
279
280   TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
281   persisted_logs.StoreLog(kFooText);
282   persisted_logs.StageLog();
283
284   EXPECT_EQ(Compress(kFooText), persisted_logs.staged_log());
285   EXPECT_EQ(foo_hash, persisted_logs.staged_log_hash());
286 }
287
288 }  // namespace metrics