blob: 0ca379262f11da917be879d98df6e690ed311fe9 [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 <glib.h>
10
Ben Chanab6cc902014-09-05 08:21:06 -070011#include <base/files/file_util.h>
Ben Chan7e776902014-06-18 13:19:51 -070012#include <base/strings/string_util.h>
13#include <base/strings/stringprintf.h>
14#include <chromeos/syslog_logging.h>
Ben Chan7e776902014-06-18 13:19:51 -070015#include <gtest/gtest.h>
16
Ken Mixter03403162010-08-18 15:23:16 -070017#include "crash-reporter/crash_collector.h"
Ken Mixter03403162010-08-18 15:23:16 -070018
Simon Que9f90aca2013-02-19 17:19:52 -080019using base::FilePath;
Mike Frysingera557c112014-02-05 22:55:39 -050020using base::StringPrintf;
Ken Mixtera3249322011-03-03 08:47:38 -080021using chromeos::FindLog;
Mike Frysingerf19b5182013-05-17 19:36:47 -040022using ::testing::Return;
Ken Mixtera3249322011-03-03 08:47:38 -080023
Daniel Eratd257ea12015-01-28 10:23:28 -070024namespace {
25
Ken Mixter03403162010-08-18 15:23:16 -070026void CountCrash() {
27 ADD_FAILURE();
28}
29
30bool IsMetrics() {
31 ADD_FAILURE();
32 return false;
33}
34
Daniel Eratd257ea12015-01-28 10:23:28 -070035} // namespace
36
Ken Mixter03403162010-08-18 15:23:16 -070037class CrashCollectorTest : public ::testing::Test {
Ken Mixter04ec10f2010-08-26 16:02:02 -070038 public:
Ken Mixter03403162010-08-18 15:23:16 -070039 void SetUp() {
Lei Zhang9b1f3002014-04-24 02:10:57 -070040 collector_.Initialize(CountCrash, IsMetrics);
Ken Mixter04ec10f2010-08-26 16:02:02 -070041 test_dir_ = FilePath("test");
Mike Frysingera557c112014-02-05 22:55:39 -050042 base::CreateDirectory(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -080043 chromeos::ClearLog();
Ken Mixter03403162010-08-18 15:23:16 -070044 }
Ken Mixter04ec10f2010-08-26 16:02:02 -070045
46 void TearDown() {
Mike Frysingera557c112014-02-05 22:55:39 -050047 base::DeleteFile(test_dir_, true);
Ken Mixter04ec10f2010-08-26 16:02:02 -070048 }
49
50 bool CheckHasCapacity();
51
Ken Mixter03403162010-08-18 15:23:16 -070052 protected:
Mike Frysingerf19b5182013-05-17 19:36:47 -040053 CrashCollectorMock collector_;
Ken Mixter04ec10f2010-08-26 16:02:02 -070054 FilePath test_dir_;
Ken Mixter03403162010-08-18 15:23:16 -070055};
56
57TEST_F(CrashCollectorTest, Initialize) {
58 ASSERT_TRUE(CountCrash == collector_.count_crash_function_);
59 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_);
Ken Mixter03403162010-08-18 15:23:16 -070060}
61
Ken Mixter9b346472010-11-07 13:45:45 -080062TEST_F(CrashCollectorTest, WriteNewFile) {
63 FilePath test_file = test_dir_.Append("test_new");
64 const char kBuffer[] = "buffer";
65 EXPECT_EQ(strlen(kBuffer),
66 collector_.WriteNewFile(test_file,
67 kBuffer,
68 strlen(kBuffer)));
69 EXPECT_LT(collector_.WriteNewFile(test_file,
70 kBuffer,
71 strlen(kBuffer)), 0);
72}
73
Ken Mixteree849c52010-09-30 15:30:10 -070074TEST_F(CrashCollectorTest, Sanitize) {
75 EXPECT_EQ("chrome", collector_.Sanitize("chrome"));
76 EXPECT_EQ("CHROME", collector_.Sanitize("CHROME"));
77 EXPECT_EQ("1chrome2", collector_.Sanitize("1chrome2"));
78 EXPECT_EQ("chrome__deleted_", collector_.Sanitize("chrome (deleted)"));
79 EXPECT_EQ("foo_bar", collector_.Sanitize("foo.bar"));
80 EXPECT_EQ("", collector_.Sanitize(""));
81 EXPECT_EQ("_", collector_.Sanitize(" "));
82}
83
Ken Mixter03403162010-08-18 15:23:16 -070084TEST_F(CrashCollectorTest, GetCrashDirectoryInfo) {
85 FilePath path;
86 const int kRootUid = 0;
87 const int kRootGid = 0;
88 const int kNtpUid = 5;
89 const int kChronosUid = 1000;
90 const int kChronosGid = 1001;
91 const mode_t kExpectedSystemMode = 01755;
92 const mode_t kExpectedUserMode = 0755;
93
94 mode_t directory_mode;
95 uid_t directory_owner;
96 gid_t directory_group;
97
98 path = collector_.GetCrashDirectoryInfo(kRootUid,
99 kChronosUid,
100 kChronosGid,
101 &directory_mode,
102 &directory_owner,
103 &directory_group);
104 EXPECT_EQ("/var/spool/crash", path.value());
105 EXPECT_EQ(kExpectedSystemMode, directory_mode);
106 EXPECT_EQ(kRootUid, directory_owner);
107 EXPECT_EQ(kRootGid, directory_group);
108
109 path = collector_.GetCrashDirectoryInfo(kNtpUid,
110 kChronosUid,
111 kChronosGid,
112 &directory_mode,
113 &directory_owner,
114 &directory_group);
115 EXPECT_EQ("/var/spool/crash", path.value());
116 EXPECT_EQ(kExpectedSystemMode, directory_mode);
117 EXPECT_EQ(kRootUid, directory_owner);
118 EXPECT_EQ(kRootGid, directory_group);
119
Mike Frysingerf19b5182013-05-17 19:36:47 -0400120 // No need to destroy the hash as GetCrashDirectoryInfo() will do it for us.
Ben Chan7e776902014-06-18 13:19:51 -0700121 GHashTable *active_sessions = g_hash_table_new(g_str_hash, g_str_equal);
Mike Frysingerf19b5182013-05-17 19:36:47 -0400122 char kUser[] = "chicken@butt.com";
123 char kHash[] = "hashcakes";
Ben Chan7e776902014-06-18 13:19:51 -0700124 g_hash_table_insert(active_sessions,
125 static_cast<gpointer>(kUser),
126 static_cast<gpointer>(kHash));
Mike Frysingerf19b5182013-05-17 19:36:47 -0400127 EXPECT_CALL(collector_, GetActiveUserSessions())
128 .WillOnce(Return(active_sessions));
129
130 EXPECT_EQ(collector_.IsUserSpecificDirectoryEnabled(), true);
131
Ken Mixter03403162010-08-18 15:23:16 -0700132 path = collector_.GetCrashDirectoryInfo(kChronosUid,
133 kChronosUid,
134 kChronosGid,
135 &directory_mode,
136 &directory_owner,
137 &directory_group);
Mike Frysinger37843a92013-06-11 17:03:59 -0400138 EXPECT_EQ("/home/user/hashcakes/crash", path.value());
Ken Mixter03403162010-08-18 15:23:16 -0700139 EXPECT_EQ(kExpectedUserMode, directory_mode);
140 EXPECT_EQ(kChronosUid, directory_owner);
141 EXPECT_EQ(kChronosGid, directory_group);
142}
143
144TEST_F(CrashCollectorTest, FormatDumpBasename) {
145 struct tm tm = {0};
146 tm.tm_sec = 15;
147 tm.tm_min = 50;
148 tm.tm_hour = 13;
149 tm.tm_mday = 23;
150 tm.tm_mon = 4;
151 tm.tm_year = 110;
152 tm.tm_isdst = -1;
153 std::string basename =
154 collector_.FormatDumpBasename("foo", mktime(&tm), 100);
155 ASSERT_EQ("foo.20100523.135015.100", basename);
156}
157
Ken Mixter207694d2010-10-28 15:42:37 -0700158TEST_F(CrashCollectorTest, GetCrashPath) {
159 EXPECT_EQ("/var/spool/crash/myprog.20100101.1200.1234.core",
160 collector_.GetCrashPath(FilePath("/var/spool/crash"),
161 "myprog.20100101.1200.1234",
162 "core").value());
163 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp",
164 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"),
165 "chrome.20100101.1200.1234",
166 "dmp").value());
167}
168
169
Ken Mixter04ec10f2010-08-26 16:02:02 -0700170bool CrashCollectorTest::CheckHasCapacity() {
171 static const char kFullMessage[] = "Crash directory test already full";
172 bool has_capacity = collector_.CheckHasCapacity(test_dir_);
Ken Mixtera3249322011-03-03 08:47:38 -0800173 bool has_message = FindLog(kFullMessage);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700174 EXPECT_EQ(has_message, !has_capacity);
175 return has_capacity;
176}
177
Ken Mixteree849c52010-09-30 15:30:10 -0700178TEST_F(CrashCollectorTest, CheckHasCapacityUsual) {
179 // Test kMaxCrashDirectorySize - 1 non-meta files can be added.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700180 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700181 base::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700182 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700183 }
184
Ken Mixteree849c52010-09-30 15:30:10 -0700185 // Test an additional kMaxCrashDirectorySize - 1 meta files fit.
186 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700187 base::WriteFile(test_dir_.Append(StringPrintf("file%d.meta", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700188 EXPECT_TRUE(CheckHasCapacity());
189 }
190
191 // Test an additional kMaxCrashDirectorySize meta files don't fit.
Ken Mixter04ec10f2010-08-26 16:02:02 -0700192 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700193 base::WriteFile(test_dir_.Append(StringPrintf("overage%d.meta", i)), "", 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) {
Ben Chanf30c6412014-05-22 23:09:01 -0700201 base::WriteFile(test_dir_.Append(StringPrintf("file.%d.core", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700202 EXPECT_TRUE(CheckHasCapacity());
Ken Mixter04ec10f2010-08-26 16:02:02 -0700203 }
Ben Chanf30c6412014-05-22 23:09:01 -0700204 base::WriteFile(test_dir_.Append("file.last.core"), "", 0);
Ken Mixter04ec10f2010-08-26 16:02:02 -0700205 EXPECT_FALSE(CheckHasCapacity());
206}
207
Ken Mixteree849c52010-09-30 15:30:10 -0700208TEST_F(CrashCollectorTest, CheckHasCapacityStrangeNames) {
209 // Test many files with different extensions and same base fit.
210 for (int i = 0; i < 5 * CrashCollector::kMaxCrashDirectorySize; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700211 base::WriteFile(test_dir_.Append(StringPrintf("a.%d", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700212 EXPECT_TRUE(CheckHasCapacity());
213 }
214 // Test dot files are treated as individual files.
215 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 2; ++i) {
Ben Chanf30c6412014-05-22 23:09:01 -0700216 base::WriteFile(test_dir_.Append(StringPrintf(".file%d", i)), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700217 EXPECT_TRUE(CheckHasCapacity());
218 }
Ben Chanf30c6412014-05-22 23:09:01 -0700219 base::WriteFile(test_dir_.Append("normal.meta"), "", 0);
Ken Mixteree849c52010-09-30 15:30:10 -0700220 EXPECT_FALSE(CheckHasCapacity());
221}
222
Ken Mixterafcf8082010-10-26 14:45:01 -0700223TEST_F(CrashCollectorTest, MetaData) {
Ken Mixter9b346472010-11-07 13:45:45 -0800224 const char kMetaFileBasename[] = "generated.meta";
225 FilePath meta_file = test_dir_.Append(kMetaFileBasename);
Ken Mixterafcf8082010-10-26 14:45:01 -0700226 FilePath lsb_release = test_dir_.Append("lsb-release");
227 FilePath payload_file = test_dir_.Append("payload-file");
228 std::string contents;
Lei Zhang9b1f3002014-04-24 02:10:57 -0700229 collector_.lsb_release_ = lsb_release.value();
Daniel Erat731da332015-01-28 09:48:10 -0700230 const char kLsbContents[] =
231 "CHROMEOS_RELEASE_BOARD=lumpy\n"
232 "CHROMEOS_RELEASE_VERSION=6727.0.2015_01_26_0853\n"
233 "CHROMEOS_RELEASE_NAME=Chromium OS\n";
Ben Chanf30c6412014-05-22 23:09:01 -0700234 ASSERT_TRUE(base::WriteFile(lsb_release, kLsbContents, strlen(kLsbContents)));
Ken Mixterafcf8082010-10-26 14:45:01 -0700235 const char kPayload[] = "foo";
Ben Chanf30c6412014-05-22 23:09:01 -0700236 ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
Ken Mixterafcf8082010-10-26 14:45:01 -0700237 collector_.AddCrashMetaData("foo", "bar");
238 collector_.WriteCrashMetaData(meta_file, "kernel", payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500239 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800240 const char kExpectedMeta[] =
241 "foo=bar\n"
242 "exec_name=kernel\n"
Daniel Erat731da332015-01-28 09:48:10 -0700243 "ver=6727.0.2015_01_26_0853\n"
Ken Mixter9b346472010-11-07 13:45:45 -0800244 "payload=test/payload-file\n"
245 "payload_size=3\n"
246 "done=1\n";
247 EXPECT_EQ(kExpectedMeta, contents);
248
249 // Test target of symlink is not overwritten.
250 payload_file = test_dir_.Append("payload2-file");
Ben Chanf30c6412014-05-22 23:09:01 -0700251 ASSERT_TRUE(base::WriteFile(payload_file, kPayload, strlen(kPayload)));
Ken Mixter9b346472010-11-07 13:45:45 -0800252 FilePath meta_symlink_path = test_dir_.Append("symlink.meta");
253 ASSERT_EQ(0,
254 symlink(kMetaFileBasename,
255 meta_symlink_path.value().c_str()));
Mike Frysingera557c112014-02-05 22:55:39 -0500256 ASSERT_TRUE(base::PathExists(meta_symlink_path));
Ken Mixtera3249322011-03-03 08:47:38 -0800257 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800258 collector_.WriteCrashMetaData(meta_symlink_path,
259 "kernel",
260 payload_file.value());
Ken Mixtera3249322011-03-03 08:47:38 -0800261 // Target metadata contents should have stayed the same.
Ken Mixter9b346472010-11-07 13:45:45 -0800262 contents.clear();
Mike Frysingera557c112014-02-05 22:55:39 -0500263 EXPECT_TRUE(base::ReadFileToString(meta_file, &contents));
Ken Mixter9b346472010-11-07 13:45:45 -0800264 EXPECT_EQ(kExpectedMeta, contents);
Ken Mixtera3249322011-03-03 08:47:38 -0800265 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixter9b346472010-11-07 13:45:45 -0800266
267 // Test target of dangling symlink is not created.
Mike Frysingera557c112014-02-05 22:55:39 -0500268 base::DeleteFile(meta_file, false);
269 ASSERT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800270 chromeos::ClearLog();
Ken Mixter9b346472010-11-07 13:45:45 -0800271 collector_.WriteCrashMetaData(meta_symlink_path, "kernel",
272 payload_file.value());
Mike Frysingera557c112014-02-05 22:55:39 -0500273 EXPECT_FALSE(base::PathExists(meta_file));
Ken Mixtera3249322011-03-03 08:47:38 -0800274 EXPECT_TRUE(FindLog("Unable to write"));
Ken Mixterafcf8082010-10-26 14:45:01 -0700275}
276
Ken Mixterc49dbd42010-12-14 17:44:11 -0800277TEST_F(CrashCollectorTest, GetLogContents) {
278 FilePath config_file = test_dir_.Append("crash_config");
279 FilePath output_file = test_dir_.Append("crash_log");
280 const char kConfigContents[] =
Daniel Erat731da332015-01-28 09:48:10 -0700281 "foobar=echo hello there | \\\n sed -e \"s/there/world/\"";
Ken Mixterc49dbd42010-12-14 17:44:11 -0800282 ASSERT_TRUE(
Ben Chanf30c6412014-05-22 23:09:01 -0700283 base::WriteFile(config_file, kConfigContents, strlen(kConfigContents)));
Mike Frysingera557c112014-02-05 22:55:39 -0500284 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800285 EXPECT_FALSE(collector_.GetLogContents(config_file,
286 "barfoo",
287 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500288 EXPECT_FALSE(base::PathExists(output_file));
289 base::DeleteFile(FilePath(output_file), false);
Ken Mixterc49dbd42010-12-14 17:44:11 -0800290 EXPECT_TRUE(collector_.GetLogContents(config_file,
291 "foobar",
292 output_file));
Mike Frysingera557c112014-02-05 22:55:39 -0500293 ASSERT_TRUE(base::PathExists(output_file));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800294 std::string contents;
Mike Frysingera557c112014-02-05 22:55:39 -0500295 EXPECT_TRUE(base::ReadFileToString(output_file, &contents));
Ken Mixterc49dbd42010-12-14 17:44:11 -0800296 EXPECT_EQ("hello world\n", contents);
297}