1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "unclean_shutdown_collector.h" 18 19 #include <unistd.h> 20 21 #include <base/files/file_util.h> 22 #include <base/files/scoped_temp_dir.h> 23 #include <base/strings/string_util.h> 24 #include <brillo/syslog_logging.h> 25 #include <gmock/gmock.h> 26 #include <gtest/gtest.h> 27 28 using base::FilePath; 29 using ::brillo::FindLog; 30 31 namespace { 32 33 int s_crashes = 0; 34 bool s_metrics = true; 35 36 void CountCrash() { 37 ++s_crashes; 38 } 39 40 bool IsMetrics() { 41 return s_metrics; 42 } 43 44 } // namespace 45 46 class UncleanShutdownCollectorMock : public UncleanShutdownCollector { 47 public: 48 MOCK_METHOD0(SetUpDBus, void()); 49 }; 50 51 class UncleanShutdownCollectorTest : public ::testing::Test { 52 void SetUp() { 53 s_crashes = 0; 54 55 EXPECT_CALL(collector_, SetUpDBus()).WillRepeatedly(testing::Return()); 56 57 collector_.Initialize(CountCrash, 58 IsMetrics); 59 60 EXPECT_TRUE(test_dir_.CreateUniqueTempDir()); 61 62 test_directory_ = test_dir_.path().Append("test"); 63 test_unclean_ = test_dir_.path().Append("test/unclean"); 64 65 collector_.unclean_shutdown_file_ = test_unclean_.value().c_str(); 66 base::DeleteFile(test_unclean_, true); 67 // Set up an alternate power manager state file as well 68 collector_.powerd_suspended_file_ = 69 test_dir_.path().Append("test/suspended"); 70 brillo::ClearLog(); 71 } 72 73 protected: 74 void WriteStringToFile(const FilePath &file_path, 75 const char *data) { 76 ASSERT_EQ(strlen(data), base::WriteFile(file_path, data, strlen(data))); 77 } 78 79 UncleanShutdownCollectorMock collector_; 80 81 // Temporary directory used for tests. 82 base::ScopedTempDir test_dir_; 83 FilePath test_directory_; 84 FilePath test_unclean_; 85 }; 86 87 TEST_F(UncleanShutdownCollectorTest, EnableWithoutParent) { 88 ASSERT_TRUE(collector_.Enable()); 89 ASSERT_TRUE(base::PathExists(test_unclean_)); 90 } 91 92 TEST_F(UncleanShutdownCollectorTest, EnableWithParent) { 93 mkdir(test_directory_.value().c_str(), 0777); 94 ASSERT_TRUE(collector_.Enable()); 95 ASSERT_TRUE(base::PathExists(test_unclean_)); 96 } 97 98 TEST_F(UncleanShutdownCollectorTest, EnableCannotWrite) { 99 collector_.unclean_shutdown_file_ = "/bad/path"; 100 ASSERT_FALSE(collector_.Enable()); 101 ASSERT_TRUE(FindLog("Unable to create shutdown check file")); 102 } 103 104 TEST_F(UncleanShutdownCollectorTest, CollectTrue) { 105 ASSERT_TRUE(collector_.Enable()); 106 ASSERT_TRUE(base::PathExists(test_unclean_)); 107 ASSERT_TRUE(collector_.Collect()); 108 ASSERT_FALSE(base::PathExists(test_unclean_)); 109 ASSERT_EQ(1, s_crashes); 110 ASSERT_TRUE(FindLog("Last shutdown was not clean")); 111 } 112 113 TEST_F(UncleanShutdownCollectorTest, CollectFalse) { 114 ASSERT_FALSE(collector_.Collect()); 115 ASSERT_EQ(0, s_crashes); 116 } 117 118 TEST_F(UncleanShutdownCollectorTest, CollectDeadBatterySuspended) { 119 ASSERT_TRUE(collector_.Enable()); 120 ASSERT_TRUE(base::PathExists(test_unclean_)); 121 base::WriteFile(collector_.powerd_suspended_file_, "", 0); 122 ASSERT_FALSE(collector_.Collect()); 123 ASSERT_FALSE(base::PathExists(test_unclean_)); 124 ASSERT_FALSE(base::PathExists(collector_.powerd_suspended_file_)); 125 ASSERT_EQ(0, s_crashes); 126 ASSERT_TRUE(FindLog("Unclean shutdown occurred while suspended.")); 127 } 128 129 TEST_F(UncleanShutdownCollectorTest, Disable) { 130 ASSERT_TRUE(collector_.Enable()); 131 ASSERT_TRUE(base::PathExists(test_unclean_)); 132 ASSERT_TRUE(collector_.Disable()); 133 ASSERT_FALSE(base::PathExists(test_unclean_)); 134 ASSERT_FALSE(collector_.Collect()); 135 } 136 137 TEST_F(UncleanShutdownCollectorTest, DisableWhenNotEnabled) { 138 ASSERT_TRUE(collector_.Disable()); 139 } 140 141 TEST_F(UncleanShutdownCollectorTest, CantDisable) { 142 mkdir(test_directory_.value().c_str(), 0700); 143 if (mkdir(test_unclean_.value().c_str(), 0700)) { 144 ASSERT_EQ(EEXIST, errno) 145 << "Error while creating directory '" << test_unclean_.value() 146 << "': " << strerror(errno); 147 } 148 ASSERT_EQ(0, base::WriteFile(test_unclean_.Append("foo"), "", 0)) 149 << "Error while creating empty file '" 150 << test_unclean_.Append("foo").value() << "': " << strerror(errno); 151 ASSERT_FALSE(collector_.Disable()); 152 rmdir(test_unclean_.value().c_str()); 153 } 154