OLD | NEW |
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <unistd.h> | 5 #include <unistd.h> |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "crash-reporter/system_logging_mock.h" | 8 #include "chromeos/syslog_logging.h" |
| 9 #include "chromeos/test_helpers.h" |
9 #include "crash-reporter/user_collector.h" | 10 #include "crash-reporter/user_collector.h" |
10 #include "crash-reporter/test_helpers.h" | |
11 #include "gflags/gflags.h" | 11 #include "gflags/gflags.h" |
12 #include "gtest/gtest.h" | 12 #include "gtest/gtest.h" |
13 | 13 |
14 static int s_crashes = 0; | 14 static int s_crashes = 0; |
15 static bool s_metrics = false; | 15 static bool s_metrics = false; |
16 | 16 |
17 static const char kFilePath[] = "/my/path"; | 17 static const char kFilePath[] = "/my/path"; |
18 | 18 |
19 void CountCrash() { | 19 void CountCrash() { |
20 ++s_crashes; | 20 ++s_crashes; |
21 } | 21 } |
22 | 22 |
23 bool IsMetrics() { | 23 bool IsMetrics() { |
24 return s_metrics; | 24 return s_metrics; |
25 } | 25 } |
26 | 26 |
27 class UserCollectorTest : public ::testing::Test { | 27 class UserCollectorTest : public ::testing::Test { |
28 void SetUp() { | 28 void SetUp() { |
29 s_crashes = 0; | 29 s_crashes = 0; |
30 collector_.Initialize(CountCrash, | 30 collector_.Initialize(CountCrash, |
31 kFilePath, | 31 kFilePath, |
32 IsMetrics, | 32 IsMetrics, |
33 &logging_, | |
34 false); | 33 false); |
35 file_util::Delete(FilePath("test"), true); | 34 file_util::Delete(FilePath("test"), true); |
36 mkdir("test", 0777); | 35 mkdir("test", 0777); |
37 collector_.set_core_pattern_file("test/core_pattern"); | 36 collector_.set_core_pattern_file("test/core_pattern"); |
38 collector_.set_core_pipe_limit_file("test/core_pipe_limit"); | 37 collector_.set_core_pipe_limit_file("test/core_pipe_limit"); |
39 pid_ = getpid(); | 38 pid_ = getpid(); |
| 39 syslog_logging::ClearAccumulatedLog(); |
40 } | 40 } |
41 protected: | 41 protected: |
42 void ExpectFileEquals(const char *golden, | 42 void ExpectFileEquals(const char *golden, |
43 const char *file_path) { | 43 const char *file_path) { |
44 std::string contents; | 44 std::string contents; |
45 EXPECT_TRUE(file_util::ReadFileToString(FilePath(file_path), | 45 EXPECT_TRUE(file_util::ReadFileToString(FilePath(file_path), |
46 &contents)); | 46 &contents)); |
47 EXPECT_EQ(golden, contents); | 47 EXPECT_EQ(golden, contents); |
48 } | 48 } |
49 | 49 |
50 SystemLoggingMock logging_; | |
51 UserCollector collector_; | 50 UserCollector collector_; |
52 pid_t pid_; | 51 pid_t pid_; |
53 }; | 52 }; |
54 | 53 |
55 TEST_F(UserCollectorTest, EnableOK) { | 54 TEST_F(UserCollectorTest, EnableOK) { |
56 ASSERT_TRUE(collector_.Enable()); | 55 ASSERT_TRUE(collector_.Enable()); |
57 ExpectFileEquals("|/my/path --user=%p:%s:%e", "test/core_pattern"); | 56 ExpectFileEquals("|/my/path --user=%p:%s:%e", "test/core_pattern"); |
58 ExpectFileEquals("4", "test/core_pipe_limit"); | 57 ExpectFileEquals("4", "test/core_pipe_limit"); |
59 ASSERT_EQ(s_crashes, 0); | 58 ASSERT_EQ(s_crashes, 0); |
60 ASSERT_NE(logging_.log().find("Enabling user crash handling"), | 59 EXPECT_TRUE(syslog_logging::Contains("Enabling user crash handling")); |
61 std::string::npos); | |
62 } | 60 } |
63 | 61 |
64 TEST_F(UserCollectorTest, EnableNoPatternFileAccess) { | 62 TEST_F(UserCollectorTest, EnableNoPatternFileAccess) { |
65 collector_.set_core_pattern_file("/does_not_exist"); | 63 collector_.set_core_pattern_file("/does_not_exist"); |
66 ASSERT_FALSE(collector_.Enable()); | 64 ASSERT_FALSE(collector_.Enable()); |
67 ASSERT_EQ(s_crashes, 0); | 65 ASSERT_EQ(s_crashes, 0); |
68 ASSERT_NE(logging_.log().find("Enabling user crash handling"), | 66 EXPECT_TRUE(syslog_logging::Contains("Enabling user crash handling")); |
69 std::string::npos); | 67 EXPECT_TRUE(syslog_logging::Contains("Unable to write /does_not_exist")); |
70 ASSERT_NE(logging_.log().find("Unable to write /does_not_exist"), | |
71 std::string::npos); | |
72 } | 68 } |
73 | 69 |
74 TEST_F(UserCollectorTest, EnableNoPipeLimitFileAccess) { | 70 TEST_F(UserCollectorTest, EnableNoPipeLimitFileAccess) { |
75 collector_.set_core_pipe_limit_file("/does_not_exist"); | 71 collector_.set_core_pipe_limit_file("/does_not_exist"); |
76 ASSERT_FALSE(collector_.Enable()); | 72 ASSERT_FALSE(collector_.Enable()); |
77 ASSERT_EQ(s_crashes, 0); | 73 ASSERT_EQ(s_crashes, 0); |
78 // Core pattern should not be written if we cannot access the pipe limit | 74 // Core pattern should not be written if we cannot access the pipe limit |
79 // or otherwise we may set a pattern that results in infinite recursion. | 75 // or otherwise we may set a pattern that results in infinite recursion. |
80 ASSERT_FALSE(file_util::PathExists(FilePath("test/core_pattern"))); | 76 ASSERT_FALSE(file_util::PathExists(FilePath("test/core_pattern"))); |
81 ASSERT_NE(logging_.log().find("Enabling user crash handling"), | 77 EXPECT_TRUE(syslog_logging::Contains("Enabling user crash handling")); |
82 std::string::npos); | 78 EXPECT_TRUE(syslog_logging::Contains("Unable to write /does_not_exist")); |
83 ASSERT_NE(logging_.log().find("Unable to write /does_not_exist"), | |
84 std::string::npos); | |
85 } | 79 } |
86 | 80 |
87 TEST_F(UserCollectorTest, DisableOK) { | 81 TEST_F(UserCollectorTest, DisableOK) { |
88 ASSERT_TRUE(collector_.Disable()); | 82 ASSERT_TRUE(collector_.Disable()); |
89 ExpectFileEquals("core", "test/core_pattern"); | 83 ExpectFileEquals("core", "test/core_pattern"); |
90 ASSERT_EQ(s_crashes, 0); | 84 ASSERT_EQ(s_crashes, 0); |
91 ASSERT_NE(logging_.log().find("Disabling user crash handling"), | 85 EXPECT_TRUE(syslog_logging::Contains("Disabling user crash handling")); |
92 std::string::npos); | |
93 } | 86 } |
94 | 87 |
95 TEST_F(UserCollectorTest, DisableNoFileAccess) { | 88 TEST_F(UserCollectorTest, DisableNoFileAccess) { |
96 collector_.set_core_pattern_file("/does_not_exist"); | 89 collector_.set_core_pattern_file("/does_not_exist"); |
97 ASSERT_FALSE(collector_.Disable()); | 90 ASSERT_FALSE(collector_.Disable()); |
98 ASSERT_EQ(s_crashes, 0); | 91 ASSERT_EQ(s_crashes, 0); |
99 ASSERT_NE(logging_.log().find("Disabling user crash handling"), | 92 EXPECT_TRUE(syslog_logging::Contains("Disabling user crash handling")); |
100 std::string::npos); | 93 EXPECT_TRUE(syslog_logging::Contains("Unable to write /does_not_exist")); |
101 ASSERT_NE(logging_.log().find("Unable to write /does_not_exist"), | |
102 std::string::npos); | |
103 } | 94 } |
104 | 95 |
105 TEST_F(UserCollectorTest, ParseCrashAttributes) { | 96 TEST_F(UserCollectorTest, ParseCrashAttributes) { |
106 pid_t pid; | 97 pid_t pid; |
107 int signal; | 98 int signal; |
108 std::string exec_name; | 99 std::string exec_name; |
109 EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:foobar", | 100 EXPECT_TRUE(collector_.ParseCrashAttributes("123456:11:foobar", |
110 &pid, &signal, &exec_name)); | 101 &pid, &signal, &exec_name)); |
111 EXPECT_EQ(123456, pid); | 102 EXPECT_EQ(123456, pid); |
112 EXPECT_EQ(11, signal); | 103 EXPECT_EQ(11, signal); |
(...skipping 12 matching lines...) Expand all Loading... |
125 EXPECT_FALSE(collector_.ParseCrashAttributes("123456:1 :foobar", | 116 EXPECT_FALSE(collector_.ParseCrashAttributes("123456:1 :foobar", |
126 &pid, &signal, &exec_name)); | 117 &pid, &signal, &exec_name)); |
127 | 118 |
128 EXPECT_FALSE(collector_.ParseCrashAttributes("123456::foobar", | 119 EXPECT_FALSE(collector_.ParseCrashAttributes("123456::foobar", |
129 &pid, &signal, &exec_name)); | 120 &pid, &signal, &exec_name)); |
130 } | 121 } |
131 | 122 |
132 TEST_F(UserCollectorTest, HandleCrashWithoutMetrics) { | 123 TEST_F(UserCollectorTest, HandleCrashWithoutMetrics) { |
133 s_metrics = false; | 124 s_metrics = false; |
134 collector_.HandleCrash("20:10:ignored", "foobar"); | 125 collector_.HandleCrash("20:10:ignored", "foobar"); |
135 ASSERT_NE(std::string::npos, | 126 EXPECT_TRUE(syslog_logging::Contains( |
136 logging_.log().find( | 127 "Received crash notification for foobar[20] sig 10")); |
137 "Received crash notification for foobar[20] sig 10")); | |
138 ASSERT_EQ(s_crashes, 0); | 128 ASSERT_EQ(s_crashes, 0); |
139 } | 129 } |
140 | 130 |
141 TEST_F(UserCollectorTest, HandleNonChromeCrashWithMetrics) { | 131 TEST_F(UserCollectorTest, HandleNonChromeCrashWithMetrics) { |
142 s_metrics = true; | 132 s_metrics = true; |
143 collector_.HandleCrash("5:2:ignored", "chromeos-wm"); | 133 collector_.HandleCrash("5:2:ignored", "chromeos-wm"); |
144 ASSERT_NE(std::string::npos, | 134 EXPECT_TRUE(syslog_logging::Contains( |
145 logging_.log().find( | 135 "Received crash notification for chromeos-wm[5] sig 2")); |
146 "Received crash notification for chromeos-wm[5] sig 2")); | |
147 ASSERT_EQ(s_crashes, 1); | 136 ASSERT_EQ(s_crashes, 1); |
148 } | 137 } |
149 | 138 |
150 TEST_F(UserCollectorTest, HandleChromeCrashWithMetrics) { | 139 TEST_F(UserCollectorTest, HandleChromeCrashWithMetrics) { |
151 s_metrics = true; | 140 s_metrics = true; |
152 collector_.HandleCrash("5:2:ignored", "chrome"); | 141 collector_.HandleCrash("5:2:ignored", "chrome"); |
153 ASSERT_NE(std::string::npos, | 142 EXPECT_TRUE(syslog_logging::Contains( |
154 logging_.log().find( | 143 "Received crash notification for chrome[5] sig 2")); |
155 "Received crash notification for chrome[5] sig 2")); | 144 EXPECT_TRUE(syslog_logging::Contains("(ignoring - chrome crash)")); |
156 ASSERT_NE(std::string::npos, | |
157 logging_.log().find("(ignoring - chrome crash)")); | |
158 ASSERT_EQ(s_crashes, 0); | 145 ASSERT_EQ(s_crashes, 0); |
159 } | 146 } |
160 | 147 |
161 TEST_F(UserCollectorTest, HandleSuppliedChromeCrashWithMetrics) { | 148 TEST_F(UserCollectorTest, HandleSuppliedChromeCrashWithMetrics) { |
162 s_metrics = true; | 149 s_metrics = true; |
163 collector_.HandleCrash("0:2:chrome", NULL); | 150 collector_.HandleCrash("0:2:chrome", NULL); |
164 ASSERT_NE(std::string::npos, | 151 EXPECT_TRUE(syslog_logging::Contains( |
165 logging_.log().find( | 152 "Received crash notification for supplied_chrome[0] sig 2")); |
166 "Received crash notification for supplied_chrome[0] sig 2")); | 153 EXPECT_TRUE(syslog_logging::Contains("(ignoring - chrome crash)")); |
167 ASSERT_NE(std::string::npos, | |
168 logging_.log().find("(ignoring - chrome crash)")); | |
169 ASSERT_EQ(s_crashes, 0); | 154 ASSERT_EQ(s_crashes, 0); |
170 } | 155 } |
171 | 156 |
172 TEST_F(UserCollectorTest, GetProcessPath) { | 157 TEST_F(UserCollectorTest, GetProcessPath) { |
173 FilePath path = collector_.GetProcessPath(100); | 158 FilePath path = collector_.GetProcessPath(100); |
174 ASSERT_EQ("/proc/100", path.value()); | 159 ASSERT_EQ("/proc/100", path.value()); |
175 } | 160 } |
176 | 161 |
177 TEST_F(UserCollectorTest, GetSymlinkTarget) { | 162 TEST_F(UserCollectorTest, GetSymlinkTarget) { |
178 FilePath result; | 163 FilePath result; |
179 ASSERT_FALSE(collector_.GetSymlinkTarget(FilePath("/does_not_exist"), | 164 ASSERT_FALSE(collector_.GetSymlinkTarget(FilePath("/does_not_exist"), |
180 &result)); | 165 &result)); |
181 ASSERT_NE(std::string::npos, | 166 ASSERT_TRUE(syslog_logging::Contains( |
182 logging_.log().find( | 167 "Readlink failed on /does_not_exist with 2")); |
183 "Readlink failed on /does_not_exist with 2")); | |
184 std::string long_link; | 168 std::string long_link; |
185 for (int i = 0; i < 50; ++i) | 169 for (int i = 0; i < 50; ++i) |
186 long_link += "0123456789"; | 170 long_link += "0123456789"; |
187 long_link += "/gold"; | 171 long_link += "/gold"; |
188 | 172 |
189 for (size_t len = 1; len <= long_link.size(); ++len) { | 173 for (size_t len = 1; len <= long_link.size(); ++len) { |
190 std::string this_link; | 174 std::string this_link; |
191 static const char kLink[] = "test/this_link"; | 175 static const char kLink[] = "test/this_link"; |
192 this_link.assign(long_link.c_str(), len); | 176 this_link.assign(long_link.c_str(), len); |
193 ASSERT_EQ(len, this_link.size()); | 177 ASSERT_EQ(len, this_link.size()); |
194 unlink(kLink); | 178 unlink(kLink); |
195 ASSERT_EQ(0, symlink(this_link.c_str(), kLink)); | 179 ASSERT_EQ(0, symlink(this_link.c_str(), kLink)); |
196 ASSERT_TRUE(collector_.GetSymlinkTarget(FilePath(kLink), &result)); | 180 ASSERT_TRUE(collector_.GetSymlinkTarget(FilePath(kLink), &result)); |
197 ASSERT_EQ(this_link, result.value()); | 181 ASSERT_EQ(this_link, result.value()); |
198 } | 182 } |
199 } | 183 } |
200 | 184 |
201 TEST_F(UserCollectorTest, GetExecutableBaseNameFromPid) { | 185 TEST_F(UserCollectorTest, GetExecutableBaseNameFromPid) { |
202 std::string base_name; | 186 std::string base_name; |
203 EXPECT_FALSE(collector_.GetExecutableBaseNameFromPid(0, &base_name)); | 187 EXPECT_FALSE(collector_.GetExecutableBaseNameFromPid(0, &base_name)); |
204 EXPECT_NE(std::string::npos, | 188 EXPECT_TRUE(syslog_logging::Contains( |
205 logging_.log().find( | 189 "Readlink failed on /proc/0/exe with 2")); |
206 "Readlink failed on /proc/0/exe with 2")); | 190 EXPECT_TRUE(syslog_logging::Contains( |
207 EXPECT_NE(std::string::npos, | 191 "GetSymlinkTarget failed - Path /proc/0 DirectoryExists: 0")); |
208 logging_.log().find( | 192 EXPECT_TRUE(syslog_logging::Contains("stat /proc/0/exe failed: -1 2")); |
209 "GetSymlinkTarget failed - Path " | |
210 "/proc/0 DirectoryExists: 0")); | |
211 EXPECT_NE(std::string::npos, | |
212 logging_.log().find( | |
213 "stat /proc/0/exe failed: -1 2")); | |
214 | 193 |
215 logging_.clear(); | 194 syslog_logging::ClearAccumulatedLog(); |
216 pid_t my_pid = getpid(); | 195 pid_t my_pid = getpid(); |
217 EXPECT_TRUE(collector_.GetExecutableBaseNameFromPid(my_pid, &base_name)); | 196 EXPECT_TRUE(collector_.GetExecutableBaseNameFromPid(my_pid, &base_name)); |
218 EXPECT_EQ(std::string::npos, | 197 EXPECT_FALSE(syslog_logging::Contains("Readlink failed")); |
219 logging_.log().find( | |
220 "Readlink failed")); | |
221 EXPECT_EQ("user_collector_test", base_name); | 198 EXPECT_EQ("user_collector_test", base_name); |
222 } | 199 } |
223 | 200 |
224 TEST_F(UserCollectorTest, GetIdFromStatus) { | 201 TEST_F(UserCollectorTest, GetIdFromStatus) { |
225 int id = 1; | 202 int id = 1; |
226 EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId, | 203 EXPECT_FALSE(collector_.GetIdFromStatus(UserCollector::kUserId, |
227 UserCollector::kIdEffective, | 204 UserCollector::kIdEffective, |
228 "nothing here", | 205 "nothing here", |
229 &id)); | 206 &id)); |
230 EXPECT_EQ(id, 1); | 207 EXPECT_EQ(id, 1); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 gid_t gid = 100; | 273 gid_t gid = 100; |
297 uid_t uid = 100; | 274 uid_t uid = 100; |
298 EXPECT_TRUE(collector_.GetUserInfoFromName("root", &uid, &gid)); | 275 EXPECT_TRUE(collector_.GetUserInfoFromName("root", &uid, &gid)); |
299 EXPECT_EQ(0, uid); | 276 EXPECT_EQ(0, uid); |
300 EXPECT_EQ(0, gid); | 277 EXPECT_EQ(0, gid); |
301 } | 278 } |
302 | 279 |
303 TEST_F(UserCollectorTest, CopyOffProcFilesBadPath) { | 280 TEST_F(UserCollectorTest, CopyOffProcFilesBadPath) { |
304 // Try a path that is not writable. | 281 // Try a path that is not writable. |
305 ASSERT_FALSE(collector_.CopyOffProcFiles(pid_, FilePath("/bad/path"))); | 282 ASSERT_FALSE(collector_.CopyOffProcFiles(pid_, FilePath("/bad/path"))); |
306 ASSERT_NE(logging_.log().find( | 283 EXPECT_TRUE(syslog_logging::Contains("Could not create /bad/path")); |
307 "Could not create /bad/path"), | |
308 std::string::npos); | |
309 } | 284 } |
310 | 285 |
311 TEST_F(UserCollectorTest, CopyOffProcFilesBadPid) { | 286 TEST_F(UserCollectorTest, CopyOffProcFilesBadPid) { |
312 FilePath container_path("test/container"); | 287 FilePath container_path("test/container"); |
313 ASSERT_FALSE(collector_.CopyOffProcFiles(0, container_path)); | 288 ASSERT_FALSE(collector_.CopyOffProcFiles(0, container_path)); |
314 ASSERT_NE(logging_.log().find( | 289 EXPECT_TRUE(syslog_logging::Contains("Path /proc/0 does not exist")); |
315 "Path /proc/0 does not exist"), | |
316 std::string::npos); | |
317 } | 290 } |
318 | 291 |
319 TEST_F(UserCollectorTest, CopyOffProcFilesOK) { | 292 TEST_F(UserCollectorTest, CopyOffProcFilesOK) { |
320 FilePath container_path("test/container"); | 293 FilePath container_path("test/container"); |
321 ASSERT_TRUE(collector_.CopyOffProcFiles(pid_, container_path)); | 294 ASSERT_TRUE(collector_.CopyOffProcFiles(pid_, container_path)); |
322 ASSERT_EQ(logging_.log().find( | 295 EXPECT_FALSE(syslog_logging::Contains("Could not copy")); |
323 "Could not copy"), std::string::npos); | |
324 static struct { | 296 static struct { |
325 const char *name; | 297 const char *name; |
326 bool exists; | 298 bool exists; |
327 } expectations[] = { | 299 } expectations[] = { |
328 { "auxv", true }, | 300 { "auxv", true }, |
329 { "cmdline", true }, | 301 { "cmdline", true }, |
330 { "environ", true }, | 302 { "environ", true }, |
331 { "maps", true }, | 303 { "maps", true }, |
332 { "mem", false }, | 304 { "mem", false }, |
333 { "mounts", false }, | 305 { "mounts", false }, |
334 { "sched", false }, | 306 { "sched", false }, |
335 { "status", true } | 307 { "status", true } |
336 }; | 308 }; |
337 for (unsigned i = 0; i < sizeof(expectations)/sizeof(expectations[0]); ++i) { | 309 for (unsigned i = 0; i < sizeof(expectations)/sizeof(expectations[0]); ++i) { |
338 EXPECT_EQ(expectations[i].exists, | 310 EXPECT_EQ(expectations[i].exists, |
339 file_util::PathExists( | 311 file_util::PathExists( |
340 container_path.Append(expectations[i].name))); | 312 container_path.Append(expectations[i].name))); |
341 } | 313 } |
342 } | 314 } |
343 | 315 |
344 int main(int argc, char **argv) { | 316 int main(int argc, char **argv) { |
345 ::testing::InitGoogleTest(&argc, argv); | 317 SetUpTests(&argc, argv, false); |
346 return RUN_ALL_TESTS(); | 318 return RUN_ALL_TESTS(); |
347 } | 319 } |
OLD | NEW |