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
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/memory/scoped_ptr.h"
11 #include "chrome/browser/chromeos/external_metrics.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace chromeos { // Need this because of the FRIEND_TEST
15
16 class 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
SendMessage(const char * path,const char * name,const char * value)24 static 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
34 static scoped_ptr<std::string> received_name;
35 static scoped_ptr<std::string> received_value;
36 int received_count = 0;
37
ReceiveMessage(const char * name,const char * value)38 static 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
CheckMessage(const char * name,const char * value,int count)44 static 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
TEST(ExternalMetricsTest,ParseExternalMetricsFile)50 TEST(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