Fix experimental app list search box disappearing on profile switch.
[chromium-blink-merge.git] / components / metrics / persisted_logs_unittest.cc
blobc9153de82e4a94ea5ea86a531a82b3d7f5bf0ab4
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.
5 #include "components/metrics/persisted_logs.h"
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"
17 namespace metrics {
19 namespace {
21 const char kTestPrefName[] = "TestPref";
22 const size_t kLogCountLimit = 3;
23 const size_t kLogByteLimit = 1000;
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;
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;
47 class PersistedLogsTest : public testing::Test {
48 public:
49 PersistedLogsTest() {
50 prefs_.registry()->RegisterListPref(kTestPrefName);
53 protected:
54 TestingPrefServiceSimple prefs_;
56 private:
57 DISALLOW_COPY_AND_ASSIGN(PersistedLogsTest);
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) {
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();
74 private:
75 DISALLOW_COPY_AND_ASSIGN(TestPersistedLogs);
78 } // namespace
80 // Store and retrieve empty list_value.
81 TEST_F(PersistedLogsTest, EmptyLogList) {
82 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
84 persisted_logs.SerializeLogs();
85 const base::ListValue* list_value = prefs_.GetList(kTestPrefName);
86 EXPECT_EQ(0U, list_value->GetSize());
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());
93 // Store and retrieve a single log value.
94 TEST_F(PersistedLogsTest, SingleElementLogList) {
95 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
97 persisted_logs.StoreLog("Hello world!");
98 persisted_logs.SerializeLogs();
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());
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());
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);
118 size_t log_count = kLogCountLimit * 5;
119 for (size_t i = 0; i < log_count; ++i)
120 persisted_logs.StoreLog("x");
122 persisted_logs.SerializeLogs();
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());
129 result_persisted_logs.ExpectNextLog("x");
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;
138 std::string first_kept = "First to keep";
139 first_kept.resize(log_size, ' ');
141 std::string blank_log = std::string(log_size, ' ');
143 std::string last_kept = "Last to keep";
144 last_kept.resize(log_size, ' ');
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);
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);
158 persisted_logs.StoreLog(last_kept);
159 persisted_logs.SerializeLogs();
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());
166 result_persisted_logs.ExpectNextLog(last_kept);
167 while (result_persisted_logs.size() > 1) {
168 result_persisted_logs.ExpectNextLog(blank_log);
170 result_persisted_logs.ExpectNextLog(first_kept);
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);
181 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
182 for (size_t i = 0; i < log_count; ++i) {
183 persisted_logs.StoreLog(log_data);
185 persisted_logs.SerializeLogs();
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());
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);
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;
203 std::string target_log = "First to keep";
204 target_log += GenerateLogWithMinCompressedSize(log_size);
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);
214 persisted_logs.SerializeLogs();
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());
221 while (result_persisted_logs.size() > 1) {
222 result_persisted_logs.ExpectNextLog(log_data);
224 result_persisted_logs.ExpectNextLog(target_log);
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;
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);
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);
260 persisted_logs.StoreLog("one");
261 persisted_logs.StageLog();
262 persisted_logs.StoreLog("two");
263 persisted_logs.DiscardStagedLog();
264 persisted_logs.SerializeLogs();
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");
274 TEST_F(PersistedLogsTest, Hashes) {
275 const char kFooText[] = "foo";
276 const std::string foo_hash = base::SHA1HashString(kFooText);
278 TestPersistedLogs persisted_logs(&prefs_, kLogByteLimit);
279 persisted_logs.StoreLog(kFooText);
280 persisted_logs.StageLog();
282 EXPECT_EQ(Compress(kFooText), persisted_logs.staged_log());
283 EXPECT_EQ(foo_hash, persisted_logs.staged_log_hash());
286 } // namespace metrics