- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / metrics / metrics_log_manager_unittest.cc
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 = 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());
57
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());
62
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());
66
67   log_manager.StageNextLogForUpload();
68   EXPECT_TRUE(log_manager.has_staged_log());
69   EXPECT_FALSE(log_manager.staged_log_text().empty());
70
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());
76
77   EXPECT_FALSE(log_manager.has_unsent_logs());
78 }
79
80 TEST(MetricsLogManagerTest, AbandonedLog) {
81   MetricsLogManager log_manager;
82
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());
86
87   log_manager.DiscardCurrentLog();
88   EXPECT_EQ(NULL, log_manager.current_log());
89   EXPECT_FALSE(log_manager.has_staged_log());
90 }
91
92 TEST(MetricsLogManagerTest, InterjectedLog) {
93   MetricsLogManager log_manager;
94
95   MetricsLogBase* ongoing_log = new MetricsLogBase("id", 0, "version");
96   MetricsLogBase* temp_log = new MetricsLogBase("id", 0, "version");
97
98   log_manager.BeginLoggingWithLog(ongoing_log, MetricsLogManager::ONGOING_LOG);
99   EXPECT_EQ(ongoing_log, log_manager.current_log());
100
101   log_manager.PauseCurrentLog();
102   EXPECT_EQ(NULL, log_manager.current_log());
103
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());
108
109   log_manager.ResumePausedLog();
110   EXPECT_EQ(ongoing_log, log_manager.current_log());
111
112   EXPECT_FALSE(log_manager.has_staged_log());
113   log_manager.StageNextLogForUpload();
114   log_manager.DiscardStagedLog();
115   EXPECT_FALSE(log_manager.has_unsent_logs());
116 }
117
118 TEST(MetricsLogManagerTest, InterjectedLogPreservesType) {
119   MetricsLogManager log_manager;
120
121   MetricsLogBase* ongoing_log = new MetricsLogBase("id", 0, "version");
122   MetricsLogBase* temp_log = new MetricsLogBase("id", 0, "version");
123
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();
131
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));
140 }
141
142 TEST(MetricsLogManagerTest, StoreAndLoad) {
143   std::vector<MetricsLogManager::SerializedLog> initial_logs;
144   std::vector<MetricsLogManager::SerializedLog> ongoing_logs;
145
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.
148   {
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());
160
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();
169
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));
176
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];
181   }
182
183   // Now simulate the relaunch, ensure that the log manager restores
184   // everything correctly, and verify that once the are handled they are not
185   // re-persisted.
186   {
187     MetricsLogManager log_manager;
188
189     DummyLogSerializer* serializer = new DummyLogSerializer;
190     serializer->persisted_logs_[MetricsLogManager::INITIAL_LOG] = initial_logs;
191     serializer->persisted_logs_[MetricsLogManager::ONGOING_LOG] = ongoing_logs;
192
193     log_manager.set_log_serializer(serializer);
194     log_manager.LoadPersistedUnsentLogs();
195     EXPECT_TRUE(log_manager.has_unsent_logs());
196
197     log_manager.StageNextLogForUpload();
198     log_manager.DiscardStagedLog();
199     // The initial log should be sent first; update the persisted storage to
200     // verify.
201     log_manager.PersistUnsentLogs();
202     EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
203     EXPECT_EQ(2U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
204
205     // Handle the first ongoing log.
206     log_manager.StageNextLogForUpload();
207     log_manager.DiscardStagedLog();
208     EXPECT_TRUE(log_manager.has_unsent_logs());
209
210     // Handle the last log.
211     log_manager.StageNextLogForUpload();
212     log_manager.DiscardStagedLog();
213     EXPECT_FALSE(log_manager.has_unsent_logs());
214
215     // Nothing should have changed "on disk" since PersistUnsentLogs hasn't been
216     // called again.
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));
222   }
223 }
224
225 TEST(MetricsLogManagerTest, StoreStagedLogTypes) {
226   // Ensure that types are preserved when storing staged logs.
227   {
228     MetricsLogManager log_manager;
229     DummyLogSerializer* serializer = new DummyLogSerializer;
230     log_manager.set_log_serializer(serializer);
231
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();
238
239     EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
240     EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
241   }
242
243   {
244     MetricsLogManager log_manager;
245     DummyLogSerializer* serializer = new DummyLogSerializer;
246     log_manager.set_log_serializer(serializer);
247
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();
254
255     EXPECT_EQ(1U, serializer->TypeCount(MetricsLogManager::INITIAL_LOG));
256     EXPECT_EQ(0U, serializer->TypeCount(MetricsLogManager::ONGOING_LOG));
257   }
258 }
259
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);
266
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();
273
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));
278 }
279
280 TEST(MetricsLogManagerTest, ProvisionalStoreStandardFlow) {
281   // Ensure that provisional store works, and discards the correct log.
282   {
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();
293
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));
299   }
300 }
301
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.
305   {
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();
320
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));
325   }
326
327   // Ensure that trying to drop more than once is a no-op
328   {
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();
342
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));
347   }
348 }
349
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);
355
356   MetricsLogManager::SerializedLog log;
357   EXPECT_TRUE(log.log_text().empty());
358   EXPECT_TRUE(log.log_hash().empty());
359
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());
366
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());
373
374   log.Clear();
375   EXPECT_TRUE(log.IsEmpty());
376   EXPECT_TRUE(log.log_text().empty());
377   EXPECT_TRUE(log.log_hash().empty());
378
379   MetricsLogManager::SerializedLog log2;
380   foo = kFooText;
381   log2.SwapLogText(&foo);
382   log.Swap(&log2);
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());
389 }