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 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 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 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 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