1 // Copyright (c) 2010 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/browser/metrics/metrics_service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/base64.h"
11 #include "base/md5.h"
12 #include "base/values.h"
13
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 class MetricsServiceTest : public ::testing::Test {
17 };
18
19 static const size_t kMaxLocalListSize = 3;
20
21 // Ensure the ClientId is formatted as expected.
TEST(MetricsServiceTest,ClientIdCorrectlyFormatted)22 TEST(MetricsServiceTest, ClientIdCorrectlyFormatted) {
23 std::string clientid = MetricsService::GenerateClientID();
24 EXPECT_EQ(36U, clientid.length());
25 std::string hexchars = "0123456789ABCDEF";
26 for (uint32 i = 0; i < clientid.length(); i++) {
27 char current = clientid.at(i);
28 if (i == 8 || i == 13 || i == 18 || i == 23) {
29 EXPECT_EQ('-', current);
30 } else {
31 EXPECT_TRUE(std::string::npos != hexchars.find(current));
32 }
33 }
34 }
35
36 // Store and retrieve empty list.
TEST(MetricsServiceTest,EmptyLogList)37 TEST(MetricsServiceTest, EmptyLogList) {
38 ListValue list;
39 std::vector<std::string> local_list;
40
41 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
42 EXPECT_EQ(0U, list.GetSize());
43
44 local_list.clear(); // RecallUnsentLogsHelper() expects empty |local_list|.
45 EXPECT_EQ(MetricsService::LIST_EMPTY,
46 MetricsService::RecallUnsentLogsHelper(list, &local_list));
47 EXPECT_EQ(0U, local_list.size());
48 }
49
50 // Store and retrieve a single log value.
TEST(MetricsServiceTest,SingleElementLogList)51 TEST(MetricsServiceTest, SingleElementLogList) {
52 ListValue list;
53 std::vector<std::string> local_list;
54
55 local_list.push_back("Hello world!");
56 EXPECT_EQ(1U, local_list.size());
57
58 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
59
60 // |list| will now contain the following:
61 // [1, Base64Encode("Hello world!"), MD5("Hello world!")].
62 EXPECT_EQ(3U, list.GetSize());
63
64 // Examine each element.
65 ListValue::const_iterator it = list.begin();
66 int size = 0;
67 (*it)->GetAsInteger(&size);
68 EXPECT_EQ(1, size);
69
70 ++it;
71 std::string str;
72 (*it)->GetAsString(&str); // Base64 encoded "Hello world!" string.
73 std::string encoded;
74 base::Base64Encode("Hello world!", &encoded);
75 EXPECT_TRUE(encoded == str);
76
77 ++it;
78 (*it)->GetAsString(&str); // MD5 for encoded "Hello world!" string.
79 EXPECT_TRUE(MD5String(encoded) == str);
80
81 ++it;
82 EXPECT_TRUE(it == list.end()); // Reached end of list.
83
84 local_list.clear();
85 EXPECT_EQ(MetricsService::RECALL_SUCCESS,
86 MetricsService::RecallUnsentLogsHelper(list, &local_list));
87 EXPECT_EQ(1U, local_list.size());
88 }
89
90 // Store elements greater than the limit.
TEST(MetricsServiceTest,OverLimitLogList)91 TEST(MetricsServiceTest, OverLimitLogList) {
92 ListValue list;
93 std::vector<std::string> local_list;
94
95 local_list.push_back("one");
96 local_list.push_back("two");
97 local_list.push_back("three");
98 local_list.push_back("four");
99 EXPECT_EQ(4U, local_list.size());
100
101 std::string expected_first;
102 base::Base64Encode(local_list[local_list.size() - kMaxLocalListSize],
103 &expected_first);
104 std::string expected_last;
105 base::Base64Encode(local_list[local_list.size() - 1],
106 &expected_last);
107
108 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
109 EXPECT_EQ(kMaxLocalListSize + 2, list.GetSize());
110
111 std::string actual_first;
112 EXPECT_TRUE((*(list.begin() + 1))->GetAsString(&actual_first));
113 EXPECT_TRUE(expected_first == actual_first);
114
115 std::string actual_last;
116 EXPECT_TRUE((*(list.end() - 2))->GetAsString(&actual_last));
117 EXPECT_TRUE(expected_last == actual_last);
118
119 local_list.clear();
120 EXPECT_EQ(MetricsService::RECALL_SUCCESS,
121 MetricsService::RecallUnsentLogsHelper(list, &local_list));
122 EXPECT_EQ(kMaxLocalListSize, local_list.size());
123 }
124
125 // Induce LIST_SIZE_TOO_SMALL corruption
TEST(MetricsServiceTest,SmallRecoveredListSize)126 TEST(MetricsServiceTest, SmallRecoveredListSize) {
127 ListValue list;
128 std::vector<std::string> local_list;
129
130 local_list.push_back("Hello world!");
131 EXPECT_EQ(1U, local_list.size());
132 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
133 EXPECT_EQ(3U, list.GetSize());
134
135 // Remove last element.
136 list.Remove(list.GetSize() - 1, NULL);
137 EXPECT_EQ(2U, list.GetSize());
138
139 local_list.clear();
140 EXPECT_EQ(MetricsService::LIST_SIZE_TOO_SMALL,
141 MetricsService::RecallUnsentLogsHelper(list, &local_list));
142 }
143
144 // Remove size from the stored list.
TEST(MetricsServiceTest,RemoveSizeFromLogList)145 TEST(MetricsServiceTest, RemoveSizeFromLogList) {
146 ListValue list;
147 std::vector<std::string> local_list;
148
149 local_list.push_back("one");
150 local_list.push_back("two");
151 EXPECT_EQ(2U, local_list.size());
152 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
153 EXPECT_EQ(4U, list.GetSize());
154
155 list.Remove(0, NULL); // Delete size (1st element).
156 EXPECT_EQ(3U, list.GetSize());
157
158 local_list.clear();
159 EXPECT_EQ(MetricsService::LIST_SIZE_MISSING,
160 MetricsService::RecallUnsentLogsHelper(list, &local_list));
161 }
162
163 // Corrupt size of stored list.
TEST(MetricsServiceTest,CorruptSizeOfLogList)164 TEST(MetricsServiceTest, CorruptSizeOfLogList) {
165 ListValue list;
166 std::vector<std::string> local_list;
167
168 local_list.push_back("Hello world!");
169 EXPECT_EQ(1U, local_list.size());
170 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
171 EXPECT_EQ(3U, list.GetSize());
172
173 // Change list size from 1 to 2.
174 EXPECT_TRUE(list.Set(0, Value::CreateIntegerValue(2)));
175 EXPECT_EQ(3U, list.GetSize());
176
177 local_list.clear();
178 EXPECT_EQ(MetricsService::LIST_SIZE_CORRUPTION,
179 MetricsService::RecallUnsentLogsHelper(list, &local_list));
180 }
181
182 // Corrupt checksum of stored list.
TEST(MetricsServiceTest,CorruptChecksumOfLogList)183 TEST(MetricsServiceTest, CorruptChecksumOfLogList) {
184 ListValue list;
185 std::vector<std::string> local_list;
186
187 local_list.clear();
188 local_list.push_back("Hello world!");
189 EXPECT_EQ(1U, local_list.size());
190 MetricsService::StoreUnsentLogsHelper(local_list, kMaxLocalListSize, &list);
191 EXPECT_EQ(3U, list.GetSize());
192
193 // Fetch checksum (last element) and change it.
194 std::string checksum;
195 EXPECT_TRUE((*(list.end() - 1))->GetAsString(&checksum));
196 checksum[0] = (checksum[0] == 'a') ? 'b' : 'a';
197 EXPECT_TRUE(list.Set(2, Value::CreateStringValue(checksum)));
198 EXPECT_EQ(3U, list.GetSize());
199
200 local_list.clear();
201 EXPECT_EQ(MetricsService::CHECKSUM_CORRUPTION,
202 MetricsService::RecallUnsentLogsHelper(list, &local_list));
203 }
204