OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <string> | 5 #include <string> |
6 | 6 |
7 #include "base/stringprintf.h" | 7 #include "base/stringprintf.h" |
8 #include "base/string_util.h" | 8 #include "base/string_util.h" |
9 #include "base/time.h" | 9 #include "base/time.h" |
10 #include "chrome/browser/metrics/metrics_log.h" | 10 #include "chrome/browser/metrics/metrics_log.h" |
11 #include "chrome/browser/prefs/browser_prefs.h" | 11 #include "chrome/browser/prefs/browser_prefs.h" |
12 #include "chrome/browser/prefs/pref_service.h" | 12 #include "chrome/browser/prefs/pref_service.h" |
13 #include "chrome/common/pref_names.h" | 13 #include "chrome/common/pref_names.h" |
14 #include "chrome/test/base/testing_pref_service.h" | 14 #include "chrome/test/base/testing_pref_service.h" |
15 #include "googleurl/src/gurl.h" | 15 #include "googleurl/src/gurl.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "webkit/plugins/webplugininfo.h" |
17 | 18 |
18 using base::TimeDelta; | 19 using base::TimeDelta; |
19 | 20 |
20 namespace { | 21 namespace { |
21 class MetricsLogTest : public testing::Test { | |
22 }; | |
23 }; | |
24 | |
25 | 22 |
26 // Since buildtime is highly variable, this function will scan an output log and | 23 // Since buildtime is highly variable, this function will scan an output log and |
27 // replace it with a consistent number. | 24 // replace it with a consistent number. |
28 static void NormalizeBuildtime(std::string* xml_encoded) { | 25 void NormalizeBuildtime(std::string* xml_encoded) { |
29 std::string prefix = "buildtime=\""; | 26 std::string prefix = "buildtime=\""; |
30 const char postfix = '\"'; | 27 const char postfix = '\"'; |
31 size_t offset = xml_encoded->find(prefix); | 28 size_t offset = xml_encoded->find(prefix); |
32 ASSERT_NE(std::string::npos, offset); | 29 ASSERT_NE(std::string::npos, offset); |
33 offset += prefix.size(); | 30 offset += prefix.size(); |
34 size_t postfix_position = xml_encoded->find(postfix, offset); | 31 size_t postfix_position = xml_encoded->find(postfix, offset); |
35 ASSERT_NE(std::string::npos, postfix_position); | 32 ASSERT_NE(std::string::npos, postfix_position); |
36 for (size_t i = offset; i < postfix_position; ++i) { | 33 for (size_t i = offset; i < postfix_position; ++i) { |
37 char digit = xml_encoded->at(i); | 34 char digit = xml_encoded->at(i); |
38 ASSERT_GE(digit, '0'); | 35 ASSERT_GE(digit, '0'); |
39 ASSERT_LE(digit, '9'); | 36 ASSERT_LE(digit, '9'); |
40 } | 37 } |
41 | 38 |
42 // Insert a single fake buildtime. | 39 // Insert a single fake buildtime. |
43 xml_encoded->replace(offset, postfix_position - offset, "123246"); | 40 xml_encoded->replace(offset, postfix_position - offset, "123246"); |
44 } | 41 } |
45 | 42 |
46 TEST(MetricsLogTest, EmptyRecord) { | |
47 std::string expected_output = base::StringPrintf( | |
48 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | |
49 "appversion=\"%s\"/>", MetricsLog::GetVersionString().c_str()); | |
50 | |
51 MetricsLog log("bogus client ID", 0); | |
52 log.CloseLog(); | |
53 | |
54 int size = log.GetEncodedLogSize(); | |
55 ASSERT_GT(size, 0); | |
56 | |
57 std::string encoded; | |
58 // Leave room for the NUL terminator. | |
59 ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size)); | |
60 TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded); | |
61 NormalizeBuildtime(&encoded); | |
62 NormalizeBuildtime(&expected_output); | |
63 | |
64 ASSERT_EQ(expected_output, encoded); | |
65 } | |
66 | |
67 #if defined(OS_CHROMEOS) | |
68 TEST(MetricsLogTest, ChromeOSEmptyRecord) { | |
69 std::string expected_output = base::StringPrintf( | |
70 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | |
71 "appversion=\"%s\" hardwareclass=\"sample-class\"/>", | |
72 MetricsLog::GetVersionString().c_str()); | |
73 | |
74 MetricsLog log("bogus client ID", 0); | |
75 log.set_hardware_class("sample-class"); | |
76 log.CloseLog(); | |
77 | |
78 int size = log.GetEncodedLogSize(); | |
79 ASSERT_GT(size, 0); | |
80 | |
81 std::string encoded; | |
82 // Leave room for the NUL terminator. | |
83 ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size)); | |
84 TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded); | |
85 NormalizeBuildtime(&encoded); | |
86 NormalizeBuildtime(&expected_output); | |
87 | |
88 ASSERT_EQ(expected_output, encoded); | |
89 } | |
90 #endif // OS_CHROMEOS | |
91 | |
92 namespace { | |
93 | |
94 class NoTimeMetricsLog : public MetricsLog { | 43 class NoTimeMetricsLog : public MetricsLog { |
95 public: | 44 public: |
96 NoTimeMetricsLog(std::string client_id, int session_id): | 45 NoTimeMetricsLog(std::string client_id, int session_id): |
97 MetricsLog(client_id, session_id) {} | 46 MetricsLog(client_id, session_id) {} |
98 virtual ~NoTimeMetricsLog() {} | 47 virtual ~NoTimeMetricsLog() {} |
99 | 48 |
100 // Override this so that output is testable. | 49 // Override this so that output is testable. |
101 virtual std::string GetCurrentTimeString() { | 50 virtual std::string GetCurrentTimeString() { |
102 return std::string(); | 51 return std::string(); |
103 } | 52 } |
104 }; | 53 }; |
105 | 54 |
106 }; // namespace | 55 } // namespace |
107 | 56 |
108 TEST(MetricsLogTest, WindowEvent) { | 57 class MetricsLogTest : public testing::Test { |
109 std::string expected_output = base::StringPrintf( | 58 }; |
110 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | |
111 "appversion=\"%s\">\n" | |
112 " <window action=\"create\" windowid=\"0\" session=\"0\" time=\"\"/>\n" | |
113 " <window action=\"open\" windowid=\"1\" parent=\"0\" " | |
114 "session=\"0\" time=\"\"/>\n" | |
115 " <window action=\"close\" windowid=\"1\" parent=\"0\" " | |
116 "session=\"0\" time=\"\"/>\n" | |
117 " <window action=\"destroy\" windowid=\"0\" session=\"0\" time=\"\"/>\n" | |
118 "</log>", MetricsLog::GetVersionString().c_str()); | |
119 | |
120 NoTimeMetricsLog log("bogus client ID", 0); | |
121 log.RecordWindowEvent(MetricsLog::WINDOW_CREATE, 0, -1); | |
122 log.RecordWindowEvent(MetricsLog::WINDOW_OPEN, 1, 0); | |
123 log.RecordWindowEvent(MetricsLog::WINDOW_CLOSE, 1, 0); | |
124 log.RecordWindowEvent(MetricsLog::WINDOW_DESTROY, 0, -1); | |
125 log.CloseLog(); | |
126 | |
127 ASSERT_EQ(4, log.num_events()); | |
128 | |
129 int size = log.GetEncodedLogSize(); | |
130 ASSERT_GT(size, 0); | |
131 | |
132 std::string encoded; | |
133 // Leave room for the NUL terminator. | |
134 ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size)); | |
135 TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded); | |
136 NormalizeBuildtime(&encoded); | |
137 NormalizeBuildtime(&expected_output); | |
138 | |
139 ASSERT_EQ(expected_output, encoded); | |
140 } | |
141 | |
142 TEST(MetricsLogTest, LoadEvent) { | |
143 std::string expected_output = base::StringPrintf( | |
144 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | |
145 "appversion=\"%s\">\n" | |
146 " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" " | |
147 "origin=\"link\" session=\"0\" time=\"\"/>\n" | |
148 "</log>", MetricsLog::GetVersionString().c_str()); | |
149 | |
150 NoTimeMetricsLog log("bogus client ID", 0); | |
151 log.RecordLoadEvent(3, GURL("http://google.com"), | |
152 content::PAGE_TRANSITION_LINK, 1, | |
153 TimeDelta::FromMilliseconds(7219)); | |
154 | |
155 log.CloseLog(); | |
156 | |
157 ASSERT_EQ(1, log.num_events()); | |
158 | |
159 int size = log.GetEncodedLogSize(); | |
160 ASSERT_GT(size, 0); | |
161 | |
162 std::string encoded; | |
163 // Leave room for the NUL terminator. | |
164 ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size)); | |
165 TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded); | |
166 NormalizeBuildtime(&encoded); | |
167 NormalizeBuildtime(&expected_output); | |
168 | |
169 ASSERT_EQ(expected_output, encoded); | |
170 } | |
171 | 59 |
172 #if defined(OS_CHROMEOS) | 60 #if defined(OS_CHROMEOS) |
173 TEST(MetricsLogTest, ChromeOSLoadEvent) { | |
174 std::string expected_output = base::StringPrintf( | |
175 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | |
176 "appversion=\"%s\" hardwareclass=\"sample-class\">\n" | |
177 " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" " | |
178 "origin=\"link\" session=\"0\" time=\"\"/>\n" | |
179 "</log>", MetricsLog::GetVersionString().c_str()); | |
180 | |
181 NoTimeMetricsLog log("bogus client ID", 0); | |
182 log.RecordLoadEvent(3, GURL("http://google.com"), | |
183 content::PAGE_TRANSITION_LINK, 1, | |
184 TimeDelta::FromMilliseconds(7219)); | |
185 log.set_hardware_class("sample-class"); | |
186 log.CloseLog(); | |
187 | |
188 ASSERT_EQ(1, log.num_events()); | |
189 | |
190 int size = log.GetEncodedLogSize(); | |
191 ASSERT_GT(size, 0); | |
192 | |
193 std::string encoded; | |
194 // Leave room for the NUL terminator. | |
195 ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size)); | |
196 TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded); | |
197 NormalizeBuildtime(&encoded); | |
198 NormalizeBuildtime(&expected_output); | |
199 | |
200 ASSERT_EQ(expected_output, encoded); | |
201 } | |
202 | |
203 TEST(MetricsLogTest, ChromeOSStabilityData) { | 61 TEST(MetricsLogTest, ChromeOSStabilityData) { |
204 NoTimeMetricsLog log("bogus client ID", 0); | 62 NoTimeMetricsLog log("bogus client ID", 0); |
205 TestingPrefService prefs; | 63 TestingPrefService prefs; |
206 browser::RegisterLocalState(&prefs); | 64 browser::RegisterLocalState(&prefs); |
207 | 65 |
208 prefs.SetInteger(prefs::kStabilityChildProcessCrashCount, 10); | 66 prefs.SetInteger(prefs::kStabilityChildProcessCrashCount, 10); |
209 prefs.SetInteger(prefs::kStabilityOtherUserCrashCount, 11); | 67 prefs.SetInteger(prefs::kStabilityOtherUserCrashCount, 11); |
210 prefs.SetInteger(prefs::kStabilityKernelCrashCount, 12); | 68 prefs.SetInteger(prefs::kStabilityKernelCrashCount, 12); |
211 prefs.SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13); | 69 prefs.SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 13); |
| 70 |
| 71 std::vector<webkit::WebPluginInfo> plugins; |
| 72 |
212 std::string expected_output = base::StringPrintf( | 73 std::string expected_output = base::StringPrintf( |
213 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " | 74 "<log clientid=\"bogus client ID\" buildtime=\"123456789\" " |
214 "appversion=\"%s\">\n" | 75 "appversion=\"%s\">\n" |
215 "<stability stuff>\n", MetricsLog::GetVersionString().c_str()); | 76 "<stability stuff>\n", MetricsLog::GetVersionString().c_str()); |
216 // Expect 3 warnings about not yet being able to send the | 77 // Expect 3 warnings about not yet being able to send the |
217 // Chrome OS stability stats. | 78 // Chrome OS stability stats. |
218 log.WriteStabilityElement(&prefs); | 79 log.WriteStabilityElement(plugins, &prefs); |
219 log.CloseLog(); | 80 log.CloseLog(); |
220 | 81 |
221 int size = log.GetEncodedLogSize(); | 82 int size = log.GetEncodedLogSizeXml(); |
222 ASSERT_GT(size, 0); | 83 ASSERT_GT(size, 0); |
223 | 84 |
224 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityChildProcessCrashCount)); | 85 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityChildProcessCrashCount)); |
225 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityOtherUserCrashCount)); | 86 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityOtherUserCrashCount)); |
226 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityKernelCrashCount)); | 87 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilityKernelCrashCount)); |
227 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilitySystemUncleanShutdownCount)); | 88 EXPECT_EQ(0, prefs.GetInteger(prefs::kStabilitySystemUncleanShutdownCount)); |
228 | 89 |
229 std::string encoded; | 90 std::string encoded; |
230 // Leave room for the NUL terminator. | 91 // Leave room for the NUL terminator. |
231 bool encoding_result = log.GetEncodedLog( | 92 bool encoding_result = log.GetEncodedLogXml( |
232 WriteInto(&encoded, size + 1), size); | 93 WriteInto(&encoded, size + 1), size); |
233 ASSERT_TRUE(encoding_result); | 94 ASSERT_TRUE(encoding_result); |
234 | 95 |
235 // Check that we can find childprocesscrashcount, but not | 96 // Check that we can find childprocesscrashcount, but not |
236 // any of the ChromeOS ones that we are not emitting until log | 97 // any of the ChromeOS ones that we are not emitting until log |
237 // servers can handle them. | 98 // servers can handle them. |
238 EXPECT_NE(std::string::npos, | 99 EXPECT_NE(std::string::npos, |
239 encoded.find(" childprocesscrashcount=\"10\"")); | 100 encoded.find(" childprocesscrashcount=\"10\"")); |
240 EXPECT_EQ(std::string::npos, | 101 EXPECT_EQ(std::string::npos, |
241 encoded.find(" otherusercrashcount=")); | 102 encoded.find(" otherusercrashcount=")); |
242 EXPECT_EQ(std::string::npos, | 103 EXPECT_EQ(std::string::npos, |
243 encoded.find(" kernelcrashcount=")); | 104 encoded.find(" kernelcrashcount=")); |
244 EXPECT_EQ(std::string::npos, | 105 EXPECT_EQ(std::string::npos, |
245 encoded.find(" systemuncleanshutdowns=")); | 106 encoded.find(" systemuncleanshutdowns=")); |
246 } | 107 } |
247 | |
248 #endif // OS_CHROMEOS | 108 #endif // OS_CHROMEOS |
249 | |
250 // Make sure our ID hashes are the same as what we see on the server side. | |
251 TEST(MetricsLogTest, CreateHash) { | |
252 static const struct { | |
253 std::string input; | |
254 std::string output; | |
255 } cases[] = { | |
256 {"Back", "0x0557fa923dcee4d0"}, | |
257 {"Forward", "0x67d2f6740a8eaebf"}, | |
258 {"NewTab", "0x290eb683f96572f1"}, | |
259 }; | |
260 | |
261 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) { | |
262 std::string hash_string = MetricsLog::CreateHash(cases[i].input); | |
263 | |
264 // Convert to hex string | |
265 // We're only checking the first 8 bytes, because that's what | |
266 // the metrics server uses. | |
267 std::string hash_hex = "0x"; | |
268 for (size_t j = 0; j < 8; j++) { | |
269 base::StringAppendF(&hash_hex, "%02x", | |
270 static_cast<uint8>(hash_string.data()[j])); | |
271 } | |
272 EXPECT_EQ(cases[i].output, hash_hex); | |
273 } | |
274 }; | |
OLD | NEW |