OLD | NEW |
| (Empty) |
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 "chrome/common/metrics/metrics_log_manager.h" | |
6 | |
7 #include <string> | |
8 #include <utility> | |
9 #include <vector> | |
10 | |
11 #include "base/sha1.h" | |
12 #include "chrome/common/metrics/metrics_log_base.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 | |
15 namespace { | |
16 | |
17 // Dummy serializer that just stores logs in memory. | |
18 class DummyLogSerializer : public MetricsLogManager::LogSerializer { | |
19 public: | |
20 virtual void SerializeLogs( | |
21 const std::vector<MetricsLogManager::SerializedLog>& logs, | |
22 MetricsLogManager::LogType log_type) OVERRIDE { | |
23 persisted_logs_[log_type] = logs; | |
24 } | |
25 | |
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]; | |
31 } | |
32 | |
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(); | |
36 } | |
37 | |
38 // In-memory "persitent storage". | |
39 std::vector<MetricsLogManager::SerializedLog> persisted_logs_[2]; | |
40 }; | |
41 | |
42 } // namespace | |
43 | |
44 TEST(MetricsLogManagerTest, StandardFlow) { | |
45 MetricsLogManager log_manager; | |
46 | |
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()); | |
51 | |
52 // Check that the normal flow works. | |
53 MetricsLogBase* initial_log = | |
54 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
55 log_manager.BeginLoggingWithLog(initial_log); | |
56 EXPECT_EQ(initial_log, log_manager.current_log()); | |
57 EXPECT_FALSE(log_manager.has_staged_log()); | |
58 | |
59 log_manager.FinishCurrentLog(); | |
60 EXPECT_EQ(NULL, log_manager.current_log()); | |
61 EXPECT_TRUE(log_manager.has_unsent_logs()); | |
62 EXPECT_FALSE(log_manager.has_staged_log()); | |
63 | |
64 MetricsLogBase* second_log = | |
65 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
66 log_manager.BeginLoggingWithLog(second_log); | |
67 EXPECT_EQ(second_log, log_manager.current_log()); | |
68 | |
69 log_manager.StageNextLogForUpload(); | |
70 EXPECT_TRUE(log_manager.has_staged_log()); | |
71 EXPECT_FALSE(log_manager.staged_log_text().empty()); | |
72 | |
73 log_manager.DiscardStagedLog(); | |
74 EXPECT_EQ(second_log, log_manager.current_log()); | |
75 EXPECT_FALSE(log_manager.has_staged_log()); | |
76 EXPECT_FALSE(log_manager.has_unsent_logs()); | |
77 EXPECT_TRUE(log_manager.staged_log_text().empty()); | |
78 | |
79 EXPECT_FALSE(log_manager.has_unsent_logs()); | |
80 } | |
81 | |
82 TEST(MetricsLogManagerTest, AbandonedLog) { | |
83 MetricsLogManager log_manager; | |
84 | |
85 MetricsLogBase* dummy_log = | |
86 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
87 log_manager.BeginLoggingWithLog(dummy_log); | |
88 EXPECT_EQ(dummy_log, log_manager.current_log()); | |
89 | |
90 log_manager.DiscardCurrentLog(); | |
91 EXPECT_EQ(NULL, log_manager.current_log()); | |
92 EXPECT_FALSE(log_manager.has_staged_log()); | |
93 } | |
94 | |
95 TEST(MetricsLogManagerTest, InterjectedLog) { | |
96 MetricsLogManager log_manager; | |
97 | |
98 MetricsLogBase* ongoing_log = | |
99 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "v"); | |
100 MetricsLogBase* temp_log = | |
101 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
102 | |
103 log_manager.BeginLoggingWithLog(ongoing_log); | |
104 EXPECT_EQ(ongoing_log, log_manager.current_log()); | |
105 | |
106 log_manager.PauseCurrentLog(); | |
107 EXPECT_EQ(NULL, log_manager.current_log()); | |
108 | |
109 log_manager.BeginLoggingWithLog(temp_log); | |
110 EXPECT_EQ(temp_log, log_manager.current_log()); | |
111 log_manager.FinishCurrentLog(); | |
112 EXPECT_EQ(NULL, log_manager.current_log()); | |
113 | |
114 log_manager.ResumePausedLog(); | |
115 EXPECT_EQ(ongoing_log, log_manager.current_log()); | |
116 | |
117 EXPECT_FALSE(log_manager.has_staged_log()); | |
118 log_manager.StageNextLogForUpload(); | |
119 log_manager.DiscardStagedLog(); | |
120 EXPECT_FALSE(log_manager.has_unsent_logs()); | |
121 } | |
122 | |
123 TEST(MetricsLogManagerTest, InterjectedLogPreservesType) { | |
124 MetricsLogManager log_manager; | |
125 DummyLogSerializer* serializer = new DummyLogSerializer; | |
126 log_manager.set_log_serializer(serializer); | |
127 log_manager.LoadPersistedUnsentLogs(); | |
128 | |
129 MetricsLogBase* ongoing_log = | |
130 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "v"); | |
131 MetricsLogBase* temp_log = | |
132 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
133 | |
134 log_manager.BeginLoggingWithLog(ongoing_log); | |
135 log_manager.PauseCurrentLog(); | |
136 log_manager.BeginLoggingWithLog(temp_log); | |
137 log_manager.FinishCurrentLog(); | |
138 log_manager.ResumePausedLog(); | |
139 log_manager.StageNextLogForUpload(); | |
140 log_manager.DiscardStagedLog(); | |
141 | |
142 // Verify that the remaining log (which is the original ongoing log) still | |
143 // has the right type. | |
144 log_manager.FinishCurrentLog(); | |
145 log_manager.PersistUnsentLogs(); | |
146 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
147 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
148 } | |
149 | |
150 TEST(MetricsLogManagerTest, StoreAndLoad) { | |
151 std::vector<MetricsLogManager::SerializedLog> initial_logs; | |
152 std::vector<MetricsLogManager::SerializedLog> ongoing_logs; | |
153 | |
154 // Set up some in-progress logging in a scoped log manager simulating the | |
155 // leadup to quitting, then persist as would be done on quit. | |
156 { | |
157 MetricsLogManager log_manager; | |
158 DummyLogSerializer* serializer = new DummyLogSerializer; | |
159 log_manager.set_log_serializer(serializer); | |
160 log_manager.LoadPersistedUnsentLogs(); | |
161 | |
162 // Simulate a log having already been unsent from a previous session. | |
163 MetricsLogManager::SerializedLog log; | |
164 std::string text = "proto"; | |
165 log.SwapLogText(&text); | |
166 serializer->persisted_logs_[MetricsLogBase::ONGOING_LOG].push_back(log); | |
167 EXPECT_FALSE(log_manager.has_unsent_logs()); | |
168 log_manager.LoadPersistedUnsentLogs(); | |
169 EXPECT_TRUE(log_manager.has_unsent_logs()); | |
170 | |
171 MetricsLogBase* log1 = | |
172 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
173 MetricsLogBase* log2 = | |
174 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "v"); | |
175 log_manager.BeginLoggingWithLog(log1); | |
176 log_manager.FinishCurrentLog(); | |
177 log_manager.BeginLoggingWithLog(log2); | |
178 log_manager.StageNextLogForUpload(); | |
179 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE); | |
180 log_manager.FinishCurrentLog(); | |
181 | |
182 // Nothing should be written out until PersistUnsentLogs is called. | |
183 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
184 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
185 log_manager.PersistUnsentLogs(); | |
186 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
187 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
188 | |
189 // Save the logs to transfer over to a new serializer (since log_manager | |
190 // owns |serializer|, so it's about to go away. | |
191 initial_logs = | |
192 serializer->persisted_logs_[MetricsLogBase::INITIAL_STABILITY_LOG]; | |
193 ongoing_logs = serializer->persisted_logs_[MetricsLogBase::ONGOING_LOG]; | |
194 } | |
195 | |
196 // Now simulate the relaunch, ensure that the log manager restores | |
197 // everything correctly, and verify that once the are handled they are not | |
198 // re-persisted. | |
199 { | |
200 MetricsLogManager log_manager; | |
201 | |
202 DummyLogSerializer* serializer = new DummyLogSerializer; | |
203 serializer->persisted_logs_[MetricsLogBase::INITIAL_STABILITY_LOG] = | |
204 initial_logs; | |
205 serializer->persisted_logs_[MetricsLogBase::ONGOING_LOG] = ongoing_logs; | |
206 | |
207 log_manager.set_log_serializer(serializer); | |
208 log_manager.LoadPersistedUnsentLogs(); | |
209 EXPECT_TRUE(log_manager.has_unsent_logs()); | |
210 | |
211 log_manager.StageNextLogForUpload(); | |
212 log_manager.DiscardStagedLog(); | |
213 // The initial log should be sent first; update the persisted storage to | |
214 // verify. | |
215 log_manager.PersistUnsentLogs(); | |
216 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
217 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
218 | |
219 // Handle the first ongoing log. | |
220 log_manager.StageNextLogForUpload(); | |
221 log_manager.DiscardStagedLog(); | |
222 EXPECT_TRUE(log_manager.has_unsent_logs()); | |
223 | |
224 // Handle the last log. | |
225 log_manager.StageNextLogForUpload(); | |
226 log_manager.DiscardStagedLog(); | |
227 EXPECT_FALSE(log_manager.has_unsent_logs()); | |
228 | |
229 // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been | |
230 // called again. | |
231 EXPECT_EQ(2U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
232 // Persist, and make sure nothing is left. | |
233 log_manager.PersistUnsentLogs(); | |
234 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
235 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
236 } | |
237 } | |
238 | |
239 TEST(MetricsLogManagerTest, StoreStagedLogTypes) { | |
240 // Ensure that types are preserved when storing staged logs. | |
241 { | |
242 MetricsLogManager log_manager; | |
243 DummyLogSerializer* serializer = new DummyLogSerializer; | |
244 log_manager.set_log_serializer(serializer); | |
245 log_manager.LoadPersistedUnsentLogs(); | |
246 | |
247 MetricsLogBase* log = | |
248 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
249 log_manager.BeginLoggingWithLog(log); | |
250 log_manager.FinishCurrentLog(); | |
251 log_manager.StageNextLogForUpload(); | |
252 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE); | |
253 log_manager.PersistUnsentLogs(); | |
254 | |
255 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
256 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
257 } | |
258 | |
259 { | |
260 MetricsLogManager log_manager; | |
261 DummyLogSerializer* serializer = new DummyLogSerializer; | |
262 log_manager.set_log_serializer(serializer); | |
263 log_manager.LoadPersistedUnsentLogs(); | |
264 | |
265 MetricsLogBase* log = | |
266 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
267 log_manager.BeginLoggingWithLog(log); | |
268 log_manager.FinishCurrentLog(); | |
269 log_manager.StageNextLogForUpload(); | |
270 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE); | |
271 log_manager.PersistUnsentLogs(); | |
272 | |
273 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
274 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
275 } | |
276 } | |
277 | |
278 TEST(MetricsLogManagerTest, LargeLogDiscarding) { | |
279 MetricsLogManager log_manager; | |
280 DummyLogSerializer* serializer = new DummyLogSerializer; | |
281 log_manager.set_log_serializer(serializer); | |
282 log_manager.LoadPersistedUnsentLogs(); | |
283 | |
284 // Set the size threshold very low, to verify that it's honored. | |
285 log_manager.set_max_ongoing_log_store_size(1); | |
286 | |
287 MetricsLogBase* log1 = | |
288 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
289 MetricsLogBase* log2 = | |
290 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "v"); | |
291 log_manager.BeginLoggingWithLog(log1); | |
292 log_manager.FinishCurrentLog(); | |
293 log_manager.BeginLoggingWithLog(log2); | |
294 log_manager.FinishCurrentLog(); | |
295 | |
296 // Only the ongoing log should be written out, due to the threshold. | |
297 log_manager.PersistUnsentLogs(); | |
298 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
299 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
300 } | |
301 | |
302 TEST(MetricsLogManagerTest, ProvisionalStoreStandardFlow) { | |
303 // Ensure that provisional store works, and discards the correct log. | |
304 { | |
305 MetricsLogManager log_manager; | |
306 DummyLogSerializer* serializer = new DummyLogSerializer; | |
307 log_manager.set_log_serializer(serializer); | |
308 log_manager.LoadPersistedUnsentLogs(); | |
309 | |
310 MetricsLogBase* log1 = | |
311 new MetricsLogBase("id", 0, MetricsLogBase::INITIAL_STABILITY_LOG, "v"); | |
312 MetricsLogBase* log2 = | |
313 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "v"); | |
314 log_manager.BeginLoggingWithLog(log1); | |
315 log_manager.FinishCurrentLog(); | |
316 log_manager.BeginLoggingWithLog(log2); | |
317 log_manager.StageNextLogForUpload(); | |
318 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE); | |
319 log_manager.FinishCurrentLog(); | |
320 log_manager.DiscardLastProvisionalStore(); | |
321 | |
322 log_manager.PersistUnsentLogs(); | |
323 EXPECT_EQ(0U, serializer->TypeCount(MetricsLogBase::INITIAL_STABILITY_LOG)); | |
324 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
325 } | |
326 } | |
327 | |
328 TEST(MetricsLogManagerTest, ProvisionalStoreNoop) { | |
329 // Ensure that trying to drop a sent log is a no-op, even if another log has | |
330 // since been staged. | |
331 { | |
332 MetricsLogManager log_manager; | |
333 DummyLogSerializer* serializer = new DummyLogSerializer; | |
334 log_manager.set_log_serializer(serializer); | |
335 log_manager.LoadPersistedUnsentLogs(); | |
336 | |
337 MetricsLogBase* log1 = | |
338 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
339 MetricsLogBase* log2 = | |
340 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
341 log_manager.BeginLoggingWithLog(log1); | |
342 log_manager.FinishCurrentLog(); | |
343 log_manager.StageNextLogForUpload(); | |
344 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE); | |
345 log_manager.StageNextLogForUpload(); | |
346 log_manager.DiscardStagedLog(); | |
347 log_manager.BeginLoggingWithLog(log2); | |
348 log_manager.FinishCurrentLog(); | |
349 log_manager.StageNextLogForUpload(); | |
350 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE); | |
351 log_manager.DiscardLastProvisionalStore(); | |
352 | |
353 log_manager.PersistUnsentLogs(); | |
354 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
355 } | |
356 | |
357 // Ensure that trying to drop more than once is a no-op | |
358 { | |
359 MetricsLogManager log_manager; | |
360 DummyLogSerializer* serializer = new DummyLogSerializer; | |
361 log_manager.set_log_serializer(serializer); | |
362 log_manager.LoadPersistedUnsentLogs(); | |
363 | |
364 MetricsLogBase* log1 = | |
365 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
366 MetricsLogBase* log2 = | |
367 new MetricsLogBase("id", 0, MetricsLogBase::ONGOING_LOG, "version"); | |
368 log_manager.BeginLoggingWithLog(log1); | |
369 log_manager.FinishCurrentLog(); | |
370 log_manager.StageNextLogForUpload(); | |
371 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::NORMAL_STORE); | |
372 log_manager.BeginLoggingWithLog(log2); | |
373 log_manager.FinishCurrentLog(); | |
374 log_manager.StageNextLogForUpload(); | |
375 log_manager.StoreStagedLogAsUnsent(MetricsLogManager::PROVISIONAL_STORE); | |
376 log_manager.DiscardLastProvisionalStore(); | |
377 log_manager.DiscardLastProvisionalStore(); | |
378 | |
379 log_manager.PersistUnsentLogs(); | |
380 EXPECT_EQ(1U, serializer->TypeCount(MetricsLogBase::ONGOING_LOG)); | |
381 } | |
382 } | |
383 | |
384 TEST(MetricsLogManagerTest, SerializedLog) { | |
385 const char kFooText[] = "foo"; | |
386 const std::string foo_hash = base::SHA1HashString(kFooText); | |
387 const char kBarText[] = "bar"; | |
388 const std::string bar_hash = base::SHA1HashString(kBarText); | |
389 | |
390 MetricsLogManager::SerializedLog log; | |
391 EXPECT_TRUE(log.log_text().empty()); | |
392 EXPECT_TRUE(log.log_hash().empty()); | |
393 | |
394 std::string foo = kFooText; | |
395 log.SwapLogText(&foo); | |
396 EXPECT_TRUE(foo.empty()); | |
397 EXPECT_FALSE(log.IsEmpty()); | |
398 EXPECT_EQ(kFooText, log.log_text()); | |
399 EXPECT_EQ(foo_hash, log.log_hash()); | |
400 | |
401 std::string bar = kBarText; | |
402 log.SwapLogText(&bar); | |
403 EXPECT_EQ(kFooText, bar); | |
404 EXPECT_FALSE(log.IsEmpty()); | |
405 EXPECT_EQ(kBarText, log.log_text()); | |
406 EXPECT_EQ(bar_hash, log.log_hash()); | |
407 | |
408 log.Clear(); | |
409 EXPECT_TRUE(log.IsEmpty()); | |
410 EXPECT_TRUE(log.log_text().empty()); | |
411 EXPECT_TRUE(log.log_hash().empty()); | |
412 | |
413 MetricsLogManager::SerializedLog log2; | |
414 foo = kFooText; | |
415 log2.SwapLogText(&foo); | |
416 log.Swap(&log2); | |
417 EXPECT_FALSE(log.IsEmpty()); | |
418 EXPECT_EQ(kFooText, log.log_text()); | |
419 EXPECT_EQ(foo_hash, log.log_hash()); | |
420 EXPECT_TRUE(log2.IsEmpty()); | |
421 EXPECT_TRUE(log2.log_text().empty()); | |
422 EXPECT_TRUE(log2.log_hash().empty()); | |
423 } | |
OLD | NEW |