external_metrics_unittest.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2009 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 <errno.h>
6#include <sys/file.h>
7
8#include "base/basictypes.h"
9#include "base/hash_tables.h"
10#include "base/scoped_ptr.h"
11#include "chrome/browser/chromeos/external_metrics.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace chromeos {  // Need this because of the FRIEND_TEST
15
16class ExternalMetricsTest : public testing::Test {
17};
18
19// Because the metrics service is not essential, errors will not cause the
20// program to terminate.  However, the errors produce logs.
21
22#define MAXLENGTH ExternalMetrics::kMetricsMessageMaxLength
23
24static void SendMessage(const char* path, const char* name, const char* value) {
25  int fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0666);
26  int32 l = strlen(name) + strlen(value) + 2 + sizeof(l);
27  int num_bytes;
28  num_bytes = write(fd, &l, sizeof(l));
29  num_bytes = write(fd, name, strlen(name) + 1);
30  num_bytes = write(fd, value, strlen(value) + 1);
31  close(fd);
32}
33
34static scoped_ptr<std::string> received_name;
35static scoped_ptr<std::string> received_value;
36int received_count = 0;
37
38static void ReceiveMessage(const char* name, const char* value) {
39  received_name.reset(new std::string(name));
40  received_value.reset(new std::string(value));
41  received_count++;
42}
43
44static void CheckMessage(const char* name, const char* value, int count) {
45  EXPECT_EQ(*received_name.get(), name);
46  EXPECT_EQ(*received_value.get(), value);
47  EXPECT_EQ(received_count, count);
48}
49
50TEST(ExternalMetricsTest, ParseExternalMetricsFile) {
51  const char *histogram_data[] = {
52    "BootTime 9500 0 20000 50",
53    "BootTime 10000 0 20000 50",
54    "BootTime 9200 0 20000 50",
55    "ConnmanIdle 1000 0 2000 20",
56    "ConnmanIdle 1200 0 2000 20",
57    "ConnmanDisconnect 1000 0 2000 20",
58    "ConnmanFailure 1000 0 2000 20",
59    "ConnmanFailure 13000 2000 20",
60    "ConnmanAssociation 1000 0 2000 20",
61    "ConnmanConfiguration 1000 0 2000 20",
62    "ConnmanOffline 1000 0 2000 20",
63    "ConnmanOnline 1000 0 2000 20",
64    "ConnmanOffline 2000 0 2000 20",
65    "ConnmanReady 33000 0 100000 50",
66    "ConnmanReady 44000 0 100000 50",
67    "ConnmanReady 22000 0 100000 50",
68  };
69  int nhist = ARRAYSIZE_UNSAFE(histogram_data);
70  int32 i;
71  const char* path = "/tmp/.chromeos-metrics";
72  scoped_refptr<chromeos::ExternalMetrics>
73      external_metrics(new chromeos::ExternalMetrics());
74  external_metrics->test_recorder_ = &ReceiveMessage;
75  external_metrics->test_path_ = FilePath(path);
76  EXPECT_TRUE(unlink(path) == 0 || errno == ENOENT);
77
78  // Sends a few valid messages.  Once in a while, collects them and checks the
79  // last message.  We don't want to check every single message because we also
80  // want to test the ability to deal with a file containing more than one
81  // message.
82  for (i = 0; i < nhist; i++) {
83    SendMessage(path, "histogram", histogram_data[i]);
84    if (i % 3 == 2) {
85      external_metrics->CollectEvents();
86      CheckMessage("histogram", histogram_data[i], i + 1);
87    }
88  }
89
90  // Sends a crash message.
91  int expect_count = nhist;
92  SendMessage(path, "crash", "user");
93  external_metrics->CollectEvents();
94  CheckMessage("crash", "user", ++expect_count);
95
96  // Sends a message that's too large.
97  char b[MAXLENGTH + 100];
98  for (i = 0; i < MAXLENGTH + 99; i++) {
99    b[i] = 'x';
100  }
101  b[i] = '\0';
102  SendMessage(path, b, "yyy");
103  // Expect logged errors about bad message size.
104  external_metrics->CollectEvents();
105  EXPECT_EQ(expect_count, received_count);
106
107  // Sends a malformed message (first string is not null-terminated).
108  i = 100 + sizeof(i);
109  int fd = open(path, O_CREAT | O_WRONLY, 0666);
110  EXPECT_GT(fd, 0);
111  EXPECT_EQ(static_cast<int>(sizeof(i)), write(fd, &i, sizeof(i)));
112  EXPECT_EQ(i, write(fd, b, i));
113  EXPECT_EQ(0, close(fd));
114
115  external_metrics->CollectEvents();
116  EXPECT_EQ(expect_count, received_count);
117
118  // Sends a malformed message (second string is not null-terminated).
119  b[50] = '\0';
120  fd = open(path, O_CREAT | O_WRONLY, 0666);
121  EXPECT_GT(fd, 0);
122  EXPECT_EQ(static_cast<int>(sizeof(i)), write(fd, &i, sizeof(i)));
123  EXPECT_EQ(i, write(fd, b, i));
124  EXPECT_EQ(0, close(fd));
125
126  external_metrics->CollectEvents();
127  EXPECT_EQ(expect_count, received_count);
128
129  // Checks that we survive when file doesn't exist.
130  EXPECT_EQ(0, unlink(path));
131  external_metrics->CollectEvents();
132  EXPECT_EQ(expect_count, received_count);
133}
134
135}  // namespace chromeos
136