metrics_log_unittest.cc revision 4a5e2dc747d50c653511c68ccb2cfbfb740bd5a7
1// Copyright (c) 2006-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 <string>
6
7#include "base/string_util.h"
8#include "base/time.h"
9#include "chrome/browser/metrics/metrics_log.h"
10#include "googleurl/src/gurl.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13using base::TimeDelta;
14
15namespace {
16  class MetricsLogTest : public testing::Test {
17  };
18};
19
20
21// Since buildtime is highly variable, this function will scan an output log and
22// replace it with a consistent number.
23static void NormalizeBuildtime(std::string* xml_encoded) {
24  std::string prefix = "buildtime=\"";
25  const char postfix = '\"';
26  size_t offset = xml_encoded->find(prefix);
27  ASSERT_GT(offset, 0u);
28  offset += prefix.size();
29  size_t postfix_position = xml_encoded->find(postfix, offset);
30  ASSERT_GT(postfix_position, offset);
31  for (size_t i = offset; i < postfix_position; ++i) {
32    char digit = xml_encoded->at(i);
33    ASSERT_GE(digit, '0');
34    ASSERT_LE(digit, '9');
35  }
36
37  // Insert a single fake buildtime.
38  xml_encoded->replace(offset, postfix_position - offset, "123246");
39}
40
41TEST(MetricsLogTest, EmptyRecord) {
42  std::string expected_output = StringPrintf(
43      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
44      "appversion=\"%s\"/>", MetricsLog::GetVersionString().c_str());
45
46  MetricsLog log("bogus client ID", 0);
47  log.CloseLog();
48
49  int size = log.GetEncodedLogSize();
50  ASSERT_GT(size, 0);
51
52  std::string encoded;
53  // Leave room for the NUL terminator.
54  ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size));
55  TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded);
56  NormalizeBuildtime(&encoded);
57  NormalizeBuildtime(&expected_output);
58
59  ASSERT_EQ(expected_output, encoded);
60}
61
62#if defined(OS_CHROMEOS)
63TEST(MetricsLogTest, ChromeOSEmptyRecord) {
64  std::string expected_output = StringPrintf(
65      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
66      "appversion=\"%s\" hardwareclass=\"sample-class\"/>",
67      MetricsLog::GetVersionString().c_str());
68
69  MetricsLog log("bogus client ID", 0);
70  log.set_hardware_class("sample-class");
71  log.CloseLog();
72
73  int size = log.GetEncodedLogSize();
74  ASSERT_GT(size, 0);
75
76  std::string encoded;
77  // Leave room for the NUL terminator.
78  ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size));
79  TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded);
80  NormalizeBuildtime(&encoded);
81  NormalizeBuildtime(&expected_output);
82
83  ASSERT_EQ(expected_output, encoded);
84}
85#endif  // OS_CHROMEOS
86
87namespace {
88
89class NoTimeMetricsLog : public MetricsLog {
90 public:
91  NoTimeMetricsLog(std::string client_id, int session_id):
92      MetricsLog(client_id, session_id) {}
93  virtual ~NoTimeMetricsLog() {}
94
95  // Override this so that output is testable.
96  virtual std::string GetCurrentTimeString() {
97    return std::string();
98  }
99};
100
101};  // namespace
102
103TEST(MetricsLogTest, WindowEvent) {
104  std::string expected_output = StringPrintf(
105      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
106          "appversion=\"%s\">\n"
107      " <window action=\"create\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
108      " <window action=\"open\" windowid=\"1\" parent=\"0\" "
109          "session=\"0\" time=\"\"/>\n"
110      " <window action=\"close\" windowid=\"1\" parent=\"0\" "
111          "session=\"0\" time=\"\"/>\n"
112      " <window action=\"destroy\" windowid=\"0\" session=\"0\" time=\"\"/>\n"
113      "</log>", MetricsLog::GetVersionString().c_str());
114
115  NoTimeMetricsLog log("bogus client ID", 0);
116  log.RecordWindowEvent(MetricsLog::WINDOW_CREATE, 0, -1);
117  log.RecordWindowEvent(MetricsLog::WINDOW_OPEN, 1, 0);
118  log.RecordWindowEvent(MetricsLog::WINDOW_CLOSE, 1, 0);
119  log.RecordWindowEvent(MetricsLog::WINDOW_DESTROY, 0, -1);
120  log.CloseLog();
121
122  ASSERT_EQ(4, log.num_events());
123
124  int size = log.GetEncodedLogSize();
125  ASSERT_GT(size, 0);
126
127  std::string encoded;
128  // Leave room for the NUL terminator.
129  ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size));
130  TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded);
131  NormalizeBuildtime(&encoded);
132  NormalizeBuildtime(&expected_output);
133
134  ASSERT_EQ(expected_output, encoded);
135}
136
137TEST(MetricsLogTest, LoadEvent) {
138  std::string expected_output = StringPrintf(
139      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
140          "appversion=\"%s\">\n"
141      " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" "
142          "origin=\"link\" session=\"0\" time=\"\"/>\n"
143      "</log>", MetricsLog::GetVersionString().c_str());
144
145  NoTimeMetricsLog log("bogus client ID", 0);
146  log.RecordLoadEvent(3, GURL("http://google.com"), PageTransition::LINK,
147                      1, TimeDelta::FromMilliseconds(7219));
148
149  log.CloseLog();
150
151  ASSERT_EQ(1, log.num_events());
152
153  int size = log.GetEncodedLogSize();
154  ASSERT_GT(size, 0);
155
156  std::string encoded;
157  // Leave room for the NUL terminator.
158  ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size));
159  TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded);
160  NormalizeBuildtime(&encoded);
161  NormalizeBuildtime(&expected_output);
162
163  ASSERT_EQ(expected_output, encoded);
164}
165
166#if defined(OS_CHROMEOS)
167TEST(MetricsLogTest, ChromeOSLoadEvent) {
168  std::string expected_output = StringPrintf(
169      "<log clientid=\"bogus client ID\" buildtime=\"123456789\" "
170          "appversion=\"%s\" hardwareclass=\"sample-class\">\n"
171      " <document action=\"load\" docid=\"1\" window=\"3\" loadtime=\"7219\" "
172          "origin=\"link\" session=\"0\" time=\"\"/>\n"
173      "</log>", MetricsLog::GetVersionString().c_str());
174
175  NoTimeMetricsLog log("bogus client ID", 0);
176  log.RecordLoadEvent(3, GURL("http://google.com"), PageTransition::LINK,
177                      1, TimeDelta::FromMilliseconds(7219));
178  log.set_hardware_class("sample-class");
179  log.CloseLog();
180
181  ASSERT_EQ(1, log.num_events());
182
183  int size = log.GetEncodedLogSize();
184  ASSERT_GT(size, 0);
185
186  std::string encoded;
187  // Leave room for the NUL terminator.
188  ASSERT_TRUE(log.GetEncodedLog(WriteInto(&encoded, size + 1), size));
189  TrimWhitespaceASCII(encoded, TRIM_ALL, &encoded);
190  NormalizeBuildtime(&encoded);
191  NormalizeBuildtime(&expected_output);
192
193  ASSERT_EQ(expected_output, encoded);
194}
195#endif  // OS_CHROMEOS
196
197// Make sure our ID hashes are the same as what we see on the server side.
198TEST(MetricsLogTest, CreateHash) {
199  static const struct {
200    std::string input;
201    std::string output;
202  } cases[] = {
203    {"Back", "0x0557fa923dcee4d0"},
204    {"Forward", "0x67d2f6740a8eaebf"},
205    {"NewTab", "0x290eb683f96572f1"},
206  };
207
208  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); i++) {
209    std::string hash_string = MetricsLog::CreateHash(cases[i].input);
210
211    // Convert to hex string
212    // We're only checking the first 8 bytes, because that's what
213    // the metrics server uses.
214    std::string hash_hex = "0x";
215    for (size_t j = 0; j < 8; j++) {
216      base::StringAppendF(&hash_hex, "%02x",
217                          static_cast<uint8>(hash_string.data()[j]));
218    }
219    EXPECT_EQ(cases[i].output, hash_hex);
220  }
221};
222