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.
5 #include "chrome/common/metrics/metrics_log_manager.h"
11 #include "base/sha1.h"
12 #include "chrome/common/metrics/metrics_log_base.h"
13 #include "testing/gtest/include/gtest/gtest.h"
17 // Dummy serializer that just stores logs in memory.
18 class DummyLogSerializer : public MetricsLogManager::LogSerializer {
20 virtual void SerializeLogs(
21 const std::vector<MetricsLogManager::SerializedLog>& logs,
22 MetricsLogManager::LogType log_type) OVERRIDE {
23 persisted_logs_[log_type] = logs;
26 virtual void DeserializeLogs(
27 MetricsLogManager::LogType log_type,
28 std::vector<MetricsLogManager::SerializedLog>* logs) OVERRIDE {
29 ASSERT_NE(static_cast<void*>(NULL), logs);
30 *logs = persisted_logs_[log_type];
33 // Returns the number of logs of the given type.
34 size_t TypeCount(MetricsLogManager::LogType log_type) {
35 return persisted_logs_[log_type].size();
38 // In-memory "persitent storage".
39 std::vector<MetricsLogManager::SerializedLog> persisted_logs_[2];
44 TEST(MetricsLogManagerTest, StandardFlow) {
45 MetricsLogManager log_manager;
47 // Make sure a new manager has a clean slate.
48 EXPECT_EQ(NULL, log_manager.current_log());
49 EXPECT_FALSE(log_manager.has_staged_log());
50 EXPECT_FALSE(log_manager.has_unsent_logs());
52 // Check that the normal flow works.
53 MetricsLogBase* initial_log = new MetricsLogBase("id", 0, "version");
54 log_manager.BeginLoggingWithLog(initial_log, MetricsLogManager::INITIAL_LOG);
55 EXPECT_EQ(initial_log, log_manager.current_log());
56 EXPECT_FALSE(log_manager.has_staged_log());
58 log_manager.FinishCurrentLog();
59 EXPECT_EQ(NULL, log_manager.current_log());
60 EXPECT_TRUE(log_manager.has_unsent_logs());
61 EXPECT_FALSE(log_manager.has_staged_log());
63 MetricsLogBase* second_log = new MetricsLogBase("id", 0, "version");
64 log_manager.BeginLoggingWithLog(second_log, MetricsLogManager::ONGOING_LOG);
65 EXPECT_EQ(second_log, log_manager.current_log());
67 log_manager.StageNextLogForUpload();
68 EXPECT_TRUE(log_manager.has_staged_log());
69 EXPECT_FALSE(log_manager.staged_log_text().empty());
71 log_manager.DiscardStagedLog();
72 EXPECT_EQ(second_log, log_manager.current_log());
73 EXPECT_FALSE(log_manager.has_staged_log());
74 EXPECT_FALSE(log_manager.has_unsent_logs());
75 EXPECT_TRUE(log_manager.staged_log_text().empty());
77 EXPECT_FALSE(log_manager.has_unsent_logs());
80 TEST(MetricsLogManagerTest, AbandonedLog) {
81 MetricsLogManager log_manager;
83 MetricsLogBase* dummy_log = new MetricsLogBase("id", 0, "version");
84 log_manager.BeginLoggingWithLog(dummy_log, MetricsLogManager::INITIAL_LOG);
85 EXPECT_EQ(dummy_log, log_manager.current_log());
87 log_manager.DiscardCurrentLog();
88 EXPECT_EQ(NULL, log_manager.current_log());
89 EXPECT_FALSE(log_manager.has_staged_log());
92 TEST(MetricsLogManagerTest, InterjectedLog) {
93 MetricsLogManager log_manager;
95 MetricsLogBase* ongoing_log = new MetricsLogBase("id", 0, "version");
96 MetricsLogBase* temp_log = new MetricsLogBase("id", 0, "version");
98 log_manager.BeginLoggingWithLog(ongoing_log, MetricsLogManager::ONGOING_LOG);
99 EXPECT_EQ(ongoing_log, log_manager.current_log());
101 log_manager.PauseCurrentLog();
102 EXPECT_EQ(NULL, log_manager.current_log());
104 log_manager.BeginLoggingWithLog(temp_log, MetricsLogManager::INITIAL_LOG);
105 EXPECT_EQ(temp_log, log_manager.current_log());
106 log_manager.FinishCurrentLog();
107 EXPECT_EQ(NULL, log_manager.current_log());
109 log_manager.ResumePausedLog();
110 EXPECT_EQ(ongoing_log, log_manager.current_log());
112 EXPECT_FALSE(log_manager.has_staged_log());
113 log_manager.StageNextLogForUpload();
114 log_manager.DiscardStagedLog();
115 EXPECT_FALSE(log_manager.has_unsent_logs());
118 TEST(MetricsLogManagerTest, InterjectedLogPreservesType) {
119 MetricsLogManager log_manager;
121 MetricsLogBase* ongoing_log = new MetricsLogBase("id", 0, "version");
122 MetricsLogBase* temp_log = new MetricsLogBase("id", 0, "version");
124 log_manager.BeginLoggingWithLog(ongoing_log, MetricsLogManager::ONGOING_LOG);
125 log_manager.PauseCurrentLog();
126 log_manager.BeginLoggingWithLog(temp_log, MetricsLogManager::INITIAL_LOG);
127 log_manager.FinishCurrentLog();
128 log_manager.ResumePausedLog();
129 log_manager.StageNextLogForUpload();
130 log_manager.DiscardStagedLog();
132 // Verify that the remaining log (which is the original ongoing log) still
133 // has the right type.
134 DummyLogSerializer* serializer = new DummyLogSerializer;
135 log_manager.set_log_serializer(serializer);
136 log_manager.FinishCurrentLog();
137 log_manager.PersistUnsentLogs();
138 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
139 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
142 TEST(MetricsLogManagerTest, StoreAndLoad) {
143 std::vector<MetricsLogManager::SerializedLog> initial_logs;
144 std::vector<MetricsLogManager::SerializedLog> ongoing_logs;
146 // Set up some in-progress logging in a scoped log manager simulating the
147 // leadup to quitting, then persist as would be done on quit.
149 MetricsLogManager log_manager;
150 DummyLogSerializer* serializer = new DummyLogSerializer;
151 log_manager.set_log_serializer(serializer);
152 // Simulate a log having already been unsent from a previous session.
153 MetricsLogManager::SerializedLog log;
154 std::string text = "proto";
155 log.SwapLogText(&text);
156 serializer->persisted_logs_[MetricsLogManager::ONGOING_LOG].push_back(log);
157 EXPECT_FALSE(log_manager.has_unsent_logs());
158 log_manager.LoadPersistedUnsentLogs();
159 EXPECT_TRUE(log_manager.has_unsent_logs());
161 MetricsLogBase* log1 = new MetricsLogBase("id", 0, "version");
162 MetricsLogBase* log2 = new MetricsLogBase("id", 0, "version");
163 log_manager.BeginLoggingWithLog(log1, MetricsLogManager::INITIAL_LOG);
164 log_manager.FinishCurrentLog();
165 log_manager.BeginLoggingWithLog(log2, MetricsLogManager::ONGOING_LOG);
166 log_manager.StageNextLogForUpload();
167 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE);
168 log_manager.FinishCurrentLog();
170 // Nothing should be written out until PersistUnsentLogs is called.
171 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
172 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
173 log_manager.PersistUnsentLogs();
174 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
175 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
177 // Save the logs to transfer over to a new serializer (since log_manager
178 // owns |serializer|, so it's about to go away.
179 initial_logs = serializer->persisted_logs_[MetricsLogManager::INITIAL_LOG];
180 ongoing_logs = serializer->persisted_logs_[MetricsLogManager::ONGOING_LOG];
183 // Now simulate the relaunch, ensure that the log manager restores
184 // everything correctly, and verify that once the are handled they are not
187 MetricsLogManager log_manager;
189 DummyLogSerializer* serializer = new DummyLogSerializer;
190 serializer->persisted_logs_[MetricsLogManager::INITIAL_LOG] = initial_logs;
191 serializer->persisted_logs_[MetricsLogManager::ONGOING_LOG] = ongoing_logs;
193 log_manager.set_log_serializer(serializer);
194 log_manager.LoadPersistedUnsentLogs();
195 EXPECT_TRUE(log_manager.has_unsent_logs());
197 log_manager.StageNextLogForUpload();
198 log_manager.DiscardStagedLog();
199 // The initial log should be sent first; update the persisted storage to
201 log_manager.PersistUnsentLogs();
202 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
203 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
205 // Handle the first ongoing log.
206 log_manager.StageNextLogForUpload();
207 log_manager.DiscardStagedLog();
208 EXPECT_TRUE(log_manager.has_unsent_logs());
210 // Handle the last log.
211 log_manager.StageNextLogForUpload();
212 log_manager.DiscardStagedLog();
213 EXPECT_FALSE(log_manager.has_unsent_logs());
215 // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been
217 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
218 // Persist, and make sure nothing is left.
219 log_manager.PersistUnsentLogs();
220 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
221 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
225 TEST(MetricsLogManagerTest, StoreStagedLogTypes) {
226 // Ensure that types are preserved when storing staged logs.
228 MetricsLogManager log_manager;
229 DummyLogSerializer* serializer = new DummyLogSerializer;
230 log_manager.set_log_serializer(serializer);
232 MetricsLogBase* log = new MetricsLogBase("id", 0, "version");
233 log_manager.BeginLoggingWithLog(log, MetricsLogManager::ONGOING_LOG);
234 log_manager.FinishCurrentLog();
235 log_manager.StageNextLogForUpload();
236 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE);
237 log_manager.PersistUnsentLogs();
239 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
240 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
244 MetricsLogManager log_manager;
245 DummyLogSerializer* serializer = new DummyLogSerializer;
246 log_manager.set_log_serializer(serializer);
248 MetricsLogBase* log = new MetricsLogBase("id", 0, "version");
249 log_manager.BeginLoggingWithLog(log, MetricsLogManager::INITIAL_LOG);
250 log_manager.FinishCurrentLog();
251 log_manager.StageNextLogForUpload();
252 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE);
253 log_manager.PersistUnsentLogs();
255 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
256 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
260 TEST(MetricsLogManagerTest, LargeLogDiscarding) {
261 MetricsLogManager log_manager;
262 DummyLogSerializer* serializer = new DummyLogSerializer;
263 log_manager.set_log_serializer(serializer);
264 // Set the size threshold very low, to verify that it's honored.
265 log_manager.set_max_ongoing_log_store_size(1);
267 MetricsLogBase* log1 = new MetricsLogBase("id", 0, "version");
268 MetricsLogBase* log2 = new MetricsLogBase("id", 0, "version");
269 log_manager.BeginLoggingWithLog(log1, MetricsLogManager::INITIAL_LOG);
270 log_manager.FinishCurrentLog();
271 log_manager.BeginLoggingWithLog(log2, MetricsLogManager::ONGOING_LOG);
272 log_manager.FinishCurrentLog();
274 // Only the ongoing log should be written out, due to the threshold.
275 log_manager.PersistUnsentLogs();
276 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
277 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
280 TEST(MetricsLogManagerTest, ProvisionalStoreStandardFlow) {
281 // Ensure that provisional store works, and discards the correct log.
283 MetricsLogManager log_manager;
284 MetricsLogBase* log1 = new MetricsLogBase("id", 0, "version");
285 MetricsLogBase* log2 = new MetricsLogBase("id", 0, "version");
286 log_manager.BeginLoggingWithLog(log1, MetricsLogManager::INITIAL_LOG);
287 log_manager.FinishCurrentLog();
288 log_manager.BeginLoggingWithLog(log2, MetricsLogManager::ONGOING_LOG);
289 log_manager.StageNextLogForUpload();
290 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE);
291 log_manager.FinishCurrentLog();
292 log_manager.DiscardLastProvisionalStore();
294 DummyLogSerializer* serializer = new DummyLogSerializer;
295 log_manager.set_log_serializer(serializer);
296 log_manager.PersistUnsentLogs();
297 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
298 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
302 TEST(MetricsLogManagerTest, ProvisionalStoreNoop) {
303 // Ensure that trying to drop a sent log is a no-op, even if another log has
304 // since been staged.
306 MetricsLogManager log_manager;
307 MetricsLogBase* log1 = new MetricsLogBase("id", 0, "version");
308 MetricsLogBase* log2 = new MetricsLogBase("id", 0, "version");
309 log_manager.BeginLoggingWithLog(log1, MetricsLogManager::ONGOING_LOG);
310 log_manager.FinishCurrentLog();
311 log_manager.StageNextLogForUpload();
312 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE);
313 log_manager.StageNextLogForUpload();
314 log_manager.DiscardStagedLog();
315 log_manager.BeginLoggingWithLog(log2, MetricsLogManager::ONGOING_LOG);
316 log_manager.FinishCurrentLog();
317 log_manager.StageNextLogForUpload();
318 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE);
319 log_manager.DiscardLastProvisionalStore();
321 DummyLogSerializer* serializer = new DummyLogSerializer;
322 log_manager.set_log_serializer(serializer);
323 log_manager.PersistUnsentLogs();
324 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
327 // Ensure that trying to drop more than once is a no-op
329 MetricsLogManager log_manager;
330 MetricsLogBase* log1 = new MetricsLogBase("id", 0, "version");
331 MetricsLogBase* log2 = new MetricsLogBase("id", 0, "version");
332 log_manager.BeginLoggingWithLog(log1, MetricsLogManager::ONGOING_LOG);
333 log_manager.FinishCurrentLog();
334 log_manager.StageNextLogForUpload();
335 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE);
336 log_manager.BeginLoggingWithLog(log2, MetricsLogManager::ONGOING_LOG);
337 log_manager.FinishCurrentLog();
338 log_manager.StageNextLogForUpload();
339 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE);
340 log_manager.DiscardLastProvisionalStore();
341 log_manager.DiscardLastProvisionalStore();
343 DummyLogSerializer* serializer = new DummyLogSerializer;
344 log_manager.set_log_serializer(serializer);
345 log_manager.PersistUnsentLogs();
346 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
350 TEST(MetricsLogManagerTest, SerializedLog) {
351 const char kFooText[] = "foo";
352 const std::string foo_hash = base::SHA1HashString(kFooText);
353 const char kBarText[] = "bar";
354 const std::string bar_hash = base::SHA1HashString(kBarText);
356 MetricsLogManager::SerializedLog log;
357 EXPECT_TRUE(log.log_text().empty());
358 EXPECT_TRUE(log.log_hash().empty());
360 std::string foo = kFooText;
361 log.SwapLogText(&foo);
362 EXPECT_TRUE(foo.empty());
363 EXPECT_FALSE(log.IsEmpty());
364 EXPECT_EQ(kFooText, log.log_text());
365 EXPECT_EQ(foo_hash, log.log_hash());
367 std::string bar = kBarText;
368 log.SwapLogText(&bar);
369 EXPECT_EQ(kFooText, bar);
370 EXPECT_FALSE(log.IsEmpty());
371 EXPECT_EQ(kBarText, log.log_text());
372 EXPECT_EQ(bar_hash, log.log_hash());
375 EXPECT_TRUE(log.IsEmpty());
376 EXPECT_TRUE(log.log_text().empty());
377 EXPECT_TRUE(log.log_hash().empty());
379 MetricsLogManager::SerializedLog log2;
381 log2.SwapLogText(&foo);
383 EXPECT_FALSE(log.IsEmpty());
384 EXPECT_EQ(kFooText, log.log_text());
385 EXPECT_EQ(foo_hash, log.log_hash());
386 EXPECT_TRUE(log2.IsEmpty());
387 EXPECT_TRUE(log2.log_text().empty());
388 EXPECT_TRUE(log2.log_hash().empty());