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