| 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 "base/string_util.h" | 8 #include "base/string_util.h" |
| 9 #include "chromeos/syslog_logging.h" |
| 10 #include "chromeos/test_helpers.h" |
| 9 #include "crash-reporter/crash_collector.h" | 11 #include "crash-reporter/crash_collector.h" |
| 10 #include "crash-reporter/system_logging_mock.h" | |
| 11 #include "crash-reporter/test_helpers.h" | |
| 12 #include "gflags/gflags.h" | 12 #include "gflags/gflags.h" |
| 13 #include "gtest/gtest.h" | 13 #include "gtest/gtest.h" |
| 14 | 14 |
| 15 // This test assumes the following standard binaries are installed. | 15 // This test assumes the following standard binaries are installed. |
| 16 static const char kBinBash[] = "/bin/bash"; | 16 static const char kBinBash[] = "/bin/bash"; |
| 17 static const char kBinCp[] = "/bin/cp"; | 17 static const char kBinCp[] = "/bin/cp"; |
| 18 static const char kBinEcho[] = "/bin/echo"; | 18 static const char kBinEcho[] = "/bin/echo"; |
| 19 static const char kBinFalse[] = "/bin/false"; | 19 static const char kBinFalse[] = "/bin/false"; |
| 20 | 20 |
| 21 void CountCrash() { | 21 void CountCrash() { |
| 22 ADD_FAILURE(); | 22 ADD_FAILURE(); |
| 23 } | 23 } |
| 24 | 24 |
| 25 bool IsMetrics() { | 25 bool IsMetrics() { |
| 26 ADD_FAILURE(); | 26 ADD_FAILURE(); |
| 27 return false; | 27 return false; |
| 28 } | 28 } |
| 29 | 29 |
| 30 class CrashCollectorTest : public ::testing::Test { | 30 class CrashCollectorTest : public ::testing::Test { |
| 31 public: | 31 public: |
| 32 void SetUp() { | 32 void SetUp() { |
| 33 collector_.Initialize(CountCrash, | 33 collector_.Initialize(CountCrash, |
| 34 IsMetrics, | 34 IsMetrics); |
| 35 &logging_); | |
| 36 test_dir_ = FilePath("test"); | 35 test_dir_ = FilePath("test"); |
| 37 file_util::CreateDirectory(test_dir_); | 36 file_util::CreateDirectory(test_dir_); |
| 37 syslog_logging::ClearAccumulatedLog(); |
| 38 } | 38 } |
| 39 | 39 |
| 40 void TearDown() { | 40 void TearDown() { |
| 41 file_util::Delete(test_dir_, true); | 41 file_util::Delete(test_dir_, true); |
| 42 } | 42 } |
| 43 | 43 |
| 44 bool CheckHasCapacity(); | 44 bool CheckHasCapacity(); |
| 45 | 45 |
| 46 protected: | 46 protected: |
| 47 SystemLoggingMock logging_; | |
| 48 CrashCollector collector_; | 47 CrashCollector collector_; |
| 49 FilePath test_dir_; | 48 FilePath test_dir_; |
| 50 }; | 49 }; |
| 51 | 50 |
| 52 TEST_F(CrashCollectorTest, Initialize) { | 51 TEST_F(CrashCollectorTest, Initialize) { |
| 53 ASSERT_TRUE(CountCrash == collector_.count_crash_function_); | 52 ASSERT_TRUE(CountCrash == collector_.count_crash_function_); |
| 54 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_); | 53 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_); |
| 55 ASSERT_TRUE(&logging_ == collector_.logger_); | |
| 56 } | 54 } |
| 57 | 55 |
| 58 TEST_F(CrashCollectorTest, WriteNewFile) { | 56 TEST_F(CrashCollectorTest, WriteNewFile) { |
| 59 FilePath test_file = test_dir_.Append("test_new"); | 57 FilePath test_file = test_dir_.Append("test_new"); |
| 60 const char kBuffer[] = "buffer"; | 58 const char kBuffer[] = "buffer"; |
| 61 EXPECT_EQ(strlen(kBuffer), | 59 EXPECT_EQ(strlen(kBuffer), |
| 62 collector_.WriteNewFile(test_file, | 60 collector_.WriteNewFile(test_file, |
| 63 kBuffer, | 61 kBuffer, |
| 64 strlen(kBuffer))); | 62 strlen(kBuffer))); |
| 65 EXPECT_LT(collector_.WriteNewFile(test_file, | 63 EXPECT_LT(collector_.WriteNewFile(test_file, |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp", | 145 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp", |
| 148 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"), | 146 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"), |
| 149 "chrome.20100101.1200.1234", | 147 "chrome.20100101.1200.1234", |
| 150 "dmp").value()); | 148 "dmp").value()); |
| 151 } | 149 } |
| 152 | 150 |
| 153 | 151 |
| 154 bool CrashCollectorTest::CheckHasCapacity() { | 152 bool CrashCollectorTest::CheckHasCapacity() { |
| 155 static const char kFullMessage[] = "Crash directory test already full"; | 153 static const char kFullMessage[] = "Crash directory test already full"; |
| 156 bool has_capacity = collector_.CheckHasCapacity(test_dir_); | 154 bool has_capacity = collector_.CheckHasCapacity(test_dir_); |
| 157 bool has_message = (logging_.log().find(kFullMessage) != std::string::npos); | 155 bool has_message = syslog_logging::Contains(kFullMessage); |
| 158 EXPECT_EQ(has_message, !has_capacity); | 156 EXPECT_EQ(has_message, !has_capacity); |
| 159 return has_capacity; | 157 return has_capacity; |
| 160 } | 158 } |
| 161 | 159 |
| 162 TEST_F(CrashCollectorTest, CheckHasCapacityUsual) { | 160 TEST_F(CrashCollectorTest, CheckHasCapacityUsual) { |
| 163 // Test kMaxCrashDirectorySize - 1 non-meta files can be added. | 161 // Test kMaxCrashDirectorySize - 1 non-meta files can be added. |
| 164 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) { | 162 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) { |
| 165 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), | 163 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), |
| 166 "", 0); | 164 "", 0); |
| 167 EXPECT_TRUE(CheckHasCapacity()); | 165 EXPECT_TRUE(CheckHasCapacity()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 // Test target of symlink is not overwritten. | 289 // Test target of symlink is not overwritten. |
| 292 payload_file = test_dir_.Append("payload2-file"); | 290 payload_file = test_dir_.Append("payload2-file"); |
| 293 ASSERT_TRUE( | 291 ASSERT_TRUE( |
| 294 file_util::WriteFile(payload_file, | 292 file_util::WriteFile(payload_file, |
| 295 kPayload, strlen(kPayload))); | 293 kPayload, strlen(kPayload))); |
| 296 FilePath meta_symlink_path = test_dir_.Append("symlink.meta"); | 294 FilePath meta_symlink_path = test_dir_.Append("symlink.meta"); |
| 297 ASSERT_EQ(0, | 295 ASSERT_EQ(0, |
| 298 symlink(kMetaFileBasename, | 296 symlink(kMetaFileBasename, |
| 299 meta_symlink_path.value().c_str())); | 297 meta_symlink_path.value().c_str())); |
| 300 ASSERT_TRUE(file_util::PathExists(meta_symlink_path)); | 298 ASSERT_TRUE(file_util::PathExists(meta_symlink_path)); |
| 301 logging_.clear(); | 299 syslog_logging::ClearAccumulatedLog(); |
| 302 collector_.WriteCrashMetaData(meta_symlink_path, | 300 collector_.WriteCrashMetaData(meta_symlink_path, |
| 303 "kernel", | 301 "kernel", |
| 304 payload_file.value()); | 302 payload_file.value()); |
| 305 // Target metadata contents sould have stayed the same. | 303 // Target metadata contents should have stayed the same. |
| 306 contents.clear(); | 304 contents.clear(); |
| 307 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents)); | 305 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents)); |
| 308 EXPECT_EQ(kExpectedMeta, contents); | 306 EXPECT_EQ(kExpectedMeta, contents); |
| 309 EXPECT_NE(std::string::npos, logging_.log().find("Unable to write")); | 307 EXPECT_TRUE(syslog_logging::Contains("Unable to write")); |
| 310 | 308 |
| 311 // Test target of dangling symlink is not created. | 309 // Test target of dangling symlink is not created. |
| 312 file_util::Delete(meta_file, false); | 310 file_util::Delete(meta_file, false); |
| 313 ASSERT_FALSE(file_util::PathExists(meta_file)); | 311 ASSERT_FALSE(file_util::PathExists(meta_file)); |
| 314 logging_.clear(); | 312 syslog_logging::ClearAccumulatedLog(); |
| 315 collector_.WriteCrashMetaData(meta_symlink_path, "kernel", | 313 collector_.WriteCrashMetaData(meta_symlink_path, "kernel", |
| 316 payload_file.value()); | 314 payload_file.value()); |
| 317 EXPECT_FALSE(file_util::PathExists(meta_file)); | 315 EXPECT_FALSE(file_util::PathExists(meta_file)); |
| 318 EXPECT_NE(std::string::npos, logging_.log().find("Unable to write")); | 316 EXPECT_TRUE(syslog_logging::Contains("Unable to write")); |
| 319 } | 317 } |
| 320 | 318 |
| 321 TEST_F(CrashCollectorTest, GetLogContents) { | 319 TEST_F(CrashCollectorTest, GetLogContents) { |
| 322 FilePath config_file = test_dir_.Append("crash_config"); | 320 FilePath config_file = test_dir_.Append("crash_config"); |
| 323 FilePath output_file = test_dir_.Append("crash_log"); | 321 FilePath output_file = test_dir_.Append("crash_log"); |
| 324 const char kConfigContents[] = | 322 const char kConfigContents[] = |
| 325 "foobar:echo hello there | sed -e \"s/there/world/\""; | 323 "foobar:echo hello there | sed -e \"s/there/world/\""; |
| 326 ASSERT_TRUE( | 324 ASSERT_TRUE( |
| 327 file_util::WriteFile(config_file, | 325 file_util::WriteFile(config_file, |
| 328 kConfigContents, strlen(kConfigContents))); | 326 kConfigContents, strlen(kConfigContents))); |
| 329 file_util::Delete(FilePath(output_file), false); | 327 file_util::Delete(FilePath(output_file), false); |
| 330 EXPECT_FALSE(collector_.GetLogContents(config_file, | 328 EXPECT_FALSE(collector_.GetLogContents(config_file, |
| 331 "barfoo", | 329 "barfoo", |
| 332 output_file)); | 330 output_file)); |
| 333 EXPECT_FALSE(file_util::PathExists(output_file)); | 331 EXPECT_FALSE(file_util::PathExists(output_file)); |
| 334 file_util::Delete(FilePath(output_file), false); | 332 file_util::Delete(FilePath(output_file), false); |
| 335 EXPECT_TRUE(collector_.GetLogContents(config_file, | 333 EXPECT_TRUE(collector_.GetLogContents(config_file, |
| 336 "foobar", | 334 "foobar", |
| 337 output_file)); | 335 output_file)); |
| 338 ASSERT_TRUE(file_util::PathExists(output_file)); | 336 ASSERT_TRUE(file_util::PathExists(output_file)); |
| 339 std::string contents; | 337 std::string contents; |
| 340 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents)); | 338 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents)); |
| 341 EXPECT_EQ("hello world\n", contents); | 339 EXPECT_EQ("hello world\n", contents); |
| 342 } | 340 } |
| 343 | 341 |
| 344 class ForkExecAndPipeTest : public CrashCollectorTest { | |
| 345 public: | |
| 346 void SetUp() { | |
| 347 CrashCollectorTest::SetUp(); | |
| 348 output_file_ = "test/fork_out"; | |
| 349 file_util::Delete(FilePath(output_file_), false); | |
| 350 } | |
| 351 | |
| 352 void TearDown() { | |
| 353 CrashCollectorTest::TearDown(); | |
| 354 } | |
| 355 | |
| 356 protected: | |
| 357 std::vector<const char *> args_; | |
| 358 const char *output_file_; | |
| 359 }; | |
| 360 | |
| 361 TEST_F(ForkExecAndPipeTest, Basic) { | |
| 362 args_.push_back(kBinEcho); | |
| 363 args_.push_back("hello world"); | |
| 364 EXPECT_EQ(0, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 365 ExpectFileEquals("hello world\n", output_file_); | |
| 366 EXPECT_EQ("", logging_.log()); | |
| 367 } | |
| 368 | |
| 369 TEST_F(ForkExecAndPipeTest, NonZeroReturnValue) { | |
| 370 args_.push_back(kBinFalse); | |
| 371 EXPECT_EQ(1, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 372 ExpectFileEquals("", output_file_); | |
| 373 EXPECT_EQ("", logging_.log()); | |
| 374 } | |
| 375 | |
| 376 TEST_F(ForkExecAndPipeTest, BadOutputFile) { | |
| 377 EXPECT_EQ(127, collector_.ForkExecAndPipe(args_, "/bad/path")); | |
| 378 } | |
| 379 | |
| 380 TEST_F(ForkExecAndPipeTest, ExistingOutputFile) { | |
| 381 args_.push_back(kBinEcho); | |
| 382 args_.push_back("hello world"); | |
| 383 EXPECT_FALSE(file_util::PathExists(FilePath(output_file_))); | |
| 384 EXPECT_EQ(0, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 385 EXPECT_TRUE(file_util::PathExists(FilePath(output_file_))); | |
| 386 EXPECT_EQ(127, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 387 } | |
| 388 | |
| 389 TEST_F(ForkExecAndPipeTest, BadExecutable) { | |
| 390 args_.push_back("false"); | |
| 391 EXPECT_EQ(127, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 392 } | |
| 393 | |
| 394 TEST_F(ForkExecAndPipeTest, StderrCaptured) { | |
| 395 std::string contents; | |
| 396 args_.push_back(kBinCp); | |
| 397 EXPECT_EQ(1, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 398 EXPECT_TRUE(file_util::ReadFileToString(FilePath(output_file_), | |
| 399 &contents)); | |
| 400 EXPECT_NE(std::string::npos, contents.find("missing file operand")); | |
| 401 EXPECT_EQ("", logging_.log()); | |
| 402 } | |
| 403 | |
| 404 TEST_F(ForkExecAndPipeTest, NULLParam) { | |
| 405 args_.push_back(NULL); | |
| 406 EXPECT_EQ(-1, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 407 EXPECT_NE(std::string::npos, | |
| 408 logging_.log().find("Bad parameter")); | |
| 409 } | |
| 410 | |
| 411 TEST_F(ForkExecAndPipeTest, NoParams) { | |
| 412 EXPECT_EQ(127, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 413 } | |
| 414 | |
| 415 TEST_F(ForkExecAndPipeTest, SegFaultHandling) { | |
| 416 args_.push_back(kBinBash); | |
| 417 args_.push_back("-c"); | |
| 418 args_.push_back("kill -SEGV $$"); | |
| 419 EXPECT_EQ(-1, collector_.ForkExecAndPipe(args_, output_file_)); | |
| 420 EXPECT_NE(std::string::npos, | |
| 421 logging_.log().find("Process did not exit normally")); | |
| 422 } | |
| 423 | |
| 424 int main(int argc, char **argv) { | 342 int main(int argc, char **argv) { |
| 425 ::testing::InitGoogleTest(&argc, argv); | 343 SetUpTests(&argc, argv, false); |
| 426 return RUN_ALL_TESTS(); | 344 return RUN_ALL_TESTS(); |
| 427 } | 345 } |
| OLD | NEW |