blob: ffab06af85cdbfea44a7955b3be01d43188e72f5 [file] [log] [blame]
Ken Mixter03403162010-08-18 15:23:16 -07001// Copyright (c) 2010 The Chromium OS 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 <unistd.h>
6
7#include "base/file_util.h"
Ken Mixter04ec10f2010-08-26 16:02:02 -07008#include "base/string_util.h"
Ken Mixter03403162010-08-18 15:23:16 -07009#include "crash-reporter/crash_collector.h"
10#include "crash-reporter/system_logging_mock.h"
11#include "gflags/gflags.h"
12#include "gtest/gtest.h"
13
14void CountCrash() {
15 ADD_FAILURE();
16}
17
18bool IsMetrics() {
19 ADD_FAILURE();
20 return false;
21}
22
23class CrashCollectorTest : public ::testing::Test {
Ken Mixter04ec10f2010-08-26 16:02:02 -070024 public:
Ken Mixter03403162010-08-18 15:23:16 -070025 void SetUp() {
26 collector_.Initialize(CountCrash,
27 IsMetrics,
28 &logging_);
Ken Mixter04ec10f2010-08-26 16:02:02 -070029 test_dir_ = FilePath("test");
30 file_util::CreateDirectory(test_dir_);
Ken Mixter03403162010-08-18 15:23:16 -070031 }
Ken Mixter04ec10f2010-08-26 16:02:02 -070032
33 void TearDown() {
34 file_util::Delete(test_dir_, true);
35 }
36
37 bool CheckHasCapacity();
38
Ken Mixter03403162010-08-18 15:23:16 -070039 protected:
40 SystemLoggingMock logging_;
41 CrashCollector collector_;
Ken Mixter04ec10f2010-08-26 16:02:02 -070042 FilePath test_dir_;
Ken Mixter03403162010-08-18 15:23:16 -070043};
44
45TEST_F(CrashCollectorTest, Initialize) {
46 ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
47 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
48 ASSERT_TRUE(&logging_ == collector_.logger_);
49}
50
Ken Mixteree849c52010-09-30 15:30:10 -070051TEST_F(CrashCollectorTest, Sanitize) {
52 EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
53 EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
54 EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
55 EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
56 EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
57 EXPECT_EQ("", collector_.Sanitize(""));
58 EXPECT_EQ("_", collector_.Sanitize(" "));
59}
60
Ken Mixter03403162010-08-18 15:23:16 -070061TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
62 FilePath path;
63 const int kRootUid = 0;
64 const int kRootGid = 0;
65 const int kNtpUid = 5;
66 const int kChronosUid = 1000;
67 const int kChronosGid = 1001;
68 const mode_t kExpectedSystemMode = 01755;
69 const mode_t kExpectedUserMode = 0755;
70
71 mode_t directory_mode;
72 uid_t directory_owner;
73 gid_t directory_group;
74
75 path = collector_.GetCrashDirectoryInfo(kRootUid,
76 kChronosUid,
77 kChronosGid,
78 &directory_mode,
79 &directory_owner,
80 &directory_group);
81 EXPECT_EQ("/var/spool/crash", path.value());
82 EXPECT_EQ(kExpectedSystemMode, directory_mode);
83 EXPECT_EQ(kRootUid, directory_owner);
84 EXPECT_EQ(kRootGid, directory_group);
85
86 path = collector_.GetCrashDirectoryInfo(kNtpUid,
87 kChronosUid,
88 kChronosGid,
89 &directory_mode,
90 &directory_owner,
91 &directory_group);
92 EXPECT_EQ("/var/spool/crash", path.value());
93 EXPECT_EQ(kExpectedSystemMode, directory_mode);
94 EXPECT_EQ(kRootUid, directory_owner);
95 EXPECT_EQ(kRootGid, directory_group);
96
97 path = collector_.GetCrashDirectoryInfo(kChronosUid,
98 kChronosUid,
99 kChronosGid,
100 &directory_mode,
101 &directory_owner,
102 &directory_group);
103 EXPECT_EQ("/home/chronos/user/crash", path.value());
104 EXPECT_EQ(kExpectedUserMode, directory_mode);
105 EXPECT_EQ(kChronosUid, directory_owner);
106 EXPECT_EQ(kChronosGid, directory_group);
107}
108
109TEST_F(CrashCollectorTest, FormatDumpBasename) {
110 struct tm tm = {0};
111 tm.tm_sec = 15;
112 tm.tm_min = 50;
113 tm.tm_hour = 13;
114 tm.tm_mday = 23;
115 tm.tm_mon = 4;
116 tm.tm_year = 110;
117 tm.tm_isdst = -1;
118 std::string basename =
119 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
120 ASSERT_EQ("foo.20100523.135015.100", basename);
121}
122
Ken Mixter04ec10f2010-08-26 16:02:02 -0700123bool CrashCollectorTest::CheckHasCapacity() {
124 static const char kFullMessage[] = "Crash directory test already full";
125 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
126 bool has_message = (logging_.log().find(kFullMessage) != std::string::npos);
127 EXPECT_EQ(has_message, !has_capacity);
128 return has_capacity;
129}
130
Ken Mixteree849c52010-09-30 15:30:10 -0700131TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
132 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700133 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixter04ec10f2010-08-26 16:02:02 -0700134 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)),
135 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700136 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700137 }
138
Ken Mixteree849c52010-09-30 15:30:10 -0700139 // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
140 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
141 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)),
142 "", 0);
143 EXPECT_TRUE(CheckHasCapacity());
144 }
145
146 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700147 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700148 file_util::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)),
149 "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700150 EXPECT_FALSE(CheckHasCapacity());
151 }
152}
153
Ken Mixteree849c52010-09-30 15:30:10 -0700154TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
155 // Test kMaxCrashDirectorySize - 1 files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700156 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700157 file_util::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)),
Ken Mixter04ec10f2010-08-26 16:02:02 -0700158 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700159 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700160 }
Ken Mixteree849c52010-09-30 15:30:10 -0700161 file_util::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700162 EXPECT_FALSE(CheckHasCapacity());
163}
164
Ken Mixteree849c52010-09-30 15:30:10 -0700165TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
166 // Test many files with different extensions and same base fit.
167 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
168 file_util::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
169 EXPECT_TRUE(CheckHasCapacity());
170 }
171 // Test dot files are treated as individual files.
172 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
173 file_util::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
174 EXPECT_TRUE(CheckHasCapacity());
175 }
176 file_util::WriteFile(test_dir_.Append("normal.meta"), "", 0);
177 EXPECT_FALSE(CheckHasCapacity());
178}
179
180TEST_F(CrashCollectorTest, ReadKeyValueFile) {
181 const char *contents = ("a=b\n"
182 "\n"
183 " c=d \n");
184 FilePath path(test_dir_.Append("keyval"));
185 std::map<std::string, std::string> dictionary;
186 std::map<std::string, std::string>::iterator i;
187
188 file_util::WriteFile(path, contents, strlen(contents));
189
190 EXPECT_TRUE(collector_.ReadKeyValueFile(path, '=', &dictionary));
191 i = dictionary.find("a");
192 EXPECT_TRUE(i != dictionary.end() && i->second == "b");
193 i = dictionary.find("c");
194 EXPECT_TRUE(i != dictionary.end() && i->second == "d");
195
196 dictionary.clear();
197
198 contents = ("a=b c d\n"
199 "e\n"
200 " f g = h\n"
201 "i=j\n"
202 "=k\n"
203 "l=\n");
204 file_util::WriteFile(path, contents, strlen(contents));
205
206 EXPECT_FALSE(collector_.ReadKeyValueFile(path, '=', &dictionary));
207 i = dictionary.find("a");
208 EXPECT_TRUE(i != dictionary.end() && i->second == "b c d");
209 i = dictionary.find("e");
210 EXPECT_TRUE(i == dictionary.end());
211 i = dictionary.find("f g");
212 EXPECT_TRUE(i != dictionary.end() && i->second == "h");
213 i = dictionary.find("i");
214 EXPECT_TRUE(i != dictionary.end() && i->second == "j");
215 i = dictionary.find("");
216 EXPECT_TRUE(i != dictionary.end() && i->second == "k");
217 i = dictionary.find("l");
218 EXPECT_TRUE(i != dictionary.end() && i->second == "");
219}
220
Ken Mixterafcf8082010-10-26 14:45:01 -0700221TEST_F(CrashCollectorTest, MetaData) {
222 FilePath meta_file = test_dir_.Append("generated.meta");
223 FilePath lsb_release = test_dir_.Append("lsb-release");
224 FilePath payload_file = test_dir_.Append("payload-file");
225 std::string contents;
226 collector_.lsb_release_ = lsb_release.value().c_str();
227 const char kLsbContents[] = "CHROMEOS_RELEASE_VERSION=version\n";
228 ASSERT_TRUE(
229 file_util::WriteFile(lsb_release,
230 kLsbContents, strlen(kLsbContents)));
231 const char kPayload[] = "foo";
232 ASSERT_TRUE(
233 file_util::WriteFile(payload_file,
234 kPayload, strlen(kPayload)));
235 collector_.AddCrashMetaData("foo", "bar");
236 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
237 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents));
238 EXPECT_EQ("foo=bar\n"
239 "exec_name=kernel\n"
240 "ver=version\n"
241 "payload_size=3\n"
242 "done=1\n", contents);
243}
244
Ken Mixter03403162010-08-18 15:23:16 -0700245int main(int argc, char **argv) {
246 ::testing::InitGoogleTest(&argc, argv);
247 return RUN_ALL_TESTS();
248}