blob: fff22b53fa162f4e61d204ea305f6a74c12d34e2 [file] [log] [blame]
Mike Frysinger57b261c2012-04-11 14:47:09 -04001// Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Ken Mixter03403162010-08-18 15:23:16 -07002// 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"
Mike Frysinger57b261c2012-04-11 14:47:09 -04009#include "base/stringprintf.h"
Ken Mixtera3249322011-03-03 08:47:38 -080010#include "chromeos/syslog_logging.h"
11#include "chromeos/test_helpers.h"
Ken Mixter03403162010-08-18 15:23:16 -070012#include "crash-reporter/crash_collector.h"
Ken Mixter03403162010-08-18 15:23:16 -070013#include "gflags/gflags.h"
14#include "gtest/gtest.h"
15
Ken Mixter9b346472010-11-07 13:45:45 -080016// This test assumes the following standard binaries are installed.
17static const char kBinBash[] = "/bin/bash";
18static const char kBinCp[] = "/bin/cp";
19static const char kBinEcho[] = "/bin/echo";
20static const char kBinFalse[] = "/bin/false";
21
Simon Que9f90aca2013-02-19 17:19:52 -080022using base::FilePath;
Ken Mixtera3249322011-03-03 08:47:38 -080023using chromeos::FindLog;
24
Ken Mixter03403162010-08-18 15:23:16 -070025void CountCrash() {
26 ADD_FAILURE();
27}
28
29bool IsMetrics() {
30 ADD_FAILURE();
31 return false;
32}
33
34class CrashCollectorTest : public ::testing::Test {
Ken Mixter04ec10f2010-08-26 16:02:02 -070035 public:
Ken Mixter03403162010-08-18 15:23:16 -070036 void SetUp() {
37 collector_.Initialize(CountCrash,
Ken Mixtera3249322011-03-03 08:47:38 -080038 IsMetrics);
Ken Mixter04ec10f2010-08-26 16:02:02 -070039 test_dir_ = FilePath("test");
40 file_util::CreateDirectory(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -080041 chromeos::ClearLog();
Ken Mixter03403162010-08-18 15:23:16 -070042 }
Ken Mixter04ec10f2010-08-26 16:02:02 -070043
44 void TearDown() {
45 file_util::Delete(test_dir_, true);
46 }
47
48 bool CheckHasCapacity();
49
Ken Mixter03403162010-08-18 15:23:16 -070050 protected:
Ken Mixter03403162010-08-18 15:23:16 -070051 CrashCollector collector_;
Ken Mixter04ec10f2010-08-26 16:02:02 -070052 FilePath test_dir_;
Ken Mixter03403162010-08-18 15:23:16 -070053};
54
55TEST_F(CrashCollectorTest, Initialize) {
56 ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
57 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
Ken Mixter03403162010-08-18 15:23:16 -070058}
59
Ken Mixter9b346472010-11-07 13:45:45 -080060TEST_F(CrashCollectorTest, WriteNewFile) {
61 FilePath test_file = test_dir_.Append("test_new");
62 const char kBuffer[] = "buffer";
63 EXPECT_EQ(strlen(kBuffer),
64 collector_.WriteNewFile(test_file,
65 kBuffer,
66 strlen(kBuffer)));
67 EXPECT_LT(collector_.WriteNewFile(test_file,
68 kBuffer,
69 strlen(kBuffer)), 0);
70}
71
Ken Mixteree849c52010-09-30 15:30:10 -070072TEST_F(CrashCollectorTest, Sanitize) {
73 EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
74 EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
75 EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
76 EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
77 EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
78 EXPECT_EQ("", collector_.Sanitize(""));
79 EXPECT_EQ("_", collector_.Sanitize(" "));
80}
81
Ken Mixter03403162010-08-18 15:23:16 -070082TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
83 FilePath path;
84 const int kRootUid = 0;
85 const int kRootGid = 0;
86 const int kNtpUid = 5;
87 const int kChronosUid = 1000;
88 const int kChronosGid = 1001;
89 const mode_t kExpectedSystemMode = 01755;
90 const mode_t kExpectedUserMode = 0755;
91
92 mode_t directory_mode;
93 uid_t directory_owner;
94 gid_t directory_group;
95
96 path = collector_.GetCrashDirectoryInfo(kRootUid,
97 kChronosUid,
98 kChronosGid,
99 &directory_mode,
100 &directory_owner,
101 &directory_group);
102 EXPECT_EQ("/var/spool/crash", path.value());
103 EXPECT_EQ(kExpectedSystemMode, directory_mode);
104 EXPECT_EQ(kRootUid, directory_owner);
105 EXPECT_EQ(kRootGid, directory_group);
106
107 path = collector_.GetCrashDirectoryInfo(kNtpUid,
108 kChronosUid,
109 kChronosGid,
110 &directory_mode,
111 &directory_owner,
112 &directory_group);
113 EXPECT_EQ("/var/spool/crash", path.value());
114 EXPECT_EQ(kExpectedSystemMode, directory_mode);
115 EXPECT_EQ(kRootUid, directory_owner);
116 EXPECT_EQ(kRootGid, directory_group);
117
118 path = collector_.GetCrashDirectoryInfo(kChronosUid,
119 kChronosUid,
120 kChronosGid,
121 &directory_mode,
122 &directory_owner,
123 &directory_group);
124 EXPECT_EQ("/home/chronos/user/crash", path.value());
125 EXPECT_EQ(kExpectedUserMode, directory_mode);
126 EXPECT_EQ(kChronosUid, directory_owner);
127 EXPECT_EQ(kChronosGid, directory_group);
128}
129
130TEST_F(CrashCollectorTest, FormatDumpBasename) {
131 struct tm tm = {0};
132 tm.tm_sec = 15;
133 tm.tm_min = 50;
134 tm.tm_hour = 13;
135 tm.tm_mday = 23;
136 tm.tm_mon = 4;
137 tm.tm_year = 110;
138 tm.tm_isdst = -1;
139 std::string basename =
140 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
141 ASSERT_EQ("foo.20100523.135015.100", basename);
142}
143
Ken Mixter207694d2010-10-28 15:42:37 -0700144TEST_F(CrashCollectorTest, GetCrashPath) {
145 EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
146 collector_.GetCrashPath(FilePath("/var/spool/crash"),
147 "myprog.20100101.1200.1234",
148 "core").value());
149 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
150 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
151 "chrome.20100101.1200.1234",
152 "dmp").value());
153}
154
155
Ken Mixter04ec10f2010-08-26 16:02:02 -0700156bool CrashCollectorTest::CheckHasCapacity() {
157 static const char kFullMessage[] = "Crash directory test already full";
158 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -0800159 bool has_message = FindLog(kFullMessage);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700160 EXPECT_EQ(has_message, !has_capacity);
161 return has_capacity;
162}
163
Ken Mixteree849c52010-09-30 15:30:10 -0700164TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
165 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700166 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixter04ec10f2010-08-26 16:02:02 -0700167 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)),
168 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700169 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700170 }
171
Ken Mixteree849c52010-09-30 15:30:10 -0700172 // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
173 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
174 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)),
175 "", 0);
176 EXPECT_TRUE(CheckHasCapacity());
177 }
178
179 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700180 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700181 file_util::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)),
182 "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700183 EXPECT_FALSE(CheckHasCapacity());
184 }
185}
186
Ken Mixteree849c52010-09-30 15:30:10 -0700187TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
188 // Test kMaxCrashDirectorySize - 1 files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700189 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700190 file_util::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)),
Ken Mixter04ec10f2010-08-26 16:02:02 -0700191 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700192 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700193 }
Ken Mixteree849c52010-09-30 15:30:10 -0700194 file_util::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700195 EXPECT_FALSE(CheckHasCapacity());
196}
197
Ken Mixteree849c52010-09-30 15:30:10 -0700198TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
199 // Test many files with different extensions and same base fit.
200 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
201 file_util::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
202 EXPECT_TRUE(CheckHasCapacity());
203 }
204 // Test dot files are treated as individual files.
205 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
206 file_util::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
207 EXPECT_TRUE(CheckHasCapacity());
208 }
209 file_util::WriteFile(test_dir_.Append("normal.meta"), "", 0);
210 EXPECT_FALSE(CheckHasCapacity());
211}
212
Ken Mixterc49dbd42010-12-14 17:44:11 -0800213TEST_F(CrashCollectorTest, IsCommentLine) {
214 EXPECT_FALSE(CrashCollector::IsCommentLine(""));
215 EXPECT_TRUE(CrashCollector::IsCommentLine("#"));
216 EXPECT_TRUE(CrashCollector::IsCommentLine("#real comment"));
217 EXPECT_TRUE(CrashCollector::IsCommentLine(" # real comment"));
218 EXPECT_FALSE(CrashCollector::IsCommentLine("not comment"));
219 EXPECT_FALSE(CrashCollector::IsCommentLine(" not comment"));
220}
221
Ken Mixteree849c52010-09-30 15:30:10 -0700222TEST_F(CrashCollectorTest, ReadKeyValueFile) {
223 const char *contents = ("a=b\n"
224 "\n"
225 " c=d \n");
226 FilePath path(test_dir_.Append("keyval"));
227 std::map<std::string, std::string> dictionary;
228 std::map<std::string, std::string>::iterator i;
229
230 file_util::WriteFile(path, contents, strlen(contents));
231
232 EXPECT_TRUE(collector_.ReadKeyValueFile(path, '=', &dictionary));
233 i = dictionary.find("a");
234 EXPECT_TRUE(i != dictionary.end() && i->second == "b");
235 i = dictionary.find("c");
236 EXPECT_TRUE(i != dictionary.end() && i->second == "d");
237
238 dictionary.clear();
239
240 contents = ("a=b c d\n"
241 "e\n"
242 " f g = h\n"
243 "i=j\n"
244 "=k\n"
Ken Mixterc49dbd42010-12-14 17:44:11 -0800245 "#comment=0\n"
Ken Mixteree849c52010-09-30 15:30:10 -0700246 "l=\n");
247 file_util::WriteFile(path, contents, strlen(contents));
248
249 EXPECT_FALSE(collector_.ReadKeyValueFile(path, '=', &dictionary));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800250 EXPECT_EQ(5, dictionary.size());
251
Ken Mixteree849c52010-09-30 15:30:10 -0700252 i = dictionary.find("a");
253 EXPECT_TRUE(i != dictionary.end() && i->second == "b c d");
254 i = dictionary.find("e");
255 EXPECT_TRUE(i == dictionary.end());
256 i = dictionary.find("f g");
257 EXPECT_TRUE(i != dictionary.end() && i->second == "h");
258 i = dictionary.find("i");
259 EXPECT_TRUE(i != dictionary.end() && i->second == "j");
260 i = dictionary.find("");
261 EXPECT_TRUE(i != dictionary.end() && i->second == "k");
262 i = dictionary.find("l");
263 EXPECT_TRUE(i != dictionary.end() && i->second == "");
264}
265
Ken Mixterafcf8082010-10-26 14:45:01 -0700266TEST_F(CrashCollectorTest, MetaData) {
Ken Mixter9b346472010-11-07 13:45:45 -0800267 const char kMetaFileBasename[] = "generated.meta";
268 FilePath meta_file = test_dir_.Append(kMetaFileBasename);
Ken Mixterafcf8082010-10-26 14:45:01 -0700269 FilePath lsb_release = test_dir_.Append("lsb-release");
270 FilePath payload_file = test_dir_.Append("payload-file");
271 std::string contents;
272 collector_.lsb_release_ = lsb_release.value().c_str();
273 const char kLsbContents[] = "CHROMEOS_RELEASE_VERSION=version\n";
274 ASSERT_TRUE(
275 file_util::WriteFile(lsb_release,
276 kLsbContents, strlen(kLsbContents)));
277 const char kPayload[] = "foo";
278 ASSERT_TRUE(
279 file_util::WriteFile(payload_file,
280 kPayload, strlen(kPayload)));
281 collector_.AddCrashMetaData("foo", "bar");
282 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
283 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800284 const char kExpectedMeta[] =
285 "foo=bar\n"
286 "exec_name=kernel\n"
287 "ver=version\n"
288 "payload=test/payload-file\n"
289 "payload_size=3\n"
290 "done=1\n";
291 EXPECT_EQ(kExpectedMeta, contents);
292
293 // Test target of symlink is not overwritten.
294 payload_file = test_dir_.Append("payload2-file");
295 ASSERT_TRUE(
296 file_util::WriteFile(payload_file,
297 kPayload, strlen(kPayload)));
298 FilePath meta_symlink_path = test_dir_.Append("symlink.meta");
299 ASSERT_EQ(0,
300 symlink(kMetaFileBasename,
301 meta_symlink_path.value().c_str()));
302 ASSERT_TRUE(file_util::PathExists(meta_symlink_path));
Ken Mixtera3249322011-03-03 08:47:38 -0800303 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800304 collector_.WriteCrashMetaData(meta_symlink_path,
305 "kernel",
306 payload_file.value());
Ken Mixtera3249322011-03-03 08:47:38 -0800307 // Target metadata contents should have stayed the same.
Ken Mixter9b346472010-11-07 13:45:45 -0800308 contents.clear();
309 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents));
310 EXPECT_EQ(kExpectedMeta, contents);
Ken Mixtera3249322011-03-03 08:47:38 -0800311 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixter9b346472010-11-07 13:45:45 -0800312
313 // Test target of dangling symlink is not created.
314 file_util::Delete(meta_file, false);
315 ASSERT_FALSE(file_util::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800316 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800317 collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
318 payload_file.value());
319 EXPECT_FALSE(file_util::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800320 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixterafcf8082010-10-26 14:45:01 -0700321}
322
Ken Mixterc49dbd42010-12-14 17:44:11 -0800323TEST_F(CrashCollectorTest, GetLogContents) {
324 FilePath config_file = test_dir_.Append("crash_config");
325 FilePath output_file = test_dir_.Append("crash_log");
326 const char kConfigContents[] =
327 "foobar:echo hello there | sed -e \"s/there/world/\"";
328 ASSERT_TRUE(
329 file_util::WriteFile(config_file,
330 kConfigContents, strlen(kConfigContents)));
Ken Mixter1b8fe012011-01-25 13:33:05 -0800331 file_util::Delete(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800332 EXPECT_FALSE(collector_.GetLogContents(config_file,
333 "barfoo",
334 output_file));
335 EXPECT_FALSE(file_util::PathExists(output_file));
Ken Mixter1b8fe012011-01-25 13:33:05 -0800336 file_util::Delete(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800337 EXPECT_TRUE(collector_.GetLogContents(config_file,
338 "foobar",
339 output_file));
340 ASSERT_TRUE(file_util::PathExists(output_file));
341 std::string contents;
342 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents));
343 EXPECT_EQ("hello world\n", contents);
344}
345
Ken Mixter03403162010-08-18 15:23:16 -0700346int main(int argc, char **argv) {
Ken Mixtera3249322011-03-03 08:47:38 -0800347 SetUpTests(&argc, argv, false);
Ken Mixter03403162010-08-18 15:23:16 -0700348 return RUN_ALL_TESTS();
349}