| 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 |