| 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 using chromeos::FindLog; |
| 22 |
| 21 void CountCrash() { | 23 void CountCrash() { |
| 22 ADD_FAILURE(); | 24 ADD_FAILURE(); |
| 23 } | 25 } |
| 24 | 26 |
| 25 bool IsMetrics() { | 27 bool IsMetrics() { |
| 26 ADD_FAILURE(); | 28 ADD_FAILURE(); |
| 27 return false; | 29 return false; |
| 28 } | 30 } |
| 29 | 31 |
| 30 class CrashCollectorTest : public ::testing::Test { | 32 class CrashCollectorTest : public ::testing::Test { |
| 31 public: | 33 public: |
| 32 void SetUp() { | 34 void SetUp() { |
| 33 collector_.Initialize(CountCrash, | 35 collector_.Initialize(CountCrash, |
| 34 IsMetrics, | 36 IsMetrics); |
| 35 &logging_); | |
| 36 test_dir_ = FilePath("test"); | 37 test_dir_ = FilePath("test"); |
| 37 file_util::CreateDirectory(test_dir_); | 38 file_util::CreateDirectory(test_dir_); |
| 39 chromeos::ClearLog(); |
| 38 } | 40 } |
| 39 | 41 |
| 40 void TearDown() { | 42 void TearDown() { |
| 41 file_util::Delete(test_dir_, true); | 43 file_util::Delete(test_dir_, true); |
| 42 } | 44 } |
| 43 | 45 |
| 44 bool CheckHasCapacity(); | 46 bool CheckHasCapacity(); |
| 45 | 47 |
| 46 protected: | 48 protected: |
| 47 SystemLoggingMock logging_; | |
| 48 CrashCollector collector_; | 49 CrashCollector collector_; |
| 49 FilePath test_dir_; | 50 FilePath test_dir_; |
| 50 }; | 51 }; |
| 51 | 52 |
| 52 TEST_F(CrashCollectorTest, Initialize) { | 53 TEST_F(CrashCollectorTest, Initialize) { |
| 53 ASSERT_TRUE(CountCrash == collector_.count_crash_function_); | 54 ASSERT_TRUE(CountCrash == collector_.count_crash_function_); |
| 54 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_); | 55 ASSERT_TRUE(IsMetrics == collector_.is_feedback_allowed_function_); |
| 55 ASSERT_TRUE(&logging_ == collector_.logger_); | |
| 56 } | 56 } |
| 57 | 57 |
| 58 TEST_F(CrashCollectorTest, WriteNewFile) { | 58 TEST_F(CrashCollectorTest, WriteNewFile) { |
| 59 FilePath test_file = test_dir_.Append("test_new"); | 59 FilePath test_file = test_dir_.Append("test_new"); |
| 60 const char kBuffer[] = "buffer"; | 60 const char kBuffer[] = "buffer"; |
| 61 EXPECT_EQ(strlen(kBuffer), | 61 EXPECT_EQ(strlen(kBuffer), |
| 62 collector_.WriteNewFile(test_file, | 62 collector_.WriteNewFile(test_file, |
| 63 kBuffer, | 63 kBuffer, |
| 64 strlen(kBuffer))); | 64 strlen(kBuffer))); |
| 65 EXPECT_LT(collector_.WriteNewFile(test_file, | 65 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", | 147 EXPECT_EQ("/home/chronos/user/crash/chrome.20100101.1200.1234.dmp", |
| 148 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"), | 148 collector_.GetCrashPath(FilePath("/home/chronos/user/crash"), |
| 149 "chrome.20100101.1200.1234", | 149 "chrome.20100101.1200.1234", |
| 150 "dmp").value()); | 150 "dmp").value()); |
| 151 } | 151 } |
| 152 | 152 |
| 153 | 153 |
| 154 bool CrashCollectorTest::CheckHasCapacity() { | 154 bool CrashCollectorTest::CheckHasCapacity() { |
| 155 static const char kFullMessage[] = "Crash directory test already full"; | 155 static const char kFullMessage[] = "Crash directory test already full"; |
| 156 bool has_capacity = collector_.CheckHasCapacity(test_dir_); | 156 bool has_capacity = collector_.CheckHasCapacity(test_dir_); |
| 157 bool has_message = (logging_.log().find(kFullMessage) != std::string::npos); | 157 bool has_message = FindLog(kFullMessage); |
| 158 EXPECT_EQ(has_message, !has_capacity); | 158 EXPECT_EQ(has_message, !has_capacity); |
| 159 return has_capacity; | 159 return has_capacity; |
| 160 } | 160 } |
| 161 | 161 |
| 162 TEST_F(CrashCollectorTest, CheckHasCapacityUsual) { | 162 TEST_F(CrashCollectorTest, CheckHasCapacityUsual) { |
| 163 // Test kMaxCrashDirectorySize - 1 non-meta files can be added. | 163 // Test kMaxCrashDirectorySize - 1 non-meta files can be added. |
| 164 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) { | 164 for (int i = 0; i < CrashCollector::kMaxCrashDirectorySize - 1; ++i) { |
| 165 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), | 165 file_util::WriteFile(test_dir_.Append(StringPrintf("file%d.core", i)), |
| 166 "", 0); | 166 "", 0); |
| 167 EXPECT_TRUE(CheckHasCapacity()); | 167 EXPECT_TRUE(CheckHasCapacity()); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 // Test target of symlink is not overwritten. | 291 // Test target of symlink is not overwritten. |
| 292 payload_file = test_dir_.Append("payload2-file"); | 292 payload_file = test_dir_.Append("payload2-file"); |
| 293 ASSERT_TRUE( | 293 ASSERT_TRUE( |
| 294 file_util::WriteFile(payload_file, | 294 file_util::WriteFile(payload_file, |
| 295 kPayload, strlen(kPayload))); | 295 kPayload, strlen(kPayload))); |
| 296 FilePath meta_symlink_path = test_dir_.Append("symlink.meta"); | 296 FilePath meta_symlink_path = test_dir_.Append("symlink.meta"); |
| 297 ASSERT_EQ(0, | 297 ASSERT_EQ(0, |
| 298 symlink(kMetaFileBasename, | 298 symlink(kMetaFileBasename, |
| 299 meta_symlink_path.value().c_str())); | 299 meta_symlink_path.value().c_str())); |
| 300 ASSERT_TRUE(file_util::PathExists(meta_symlink_path)); | 300 ASSERT_TRUE(file_util::PathExists(meta_symlink_path)); |
| 301 logging_.clear(); | 301 chromeos::ClearLog(); |
| 302 collector_.WriteCrashMetaData(meta_symlink_path, | 302 collector_.WriteCrashMetaData(meta_symlink_path, |
| 303 "kernel", | 303 "kernel", |
| 304 payload_file.value()); | 304 payload_file.value()); |
| 305 // Target metadata contents sould have stayed the same. | 305 // Target metadata contents should have stayed the same. |
| 306 contents.clear(); | 306 contents.clear(); |
| 307 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents)); | 307 EXPECT_TRUE(file_util::ReadFileToString(meta_file, &contents)); |
| 308 EXPECT_EQ(kExpectedMeta, contents); | 308 EXPECT_EQ(kExpectedMeta, contents); |
| 309 EXPECT_NE(std::string::npos, logging_.log().find("Unable to write")); | 309 EXPECT_TRUE(FindLog("Unable to write")); |
| 310 | 310 |
| 311 // Test target of dangling symlink is not created. | 311 // Test target of dangling symlink is not created. |
| 312 file_util::Delete(meta_file, false); | 312 file_util::Delete(meta_file, false); |
| 313 ASSERT_FALSE(file_util::PathExists(meta_file)); | 313 ASSERT_FALSE(file_util::PathExists(meta_file)); |
| 314 logging_.clear(); | 314 chromeos::ClearLog(); |
| 315 collector_.WriteCrashMetaData(meta_symlink_path, "kernel", | 315 collector_.WriteCrashMetaData(meta_symlink_path, "kernel", |
| 316 payload_file.value()); | 316 payload_file.value()); |
| 317 EXPECT_FALSE(file_util::PathExists(meta_file)); | 317 EXPECT_FALSE(file_util::PathExists(meta_file)); |
| 318 EXPECT_NE(std::string::npos, logging_.log().find("Unable to write")); | 318 EXPECT_TRUE(FindLog("Unable to write")); |
| 319 } | 319 } |
| 320 | 320 |
| 321 TEST_F(CrashCollectorTest, GetLogContents) { | 321 TEST_F(CrashCollectorTest, GetLogContents) { |
| 322 FilePath config_file = test_dir_.Append("crash_config"); | 322 FilePath config_file = test_dir_.Append("crash_config"); |
| 323 FilePath output_file = test_dir_.Append("crash_log"); | 323 FilePath output_file = test_dir_.Append("crash_log"); |
| 324 const char kConfigContents[] = | 324 const char kConfigContents[] = |
| 325 "foobar:echo hello there | sed -e \"s/there/world/\""; | 325 "foobar:echo hello there | sed -e \"s/there/world/\""; |
| 326 ASSERT_TRUE( | 326 ASSERT_TRUE( |
| 327 file_util::WriteFile(config_file, | 327 file_util::WriteFile(config_file, |
| 328 kConfigContents, strlen(kConfigContents))); | 328 kConfigContents, strlen(kConfigContents))); |
| 329 file_util::Delete(FilePath(output_file), false); | 329 file_util::Delete(FilePath(output_file), false); |
| 330 EXPECT_FALSE(collector_.GetLogContents(config_file, | 330 EXPECT_FALSE(collector_.GetLogContents(config_file, |
| 331 "barfoo", | 331 "barfoo", |
| 332 output_file)); | 332 output_file)); |
| 333 EXPECT_FALSE(file_util::PathExists(output_file)); | 333 EXPECT_FALSE(file_util::PathExists(output_file)); |
| 334 file_util::Delete(FilePath(output_file), false); | 334 file_util::Delete(FilePath(output_file), false); |
| 335 EXPECT_TRUE(collector_.GetLogContents(config_file, | 335 EXPECT_TRUE(collector_.GetLogContents(config_file, |
| 336 "foobar", | 336 "foobar", |
| 337 output_file)); | 337 output_file)); |
| 338 ASSERT_TRUE(file_util::PathExists(output_file)); | 338 ASSERT_TRUE(file_util::PathExists(output_file)); |
| 339 std::string contents; | 339 std::string contents; |
| 340 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents)); | 340 EXPECT_TRUE(file_util::ReadFileToString(output_file, &contents)); |
| 341 EXPECT_EQ("hello world\n", contents); | 341 EXPECT_EQ("hello world\n", contents); |
| 342 } | 342 } |
| 343 | 343 |
| 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) { | 344 int main(int argc, char **argv) { |
| 425 ::testing::InitGoogleTest(&argc, argv); | 345 SetUpTests(&argc, argv, false); |
| 426 return RUN_ALL_TESTS(); | 346 return RUN_ALL_TESTS(); |
| 427 } | 347 } |
| OLD | NEW |