blob: 7e4c7c12d7568e9347d9272784077165ca2822ec [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
Ben Chanab6cc902014-09-05 08:21:06 -070012#include <base/files/file_util.h>
Ben Chan7e776902014-06-18 13:19:51 -070013#include <base/strings/string_util.h>
14#include <base/strings/stringprintf.h>
15#include <chromeos/syslog_logging.h>
16#include <chromeos/test_helpers.h>
17#include <gtest/gtest.h>
18
Ken Mixter03403162010-08-18 15:23:16 -070019#include "crash-reporter/crash_collector.h"
Ken Mixter03403162010-08-18 15:23:16 -070020
Simon Que9f90aca2013-02-19 17:19:52 -080021using base::FilePath;
Mike Frysingera557c112014-02-05 22:55:39 -050022using base::StringPrintf;
Ken Mixtera3249322011-03-03 08:47:38 -080023using chromeos::FindLog;
Mike Frysingerf19b5182013-05-17 19:36:47 -040024using ::testing::Return;
Ken Mixtera3249322011-03-03 08:47:38 -080025
Ken Mixter03403162010-08-18 15:23:16 -070026void CountCrash() {
27 ADD_FAILURE();
28}
29
30bool IsMetrics() {
31 ADD_FAILURE();
32 return false;
33}
34
35class CrashCollectorTest : public ::testing::Test {
Ken Mixter04ec10f2010-08-26 16:02:02 -070036 public:
Ken Mixter03403162010-08-18 15:23:16 -070037 void SetUp() {
Lei Zhang9b1f3002014-04-24 02:10:57 -070038 collector_.Initialize(CountCrash, IsMetrics);
Ken Mixter04ec10f2010-08-26 16:02:02 -070039 test_dir_ = FilePath("test");
Mike Frysingera557c112014-02-05 22:55:39 -050040 base::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() {
Mike Frysingera557c112014-02-05 22:55:39 -050045 base::DeleteFile(test_dir_, true);
Ken Mixter04ec10f2010-08-26 16:02:02 -070046 }
47
48 bool CheckHasCapacity();
49
Ken Mixter03403162010-08-18 15:23:16 -070050 protected:
Mike Frysingerf19b5182013-05-17 19:36:47 -040051 CrashCollectorMock 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
Mike Frysingerf19b5182013-05-17 19:36:47 -0400118 // No need to destroy the hash as GetCrashDirectoryInfo() will do it for us.
Ben Chan7e776902014-06-18 13:19:51 -0700119 GHashTable *active_sessions = g_hash_table_new(g_str_hash, g_str_equal);
Mike Frysingerf19b5182013-05-17 19:36:47 -0400120 char kUser[] = "chicken@butt.com";
121 char kHash[] = "hashcakes";
Ben Chan7e776902014-06-18 13:19:51 -0700122 g_hash_table_insert(active_sessions,
123 static_cast<gpointer>(kUser),
124 static_cast<gpointer>(kHash));
Mike Frysingerf19b5182013-05-17 19:36:47 -0400125 EXPECT_CALL(collector_, GetActiveUserSessions())
126 .WillOnce(Return(active_sessions));
127
128 EXPECT_EQ(collector_.IsUserSpecificDirectoryEnabled(), true);
129
Ken Mixter03403162010-08-18 15:23:16 -0700130 path = collector_.GetCrashDirectoryInfo(kChronosUid,
131 kChronosUid,
132 kChronosGid,
133 &directory_mode,
134 &directory_owner,
135 &directory_group);
Mike Frysinger37843a92013-06-11 17:03:59 -0400136 EXPECT_EQ("/home/user/hashcakes/crash", path.value());
Ken Mixter03403162010-08-18 15:23:16 -0700137 EXPECT_EQ(kExpectedUserMode, directory_mode);
138 EXPECT_EQ(kChronosUid, directory_owner);
139 EXPECT_EQ(kChronosGid, directory_group);
140}
141
142TEST_F(CrashCollectorTest, FormatDumpBasename) {
143 struct tm tm = {0};
144 tm.tm_sec = 15;
145 tm.tm_min = 50;
146 tm.tm_hour = 13;
147 tm.tm_mday = 23;
148 tm.tm_mon = 4;
149 tm.tm_year = 110;
150 tm.tm_isdst = -1;
151 std::string basename =
152 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
153 ASSERT_EQ("foo.20100523.135015.100", basename);
154}
155
Ken Mixter207694d2010-10-28 15:42:37 -0700156TEST_F(CrashCollectorTest, GetCrashPath) {
157 EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
158 collector_.GetCrashPath(FilePath("/var/spool/crash"),
159 "myprog.20100101.1200.1234",
160 "core").value());
161 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
162 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
163 "chrome.20100101.1200.1234",
164 "dmp").value());
165}
166
167
Ken Mixter04ec10f2010-08-26 16:02:02 -0700168bool CrashCollectorTest::CheckHasCapacity() {
169 static const char kFullMessage[] = "Crash directory test already full";
170 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -0800171 bool has_message = FindLog(kFullMessage);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700172 EXPECT_EQ(has_message, !has_capacity);
173 return has_capacity;
174}
175
Ken Mixteree849c52010-09-30 15:30:10 -0700176TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
177 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700178 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700179 base::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), "", 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) {
Ben Chanf30c6412014-05-22 23:09:01 -0700185 base::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700186 EXPECT_TRUE(CheckHasCapacity());
187 }
188
189 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700190 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700191 base::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700192 EXPECT_FALSE(CheckHasCapacity());
193 }
194}
195
Ken Mixteree849c52010-09-30 15:30:10 -0700196TEST_F(CrashCollectorTest, CheckHasCapacityCorrectBasename) {
197 // Test kMaxCrashDirectorySize - 1 files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700198 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700199 base::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700200 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700201 }
Ben Chanf30c6412014-05-22 23:09:01 -0700202 base::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700203 EXPECT_FALSE(CheckHasCapacity());
204}
205
Ken Mixteree849c52010-09-30 15:30:10 -0700206TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
207 // Test many files with different extensions and same base fit.
208 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700209 base::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700210 EXPECT_TRUE(CheckHasCapacity());
211 }
212 // Test dot files are treated as individual files.
213 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700214 base::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700215 EXPECT_TRUE(CheckHasCapacity());
216 }
Ben Chanf30c6412014-05-22 23:09:01 -0700217 base::WriteFile(test_dir_.Append("normal.meta"), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700218 EXPECT_FALSE(CheckHasCapacity());
219}
220
Ken Mixterc49dbd42010-12-14 17:44:11 -0800221TEST_F(CrashCollectorTest, IsCommentLine) {
222 EXPECT_FALSE(CrashCollector::IsCommentLine(""));
223 EXPECT_TRUE(CrashCollector::IsCommentLine("#"));
224 EXPECT_TRUE(CrashCollector::IsCommentLine("#real comment"));
225 EXPECT_TRUE(CrashCollector::IsCommentLine(" # real comment"));
226 EXPECT_FALSE(CrashCollector::IsCommentLine("not comment"));
227 EXPECT_FALSE(CrashCollector::IsCommentLine(" not comment"));
228}
229
Ken Mixteree849c52010-09-30 15:30:10 -0700230TEST_F(CrashCollectorTest, ReadKeyValueFile) {
231 const char *contents = ("a=b\n"
232 "\n"
233 " c=d \n");
234 FilePath path(test_dir_.Append("keyval"));
235 std::map<std::string, std::string> dictionary;
236 std::map<std::string, std::string>::iterator i;
237
Ben Chanf30c6412014-05-22 23:09:01 -0700238 base::WriteFile(path, contents, strlen(contents));
Ken Mixteree849c52010-09-30 15:30:10 -0700239
240 EXPECT_TRUE(collector_.ReadKeyValueFile(path, '=', &dictionary));
241 i = dictionary.find("a");
242 EXPECT_TRUE(i != dictionary.end() && i->second == "b");
243 i = dictionary.find("c");
244 EXPECT_TRUE(i != dictionary.end() && i->second == "d");
245
246 dictionary.clear();
247
248 contents = ("a=b c d\n"
249 "e\n"
250 " f g = h\n"
251 "i=j\n"
252 "=k\n"
Ken Mixterc49dbd42010-12-14 17:44:11 -0800253 "#comment=0\n"
Ken Mixteree849c52010-09-30 15:30:10 -0700254 "l=\n");
Ben Chanf30c6412014-05-22 23:09:01 -0700255 base::WriteFile(path, contents, strlen(contents));
Ken Mixteree849c52010-09-30 15:30:10 -0700256
257 EXPECT_FALSE(collector_.ReadKeyValueFile(path, '=', &dictionary));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800258 EXPECT_EQ(5, dictionary.size());
259
Ken Mixteree849c52010-09-30 15:30:10 -0700260 i = dictionary.find("a");
261 EXPECT_TRUE(i != dictionary.end() && i->second == "b c d");
262 i = dictionary.find("e");
263 EXPECT_TRUE(i == dictionary.end());
264 i = dictionary.find("f g");
265 EXPECT_TRUE(i != dictionary.end() && i->second == "h");
266 i = dictionary.find("i");
267 EXPECT_TRUE(i != dictionary.end() && i->second == "j");
268 i = dictionary.find("");
269 EXPECT_TRUE(i != dictionary.end() && i->second == "k");
270 i = dictionary.find("l");
271 EXPECT_TRUE(i != dictionary.end() && i->second == "");
272}
273
Ken Mixterafcf8082010-10-26 14:45:01 -0700274TEST_F(CrashCollectorTest, MetaData) {
Ken Mixter9b346472010-11-07 13:45:45 -0800275 const char kMetaFileBasename[] = "generated.meta";
276 FilePath meta_file = test_dir_.Append(kMetaFileBasename);
Ken Mixterafcf8082010-10-26 14:45:01 -0700277 FilePath lsb_release = test_dir_.Append("lsb-release");
278 FilePath payload_file = test_dir_.Append("payload-file");
279 std::string contents;
Lei Zhang9b1f3002014-04-24 02:10:57 -0700280 collector_.lsb_release_ = lsb_release.value();
Ken Mixterafcf8082010-10-26 14:45:01 -0700281 const char kLsbContents[] = "CHROMEOS_RELEASE_VERSION=version\n";
Ben Chanf30c6412014-05-22 23:09:01 -0700282 ASSERT_TRUE(base::WriteFile(lsb_release, kLsbContents, strlen(kLsbContents)));
Ken Mixterafcf8082010-10-26 14:45:01 -0700283 const char kPayload[] = "foo";
Ben Chanf30c6412014-05-22 23:09:01 -0700284 ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
Ken Mixterafcf8082010-10-26 14:45:01 -0700285 collector_.AddCrashMetaData("foo", "bar");
286 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500287 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800288 const char kExpectedMeta[] =
289 "foo=bar\n"
290 "exec_name=kernel\n"
291 "ver=version\n"
292 "payload=test/payload-file\n"
293 "payload_size=3\n"
294 "done=1\n";
295 EXPECT_EQ(kExpectedMeta, contents);
296
297 // Test target of symlink is not overwritten.
298 payload_file = test_dir_.Append("payload2-file");
Ben Chanf30c6412014-05-22 23:09:01 -0700299 ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
Ken Mixter9b346472010-11-07 13:45:45 -0800300 FilePath meta_symlink_path = test_dir_.Append("symlink.meta");
301 ASSERT_EQ(0,
302 symlink(kMetaFileBasename,
303 meta_symlink_path.value().c_str()));
Mike Frysingera557c112014-02-05 22:55:39 -0500304 ASSERT_TRUE(base::PathExists(meta_symlink_path));
Ken Mixtera3249322011-03-03 08:47:38 -0800305 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800306 collector_.WriteCrashMetaData(meta_symlink_path,
307 "kernel",
308 payload_file.value());
Ken Mixtera3249322011-03-03 08:47:38 -0800309 // Target metadata contents should have stayed the same.
Ken Mixter9b346472010-11-07 13:45:45 -0800310 contents.clear();
Mike Frysingera557c112014-02-05 22:55:39 -0500311 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800312 EXPECT_EQ(kExpectedMeta, contents);
Ken Mixtera3249322011-03-03 08:47:38 -0800313 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixter9b346472010-11-07 13:45:45 -0800314
315 // Test target of dangling symlink is not created.
Mike Frysingera557c112014-02-05 22:55:39 -0500316 base::DeleteFile(meta_file, false);
317 ASSERT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800318 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800319 collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
320 payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500321 EXPECT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800322 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixterafcf8082010-10-26 14:45:01 -0700323}
324
Ken Mixterc49dbd42010-12-14 17:44:11 -0800325TEST_F(CrashCollectorTest, GetLogContents) {
326 FilePath config_file = test_dir_.Append("crash_config");
327 FilePath output_file = test_dir_.Append("crash_log");
328 const char kConfigContents[] =
329 "foobar:echo hello there | sed -e \"s/there/world/\"";
330 ASSERT_TRUE(
Ben Chanf30c6412014-05-22 23:09:01 -0700331 base::WriteFile(config_file, kConfigContents, strlen(kConfigContents)));
Mike Frysingera557c112014-02-05 22:55:39 -0500332 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800333 EXPECT_FALSE(collector_.GetLogContents(config_file,
334 "barfoo",
335 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500336 EXPECT_FALSE(base::PathExists(output_file));
337 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800338 EXPECT_TRUE(collector_.GetLogContents(config_file,
339 "foobar",
340 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500341 ASSERT_TRUE(base::PathExists(output_file));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800342 std::string contents;
Mike Frysingera557c112014-02-05 22:55:39 -0500343 EXPECT_TRUE(base::ReadFileToString(output_file, &contents));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800344 EXPECT_EQ("hello world\n", contents);
345}
346
Ken Mixter03403162010-08-18 15:23:16 -0700347int main(int argc, char **argv) {
Mike Frysingerf19b5182013-05-17 19:36:47 -0400348 ::g_type_init();
Ken Mixtera3249322011-03-03 08:47:38 -0800349 SetUpTests(&argc, argv, false);
Ken Mixter03403162010-08-18 15:23:16 -0700350 return RUN_ALL_TESTS();
351}