| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (C) 2016 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 |  | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 17 | #define LOG_TAG "dumpstate" | 
 | 18 | #include <cutils/log.h> | 
 | 19 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 20 | #include "DumpstateInternal.h" | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 21 | #include "DumpstateService.h" | 
 | 22 | #include "android/os/BnDumpstate.h" | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 23 | #include "dumpstate.h" | 
 | 24 |  | 
 | 25 | #include <gmock/gmock.h> | 
 | 26 | #include <gtest/gtest.h> | 
 | 27 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 28 | #include <fcntl.h> | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 29 | #include <libgen.h> | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 30 | #include <signal.h> | 
 | 31 | #include <sys/types.h> | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 32 | #include <unistd.h> | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 33 | #include <thread> | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 34 |  | 
 | 35 | #include <android-base/file.h> | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 36 | #include <android-base/properties.h> | 
 | 37 | #include <android-base/stringprintf.h> | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 38 | #include <android-base/strings.h> | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 39 |  | 
| Felipe Leme | 47e9be2 | 2016-12-21 15:37:07 -0800 | [diff] [blame] | 40 | namespace android { | 
 | 41 | namespace os { | 
 | 42 | namespace dumpstate { | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 43 |  | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 44 | using ::testing::EndsWith; | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 45 | using ::testing::HasSubstr; | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 46 | using ::testing::IsNull; | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 47 | using ::testing::IsEmpty; | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 48 | using ::testing::NotNull; | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 49 | using ::testing::StrEq; | 
 | 50 | using ::testing::StartsWith; | 
 | 51 | using ::testing::Test; | 
 | 52 | using ::testing::internal::CaptureStderr; | 
 | 53 | using ::testing::internal::CaptureStdout; | 
 | 54 | using ::testing::internal::GetCapturedStderr; | 
 | 55 | using ::testing::internal::GetCapturedStdout; | 
 | 56 |  | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 57 | class DumpstateListenerMock : public IDumpstateListener { | 
 | 58 |   public: | 
 | 59 |     MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress)); | 
 | 60 |     MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress)); | 
 | 61 |  | 
 | 62 |   protected: | 
 | 63 |     MOCK_METHOD0(onAsBinder, IBinder*()); | 
 | 64 | }; | 
 | 65 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 66 | static int calls_; | 
 | 67 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 68 | // Base class for all tests in this file | 
 | 69 | class DumpstateBaseTest : public Test { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 70 |   public: | 
 | 71 |     virtual void SetUp() override { | 
 | 72 |         calls_++; | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 73 |         SetDryRun(false); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 74 |     } | 
 | 75 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 76 |     void SetDryRun(bool dry_run) const { | 
 | 77 |         PropertiesHelper::dry_run_ = dry_run; | 
 | 78 |     } | 
 | 79 |  | 
 | 80 |     void SetBuildType(const std::string& build_type) const { | 
 | 81 |         PropertiesHelper::build_type_ = build_type; | 
 | 82 |     } | 
 | 83 |  | 
 | 84 |     bool IsStandalone() const { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 85 |         return calls_ == 1; | 
 | 86 |     } | 
 | 87 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 88 |     void DropRoot() const { | 
 | 89 |         DropRootUser(); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 90 |         uid_t uid = getuid(); | 
 | 91 |         ASSERT_EQ(2000, (int)uid); | 
 | 92 |     } | 
 | 93 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 94 |   protected: | 
 | 95 |     const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str()); | 
 | 96 |     const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/"; | 
 | 97 |     const std::string kTestDataPath = kFixturesPath + "/testdata/"; | 
 | 98 |     const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture"; | 
 | 99 |     const std::string kEchoCommand = "/system/bin/echo"; | 
 | 100 |  | 
 | 101 |     /* | 
 | 102 |      * Copies a text file fixture to a temporary file, returning it's path. | 
 | 103 |      * | 
 | 104 |      * Useful in cases where the test case changes the content of the tile. | 
 | 105 |      */ | 
 | 106 |     std::string CopyTextFileFixture(const std::string& relative_name) { | 
 | 107 |         std::string from = kTestDataPath + relative_name; | 
 | 108 |         // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it | 
 | 109 |         // around for poking when the test fails. | 
 | 110 |         std::string to = kTestDataPath + relative_name + ".tmp"; | 
 | 111 |         ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str()); | 
 | 112 |         android::base::RemoveFileIfExists(to); | 
 | 113 |         CopyTextFile(from, to); | 
 | 114 |         return to.c_str(); | 
 | 115 |     } | 
 | 116 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 117 |     // Need functions that returns void to use assertions - | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 118 |     // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 119 |     void ReadFileToString(const std::string& path, std::string* content) { | 
 | 120 |         ASSERT_TRUE(android::base::ReadFileToString(path, content)) | 
 | 121 |             << "could not read contents from " << path; | 
 | 122 |     } | 
 | 123 |     void WriteStringToFile(const std::string& content, const std::string& path) { | 
 | 124 |         ASSERT_TRUE(android::base::WriteStringToFile(content, path)) | 
 | 125 |             << "could not write contents to " << path; | 
 | 126 |     } | 
 | 127 |  | 
 | 128 |   private: | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 129 |     void CopyTextFile(const std::string& from, const std::string& to) { | 
 | 130 |         std::string content; | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 131 |         ReadFileToString(from, &content); | 
 | 132 |         WriteStringToFile(content, to); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 133 |     } | 
 | 134 | }; | 
 | 135 |  | 
 | 136 | class DumpstateTest : public DumpstateBaseTest { | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 137 |   public: | 
 | 138 |     void SetUp() { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 139 |         DumpstateBaseTest::SetUp(); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 140 |         SetDryRun(false); | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 141 |         SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)")); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 142 |         ds.progress_.reset(new Progress()); | 
| Felipe Leme | 9a523ae | 2016-10-20 15:10:33 -0700 | [diff] [blame] | 143 |         ds.update_progress_ = false; | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 144 |         ds.update_progress_threshold_ = 0; | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 145 |     } | 
 | 146 |  | 
 | 147 |     // Runs a command and capture `stdout` and `stderr`. | 
| Felipe Leme | 9a523ae | 2016-10-20 15:10:33 -0700 | [diff] [blame] | 148 |     int RunCommand(const std::string& title, const std::vector<std::string>& full_command, | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 149 |                    const CommandOptions& options = CommandOptions::DEFAULT) { | 
 | 150 |         CaptureStdout(); | 
 | 151 |         CaptureStderr(); | 
| Felipe Leme | 9a523ae | 2016-10-20 15:10:33 -0700 | [diff] [blame] | 152 |         int status = ds.RunCommand(title, full_command, options); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 153 |         out = GetCapturedStdout(); | 
 | 154 |         err = GetCapturedStderr(); | 
 | 155 |         return status; | 
 | 156 |     } | 
 | 157 |  | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 158 |     // Dumps a file and capture `stdout` and `stderr`. | 
 | 159 |     int DumpFile(const std::string& title, const std::string& path) { | 
 | 160 |         CaptureStdout(); | 
 | 161 |         CaptureStderr(); | 
 | 162 |         int status = ds.DumpFile(title, path); | 
 | 163 |         out = GetCapturedStdout(); | 
 | 164 |         err = GetCapturedStderr(); | 
 | 165 |         return status; | 
 | 166 |     } | 
 | 167 |  | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 168 |     void SetProgress(long progress, long initial_max, long threshold = 0) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 169 |         ds.update_progress_ = true; | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 170 |         ds.update_progress_threshold_ = threshold; | 
 | 171 |         ds.last_updated_progress_ = 0; | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 172 |         ds.progress_.reset(new Progress(initial_max, progress, 1.2)); | 
 | 173 |     } | 
 | 174 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 175 |     std::string GetProgressMessage(const std::string& listener_name, int progress, int max, | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 176 |                                    int old_max = 0, bool update_progress = true) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 177 |         EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress"; | 
 | 178 |         EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max"; | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 179 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 180 |         bool max_increased = old_max > 0; | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 181 |  | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 182 |         std::string message = ""; | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 183 |         if (max_increased) { | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 184 |             message = | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 185 |                 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 186 |         } | 
 | 187 |  | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 188 |         if (update_progress) { | 
 | 189 |             message += android::base::StringPrintf("Setting progress (%s): %d/%d\n", | 
 | 190 |                                                    listener_name.c_str(), progress, max); | 
 | 191 |         } | 
 | 192 |  | 
 | 193 |         return message; | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 194 |     } | 
 | 195 |  | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 196 |     // `stdout` and `stderr` from the last command ran. | 
 | 197 |     std::string out, err; | 
 | 198 |  | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 199 |     Dumpstate& ds = Dumpstate::GetInstance(); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 200 | }; | 
 | 201 |  | 
 | 202 | TEST_F(DumpstateTest, RunCommandNoArgs) { | 
 | 203 |     EXPECT_EQ(-1, RunCommand("", {})); | 
 | 204 | } | 
 | 205 |  | 
 | 206 | TEST_F(DumpstateTest, RunCommandNoTitle) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 207 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 208 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 209 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 210 | } | 
 | 211 |  | 
 | 212 | TEST_F(DumpstateTest, RunCommandWithTitle) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 213 |     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 214 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 215 |     // We don't know the exact duration, so we check the prefix and suffix | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 216 |     EXPECT_THAT(out, | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 217 |                 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------")); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 218 |     EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); | 
 | 219 | } | 
 | 220 |  | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 221 | TEST_F(DumpstateTest, RunCommandWithLoggingMessage) { | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 222 |     EXPECT_EQ( | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 223 |         0, RunCommand("", {kSimpleCommand}, | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 224 |                       CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build())); | 
 | 225 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 226 |     EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n")); | 
 | 227 | } | 
 | 228 |  | 
 | 229 | TEST_F(DumpstateTest, RunCommandRedirectStderr) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 230 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 231 |                             CommandOptions::WithTimeout(10).RedirectStderr().Build())); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 232 |     EXPECT_THAT(out, IsEmpty()); | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 233 |     EXPECT_THAT(err, StrEq("stdout\nstderr\n")); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 234 | } | 
 | 235 |  | 
 | 236 | TEST_F(DumpstateTest, RunCommandWithOneArg) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 237 |     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 238 |     EXPECT_THAT(err, IsEmpty()); | 
 | 239 |     EXPECT_THAT(out, StrEq("one\n")); | 
 | 240 | } | 
 | 241 |  | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 242 | TEST_F(DumpstateTest, RunCommandWithMultipleArgs) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 243 |     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 244 |     EXPECT_THAT(err, IsEmpty()); | 
 | 245 |     EXPECT_THAT(out, StrEq("one is the loniest number\n")); | 
 | 246 | } | 
 | 247 |  | 
 | 248 | TEST_F(DumpstateTest, RunCommandDryRun) { | 
 | 249 |     SetDryRun(true); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 250 |     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 251 |     // We don't know the exact duration, so we check the prefix and suffix | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 252 |     EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand + | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 253 |                                 ") ------\n\t(skipped on dry run)\n------")); | 
 | 254 |     EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); | 
 | 255 |     EXPECT_THAT(err, IsEmpty()); | 
 | 256 | } | 
 | 257 |  | 
 | 258 | TEST_F(DumpstateTest, RunCommandDryRunNoTitle) { | 
 | 259 |     SetDryRun(true); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 260 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 261 |     EXPECT_THAT(out, IsEmpty()); | 
 | 262 |     EXPECT_THAT(err, IsEmpty()); | 
 | 263 | } | 
 | 264 |  | 
 | 265 | TEST_F(DumpstateTest, RunCommandDryRunAlways) { | 
 | 266 |     SetDryRun(true); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 267 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build())); | 
| Felipe Leme | 4c2d663 | 2016-09-28 14:32:00 -0700 | [diff] [blame] | 268 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 269 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 270 | } | 
 | 271 |  | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 272 | TEST_F(DumpstateTest, RunCommandNotFound) { | 
 | 273 |     EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"})); | 
 | 274 |     EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code")); | 
 | 275 |     EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed")); | 
 | 276 | } | 
 | 277 |  | 
 | 278 | TEST_F(DumpstateTest, RunCommandFails) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 279 |     EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"})); | 
 | 280 |     EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand + | 
| Felipe Leme | 9a523ae | 2016-10-20 15:10:33 -0700 | [diff] [blame] | 281 |                            " --exit 42' failed: exit code 42\n")); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 282 |     EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand + | 
| Felipe Leme | 9a523ae | 2016-10-20 15:10:33 -0700 | [diff] [blame] | 283 |                            " --exit 42' failed: exit code 42\n")); | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 284 | } | 
 | 285 |  | 
 | 286 | TEST_F(DumpstateTest, RunCommandCrashes) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 287 |     EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"})); | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 288 |     // We don't know the exit code, so check just the prefix. | 
 | 289 |     EXPECT_THAT( | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 290 |         out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 291 |     EXPECT_THAT( | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 292 |         err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 293 | } | 
 | 294 |  | 
 | 295 | TEST_F(DumpstateTest, RunCommandTimesout) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 296 |     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"}, | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 297 |                              CommandOptions::WithTimeout(1).Build())); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 298 |     EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand + | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 299 |                                 " --sleep 2' timed out after 1")); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 300 |     EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand + | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 301 |                                 " --sleep 2' timed out after 1")); | 
 | 302 | } | 
 | 303 |  | 
 | 304 | TEST_F(DumpstateTest, RunCommandIsKilled) { | 
 | 305 |     CaptureStdout(); | 
 | 306 |     CaptureStderr(); | 
 | 307 |  | 
 | 308 |     std::thread t([=]() { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 309 |         EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"}, | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 310 |                                          CommandOptions::WithTimeout(100).Always().Build())); | 
 | 311 |     }); | 
 | 312 |  | 
 | 313 |     // Capture pid and pre-sleep output. | 
 | 314 |     sleep(1);  // Wait a little bit to make sure pid and 1st line were printed. | 
 | 315 |     std::string err = GetCapturedStderr(); | 
 | 316 |     EXPECT_THAT(err, StrEq("sleeping for 20s\n")); | 
 | 317 |  | 
 | 318 |     std::string out = GetCapturedStdout(); | 
 | 319 |     std::vector<std::string> lines = android::base::Split(out, "\n"); | 
 | 320 |     ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out; | 
 | 321 |  | 
 | 322 |     int pid = atoi(lines[0].c_str()); | 
 | 323 |     EXPECT_THAT(lines[1], StrEq("stdout line1")); | 
 | 324 |     EXPECT_THAT(lines[2], IsEmpty());  // \n | 
 | 325 |  | 
 | 326 |     // Then kill the process. | 
 | 327 |     CaptureStdout(); | 
 | 328 |     CaptureStderr(); | 
 | 329 |     ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid; | 
 | 330 |     t.join(); | 
 | 331 |  | 
 | 332 |     // Finally, check output after murder. | 
 | 333 |     out = GetCapturedStdout(); | 
 | 334 |     err = GetCapturedStderr(); | 
 | 335 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 336 |     EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand + | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 337 |                            " --pid --sleep 20' failed: killed by signal 15\n")); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 338 |     EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand + | 
| Felipe Leme | fd8affa | 2016-09-30 17:38:57 -0700 | [diff] [blame] | 339 |                            " --pid --sleep 20' failed: killed by signal 15\n")); | 
 | 340 | } | 
 | 341 |  | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 342 | TEST_F(DumpstateTest, RunCommandProgress) { | 
 | 343 |     sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); | 
 | 344 |     ds.listener_ = listener; | 
 | 345 |     ds.listener_name_ = "FoxMulder"; | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 346 |     SetProgress(0, 30); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 347 |  | 
 | 348 |     EXPECT_CALL(*listener, onProgressUpdated(20)); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 349 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 350 |     std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30); | 
 | 351 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 352 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 353 |  | 
 | 354 |     EXPECT_CALL(*listener, onProgressUpdated(30)); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 355 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build())); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 356 |     progress_message = GetProgressMessage(ds.listener_name_, 30, 30); | 
 | 357 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 358 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 359 |  | 
 | 360 |     // Run a command that will increase maximum timeout. | 
 | 361 |     EXPECT_CALL(*listener, onProgressUpdated(31)); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 362 |     EXPECT_CALL(*listener, onMaxProgressUpdated(37)); | 
 | 363 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); | 
 | 364 |     progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 365 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 366 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 367 |  | 
 | 368 |     // Make sure command ran while in dry_run is counted. | 
 | 369 |     SetDryRun(true); | 
 | 370 |     EXPECT_CALL(*listener, onProgressUpdated(35)); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 371 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); | 
 | 372 |     progress_message = GetProgressMessage(ds.listener_name_, 35, 37); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 373 |     EXPECT_THAT(out, IsEmpty()); | 
 | 374 |     EXPECT_THAT(err, StrEq(progress_message)); | 
 | 375 |  | 
 | 376 |     ds.listener_.clear(); | 
 | 377 | } | 
 | 378 |  | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 379 | TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) { | 
 | 380 |     sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); | 
 | 381 |     ds.listener_ = listener; | 
 | 382 |     ds.listener_name_ = "FoxMulder"; | 
 | 383 |     SetProgress(0, 8, 5);  // 8 max, 5 threshold | 
 | 384 |  | 
 | 385 |     // First update should always be sent. | 
 | 386 |     EXPECT_CALL(*listener, onProgressUpdated(1)); | 
 | 387 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); | 
 | 388 |     std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8); | 
 | 389 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 390 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 391 |  | 
 | 392 |     // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5). | 
 | 393 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); | 
 | 394 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 395 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 396 |  | 
 | 397 |     // Third update should be sent because it reaches threshold (6 - 1 = 5). | 
 | 398 |     EXPECT_CALL(*listener, onProgressUpdated(6)); | 
 | 399 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); | 
 | 400 |     progress_message = GetProgressMessage(ds.listener_name_, 6, 8); | 
 | 401 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 402 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 403 |  | 
 | 404 |     // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5). | 
 | 405 |     // But max update should be sent. | 
 | 406 |     EXPECT_CALL(*listener, onMaxProgressUpdated(10));  // 9 * 120% = 10.8 = 10 | 
 | 407 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build())); | 
 | 408 |     progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false); | 
 | 409 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 410 |     EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); | 
 | 411 |  | 
 | 412 |     ds.listener_.clear(); | 
 | 413 | } | 
 | 414 |  | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 415 | TEST_F(DumpstateTest, RunCommandDropRoot) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 416 |     if (!IsStandalone()) { | 
 | 417 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 418 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 419 |         MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n") | 
 | 420 |         return; | 
 | 421 |     } | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 422 |     // First check root case - only available when running with 'adb root'. | 
 | 423 |     uid_t uid = getuid(); | 
 | 424 |     if (uid == 0) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 425 |         EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"})); | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 426 |         EXPECT_THAT(out, StrEq("0\nstdout\n")); | 
 | 427 |         EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 428 |         return; | 
 | 429 |     } | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 430 |     // Then run dropping root. | 
 | 431 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 432 |                             CommandOptions::WithTimeout(1).DropRoot().Build())); | 
 | 433 |     EXPECT_THAT(out, StrEq("2000\nstdout\n")); | 
| Felipe Leme | 26c4157 | 2016-10-06 14:34:43 -0700 | [diff] [blame] | 434 |     EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n")); | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 435 | } | 
 | 436 |  | 
 | 437 | TEST_F(DumpstateTest, RunCommandAsRootUserBuild) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 438 |     if (!IsStandalone()) { | 
 | 439 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 440 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 441 |         MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n") | 
 | 442 |         return; | 
 | 443 |     } | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 444 |     if (!PropertiesHelper::IsUserBuild()) { | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 445 |         // Emulates user build if necessarily. | 
 | 446 |         SetBuildType("user"); | 
 | 447 |     } | 
 | 448 |  | 
 | 449 |     DropRoot(); | 
 | 450 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 451 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build())); | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 452 |  | 
 | 453 |     // We don't know the exact path of su, so we just check for the 'root ...' commands | 
 | 454 |     EXPECT_THAT(out, StartsWith("Skipping")); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 455 |     EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n")); | 
| Felipe Leme | d80e6b6 | 2016-10-03 13:08:14 -0700 | [diff] [blame] | 456 |     EXPECT_THAT(err, IsEmpty()); | 
 | 457 | } | 
 | 458 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 459 | TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) { | 
 | 460 |     if (!IsStandalone()) { | 
 | 461 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 462 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 463 |         MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n") | 
 | 464 |         return; | 
 | 465 |     } | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 466 |     if (PropertiesHelper::IsUserBuild()) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 467 |         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n"); | 
 | 468 |         return; | 
 | 469 |     } | 
 | 470 |  | 
 | 471 |     DropRoot(); | 
 | 472 |  | 
 | 473 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, | 
 | 474 |                             CommandOptions::WithTimeout(1).AsRoot().Build())); | 
 | 475 |  | 
 | 476 |     EXPECT_THAT(out, StrEq("0\nstdout\n")); | 
 | 477 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 478 | } | 
 | 479 |  | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 480 | TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) { | 
 | 481 |     EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist")); | 
 | 482 |     EXPECT_THAT(out, | 
 | 483 |                 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n")); | 
 | 484 |     EXPECT_THAT(err, IsEmpty()); | 
 | 485 | } | 
 | 486 |  | 
 | 487 | TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) { | 
 | 488 |     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); | 
 | 489 |     EXPECT_THAT(err, IsEmpty()); | 
 | 490 |     // We don't know the exact duration, so we check the prefix and suffix | 
 | 491 |     EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No " | 
 | 492 |                                 "such file or directory\n")); | 
 | 493 |     EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n")); | 
 | 494 | } | 
 | 495 |  | 
 | 496 | TEST_F(DumpstateTest, DumpFileSingleLine) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 497 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 498 |     EXPECT_THAT(err, IsEmpty()); | 
 | 499 |     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline | 
 | 500 | } | 
 | 501 |  | 
 | 502 | TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 503 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 504 |     EXPECT_THAT(err, IsEmpty()); | 
 | 505 |     EXPECT_THAT(out, StrEq("I AM LINE1\n")); | 
 | 506 | } | 
 | 507 |  | 
 | 508 | TEST_F(DumpstateTest, DumpFileMultipleLines) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 509 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 510 |     EXPECT_THAT(err, IsEmpty()); | 
 | 511 |     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); | 
 | 512 | } | 
 | 513 |  | 
 | 514 | TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 515 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 516 |     EXPECT_THAT(err, IsEmpty()); | 
 | 517 |     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); | 
 | 518 | } | 
 | 519 |  | 
 | 520 | TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) { | 
 | 521 |     SetDryRun(true); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 522 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 523 |     EXPECT_THAT(err, IsEmpty()); | 
 | 524 |     EXPECT_THAT(out, IsEmpty()); | 
 | 525 | } | 
 | 526 |  | 
 | 527 | TEST_F(DumpstateTest, DumpFileOnDryRun) { | 
 | 528 |     SetDryRun(true); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 529 |     EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 530 |     EXPECT_THAT(err, IsEmpty()); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 531 |     EXPECT_THAT( | 
 | 532 |         out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:")); | 
 | 533 |     EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 534 |     EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n")); | 
| Felipe Leme | cef0298 | 2016-10-03 17:22:22 -0700 | [diff] [blame] | 535 | } | 
 | 536 |  | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 537 | TEST_F(DumpstateTest, DumpFileUpdateProgress) { | 
 | 538 |     sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); | 
 | 539 |     ds.listener_ = listener; | 
 | 540 |     ds.listener_name_ = "FoxMulder"; | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 541 |     SetProgress(0, 30); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 542 |  | 
 | 543 |     EXPECT_CALL(*listener, onProgressUpdated(5)); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 544 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 545 |  | 
 | 546 |     std::string progress_message = | 
 | 547 |         GetProgressMessage(ds.listener_name_, 5, 30);  // TODO: unhardcode WEIGHT_FILE (5)? | 
 | 548 |     EXPECT_THAT(err, StrEq(progress_message)); | 
 | 549 |     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline | 
 | 550 |  | 
 | 551 |     ds.listener_.clear(); | 
 | 552 | } | 
 | 553 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 554 | class DumpstateServiceTest : public DumpstateBaseTest { | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 555 |   public: | 
 | 556 |     DumpstateService dss; | 
 | 557 | }; | 
 | 558 |  | 
 | 559 | TEST_F(DumpstateServiceTest, SetListenerNoName) { | 
 | 560 |     sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 561 |     sp<IDumpstateToken> token; | 
 | 562 |     EXPECT_TRUE(dss.setListener("", listener, &token).isOk()); | 
 | 563 |     ASSERT_THAT(token, IsNull()); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 564 | } | 
 | 565 |  | 
 | 566 | TEST_F(DumpstateServiceTest, SetListenerNoPointer) { | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 567 |     sp<IDumpstateToken> token; | 
 | 568 |     EXPECT_TRUE(dss.setListener("whatever", nullptr, &token).isOk()); | 
 | 569 |     ASSERT_THAT(token, IsNull()); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 570 | } | 
 | 571 |  | 
 | 572 | TEST_F(DumpstateServiceTest, SetListenerTwice) { | 
 | 573 |     sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 574 |     sp<IDumpstateToken> token; | 
 | 575 |     EXPECT_TRUE(dss.setListener("whatever", listener, &token).isOk()); | 
 | 576 |     ASSERT_THAT(token, NotNull()); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 577 |     EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); | 
 | 578 |  | 
| Felipe Leme | 009ecbb | 2016-11-07 10:18:44 -0800 | [diff] [blame] | 579 |     token.clear(); | 
 | 580 |     EXPECT_TRUE(dss.setListener("whatsoever", listener, &token).isOk()); | 
 | 581 |     ASSERT_THAT(token, IsNull()); | 
 | 582 |     EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); | 
| Felipe Leme | 75876a2 | 2016-10-27 16:31:27 -0700 | [diff] [blame] | 583 | } | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 584 |  | 
 | 585 | class ProgressTest : public DumpstateBaseTest { | 
 | 586 |   public: | 
 | 587 |     Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { | 
 | 588 |         return Progress(max, growth_factor, path); | 
 | 589 |     } | 
 | 590 |  | 
 | 591 |     void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) { | 
 | 592 |         std::string expected_content = | 
 | 593 |             android::base::StringPrintf("%d %d\n", expected_runs, expected_average); | 
 | 594 |         std::string actual_content; | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 595 |         ReadFileToString(path, &actual_content); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 596 |         ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path; | 
 | 597 |     } | 
 | 598 | }; | 
 | 599 |  | 
 | 600 | TEST_F(ProgressTest, SimpleTest) { | 
 | 601 |     Progress progress; | 
 | 602 |     EXPECT_EQ(0, progress.Get()); | 
 | 603 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); | 
 | 604 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 605 |  | 
 | 606 |     bool max_increased = progress.Inc(1); | 
 | 607 |     EXPECT_EQ(1, progress.Get()); | 
 | 608 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); | 
 | 609 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 610 |     EXPECT_FALSE(max_increased); | 
 | 611 |  | 
 | 612 |     // Ignore negative increase. | 
 | 613 |     max_increased = progress.Inc(-1); | 
 | 614 |     EXPECT_EQ(1, progress.Get()); | 
 | 615 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); | 
 | 616 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 617 |     EXPECT_FALSE(max_increased); | 
 | 618 | } | 
 | 619 |  | 
 | 620 | TEST_F(ProgressTest, MaxGrowsInsideNewRange) { | 
 | 621 |     Progress progress = GetInstance(10, 1.2);  // 20% growth factor | 
 | 622 |     EXPECT_EQ(0, progress.Get()); | 
 | 623 |     EXPECT_EQ(10, progress.GetInitialMax()); | 
 | 624 |     EXPECT_EQ(10, progress.GetMax()); | 
 | 625 |  | 
 | 626 |     // No increase | 
 | 627 |     bool max_increased = progress.Inc(10); | 
 | 628 |     EXPECT_EQ(10, progress.Get()); | 
 | 629 |     EXPECT_EQ(10, progress.GetMax()); | 
 | 630 |     EXPECT_FALSE(max_increased); | 
 | 631 |  | 
 | 632 |     // Increase, with new value < max*20% | 
 | 633 |     max_increased = progress.Inc(1); | 
 | 634 |     EXPECT_EQ(11, progress.Get()); | 
 | 635 |     EXPECT_EQ(13, progress.GetMax());  // 11 average * 20% growth = 13.2 = 13 | 
 | 636 |     EXPECT_TRUE(max_increased); | 
 | 637 | } | 
 | 638 |  | 
 | 639 | TEST_F(ProgressTest, MaxGrowsOutsideNewRange) { | 
 | 640 |     Progress progress = GetInstance(10, 1.2);  // 20% growth factor | 
 | 641 |     EXPECT_EQ(0, progress.Get()); | 
 | 642 |     EXPECT_EQ(10, progress.GetInitialMax()); | 
 | 643 |     EXPECT_EQ(10, progress.GetMax()); | 
 | 644 |  | 
 | 645 |     // No increase | 
 | 646 |     bool max_increased = progress.Inc(10); | 
 | 647 |     EXPECT_EQ(10, progress.Get()); | 
 | 648 |     EXPECT_EQ(10, progress.GetMax()); | 
 | 649 |     EXPECT_FALSE(max_increased); | 
 | 650 |  | 
 | 651 |     // Increase, with new value > max*20% | 
 | 652 |     max_increased = progress.Inc(5); | 
 | 653 |     EXPECT_EQ(15, progress.Get()); | 
 | 654 |     EXPECT_EQ(18, progress.GetMax());  // 15 average * 20% growth = 18 | 
 | 655 |     EXPECT_TRUE(max_increased); | 
 | 656 | } | 
 | 657 |  | 
 | 658 | TEST_F(ProgressTest, InvalidPath) { | 
 | 659 |     Progress progress("/devil/null"); | 
 | 660 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 661 | } | 
 | 662 |  | 
 | 663 | TEST_F(ProgressTest, EmptyFile) { | 
 | 664 |     Progress progress(CopyTextFileFixture("empty-file.txt")); | 
 | 665 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 666 | } | 
 | 667 |  | 
 | 668 | TEST_F(ProgressTest, InvalidLine1stEntryNAN) { | 
 | 669 |     Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt")); | 
 | 670 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 671 | } | 
 | 672 |  | 
 | 673 | TEST_F(ProgressTest, InvalidLine2ndEntryNAN) { | 
 | 674 |     Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt")); | 
 | 675 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 676 | } | 
 | 677 |  | 
 | 678 | TEST_F(ProgressTest, InvalidLineBothNAN) { | 
 | 679 |     Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt")); | 
 | 680 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 681 | } | 
 | 682 |  | 
 | 683 | TEST_F(ProgressTest, InvalidLine1stEntryNegative) { | 
 | 684 |     Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt")); | 
 | 685 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 686 | } | 
 | 687 |  | 
 | 688 | TEST_F(ProgressTest, InvalidLine2ndEntryNegative) { | 
 | 689 |     Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt")); | 
 | 690 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 691 | } | 
 | 692 |  | 
 | 693 | TEST_F(ProgressTest, InvalidLine1stEntryTooBig) { | 
 | 694 |     Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt")); | 
 | 695 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 696 | } | 
 | 697 |  | 
 | 698 | TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) { | 
 | 699 |     Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt")); | 
 | 700 |     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); | 
 | 701 | } | 
 | 702 |  | 
 | 703 | // Tests stats are properly saved when the file does not exists. | 
 | 704 | TEST_F(ProgressTest, FirstTime) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 705 |     if (!IsStandalone()) { | 
 | 706 |         // TODO: temporarily disabled because it's failing when running as suite | 
 | 707 |         MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n") | 
 | 708 |         return; | 
 | 709 |     } | 
 | 710 |  | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 711 |     std::string path = kTestDataPath + "FirstTime.txt"; | 
 | 712 |     android::base::RemoveFileIfExists(path); | 
 | 713 |  | 
 | 714 |     Progress run1(path); | 
 | 715 |     EXPECT_EQ(0, run1.Get()); | 
 | 716 |     EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax()); | 
 | 717 |     EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); | 
 | 718 |  | 
 | 719 |     bool max_increased = run1.Inc(20); | 
 | 720 |     EXPECT_EQ(20, run1.Get()); | 
 | 721 |     EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); | 
 | 722 |     EXPECT_FALSE(max_increased); | 
 | 723 |  | 
 | 724 |     run1.Save(); | 
 | 725 |     AssertStats(path, 1, 20); | 
 | 726 | } | 
 | 727 |  | 
 | 728 | // Tests what happens when the persistent settings contains the average duration of 1 run. | 
 | 729 | // Data on file is 1 run and 109 average. | 
 | 730 | TEST_F(ProgressTest, SecondTime) { | 
 | 731 |     std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt"); | 
 | 732 |  | 
 | 733 |     Progress run1 = GetInstance(-42, 1.2, path); | 
 | 734 |     EXPECT_EQ(0, run1.Get()); | 
 | 735 |     EXPECT_EQ(10, run1.GetInitialMax()); | 
 | 736 |     EXPECT_EQ(10, run1.GetMax()); | 
 | 737 |  | 
 | 738 |     bool max_increased = run1.Inc(20); | 
 | 739 |     EXPECT_EQ(20, run1.Get()); | 
 | 740 |     EXPECT_EQ(24, run1.GetMax()); | 
 | 741 |     EXPECT_TRUE(max_increased); | 
 | 742 |  | 
 | 743 |     // Average now is 2 runs and (10 + 20)/ 2 = 15 | 
 | 744 |     run1.Save(); | 
 | 745 |     AssertStats(path, 2, 15); | 
 | 746 |  | 
 | 747 |     Progress run2 = GetInstance(-42, 1.2, path); | 
 | 748 |     EXPECT_EQ(0, run2.Get()); | 
 | 749 |     EXPECT_EQ(15, run2.GetInitialMax()); | 
 | 750 |     EXPECT_EQ(15, run2.GetMax()); | 
 | 751 |  | 
 | 752 |     max_increased = run2.Inc(25); | 
 | 753 |     EXPECT_EQ(25, run2.Get()); | 
 | 754 |     EXPECT_EQ(30, run2.GetMax()); | 
 | 755 |     EXPECT_TRUE(max_increased); | 
 | 756 |  | 
 | 757 |     // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18 | 
 | 758 |     run2.Save(); | 
 | 759 |     AssertStats(path, 3, 18); | 
 | 760 |  | 
 | 761 |     Progress run3 = GetInstance(-42, 1.2, path); | 
 | 762 |     EXPECT_EQ(0, run3.Get()); | 
 | 763 |     EXPECT_EQ(18, run3.GetInitialMax()); | 
 | 764 |     EXPECT_EQ(18, run3.GetMax()); | 
 | 765 |  | 
 | 766 |     // Make sure average decreases as well | 
 | 767 |     max_increased = run3.Inc(5); | 
 | 768 |     EXPECT_EQ(5, run3.Get()); | 
 | 769 |     EXPECT_EQ(18, run3.GetMax()); | 
 | 770 |     EXPECT_FALSE(max_increased); | 
 | 771 |  | 
 | 772 |     // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14 | 
 | 773 |     run3.Save(); | 
 | 774 |     AssertStats(path, 4, 14); | 
 | 775 | } | 
 | 776 |  | 
 | 777 | // Tests what happens when the persistent settings contains the average duration of 2 runs. | 
 | 778 | // Data on file is 2 runs and 15 average. | 
 | 779 | TEST_F(ProgressTest, ThirdTime) { | 
 | 780 |     std::string path = CopyTextFileFixture("stats-two-runs.txt"); | 
 | 781 |     AssertStats(path, 2, 15);  // Sanity check | 
 | 782 |  | 
 | 783 |     Progress run1 = GetInstance(-42, 1.2, path); | 
 | 784 |     EXPECT_EQ(0, run1.Get()); | 
 | 785 |     EXPECT_EQ(15, run1.GetInitialMax()); | 
 | 786 |     EXPECT_EQ(15, run1.GetMax()); | 
 | 787 |  | 
 | 788 |     bool max_increased = run1.Inc(20); | 
 | 789 |     EXPECT_EQ(20, run1.Get()); | 
 | 790 |     EXPECT_EQ(24, run1.GetMax()); | 
 | 791 |     EXPECT_TRUE(max_increased); | 
 | 792 |  | 
 | 793 |     // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16 | 
 | 794 |     run1.Save(); | 
 | 795 |     AssertStats(path, 3, 16); | 
 | 796 | } | 
 | 797 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 798 | class DumpstateUtilTest : public DumpstateBaseTest { | 
 | 799 |   public: | 
 | 800 |     void SetUp() { | 
 | 801 |         DumpstateBaseTest::SetUp(); | 
 | 802 |         SetDryRun(false); | 
 | 803 |     } | 
 | 804 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 805 |     void CaptureFdOut() { | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 806 |         ReadFileToString(path_, &out); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 807 |     } | 
 | 808 |  | 
 | 809 |     void CreateFd(const std::string& name) { | 
 | 810 |         path_ = kTestDataPath + name; | 
 | 811 |         MYLOGD("Creating fd for file %s\n", path_.c_str()); | 
 | 812 |  | 
 | 813 |         fd = TEMP_FAILURE_RETRY(open(path_.c_str(), | 
 | 814 |                                      O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, | 
 | 815 |                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); | 
 | 816 |         ASSERT_GE(fd, 0) << "could not create FD for path " << path_; | 
 | 817 |     } | 
 | 818 |  | 
 | 819 |     // Runs a command into the `fd` and capture `stderr`. | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 820 |     int RunCommand(const std::string& title, const std::vector<std::string>& full_command, | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 821 |                    const CommandOptions& options = CommandOptions::DEFAULT) { | 
 | 822 |         CaptureStderr(); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 823 |         int status = RunCommandToFd(fd, title, full_command, options); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 824 |         close(fd); | 
 | 825 |  | 
 | 826 |         CaptureFdOut(); | 
 | 827 |         err = GetCapturedStderr(); | 
 | 828 |         return status; | 
 | 829 |     } | 
 | 830 |  | 
 | 831 |     // Dumps a file and into the `fd` and `stderr`. | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 832 |     int DumpFile(const std::string& title, const std::string& path) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 833 |         CaptureStderr(); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 834 |         int status = DumpFileToFd(fd, title, path); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 835 |         close(fd); | 
 | 836 |  | 
 | 837 |         CaptureFdOut(); | 
 | 838 |         err = GetCapturedStderr(); | 
 | 839 |         return status; | 
 | 840 |     } | 
 | 841 |  | 
| Ecco Park | 61ffcf7 | 2016-10-27 15:46:26 -0700 | [diff] [blame] | 842 |     // Find out the pid of the process_name | 
 | 843 |     int FindPidOfProcess(const std::string& process_name) { | 
 | 844 |         CaptureStderr(); | 
 | 845 |         int status = GetPidByName(process_name); | 
 | 846 |         err = GetCapturedStderr(); | 
 | 847 |         return status; | 
 | 848 |     } | 
 | 849 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 850 |     int fd; | 
 | 851 |  | 
 | 852 |     // 'fd` output and `stderr` from the last command ran. | 
 | 853 |     std::string out, err; | 
 | 854 |  | 
 | 855 |   private: | 
 | 856 |     std::string path_; | 
 | 857 | }; | 
 | 858 |  | 
 | 859 | TEST_F(DumpstateUtilTest, RunCommandNoArgs) { | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 860 |     CreateFd("RunCommandNoArgs.txt"); | 
 | 861 |     EXPECT_EQ(-1, RunCommand("", {})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 862 | } | 
 | 863 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 864 | TEST_F(DumpstateUtilTest, RunCommandNoTitle) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 865 |     CreateFd("RunCommandWithNoArgs.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 866 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 867 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 868 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 869 | } | 
 | 870 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 871 | TEST_F(DumpstateUtilTest, RunCommandWithTitle) { | 
 | 872 |     CreateFd("RunCommandWithNoArgs.txt"); | 
 | 873 |     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); | 
 | 874 |     EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n")); | 
 | 875 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 876 | } | 
 | 877 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 878 | TEST_F(DumpstateUtilTest, RunCommandWithOneArg) { | 
 | 879 |     CreateFd("RunCommandWithOneArg.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 880 |     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 881 |     EXPECT_THAT(err, IsEmpty()); | 
 | 882 |     EXPECT_THAT(out, StrEq("one\n")); | 
 | 883 | } | 
 | 884 |  | 
 | 885 | TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) { | 
 | 886 |     CreateFd("RunCommandWithMultipleArgs.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 887 |     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 888 |     EXPECT_THAT(err, IsEmpty()); | 
 | 889 |     EXPECT_THAT(out, StrEq("one is the loniest number\n")); | 
 | 890 | } | 
 | 891 |  | 
 | 892 | TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) { | 
 | 893 |     CreateFd("RunCommandWithLoggingMessage.txt"); | 
 | 894 |     EXPECT_EQ( | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 895 |         0, RunCommand("", {kSimpleCommand}, | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 896 |                       CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build())); | 
 | 897 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 898 |     EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n")); | 
 | 899 | } | 
 | 900 |  | 
 | 901 | TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) { | 
 | 902 |     CreateFd("RunCommandRedirectStderr.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 903 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, | 
 | 904 |                             CommandOptions::WithTimeout(10).RedirectStderr().Build())); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 905 |     EXPECT_THAT(out, IsEmpty()); | 
 | 906 |     EXPECT_THAT(err, StrEq("stdout\nstderr\n")); | 
 | 907 | } | 
 | 908 |  | 
 | 909 | TEST_F(DumpstateUtilTest, RunCommandDryRun) { | 
 | 910 |     CreateFd("RunCommandDryRun.txt"); | 
 | 911 |     SetDryRun(true); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 912 |     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); | 
 | 913 |     EXPECT_THAT(out, StrEq(android::base::StringPrintf( | 
 | 914 |                          "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n", | 
 | 915 |                          kSimpleCommand.c_str()))); | 
 | 916 |     EXPECT_THAT(err, IsEmpty()); | 
 | 917 | } | 
 | 918 |  | 
 | 919 | TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) { | 
 | 920 |     CreateFd("RunCommandDryRun.txt"); | 
 | 921 |     SetDryRun(true); | 
 | 922 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 923 |     EXPECT_THAT( | 
 | 924 |         out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str()))); | 
 | 925 |     EXPECT_THAT(err, IsEmpty()); | 
 | 926 | } | 
 | 927 |  | 
 | 928 | TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) { | 
 | 929 |     CreateFd("RunCommandDryRunAlways.txt"); | 
 | 930 |     SetDryRun(true); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 931 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build())); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 932 |     EXPECT_THAT(out, StrEq("stdout\n")); | 
 | 933 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 934 | } | 
 | 935 |  | 
 | 936 | TEST_F(DumpstateUtilTest, RunCommandNotFound) { | 
 | 937 |     CreateFd("RunCommandNotFound.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 938 |     EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 939 |     EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code")); | 
 | 940 |     EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed")); | 
 | 941 | } | 
 | 942 |  | 
 | 943 | TEST_F(DumpstateUtilTest, RunCommandFails) { | 
 | 944 |     CreateFd("RunCommandFails.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 945 |     EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 946 |     EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand + | 
 | 947 |                            " --exit 42' failed: exit code 42\n")); | 
 | 948 |     EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand + | 
 | 949 |                            " --exit 42' failed: exit code 42\n")); | 
 | 950 | } | 
 | 951 |  | 
 | 952 | TEST_F(DumpstateUtilTest, RunCommandCrashes) { | 
 | 953 |     CreateFd("RunCommandCrashes.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 954 |     EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 955 |     // We don't know the exit code, so check just the prefix. | 
 | 956 |     EXPECT_THAT( | 
 | 957 |         out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); | 
 | 958 |     EXPECT_THAT( | 
 | 959 |         err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); | 
 | 960 | } | 
 | 961 |  | 
 | 962 | TEST_F(DumpstateUtilTest, RunCommandTimesout) { | 
 | 963 |     CreateFd("RunCommandTimesout.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 964 |     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"}, | 
 | 965 |                              CommandOptions::WithTimeout(1).Build())); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 966 |     EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand + | 
 | 967 |                                 " --sleep 2' timed out after 1")); | 
 | 968 |     EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand + | 
 | 969 |                                 " --sleep 2' timed out after 1")); | 
 | 970 | } | 
 | 971 |  | 
 | 972 | TEST_F(DumpstateUtilTest, RunCommandIsKilled) { | 
 | 973 |     CreateFd("RunCommandIsKilled.txt"); | 
 | 974 |     CaptureStderr(); | 
 | 975 |  | 
 | 976 |     std::thread t([=]() { | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 977 |         EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"}, | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 978 |                                           CommandOptions::WithTimeout(100).Always().Build())); | 
 | 979 |     }); | 
 | 980 |  | 
 | 981 |     // Capture pid and pre-sleep output. | 
 | 982 |     sleep(1);  // Wait a little bit to make sure pid and 1st line were printed. | 
 | 983 |     std::string err = GetCapturedStderr(); | 
 | 984 |     EXPECT_THAT(err, StrEq("sleeping for 20s\n")); | 
 | 985 |  | 
 | 986 |     CaptureFdOut(); | 
 | 987 |     std::vector<std::string> lines = android::base::Split(out, "\n"); | 
 | 988 |     ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out; | 
 | 989 |  | 
 | 990 |     int pid = atoi(lines[0].c_str()); | 
 | 991 |     EXPECT_THAT(lines[1], StrEq("stdout line1")); | 
 | 992 |     EXPECT_THAT(lines[2], IsEmpty());  // \n | 
 | 993 |  | 
 | 994 |     // Then kill the process. | 
 | 995 |     CaptureFdOut(); | 
 | 996 |     CaptureStderr(); | 
 | 997 |     ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid; | 
 | 998 |     t.join(); | 
 | 999 |  | 
 | 1000 |     // Finally, check output after murder. | 
 | 1001 |     CaptureFdOut(); | 
 | 1002 |     err = GetCapturedStderr(); | 
 | 1003 |  | 
 | 1004 |     // out starts with the pid, which is an unknown | 
 | 1005 |     EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand + | 
 | 1006 |                               " --pid --sleep 20' failed: killed by signal 15\n")); | 
 | 1007 |     EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand + | 
 | 1008 |                            " --pid --sleep 20' failed: killed by signal 15\n")); | 
 | 1009 | } | 
 | 1010 |  | 
 | 1011 | TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) { | 
 | 1012 |     if (!IsStandalone()) { | 
 | 1013 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 1014 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 1015 |         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n") | 
 | 1016 |         return; | 
 | 1017 |     } | 
 | 1018 |     CreateFd("RunCommandAsRootUserBuild.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1019 |     if (!PropertiesHelper::IsUserBuild()) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1020 |         // Emulates user build if necessarily. | 
 | 1021 |         SetBuildType("user"); | 
 | 1022 |     } | 
 | 1023 |  | 
 | 1024 |     DropRoot(); | 
 | 1025 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1026 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build())); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1027 |  | 
 | 1028 |     // We don't know the exact path of su, so we just check for the 'root ...' commands | 
 | 1029 |     EXPECT_THAT(out, StartsWith("Skipping")); | 
 | 1030 |     EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n")); | 
 | 1031 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1032 | } | 
 | 1033 |  | 
 | 1034 | TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) { | 
 | 1035 |     if (!IsStandalone()) { | 
 | 1036 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 1037 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 1038 |         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n") | 
 | 1039 |         return; | 
 | 1040 |     } | 
 | 1041 |     CreateFd("RunCommandAsRootNonUserBuild.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1042 |     if (PropertiesHelper::IsUserBuild()) { | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 1043 |         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n"); | 
 | 1044 |         return; | 
 | 1045 |     } | 
 | 1046 |  | 
 | 1047 |     DropRoot(); | 
 | 1048 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1049 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, | 
 | 1050 |                             CommandOptions::WithTimeout(1).AsRoot().Build())); | 
| Felipe Leme | 7447d7c | 2016-11-03 18:12:22 -0700 | [diff] [blame] | 1051 |  | 
 | 1052 |     EXPECT_THAT(out, StrEq("0\nstdout\n")); | 
 | 1053 |     EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 1054 | } | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1055 |  | 
 | 1056 | TEST_F(DumpstateUtilTest, RunCommandDropRoot) { | 
 | 1057 |     if (!IsStandalone()) { | 
 | 1058 |         // TODO: temporarily disabled because it might cause other tests to fail after dropping | 
 | 1059 |         // to Shell - need to refactor tests to avoid this problem) | 
 | 1060 |         MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n") | 
 | 1061 |         return; | 
 | 1062 |     } | 
 | 1063 |     CreateFd("RunCommandDropRoot.txt"); | 
 | 1064 |     // First check root case - only available when running with 'adb root'. | 
 | 1065 |     uid_t uid = getuid(); | 
 | 1066 |     if (uid == 0) { | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1067 |         EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"})); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1068 |         EXPECT_THAT(out, StrEq("0\nstdout\n")); | 
 | 1069 |         EXPECT_THAT(err, StrEq("stderr\n")); | 
 | 1070 |         return; | 
 | 1071 |     } | 
 | 1072 |     // Then run dropping root. | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1073 |     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1074 |                             CommandOptions::WithTimeout(1).DropRoot().Build())); | 
 | 1075 |     EXPECT_THAT(out, StrEq("2000\nstdout\n")); | 
 | 1076 |     EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n")); | 
 | 1077 | } | 
 | 1078 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1079 | TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) { | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1080 |     CreateFd("DumpFileNotFound.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1081 |     EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1082 |     EXPECT_THAT(out, | 
 | 1083 |                 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n")); | 
 | 1084 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1085 | } | 
 | 1086 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1087 | TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) { | 
 | 1088 |     CreateFd("DumpFileNotFound.txt"); | 
 | 1089 |     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); | 
 | 1090 |     EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such " | 
 | 1091 |                            "file or directory\n")); | 
 | 1092 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1093 | } | 
 | 1094 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1095 | TEST_F(DumpstateUtilTest, DumpFileSingleLine) { | 
 | 1096 |     CreateFd("DumpFileSingleLine.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1097 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1098 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1099 |     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline | 
 | 1100 | } | 
 | 1101 |  | 
 | 1102 | TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) { | 
 | 1103 |     CreateFd("DumpFileSingleLineWithNewLine.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1104 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1105 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1106 |     EXPECT_THAT(out, StrEq("I AM LINE1\n")); | 
 | 1107 | } | 
 | 1108 |  | 
 | 1109 | TEST_F(DumpstateUtilTest, DumpFileMultipleLines) { | 
 | 1110 |     CreateFd("DumpFileMultipleLines.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1111 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1112 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1113 |     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); | 
 | 1114 | } | 
 | 1115 |  | 
 | 1116 | TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) { | 
 | 1117 |     CreateFd("DumpFileMultipleLinesWithNewLine.txt"); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1118 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1119 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1120 |     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); | 
 | 1121 | } | 
 | 1122 |  | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1123 | TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) { | 
 | 1124 |     CreateFd("DumpFileOnDryRun.txt"); | 
 | 1125 |     SetDryRun(true); | 
 | 1126 |     std::string path = kTestDataPath + "single-line.txt"; | 
 | 1127 |     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); | 
 | 1128 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1129 |     EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n")); | 
 | 1130 | } | 
 | 1131 |  | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1132 | TEST_F(DumpstateUtilTest, DumpFileOnDryRun) { | 
 | 1133 |     CreateFd("DumpFileOnDryRun.txt"); | 
 | 1134 |     SetDryRun(true); | 
 | 1135 |     std::string path = kTestDataPath + "single-line.txt"; | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1136 |     EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1137 |     EXPECT_THAT(err, IsEmpty()); | 
| Felipe Leme | f029297 | 2016-11-22 13:57:05 -0800 | [diff] [blame] | 1138 |     EXPECT_THAT( | 
 | 1139 |         out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:")); | 
 | 1140 |     EXPECT_THAT(out, EndsWith("skipped on dry run\n")); | 
| Felipe Leme | 46b85da | 2016-11-21 17:40:45 -0800 | [diff] [blame] | 1141 | } | 
| Ecco Park | 61ffcf7 | 2016-10-27 15:46:26 -0700 | [diff] [blame] | 1142 |  | 
 | 1143 | TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) { | 
 | 1144 |     // init process always has pid 1. | 
 | 1145 |     EXPECT_EQ(1, FindPidOfProcess("init")); | 
 | 1146 |     EXPECT_THAT(err, IsEmpty()); | 
 | 1147 | } | 
 | 1148 |  | 
 | 1149 | TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) { | 
 | 1150 |     // find the process with abnormal name. | 
 | 1151 |     EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543")); | 
 | 1152 |     EXPECT_THAT(err, StrEq("can't find the pid\n")); | 
 | 1153 | } | 
| Felipe Leme | 47e9be2 | 2016-12-21 15:37:07 -0800 | [diff] [blame] | 1154 |  | 
 | 1155 | }  // namespace dumpstate | 
 | 1156 | }  // namespace os | 
 | 1157 | }  // namespace android |