blob: d98e1af97a21d8e15263105ca155f06a6776de4d [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 Mixtera3249322011-03-03 08:47:38 -08009#include "chromeos/syslog_logging.h"
10#include "chromeos/test_helpers.h"
Ken Mixter03403162010-08-18 15:23:16 -070011#include "crash-reporter/crash_collector.h"
Ken Mixter03403162010-08-18 15:23:16 -070012#include "gflags/gflags.h"
13#include "gtest/gtest.h"
14
Ken Mixter9b346472010-11-07 13:45:45 -080015// This test assumes the following standard binaries are installed.
16static const char kBinBash[] = "/bin/bash";
17static const char kBinCp[] = "/bin/cp";
18static const char kBinEcho[] = "/bin/echo";
19static const char kBinFalse[] = "/bin/false";
20
Ken Mixtera3249322011-03-03 08:47:38 -080021using chromeos::FindLog;
22
Ken Mixter03403162010-08-18 15:23:16 -070023void CountCrash() {
24 ADD_FAILURE();
25}
26
27bool IsMetrics() {
28 ADD_FAILURE();
29 return false;
30}
31
32class CrashCollectorTest : public ::testing::Test {
Ken Mixter04ec10f2010-08-26 16:02:02 -070033 public:
Ken Mixter03403162010-08-18 15:23:16 -070034 void SetUp() {
35 collector_.Initialize(CountCrash,
Ken Mixtera3249322011-03-03 08:47:38 -080036 IsMetrics);
Ken Mixter04ec10f2010-08-26 16:02:02 -070037 test_dir_ = FilePath("test");
38 file_util::CreateDirectory(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -080039 chromeos::ClearLog();
Ken Mixter03403162010-08-18 15:23:16 -070040 }
Ken Mixter04ec10f2010-08-26 16:02:02 -070041
42 void TearDown() {
43 file_util::Delete(test_dir_, true);
44 }
45
46 bool CheckHasCapacity();
47
Ken Mixter03403162010-08-18 15:23:16 -070048 protected:
Ken Mixter03403162010-08-18 15:23:16 -070049 CrashCollector collector_;
Ken Mixter04ec10f2010-08-26 16:02:02 -070050 FilePath test_dir_;
Ken Mixter03403162010-08-18 15:23:16 -070051};
52
53TEST_F(CrashCollectorTest, Initialize) {
54 ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
55 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
Ken Mixter03403162010-08-18 15:23:16 -070056}
57
Ken Mixter9b346472010-11-07 13:45:45 -080058TEST_F(CrashCollectorTest, WriteNewFile) {
59 FilePath test_file = test_dir_.Append("test_new");
60 const char kBuffer[] = "buffer";
61 EXPECT_EQ(strlen(kBuffer),
62 collector_.WriteNewFile(test_file,
63 kBuffer,
64 strlen(kBuffer)));
65 EXPECT_LT(collector_.WriteNewFile(test_file,
66 kBuffer,
67 strlen(kBuffer)), 0);
68}
69
Ken Mixteree849c52010-09-30 15:30:10 -070070TEST_F(CrashCollectorTest, Sanitize) {
71 EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
72 EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
73 EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
74 EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
75 EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
76 EXPECT_EQ("", collector_.Sanitize(""));
77 EXPECT_EQ("_", collector_.Sanitize(" "));
78}
79
Ken Mixter03403162010-08-18 15:23:16 -070080TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
81 FilePath path;
82 const int kRootUid = 0;
83 const int kRootGid = 0;
84 const int kNtpUid = 5;
85 const int kChronosUid = 1000;
86 const int kChronosGid = 1001;
87 const mode_t kExpectedSystemMode = 01755;
88 const mode_t kExpectedUserMode = 0755;
89
90 mode_t directory_mode;
91 uid_t directory_owner;
92 gid_t directory_group;
93
94 path = collector_.GetCrashDirectoryInfo(kRootUid,
95 kChronosUid,
96 kChronosGid,
97 &directory_mode,
98 &directory_owner,
99 &directory_group);
100 EXPECT_EQ("/var/spool/crash", path.value());
101 EXPECT_EQ(kExpectedSystemMode, directory_mode);
102 EXPECT_EQ(kRootUid, directory_owner);
103 EXPECT_EQ(kRootGid, directory_group);
104
105 path = collector_.GetCrashDirectoryInfo(kNtpUid,
106 kChronosUid,
107 kChronosGid,
108 &directory_mode,
109 &directory_owner,
110 &directory_group);
111 EXPECT_EQ("/var/spool/crash", path.value());
112 EXPECT_EQ(kExpectedSystemMode, directory_mode);
113 EXPECT_EQ(kRootUid, directory_owner);
114 EXPECT_EQ(kRootGid, directory_group);
115
116 path = collector_.GetCrashDirectoryInfo(kChronosUid,
117 kChronosUid,
118 kChronosGid,
119 &directory_mode,
120 &directory_owner,
121 &directory_group);
122 EXPECT_EQ("/home/chronos/user/crash", path.value());
123 EXPECT_EQ(kExpectedUserMode, directory_mode);
124 EXPECT_EQ(kChronosUid, directory_owner);
125 EXPECT_EQ(kChronosGid, directory_group);
126}
127
128TEST_F(CrashCollectorTest, FormatDumpBasename) {
129 struct tm tm = {0};
130 tm.tm_sec = 15;
131 tm.tm_min = 50;
132 tm.tm_hour = 13;
133 tm.tm_mday = 23;
134 tm.tm_mon = 4;
135 tm.tm_year = 110;
136 tm.tm_isdst = -1;
137 std::string basename =
138 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
139 ASSERT_EQ("foo.20100523.135015.100", basename);
140}
141
Ken Mixter207694d2010-10-28 15:42:37 -0700142TEST_F(CrashCollectorTest, GetCrashPath) {
143 EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
144 collector_.GetCrashPath(FilePath("/var/spool/crash"),
145 "myprog.20100101.1200.1234",
146 "core").value());
147 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
148 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
149 "chrome.20100101.1200.1234",
150 "dmp").value());
151}
152
153
Ken Mixter04ec10f2010-08-26 16:02:02 -0700154bool CrashCollectorTest::CheckHasCapacity() {
155 static const char kFullMessage[] = "Crash directory test already full";
156 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -0800157 bool has_message = FindLog(kFullMessage);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700158 EXPECT_EQ(has_message, !has_capacity);
159 return has_capacity;
160}
161
Ken Mixteree849c52010-09-30 15:30:10 -0700162TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
163 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700164 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixter04ec10f2010-08-26 16:02:02 -0700165 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)),
166 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700167 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700168 }
169
Ken Mixteree849c52010-09-30 15:30:10 -0700170 // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
171 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
172 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)),
173 "", 0);
174 EXPECT_TRUE(CheckHasCapacity());
175 }
176
177 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700178 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700179 file_util::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)),
180 "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700181 EXPECT_FALSE(CheckHasCapacity());
182 }
183}
184
Ken Mixteree849c52010-09-30 15:30:10 -0700185TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
186 // Test kMaxCrashDirectorySize - 1 files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700187 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700188 file_util::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)),
Ken Mixter04ec10f2010-08-26 16:02:02 -0700189 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700190 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700191 }
Ken Mixteree849c52010-09-30 15:30:10 -0700192 file_util::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700193 EXPECT_FALSE(CheckHasCapacity());
194}
195
Ken Mixteree849c52010-09-30 15:30:10 -0700196TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
197 // Test many files with different extensions and same base fit.
198 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
199 file_util::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
200 EXPECT_TRUE(CheckHasCapacity());
201 }
202 // Test dot files are treated as individual files.
203 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
204 file_util::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
205 EXPECT_TRUE(CheckHasCapacity());
206 }
207 file_util::WriteFile(test_dir_.Append("normal.meta"), "", 0);
208 EXPECT_FALSE(CheckHasCapacity());
209}
210
Ken Mixterc49dbd42010-12-14 17:44:11 -0800211TEST_F(CrashCollectorTest, IsCommentLine) {
212 EXPECT_FALSE(CrashCollector::IsCommentLine(""));
213 EXPECT_TRUE(CrashCollector::IsCommentLine("#"));
214 EXPECT_TRUE(CrashCollector::IsCommentLine("#real comment"));
215 EXPECT_TRUE(CrashCollector::IsCommentLine(" # real comment"));
216 EXPECT_FALSE(CrashCollector::IsCommentLine("not comment"));
217 EXPECT_FALSE(CrashCollector::IsCommentLine(" not comment"));
218}
219
Ken Mixteree849c52010-09-30 15:30:10 -0700220TEST_F(CrashCollectorTest, ReadKeyValueFile) {
221 const char *contents = ("a=b\n"
222 "\n"
223 " c=d \n");
224 FilePath path(test_dir_.Append("keyval"));
225 std::map<std::string, std::string> dictionary;
226 std::map<std::string, std::string>::iterator i;
227
228 file_util::WriteFile(path, contents, strlen(contents));
229
230 EXPECT_TRUE(collector_.ReadKeyValueFile(path, '=', &dictionary));
231 i = dictionary.find("a");
232 EXPECT_TRUE(i != dictionary.end() && i->second == "b");
233 i = dictionary.find("c");
234 EXPECT_TRUE(i != dictionary.end() && i->second == "d");
235
236 dictionary.clear();
237
238 contents = ("a=b c d\n"
239 "e\n"
240 " f g = h\n"
241 "i=j\n"
242 "=k\n"
Ken Mixterc49dbd42010-12-14 17:44:11 -0800243 "#comment=0\n"
Ken Mixteree849c52010-09-30 15:30:10 -0700244 "l=\n");
245 file_util::WriteFile(path, contents, strlen(contents));
246
247 EXPECT_FALSE(collector_.ReadKeyValueFile(path, '=', &dictionary));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800248 EXPECT_EQ(5, dictionary.size());
249
Ken Mixteree849c52010-09-30 15:30:10 -0700250 i = dictionary.find("a");
251 EXPECT_TRUE(i != dictionary.end() && i->second == "b c d");
252 i = dictionary.find("e");
253 EXPECT_TRUE(i == dictionary.end());
254 i = dictionary.find("f g");
255 EXPECT_TRUE(i != dictionary.end() && i->second == "h");
256 i = dictionary.find("i");
257 EXPECT_TRUE(i != dictionary.end() && i->second == "j");
258 i = dictionary.find("");
259 EXPECT_TRUE(i != dictionary.end() && i->second == "k");
260 i = dictionary.find("l");
261 EXPECT_TRUE(i != dictionary.end() && i->second == "");
262}
263
Ken Mixterafcf8082010-10-26 14:45:01 -0700264TEST_F(CrashCollectorTest, MetaData) {
Ken Mixter9b346472010-11-07 13:45:45 -0800265 const char kMetaFileBasename[] = "generated.meta";
266 FilePath meta_file = test_dir_.Append(kMetaFileBasename);
Ken Mixterafcf8082010-10-26 14:45:01 -0700267 FilePath lsb_release = test_dir_.Append("lsb-release");
268 FilePath payload_file = test_dir_.Append("payload-file");
269 std::string contents;
270 collector_.lsb_release_ = lsb_release.value().c_str();
271 const char kLsbContents[] = "CHROMEOS_RELEASE_VERSION=version\n";
272 ASSERT_TRUE(
273 file_util::WriteFile(lsb_release,
274 kLsbContents, strlen(kLsbContents)));
275 const char kPayload[] = "foo";
276 ASSERT_TRUE(
277 file_util::WriteFile(payload_file,
278 kPayload, strlen(kPayload)));
279 collector_.AddCrashMetaData("foo", "bar");
280 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
281 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800282 const char kExpectedMeta[] =
283 "foo=bar\n"
284 "exec_name=kernel\n"
285 "ver=version\n"
286 "payload=test/payload-file\n"
287 "payload_size=3\n"
288 "done=1\n";
289 EXPECT_EQ(kExpectedMeta, contents);
290
291 // Test target of symlink is not overwritten.
292 payload_file = test_dir_.Append("payload2-file");
293 ASSERT_TRUE(
294 file_util::WriteFile(payload_file,
295 kPayload, strlen(kPayload)));
296 FilePath meta_symlink_path = test_dir_.Append("symlink.meta");
297 ASSERT_EQ(0,
298 symlink(kMetaFileBasename,
299 meta_symlink_path.value().c_str()));
300 ASSERT_TRUE(file_util::PathExists(meta_symlink_path));
Ken Mixtera3249322011-03-03 08:47:38 -0800301 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800302 collector_.WriteCrashMetaData(meta_symlink_path,
303 "kernel",
304 payload_file.value());
Ken Mixtera3249322011-03-03 08:47:38 -0800305 // Target metadata contents should have stayed the same.
Ken Mixter9b346472010-11-07 13:45:45 -0800306 contents.clear();
307 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents));
308 EXPECT_EQ(kExpectedMeta, contents);
Ken Mixtera3249322011-03-03 08:47:38 -0800309 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixter9b346472010-11-07 13:45:45 -0800310
311 // Test target of dangling symlink is not created.
312 file_util::Delete(meta_file, false);
313 ASSERT_FALSE(file_util::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800314 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800315 collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
316 payload_file.value());
317 EXPECT_FALSE(file_util::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800318 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixterafcf8082010-10-26 14:45:01 -0700319}
320
Ken Mixterc49dbd42010-12-14 17:44:11 -0800321TEST_F(CrashCollectorTest, GetLogContents) {
322 FilePath config_file = test_dir_.Append("crash_config");
323 FilePath output_file = test_dir_.Append("crash_log");
324 const char kConfigContents[] =
325 "foobar:echo hello there | sed -e \"s/there/world/\"";
326 ASSERT_TRUE(
327 file_util::WriteFile(config_file,
328 kConfigContents, strlen(kConfigContents)));
Ken Mixter1b8fe012011-01-25 13:33:05 -0800329 file_util::Delete(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800330 EXPECT_FALSE(collector_.GetLogContents(config_file,
331 "barfoo",
332 output_file));
333 EXPECT_FALSE(file_util::PathExists(output_file));
Ken Mixter1b8fe012011-01-25 13:33:05 -0800334 file_util::Delete(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800335 EXPECT_TRUE(collector_.GetLogContents(config_file,
336 "foobar",
337 output_file));
338 ASSERT_TRUE(file_util::PathExists(output_file));
339 std::string contents;
340 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents));
341 EXPECT_EQ("hello world\n", contents);
342}
343
Ken Mixter03403162010-08-18 15:23:16 -0700344int main(int argc, char **argv) {
Ken Mixtera3249322011-03-03 08:47:38 -0800345 SetUpTests(&argc, argv, false);
Ken Mixter03403162010-08-18 15:23:16 -0700346 return RUN_ALL_TESTS();
347}