blob: 863fed3f4b30dea1455fa35d42f7f274bb134e7f [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
Mike Frysingerf19b5182013-05-17 19:36:47 -04005#include "crash-reporter/crash_collector_test.h"
6
Ken Mixter03403162010-08-18 15:23:16 -07007#include <unistd.h>
8
Mike Frysingerf19b5182013-05-17 19:36:47 -04009#include <dbus/dbus-glib-lowlevel.h>
10#include <glib.h>
11
Ken Mixter03403162010-08-18 15:23:16 -070012#include "base/file_util.h"
Mike Frysingera557c112014-02-05 22:55:39 -050013#include "base/strings/string_util.h"
14#include "base/strings/stringprintf.h"
Ken Mixtera3249322011-03-03 08:47:38 -080015#include "chromeos/syslog_logging.h"
16#include "chromeos/test_helpers.h"
Ken Mixter03403162010-08-18 15:23:16 -070017#include "crash-reporter/crash_collector.h"
Ken Mixter03403162010-08-18 15:23:16 -070018#include "gtest/gtest.h"
19
Simon Que9f90aca2013-02-19 17:19:52 -080020using base::FilePath;
Mike Frysingera557c112014-02-05 22:55:39 -050021using base::StringPrintf;
Ken Mixtera3249322011-03-03 08:47:38 -080022using chromeos::FindLog;
Mike Frysingerf19b5182013-05-17 19:36:47 -040023using ::testing::Return;
Ken Mixtera3249322011-03-03 08:47:38 -080024
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() {
Lei Zhang9b1f3002014-04-24 02:10:57 -070037 collector_.Initialize(CountCrash, IsMetrics);
Ken Mixter04ec10f2010-08-26 16:02:02 -070038 test_dir_ = FilePath("test");
Mike Frysingera557c112014-02-05 22:55:39 -050039 base::CreateDirectory(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -080040 chromeos::ClearLog();
Ken Mixter03403162010-08-18 15:23:16 -070041 }
Ken Mixter04ec10f2010-08-26 16:02:02 -070042
43 void TearDown() {
Mike Frysingera557c112014-02-05 22:55:39 -050044 base::DeleteFile(test_dir_, true);
Ken Mixter04ec10f2010-08-26 16:02:02 -070045 }
46
47 bool CheckHasCapacity();
48
Ken Mixter03403162010-08-18 15:23:16 -070049 protected:
Mike Frysingerf19b5182013-05-17 19:36:47 -040050 CrashCollectorMock collector_;
Ken Mixter04ec10f2010-08-26 16:02:02 -070051 FilePath test_dir_;
Ken Mixter03403162010-08-18 15:23:16 -070052};
53
54TEST_F(CrashCollectorTest, Initialize) {
55 ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
56 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
Ken Mixter03403162010-08-18 15:23:16 -070057}
58
Ken Mixter9b346472010-11-07 13:45:45 -080059TEST_F(CrashCollectorTest, WriteNewFile) {
60 FilePath test_file = test_dir_.Append("test_new");
61 const char kBuffer[] = "buffer";
62 EXPECT_EQ(strlen(kBuffer),
63 collector_.WriteNewFile(test_file,
64 kBuffer,
65 strlen(kBuffer)));
66 EXPECT_LT(collector_.WriteNewFile(test_file,
67 kBuffer,
68 strlen(kBuffer)), 0);
69}
70
Ken Mixteree849c52010-09-30 15:30:10 -070071TEST_F(CrashCollectorTest, Sanitize) {
72 EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
73 EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
74 EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
75 EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
76 EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
77 EXPECT_EQ("", collector_.Sanitize(""));
78 EXPECT_EQ("_", collector_.Sanitize(" "));
79}
80
Ken Mixter03403162010-08-18 15:23:16 -070081TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
82 FilePath path;
83 const int kRootUid = 0;
84 const int kRootGid = 0;
85 const int kNtpUid = 5;
86 const int kChronosUid = 1000;
87 const int kChronosGid = 1001;
88 const mode_t kExpectedSystemMode = 01755;
89 const mode_t kExpectedUserMode = 0755;
90
91 mode_t directory_mode;
92 uid_t directory_owner;
93 gid_t directory_group;
94
95 path = collector_.GetCrashDirectoryInfo(kRootUid,
96 kChronosUid,
97 kChronosGid,
98 &directory_mode,
99 &directory_owner,
100 &directory_group);
101 EXPECT_EQ("/var/spool/crash", path.value());
102 EXPECT_EQ(kExpectedSystemMode, directory_mode);
103 EXPECT_EQ(kRootUid, directory_owner);
104 EXPECT_EQ(kRootGid, directory_group);
105
106 path = collector_.GetCrashDirectoryInfo(kNtpUid,
107 kChronosUid,
108 kChronosGid,
109 &directory_mode,
110 &directory_owner,
111 &directory_group);
112 EXPECT_EQ("/var/spool/crash", path.value());
113 EXPECT_EQ(kExpectedSystemMode, directory_mode);
114 EXPECT_EQ(kRootUid, directory_owner);
115 EXPECT_EQ(kRootGid, directory_group);
116
Mike Frysingerf19b5182013-05-17 19:36:47 -0400117 // No need to destroy the hash as GetCrashDirectoryInfo() will do it for us.
118 GHashTable *active_sessions = g_hash_table_new (g_str_hash, g_str_equal);
119 char kUser[] = "chicken@butt.com";
120 char kHash[] = "hashcakes";
121 g_hash_table_insert (active_sessions,
122 static_cast<gpointer>(kUser),
123 static_cast<gpointer>(kHash));
124 EXPECT_CALL(collector_, GetActiveUserSessions())
125 .WillOnce(Return(active_sessions));
126
127 EXPECT_EQ(collector_.IsUserSpecificDirectoryEnabled(), true);
128
Ken Mixter03403162010-08-18 15:23:16 -0700129 path = collector_.GetCrashDirectoryInfo(kChronosUid,
130 kChronosUid,
131 kChronosGid,
132 &directory_mode,
133 &directory_owner,
134 &directory_group);
Mike Frysinger37843a92013-06-11 17:03:59 -0400135 EXPECT_EQ("/home/user/hashcakes/crash", path.value());
Ken Mixter03403162010-08-18 15:23:16 -0700136 EXPECT_EQ(kExpectedUserMode, directory_mode);
137 EXPECT_EQ(kChronosUid, directory_owner);
138 EXPECT_EQ(kChronosGid, directory_group);
139}
140
141TEST_F(CrashCollectorTest, FormatDumpBasename) {
142 struct tm tm = {0};
143 tm.tm_sec = 15;
144 tm.tm_min = 50;
145 tm.tm_hour = 13;
146 tm.tm_mday = 23;
147 tm.tm_mon = 4;
148 tm.tm_year = 110;
149 tm.tm_isdst = -1;
150 std::string basename =
151 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
152 ASSERT_EQ("foo.20100523.135015.100", basename);
153}
154
Ken Mixter207694d2010-10-28 15:42:37 -0700155TEST_F(CrashCollectorTest, GetCrashPath) {
156 EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
157 collector_.GetCrashPath(FilePath("/var/spool/crash"),
158 "myprog.20100101.1200.1234",
159 "core").value());
160 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
161 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
162 "chrome.20100101.1200.1234",
163 "dmp").value());
164}
165
166
Ken Mixter04ec10f2010-08-26 16:02:02 -0700167bool CrashCollectorTest::CheckHasCapacity() {
168 static const char kFullMessage[] = "Crash directory test already full";
169 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -0800170 bool has_message = FindLog(kFullMessage);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700171 EXPECT_EQ(has_message, !has_capacity);
172 return has_capacity;
173}
174
Ken Mixteree849c52010-09-30 15:30:10 -0700175TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
176 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700177 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixter04ec10f2010-08-26 16:02:02 -0700178 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)),
179 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700180 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700181 }
182
Ken Mixteree849c52010-09-30 15:30:10 -0700183 // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
184 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
185 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)),
186 "", 0);
187 EXPECT_TRUE(CheckHasCapacity());
188 }
189
190 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700191 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700192 file_util::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)),
193 "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700194 EXPECT_FALSE(CheckHasCapacity());
195 }
196}
197
Ken Mixteree849c52010-09-30 15:30:10 -0700198TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
199 // Test kMaxCrashDirectorySize - 1 files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700200 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ken Mixteree849c52010-09-30 15:30:10 -0700201 file_util::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)),
Ken Mixter04ec10f2010-08-26 16:02:02 -0700202 "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700203 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700204 }
Ken Mixteree849c52010-09-30 15:30:10 -0700205 file_util::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700206 EXPECT_FALSE(CheckHasCapacity());
207}
208
Ken Mixteree849c52010-09-30 15:30:10 -0700209TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
210 // Test many files with different extensions and same base fit.
211 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
212 file_util::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
213 EXPECT_TRUE(CheckHasCapacity());
214 }
215 // Test dot files are treated as individual files.
216 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
217 file_util::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
218 EXPECT_TRUE(CheckHasCapacity());
219 }
220 file_util::WriteFile(test_dir_.Append("normal.meta"), "", 0);
221 EXPECT_FALSE(CheckHasCapacity());
222}
223
Ken Mixterc49dbd42010-12-14 17:44:11 -0800224TEST_F(CrashCollectorTest, IsCommentLine) {
225 EXPECT_FALSE(CrashCollector::IsCommentLine(""));
226 EXPECT_TRUE(CrashCollector::IsCommentLine("#"));
227 EXPECT_TRUE(CrashCollector::IsCommentLine("#real comment"));
228 EXPECT_TRUE(CrashCollector::IsCommentLine(" # real comment"));
229 EXPECT_FALSE(CrashCollector::IsCommentLine("not comment"));
230 EXPECT_FALSE(CrashCollector::IsCommentLine(" not comment"));
231}
232
Ken Mixteree849c52010-09-30 15:30:10 -0700233TEST_F(CrashCollectorTest, ReadKeyValueFile) {
234 const char *contents = ("a=b\n"
235 "\n"
236 " c=d \n");
237 FilePath path(test_dir_.Append("keyval"));
238 std::map<std::string, std::string> dictionary;
239 std::map<std::string, std::string>::iterator i;
240
241 file_util::WriteFile(path, contents, strlen(contents));
242
243 EXPECT_TRUE(collector_.ReadKeyValueFile(path, '=', &dictionary));
244 i = dictionary.find("a");
245 EXPECT_TRUE(i != dictionary.end() && i->second == "b");
246 i = dictionary.find("c");
247 EXPECT_TRUE(i != dictionary.end() && i->second == "d");
248
249 dictionary.clear();
250
251 contents = ("a=b c d\n"
252 "e\n"
253 " f g = h\n"
254 "i=j\n"
255 "=k\n"
Ken Mixterc49dbd42010-12-14 17:44:11 -0800256 "#comment=0\n"
Ken Mixteree849c52010-09-30 15:30:10 -0700257 "l=\n");
258 file_util::WriteFile(path, contents, strlen(contents));
259
260 EXPECT_FALSE(collector_.ReadKeyValueFile(path, '=', &dictionary));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800261 EXPECT_EQ(5, dictionary.size());
262
Ken Mixteree849c52010-09-30 15:30:10 -0700263 i = dictionary.find("a");
264 EXPECT_TRUE(i != dictionary.end() && i->second == "b c d");
265 i = dictionary.find("e");
266 EXPECT_TRUE(i == dictionary.end());
267 i = dictionary.find("f g");
268 EXPECT_TRUE(i != dictionary.end() && i->second == "h");
269 i = dictionary.find("i");
270 EXPECT_TRUE(i != dictionary.end() && i->second == "j");
271 i = dictionary.find("");
272 EXPECT_TRUE(i != dictionary.end() && i->second == "k");
273 i = dictionary.find("l");
274 EXPECT_TRUE(i != dictionary.end() && i->second == "");
275}
276
Ken Mixterafcf8082010-10-26 14:45:01 -0700277TEST_F(CrashCollectorTest, MetaData) {
Ken Mixter9b346472010-11-07 13:45:45 -0800278 const char kMetaFileBasename[] = "generated.meta";
279 FilePath meta_file = test_dir_.Append(kMetaFileBasename);
Ken Mixterafcf8082010-10-26 14:45:01 -0700280 FilePath lsb_release = test_dir_.Append("lsb-release");
281 FilePath payload_file = test_dir_.Append("payload-file");
282 std::string contents;
Lei Zhang9b1f3002014-04-24 02:10:57 -0700283 collector_.lsb_release_ = lsb_release.value();
Ken Mixterafcf8082010-10-26 14:45:01 -0700284 const char kLsbContents[] = "CHROMEOS_RELEASE_VERSION=version\n";
285 ASSERT_TRUE(
286 file_util::WriteFile(lsb_release,
287 kLsbContents, strlen(kLsbContents)));
288 const char kPayload[] = "foo";
289 ASSERT_TRUE(
290 file_util::WriteFile(payload_file,
291 kPayload, strlen(kPayload)));
292 collector_.AddCrashMetaData("foo", "bar");
293 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500294 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800295 const char kExpectedMeta[] =
296 "foo=bar\n"
297 "exec_name=kernel\n"
298 "ver=version\n"
299 "payload=test/payload-file\n"
300 "payload_size=3\n"
301 "done=1\n";
302 EXPECT_EQ(kExpectedMeta, contents);
303
304 // Test target of symlink is not overwritten.
305 payload_file = test_dir_.Append("payload2-file");
306 ASSERT_TRUE(
307 file_util::WriteFile(payload_file,
308 kPayload, strlen(kPayload)));
309 FilePath meta_symlink_path = test_dir_.Append("symlink.meta");
310 ASSERT_EQ(0,
311 symlink(kMetaFileBasename,
312 meta_symlink_path.value().c_str()));
Mike Frysingera557c112014-02-05 22:55:39 -0500313 ASSERT_TRUE(base::PathExists(meta_symlink_path));
Ken Mixtera3249322011-03-03 08:47:38 -0800314 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800315 collector_.WriteCrashMetaData(meta_symlink_path,
316 "kernel",
317 payload_file.value());
Ken Mixtera3249322011-03-03 08:47:38 -0800318 // Target metadata contents should have stayed the same.
Ken Mixter9b346472010-11-07 13:45:45 -0800319 contents.clear();
Mike Frysingera557c112014-02-05 22:55:39 -0500320 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800321 EXPECT_EQ(kExpectedMeta, contents);
Ken Mixtera3249322011-03-03 08:47:38 -0800322 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixter9b346472010-11-07 13:45:45 -0800323
324 // Test target of dangling symlink is not created.
Mike Frysingera557c112014-02-05 22:55:39 -0500325 base::DeleteFile(meta_file, false);
326 ASSERT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800327 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800328 collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
329 payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500330 EXPECT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800331 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixterafcf8082010-10-26 14:45:01 -0700332}
333
Ken Mixterc49dbd42010-12-14 17:44:11 -0800334TEST_F(CrashCollectorTest, GetLogContents) {
335 FilePath config_file = test_dir_.Append("crash_config");
336 FilePath output_file = test_dir_.Append("crash_log");
337 const char kConfigContents[] =
338 "foobar:echo hello there | sed -e \"s/there/world/\"";
339 ASSERT_TRUE(
340 file_util::WriteFile(config_file,
341 kConfigContents, strlen(kConfigContents)));
Mike Frysingera557c112014-02-05 22:55:39 -0500342 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800343 EXPECT_FALSE(collector_.GetLogContents(config_file,
344 "barfoo",
345 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500346 EXPECT_FALSE(base::PathExists(output_file));
347 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800348 EXPECT_TRUE(collector_.GetLogContents(config_file,
349 "foobar",
350 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500351 ASSERT_TRUE(base::PathExists(output_file));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800352 std::string contents;
Mike Frysingera557c112014-02-05 22:55:39 -0500353 EXPECT_TRUE(base::ReadFileToString(output_file, &contents));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800354 EXPECT_EQ("hello world\n", contents);
355}
356
Ken Mixter03403162010-08-18 15:23:16 -0700357int main(int argc, char **argv) {
Mike Frysingerf19b5182013-05-17 19:36:47 -0400358 ::g_type_init();
Ken Mixtera3249322011-03-03 08:47:38 -0800359 SetUpTests(&argc, argv, false);
Ken Mixter03403162010-08-18 15:23:16 -0700360 return RUN_ALL_TESTS();
361}