blob: 9ca894d7aebadee0040dc373ca48ac2e277a14e1 [file] [log] [blame]
Felipe Leme4c2d6632016-09-28 14:32:00 -07001/*
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 Leme75876a22016-10-27 16:31:27 -070017#define LOG_TAG "dumpstate"
18#include <cutils/log.h>
19
Felipe Lemef0292972016-11-22 13:57:05 -080020#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070021#include "DumpstateService.h"
22#include "android/os/BnDumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070023#include "dumpstate.h"
24
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
27
Felipe Leme46b85da2016-11-21 17:40:45 -080028#include <fcntl.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070029#include <libgen.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070030#include <signal.h>
31#include <sys/types.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070032#include <unistd.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070033#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070034
35#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070036#include <android-base/properties.h>
37#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070038#include <android-base/strings.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070039
Felipe Leme47e9be22016-12-21 15:37:07 -080040namespace android {
41namespace os {
42namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070043
Felipe Leme4c2d6632016-09-28 14:32:00 -070044using ::testing::EndsWith;
Felipe Leme46b85da2016-11-21 17:40:45 -080045using ::testing::HasSubstr;
Felipe Leme009ecbb2016-11-07 10:18:44 -080046using ::testing::IsNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070047using ::testing::IsEmpty;
Felipe Leme009ecbb2016-11-07 10:18:44 -080048using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070049using ::testing::StrEq;
50using ::testing::StartsWith;
51using ::testing::Test;
52using ::testing::internal::CaptureStderr;
53using ::testing::internal::CaptureStdout;
54using ::testing::internal::GetCapturedStderr;
55using ::testing::internal::GetCapturedStdout;
56
Nandana Dutt3f8c7172018-09-25 12:01:54 +010057#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
58
Felipe Leme75876a22016-10-27 16:31:27 -070059class DumpstateListenerMock : public IDumpstateListener {
60 public:
61 MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
62 MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
Vishnu Nair20cf5032018-01-05 13:15:49 -080063 MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
64 int32_t size, int32_t durationMs));
Felipe Leme75876a22016-10-27 16:31:27 -070065
66 protected:
67 MOCK_METHOD0(onAsBinder, IBinder*());
68};
69
Felipe Leme46b85da2016-11-21 17:40:45 -080070static int calls_;
71
Felipe Leme7447d7c2016-11-03 18:12:22 -070072// Base class for all tests in this file
73class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080074 public:
75 virtual void SetUp() override {
76 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080077 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080078 }
79
Felipe Lemef0292972016-11-22 13:57:05 -080080 void SetDryRun(bool dry_run) const {
81 PropertiesHelper::dry_run_ = dry_run;
82 }
83
84 void SetBuildType(const std::string& build_type) const {
85 PropertiesHelper::build_type_ = build_type;
86 }
87
Nandana Dutt4b392be2018-11-02 16:17:05 +000088 void SetUnroot(bool unroot) const {
89 PropertiesHelper::unroot_ = unroot;
90 }
91
Felipe Lemef0292972016-11-22 13:57:05 -080092 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -080093 return calls_ == 1;
94 }
95
Felipe Lemef0292972016-11-22 13:57:05 -080096 void DropRoot() const {
97 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -080098 uid_t uid = getuid();
99 ASSERT_EQ(2000, (int)uid);
100 }
101
Felipe Leme7447d7c2016-11-03 18:12:22 -0700102 protected:
103 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
104 const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
Felipe Leme7fb8dee2017-08-25 10:15:01 -0700105 const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700106 const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
107 const std::string kEchoCommand = "/system/bin/echo";
108
109 /*
110 * Copies a text file fixture to a temporary file, returning it's path.
111 *
112 * Useful in cases where the test case changes the content of the tile.
113 */
114 std::string CopyTextFileFixture(const std::string& relative_name) {
115 std::string from = kTestDataPath + relative_name;
116 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
117 // around for poking when the test fails.
118 std::string to = kTestDataPath + relative_name + ".tmp";
119 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
120 android::base::RemoveFileIfExists(to);
121 CopyTextFile(from, to);
122 return to.c_str();
123 }
124
Felipe Leme46b85da2016-11-21 17:40:45 -0800125 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700126 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800127 void ReadFileToString(const std::string& path, std::string* content) {
128 ASSERT_TRUE(android::base::ReadFileToString(path, content))
129 << "could not read contents from " << path;
130 }
131 void WriteStringToFile(const std::string& content, const std::string& path) {
132 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
133 << "could not write contents to " << path;
134 }
135
136 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700137 void CopyTextFile(const std::string& from, const std::string& to) {
138 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800139 ReadFileToString(from, &content);
140 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700141 }
142};
143
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100144class DumpOptionsTest : public Test {
145 public:
146 virtual ~DumpOptionsTest() {
147 }
148 virtual void SetUp() {
149 options_ = Dumpstate::DumpOptions();
150 }
151
152 Dumpstate::DumpOptions options_;
153};
154
155TEST_F(DumpOptionsTest, InitializeNone) {
156 // clang-format off
157 char* argv[] = {
158 const_cast<char*>("dumpstate")
159 };
160 // clang-format on
161
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100162 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
163
164 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000165
166 // These correspond to bugreport_mode = full, because that's the default.
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100167 EXPECT_FALSE(options_.do_add_date);
168 EXPECT_FALSE(options_.do_zip_file);
169 EXPECT_EQ("", options_.use_outfile);
170 EXPECT_FALSE(options_.use_socket);
171 EXPECT_FALSE(options_.use_control_socket);
172 EXPECT_FALSE(options_.show_header_only);
173 EXPECT_TRUE(options_.do_vibrate);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000174 EXPECT_TRUE(options_.do_fb);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100175 EXPECT_FALSE(options_.do_progress_updates);
176 EXPECT_FALSE(options_.is_remote_mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000177 EXPECT_TRUE(options_.do_broadcast);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100178}
179
180TEST_F(DumpOptionsTest, InitializePartial1) {
181 // clang-format off
182 char* argv[] = {
183 const_cast<char*>("dumpstate"),
184 const_cast<char*>("-d"),
185 const_cast<char*>("-z"),
186 const_cast<char*>("-o abc"),
187 const_cast<char*>("-s"),
188 const_cast<char*>("-S"),
189
190 };
191 // clang-format on
192
193 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
194
195 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
196 EXPECT_TRUE(options_.do_add_date);
197 EXPECT_TRUE(options_.do_zip_file);
198 // TODO: Maybe we should trim the filename
199 EXPECT_EQ(" abc", std::string(options_.use_outfile));
200 EXPECT_TRUE(options_.use_socket);
201 EXPECT_TRUE(options_.use_control_socket);
202
203 // Other options retain default values
204 EXPECT_FALSE(options_.show_header_only);
205 EXPECT_TRUE(options_.do_vibrate);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000206 EXPECT_TRUE(options_.do_fb);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100207 EXPECT_FALSE(options_.do_progress_updates);
208 EXPECT_FALSE(options_.is_remote_mode);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000209 EXPECT_TRUE(options_.do_broadcast);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100210}
211
212TEST_F(DumpOptionsTest, InitializePartial2) {
213 // clang-format off
214 char* argv[] = {
215 const_cast<char*>("dumpstate"),
216 const_cast<char*>("-v"),
217 const_cast<char*>("-q"),
218 const_cast<char*>("-p"),
219 const_cast<char*>("-P"),
220 const_cast<char*>("-R"),
221 const_cast<char*>("-B"),
222 };
223 // clang-format on
224
225 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
226
227 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
228 EXPECT_TRUE(options_.show_header_only);
229 EXPECT_FALSE(options_.do_vibrate);
230 EXPECT_TRUE(options_.do_fb);
231 EXPECT_TRUE(options_.do_progress_updates);
232 EXPECT_TRUE(options_.is_remote_mode);
233 EXPECT_TRUE(options_.do_broadcast);
234
235 // Other options retain default values
236 EXPECT_FALSE(options_.do_add_date);
237 EXPECT_FALSE(options_.do_zip_file);
238 EXPECT_EQ("", options_.use_outfile);
239 EXPECT_FALSE(options_.use_socket);
240 EXPECT_FALSE(options_.use_control_socket);
241}
242
243TEST_F(DumpOptionsTest, InitializeHelp) {
244 // clang-format off
245 char* argv[] = {
246 const_cast<char*>("dumpstate"),
247 const_cast<char*>("-h")
248 };
249 // clang-format on
250
251 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
252
253 // -h is for help.
254 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
255}
256
257TEST_F(DumpOptionsTest, InitializeUnknown) {
258 // clang-format off
259 char* argv[] = {
260 const_cast<char*>("dumpstate"),
261 const_cast<char*>("-u") // unknown flag
262 };
263 // clang-format on
264
265 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
266
267 // -u is unknown.
268 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
269}
270
271TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
272 options_.do_zip_file = true;
273 EXPECT_FALSE(options_.ValidateOptions());
274 options_.use_outfile = "a/b/c";
275 EXPECT_TRUE(options_.ValidateOptions());
276}
277
278TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
279 options_.do_broadcast = true;
280 EXPECT_FALSE(options_.ValidateOptions());
281 options_.use_outfile = "a/b/c";
282 EXPECT_TRUE(options_.ValidateOptions());
283}
284
285TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) {
286 options_.use_control_socket = true;
287 EXPECT_FALSE(options_.ValidateOptions());
288
289 options_.do_zip_file = true;
290 options_.use_outfile = "a/b/c"; // do_zip_file needs outfile
291 EXPECT_TRUE(options_.ValidateOptions());
292}
293
294TEST_F(DumpOptionsTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
295 options_.do_progress_updates = true;
296 options_.use_outfile = "a/b/c"; // do_progress_updates needs outfile
297 EXPECT_FALSE(options_.ValidateOptions());
298
299 options_.do_broadcast = true;
300 EXPECT_TRUE(options_.ValidateOptions());
301}
302
303TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
304 options_.is_remote_mode = true;
305 EXPECT_FALSE(options_.ValidateOptions());
306
307 options_.do_broadcast = true;
308 options_.do_zip_file = true;
309 options_.do_add_date = true;
310 options_.use_outfile = "a/b/c"; // do_broadcast needs outfile
311 EXPECT_TRUE(options_.ValidateOptions());
312}
313
Felipe Leme7447d7c2016-11-03 18:12:22 -0700314class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700315 public:
316 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800317 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700318 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700319 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700320 ds.progress_.reset(new Progress());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800321 ds.update_progress_threshold_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100322 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700323 }
324
325 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700326 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700327 const CommandOptions& options = CommandOptions::DEFAULT) {
328 CaptureStdout();
329 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700330 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700331 out = GetCapturedStdout();
332 err = GetCapturedStderr();
333 return status;
334 }
335
Felipe Lemecef02982016-10-03 17:22:22 -0700336 // Dumps a file and capture `stdout` and `stderr`.
337 int DumpFile(const std::string& title, const std::string& path) {
338 CaptureStdout();
339 CaptureStderr();
340 int status = ds.DumpFile(title, path);
341 out = GetCapturedStdout();
342 err = GetCapturedStderr();
343 return status;
344 }
345
Felipe Leme009ecbb2016-11-07 10:18:44 -0800346 void SetProgress(long progress, long initial_max, long threshold = 0) {
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100347 ds.options_->do_progress_updates = true;
Felipe Leme009ecbb2016-11-07 10:18:44 -0800348 ds.update_progress_threshold_ = threshold;
349 ds.last_updated_progress_ = 0;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700350 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
351 }
352
Felipe Leme7447d7c2016-11-03 18:12:22 -0700353 std::string GetProgressMessage(const std::string& listener_name, int progress, int max,
Felipe Leme009ecbb2016-11-07 10:18:44 -0800354 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700355 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
356 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700357
Felipe Leme7447d7c2016-11-03 18:12:22 -0700358 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700359
Felipe Leme009ecbb2016-11-07 10:18:44 -0800360 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700361 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800362 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700363 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700364 }
365
Felipe Leme009ecbb2016-11-07 10:18:44 -0800366 if (update_progress) {
367 message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
368 listener_name.c_str(), progress, max);
369 }
370
371 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700372 }
373
Felipe Leme4c2d6632016-09-28 14:32:00 -0700374 // `stdout` and `stderr` from the last command ran.
375 std::string out, err;
376
Felipe Lemefd8affa2016-09-30 17:38:57 -0700377 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700378};
379
380TEST_F(DumpstateTest, RunCommandNoArgs) {
381 EXPECT_EQ(-1, RunCommand("", {}));
382}
383
384TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700385 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700386 EXPECT_THAT(out, StrEq("stdout\n"));
387 EXPECT_THAT(err, StrEq("stderr\n"));
388}
389
390TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700391 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700392 EXPECT_THAT(err, StrEq("stderr\n"));
393 // We don't know the exact duration, so we check the prefix and suffix
Felipe Lemefd8affa2016-09-30 17:38:57 -0700394 EXPECT_THAT(out,
Felipe Leme7447d7c2016-11-03 18:12:22 -0700395 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700396 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
397}
398
Felipe Lemefd8affa2016-09-30 17:38:57 -0700399TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700400 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700401 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700402 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
403 EXPECT_THAT(out, StrEq("stdout\n"));
404 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
405}
406
407TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700408 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700409 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700410 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700411 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700412}
413
414TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700415 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700416 EXPECT_THAT(err, IsEmpty());
417 EXPECT_THAT(out, StrEq("one\n"));
418}
419
Felipe Lemefd8affa2016-09-30 17:38:57 -0700420TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700421 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700422 EXPECT_THAT(err, IsEmpty());
423 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
424}
425
426TEST_F(DumpstateTest, RunCommandDryRun) {
427 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700428 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700429 // We don't know the exact duration, so we check the prefix and suffix
Felipe Leme7447d7c2016-11-03 18:12:22 -0700430 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Felipe Leme4c2d6632016-09-28 14:32:00 -0700431 ") ------\n\t(skipped on dry run)\n------"));
432 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
433 EXPECT_THAT(err, IsEmpty());
434}
435
436TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
437 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700438 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700439 EXPECT_THAT(out, IsEmpty());
440 EXPECT_THAT(err, IsEmpty());
441}
442
443TEST_F(DumpstateTest, RunCommandDryRunAlways) {
444 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700445 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700446 EXPECT_THAT(out, StrEq("stdout\n"));
447 EXPECT_THAT(err, StrEq("stderr\n"));
448}
449
Felipe Lemefd8affa2016-09-30 17:38:57 -0700450TEST_F(DumpstateTest, RunCommandNotFound) {
451 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
452 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
453 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
454}
455
456TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700457 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
458 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700459 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700460 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700461 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700462}
463
464TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700465 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700466 // We don't know the exit code, so check just the prefix.
467 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700468 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700469 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700470 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700471}
472
473TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700474 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700475 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700476 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700477 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700478 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700479 " --sleep 2' timed out after 1"));
480}
481
482TEST_F(DumpstateTest, RunCommandIsKilled) {
483 CaptureStdout();
484 CaptureStderr();
485
486 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700487 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700488 CommandOptions::WithTimeout(100).Always().Build()));
489 });
490
491 // Capture pid and pre-sleep output.
492 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
493 std::string err = GetCapturedStderr();
494 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
495
496 std::string out = GetCapturedStdout();
497 std::vector<std::string> lines = android::base::Split(out, "\n");
498 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
499
500 int pid = atoi(lines[0].c_str());
501 EXPECT_THAT(lines[1], StrEq("stdout line1"));
502 EXPECT_THAT(lines[2], IsEmpty()); // \n
503
504 // Then kill the process.
505 CaptureStdout();
506 CaptureStderr();
507 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
508 t.join();
509
510 // Finally, check output after murder.
511 out = GetCapturedStdout();
512 err = GetCapturedStderr();
513
Felipe Leme7447d7c2016-11-03 18:12:22 -0700514 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700515 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700516 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700517 " --pid --sleep 20' failed: killed by signal 15\n"));
518}
519
Felipe Leme75876a22016-10-27 16:31:27 -0700520TEST_F(DumpstateTest, RunCommandProgress) {
521 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
522 ds.listener_ = listener;
523 ds.listener_name_ = "FoxMulder";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700524 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700525
526 EXPECT_CALL(*listener, onProgressUpdated(20));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700527 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Felipe Leme75876a22016-10-27 16:31:27 -0700528 std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
529 EXPECT_THAT(out, StrEq("stdout\n"));
530 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
531
532 EXPECT_CALL(*listener, onProgressUpdated(30));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700533 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
Felipe Leme75876a22016-10-27 16:31:27 -0700534 progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
535 EXPECT_THAT(out, StrEq("stdout\n"));
536 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
537
538 // Run a command that will increase maximum timeout.
539 EXPECT_CALL(*listener, onProgressUpdated(31));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700540 EXPECT_CALL(*listener, onMaxProgressUpdated(37));
541 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
542 progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase
Felipe Leme75876a22016-10-27 16:31:27 -0700543 EXPECT_THAT(out, StrEq("stdout\n"));
544 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
545
546 // Make sure command ran while in dry_run is counted.
547 SetDryRun(true);
548 EXPECT_CALL(*listener, onProgressUpdated(35));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700549 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
550 progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
Felipe Leme75876a22016-10-27 16:31:27 -0700551 EXPECT_THAT(out, IsEmpty());
552 EXPECT_THAT(err, StrEq(progress_message));
553
554 ds.listener_.clear();
555}
556
Felipe Leme009ecbb2016-11-07 10:18:44 -0800557TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
558 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
559 ds.listener_ = listener;
560 ds.listener_name_ = "FoxMulder";
561 SetProgress(0, 8, 5); // 8 max, 5 threshold
562
563 // First update should always be sent.
564 EXPECT_CALL(*listener, onProgressUpdated(1));
565 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
566 std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
567 EXPECT_THAT(out, StrEq("stdout\n"));
568 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
569
570 // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
571 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
572 EXPECT_THAT(out, StrEq("stdout\n"));
573 EXPECT_THAT(err, StrEq("stderr\n"));
574
575 // Third update should be sent because it reaches threshold (6 - 1 = 5).
576 EXPECT_CALL(*listener, onProgressUpdated(6));
577 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
578 progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
579 EXPECT_THAT(out, StrEq("stdout\n"));
580 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
581
582 // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
583 // But max update should be sent.
584 EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10
585 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
586 progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
587 EXPECT_THAT(out, StrEq("stdout\n"));
588 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
589
590 ds.listener_.clear();
591}
592
Felipe Lemed80e6b62016-10-03 13:08:14 -0700593TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800594 if (!IsStandalone()) {
595 // TODO: temporarily disabled because it might cause other tests to fail after dropping
596 // to Shell - need to refactor tests to avoid this problem)
597 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
598 return;
599 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700600 // First check root case - only available when running with 'adb root'.
601 uid_t uid = getuid();
602 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700603 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700604 EXPECT_THAT(out, StrEq("0\nstdout\n"));
605 EXPECT_THAT(err, StrEq("stderr\n"));
606 return;
607 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700608 // Then run dropping root.
609 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700610 CommandOptions::WithTimeout(1).DropRoot().Build()));
611 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700612 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700613}
614
615TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800616 if (!IsStandalone()) {
617 // TODO: temporarily disabled because it might cause other tests to fail after dropping
618 // to Shell - need to refactor tests to avoid this problem)
619 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
620 return;
621 }
Felipe Lemef0292972016-11-22 13:57:05 -0800622 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700623 // Emulates user build if necessarily.
624 SetBuildType("user");
625 }
626
627 DropRoot();
628
Felipe Leme7447d7c2016-11-03 18:12:22 -0700629 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700630
631 // We don't know the exact path of su, so we just check for the 'root ...' commands
632 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700633 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700634 EXPECT_THAT(err, IsEmpty());
635}
636
Felipe Leme46b85da2016-11-21 17:40:45 -0800637TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
638 if (!IsStandalone()) {
639 // TODO: temporarily disabled because it might cause other tests to fail after dropping
640 // to Shell - need to refactor tests to avoid this problem)
641 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
642 return;
643 }
Felipe Lemef0292972016-11-22 13:57:05 -0800644 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800645 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
646 return;
647 }
648
649 DropRoot();
650
651 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
652 CommandOptions::WithTimeout(1).AsRoot().Build()));
653
654 EXPECT_THAT(out, StrEq("0\nstdout\n"));
655 EXPECT_THAT(err, StrEq("stderr\n"));
656}
657
Nandana Dutt4b392be2018-11-02 16:17:05 +0000658TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
659 if (!IsStandalone()) {
660 // TODO: temporarily disabled because it might cause other tests to fail after dropping
661 // to Shell - need to refactor tests to avoid this problem)
662 MYLOGE(
663 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
664 "on test suite\n")
665 return;
666 }
667 if (PropertiesHelper::IsUserBuild()) {
668 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
669 return;
670 }
671
672 // Same test as above, but with unroot property set, which will override su availability.
673 SetUnroot(true);
674 DropRoot();
675
676 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
677 CommandOptions::WithTimeout(1).AsRoot().Build()));
678
679 // AsRoot is ineffective.
680 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
681 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
682}
683
Yifan Hong48e83a12017-10-03 14:10:07 -0700684TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
685 if (!IsStandalone()) {
686 // TODO: temporarily disabled because it might cause other tests to fail after dropping
687 // to Shell - need to refactor tests to avoid this problem)
688 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
689 return;
690 }
691 if (!PropertiesHelper::IsUserBuild()) {
692 // Emulates user build if necessarily.
693 SetBuildType("user");
694 }
695
696 DropRoot();
697
698 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
699 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
700
701 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
702 EXPECT_THAT(err, StrEq("stderr\n"));
703}
704
705TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
706 if (!IsStandalone()) {
707 // TODO: temporarily disabled because it might cause other tests to fail after dropping
708 // to Shell - need to refactor tests to avoid this problem)
709 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
710 return;
711 }
712 if (PropertiesHelper::IsUserBuild()) {
713 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
714 return;
715 }
716
717 DropRoot();
718
719 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
720 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
721
722 EXPECT_THAT(out, StrEq("0\nstdout\n"));
723 EXPECT_THAT(err, StrEq("stderr\n"));
724}
725
Nandana Dutt4b392be2018-11-02 16:17:05 +0000726TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
727 if (!IsStandalone()) {
728 // TODO: temporarily disabled because it might cause other tests to fail after dropping
729 // to Shell - need to refactor tests to avoid this problem)
730 MYLOGE(
731 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
732 "on test suite\n")
733 return;
734 }
735 if (PropertiesHelper::IsUserBuild()) {
736 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
737 return;
738 }
739 // Same test as above, but with unroot property set, which will override su availability.
740 SetUnroot(true);
741
742 DropRoot();
743
744 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
745 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
746
747 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
748 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
749 EXPECT_THAT(err, StrEq("stderr\n"));
750}
751
Felipe Lemecef02982016-10-03 17:22:22 -0700752TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
753 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
754 EXPECT_THAT(out,
755 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
756 EXPECT_THAT(err, IsEmpty());
757}
758
759TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
760 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
761 EXPECT_THAT(err, IsEmpty());
762 // We don't know the exact duration, so we check the prefix and suffix
763 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
764 "such file or directory\n"));
765 EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n"));
766}
767
768TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700769 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700770 EXPECT_THAT(err, IsEmpty());
771 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
772}
773
774TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700775 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700776 EXPECT_THAT(err, IsEmpty());
777 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
778}
779
780TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700781 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700782 EXPECT_THAT(err, IsEmpty());
783 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
784}
785
786TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700787 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700788 EXPECT_THAT(err, IsEmpty());
789 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
790}
791
792TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
793 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700794 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700795 EXPECT_THAT(err, IsEmpty());
796 EXPECT_THAT(out, IsEmpty());
797}
798
799TEST_F(DumpstateTest, DumpFileOnDryRun) {
800 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700801 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700802 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800803 EXPECT_THAT(
804 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
805 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------"));
Felipe Lemecef02982016-10-03 17:22:22 -0700806 EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700807}
808
Felipe Leme75876a22016-10-27 16:31:27 -0700809TEST_F(DumpstateTest, DumpFileUpdateProgress) {
810 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
811 ds.listener_ = listener;
812 ds.listener_name_ = "FoxMulder";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700813 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700814
815 EXPECT_CALL(*listener, onProgressUpdated(5));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700816 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700817
818 std::string progress_message =
819 GetProgressMessage(ds.listener_name_, 5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
820 EXPECT_THAT(err, StrEq(progress_message));
821 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
822
823 ds.listener_.clear();
824}
825
Felipe Leme7447d7c2016-11-03 18:12:22 -0700826class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -0700827 public:
828 DumpstateService dss;
829};
830
831TEST_F(DumpstateServiceTest, SetListenerNoName) {
832 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800833 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800834 EXPECT_TRUE(dss.setListener("", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800835 ASSERT_THAT(token, IsNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700836}
837
838TEST_F(DumpstateServiceTest, SetListenerNoPointer) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800839 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800840 EXPECT_TRUE(
841 dss.setListener("whatever", nullptr, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800842 ASSERT_THAT(token, IsNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700843}
844
845TEST_F(DumpstateServiceTest, SetListenerTwice) {
846 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800847 sp<IDumpstateToken> token;
Vishnu Nair20cf5032018-01-05 13:15:49 -0800848 EXPECT_TRUE(
849 dss.setListener("whatever", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800850 ASSERT_THAT(token, NotNull());
Felipe Leme75876a22016-10-27 16:31:27 -0700851 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
Vishnu Nair20cf5032018-01-05 13:15:49 -0800852 EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
Felipe Leme75876a22016-10-27 16:31:27 -0700853
Felipe Leme009ecbb2016-11-07 10:18:44 -0800854 token.clear();
Vishnu Nair20cf5032018-01-05 13:15:49 -0800855 EXPECT_TRUE(
856 dss.setListener("whatsoever", listener, /* getSectionDetails = */ false, &token).isOk());
Felipe Leme009ecbb2016-11-07 10:18:44 -0800857 ASSERT_THAT(token, IsNull());
858 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
Vishnu Nair20cf5032018-01-05 13:15:49 -0800859 EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
860}
861
862TEST_F(DumpstateServiceTest, SetListenerWithSectionDetails) {
863 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
864 sp<IDumpstateToken> token;
865 Dumpstate::GetInstance().listener_ = nullptr;
866 EXPECT_TRUE(
867 dss.setListener("whatever", listener, /* getSectionDetails = */ true, &token).isOk());
868 ASSERT_THAT(token, NotNull());
869 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
870 EXPECT_TRUE(Dumpstate::GetInstance().report_section_);
Felipe Leme75876a22016-10-27 16:31:27 -0700871}
Felipe Leme7447d7c2016-11-03 18:12:22 -0700872
873class ProgressTest : public DumpstateBaseTest {
874 public:
875 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
876 return Progress(max, growth_factor, path);
877 }
878
879 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
880 std::string expected_content =
881 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
882 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800883 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700884 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
885 }
886};
887
888TEST_F(ProgressTest, SimpleTest) {
889 Progress progress;
890 EXPECT_EQ(0, progress.Get());
891 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
892 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
893
894 bool max_increased = progress.Inc(1);
895 EXPECT_EQ(1, progress.Get());
896 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
897 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
898 EXPECT_FALSE(max_increased);
899
900 // Ignore negative increase.
901 max_increased = progress.Inc(-1);
902 EXPECT_EQ(1, progress.Get());
903 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
904 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
905 EXPECT_FALSE(max_increased);
906}
907
908TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
909 Progress progress = GetInstance(10, 1.2); // 20% growth factor
910 EXPECT_EQ(0, progress.Get());
911 EXPECT_EQ(10, progress.GetInitialMax());
912 EXPECT_EQ(10, progress.GetMax());
913
914 // No increase
915 bool max_increased = progress.Inc(10);
916 EXPECT_EQ(10, progress.Get());
917 EXPECT_EQ(10, progress.GetMax());
918 EXPECT_FALSE(max_increased);
919
920 // Increase, with new value < max*20%
921 max_increased = progress.Inc(1);
922 EXPECT_EQ(11, progress.Get());
923 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
924 EXPECT_TRUE(max_increased);
925}
926
927TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
928 Progress progress = GetInstance(10, 1.2); // 20% growth factor
929 EXPECT_EQ(0, progress.Get());
930 EXPECT_EQ(10, progress.GetInitialMax());
931 EXPECT_EQ(10, progress.GetMax());
932
933 // No increase
934 bool max_increased = progress.Inc(10);
935 EXPECT_EQ(10, progress.Get());
936 EXPECT_EQ(10, progress.GetMax());
937 EXPECT_FALSE(max_increased);
938
939 // Increase, with new value > max*20%
940 max_increased = progress.Inc(5);
941 EXPECT_EQ(15, progress.Get());
942 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
943 EXPECT_TRUE(max_increased);
944}
945
946TEST_F(ProgressTest, InvalidPath) {
947 Progress progress("/devil/null");
948 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
949}
950
951TEST_F(ProgressTest, EmptyFile) {
952 Progress progress(CopyTextFileFixture("empty-file.txt"));
953 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
954}
955
956TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
957 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
958 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
959}
960
961TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
962 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
963 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
964}
965
966TEST_F(ProgressTest, InvalidLineBothNAN) {
967 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
968 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
969}
970
971TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
972 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
973 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
974}
975
976TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
977 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
978 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
979}
980
981TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
982 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
983 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
984}
985
986TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
987 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
988 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
989}
990
991// Tests stats are properly saved when the file does not exists.
992TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800993 if (!IsStandalone()) {
994 // TODO: temporarily disabled because it's failing when running as suite
995 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
996 return;
997 }
998
Felipe Leme7447d7c2016-11-03 18:12:22 -0700999 std::string path = kTestDataPath + "FirstTime.txt";
1000 android::base::RemoveFileIfExists(path);
1001
1002 Progress run1(path);
1003 EXPECT_EQ(0, run1.Get());
1004 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1005 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1006
1007 bool max_increased = run1.Inc(20);
1008 EXPECT_EQ(20, run1.Get());
1009 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1010 EXPECT_FALSE(max_increased);
1011
1012 run1.Save();
1013 AssertStats(path, 1, 20);
1014}
1015
1016// Tests what happens when the persistent settings contains the average duration of 1 run.
1017// Data on file is 1 run and 109 average.
1018TEST_F(ProgressTest, SecondTime) {
1019 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1020
1021 Progress run1 = GetInstance(-42, 1.2, path);
1022 EXPECT_EQ(0, run1.Get());
1023 EXPECT_EQ(10, run1.GetInitialMax());
1024 EXPECT_EQ(10, run1.GetMax());
1025
1026 bool max_increased = run1.Inc(20);
1027 EXPECT_EQ(20, run1.Get());
1028 EXPECT_EQ(24, run1.GetMax());
1029 EXPECT_TRUE(max_increased);
1030
1031 // Average now is 2 runs and (10 + 20)/ 2 = 15
1032 run1.Save();
1033 AssertStats(path, 2, 15);
1034
1035 Progress run2 = GetInstance(-42, 1.2, path);
1036 EXPECT_EQ(0, run2.Get());
1037 EXPECT_EQ(15, run2.GetInitialMax());
1038 EXPECT_EQ(15, run2.GetMax());
1039
1040 max_increased = run2.Inc(25);
1041 EXPECT_EQ(25, run2.Get());
1042 EXPECT_EQ(30, run2.GetMax());
1043 EXPECT_TRUE(max_increased);
1044
1045 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1046 run2.Save();
1047 AssertStats(path, 3, 18);
1048
1049 Progress run3 = GetInstance(-42, 1.2, path);
1050 EXPECT_EQ(0, run3.Get());
1051 EXPECT_EQ(18, run3.GetInitialMax());
1052 EXPECT_EQ(18, run3.GetMax());
1053
1054 // Make sure average decreases as well
1055 max_increased = run3.Inc(5);
1056 EXPECT_EQ(5, run3.Get());
1057 EXPECT_EQ(18, run3.GetMax());
1058 EXPECT_FALSE(max_increased);
1059
1060 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1061 run3.Save();
1062 AssertStats(path, 4, 14);
1063}
1064
1065// Tests what happens when the persistent settings contains the average duration of 2 runs.
1066// Data on file is 2 runs and 15 average.
1067TEST_F(ProgressTest, ThirdTime) {
1068 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1069 AssertStats(path, 2, 15); // Sanity check
1070
1071 Progress run1 = GetInstance(-42, 1.2, path);
1072 EXPECT_EQ(0, run1.Get());
1073 EXPECT_EQ(15, run1.GetInitialMax());
1074 EXPECT_EQ(15, run1.GetMax());
1075
1076 bool max_increased = run1.Inc(20);
1077 EXPECT_EQ(20, run1.Get());
1078 EXPECT_EQ(24, run1.GetMax());
1079 EXPECT_TRUE(max_increased);
1080
1081 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1082 run1.Save();
1083 AssertStats(path, 3, 16);
1084}
1085
Felipe Leme46b85da2016-11-21 17:40:45 -08001086class DumpstateUtilTest : public DumpstateBaseTest {
1087 public:
1088 void SetUp() {
1089 DumpstateBaseTest::SetUp();
1090 SetDryRun(false);
1091 }
1092
Felipe Leme46b85da2016-11-21 17:40:45 -08001093 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001094 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001095 }
1096
1097 void CreateFd(const std::string& name) {
1098 path_ = kTestDataPath + name;
1099 MYLOGD("Creating fd for file %s\n", path_.c_str());
1100
1101 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1102 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1103 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1104 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1105 }
1106
1107 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001108 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001109 const CommandOptions& options = CommandOptions::DEFAULT) {
1110 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001111 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001112 close(fd);
1113
1114 CaptureFdOut();
1115 err = GetCapturedStderr();
1116 return status;
1117 }
1118
1119 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001120 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001121 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001122 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001123 close(fd);
1124
1125 CaptureFdOut();
1126 err = GetCapturedStderr();
1127 return status;
1128 }
1129
Ecco Park61ffcf72016-10-27 15:46:26 -07001130 // Find out the pid of the process_name
1131 int FindPidOfProcess(const std::string& process_name) {
1132 CaptureStderr();
1133 int status = GetPidByName(process_name);
1134 err = GetCapturedStderr();
1135 return status;
1136 }
1137
Felipe Leme46b85da2016-11-21 17:40:45 -08001138 int fd;
1139
1140 // 'fd` output and `stderr` from the last command ran.
1141 std::string out, err;
1142
1143 private:
1144 std::string path_;
1145};
1146
1147TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001148 CreateFd("RunCommandNoArgs.txt");
1149 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001150}
1151
Felipe Lemef0292972016-11-22 13:57:05 -08001152TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001153 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001154 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001155 EXPECT_THAT(out, StrEq("stdout\n"));
1156 EXPECT_THAT(err, StrEq("stderr\n"));
1157}
1158
Felipe Lemef0292972016-11-22 13:57:05 -08001159TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1160 CreateFd("RunCommandWithNoArgs.txt");
1161 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1162 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1163 EXPECT_THAT(err, StrEq("stderr\n"));
1164}
1165
Felipe Leme46b85da2016-11-21 17:40:45 -08001166TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1167 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001168 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001169 EXPECT_THAT(err, IsEmpty());
1170 EXPECT_THAT(out, StrEq("one\n"));
1171}
1172
1173TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1174 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001175 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001176 EXPECT_THAT(err, IsEmpty());
1177 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1178}
1179
1180TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1181 CreateFd("RunCommandWithLoggingMessage.txt");
1182 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001183 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001184 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1185 EXPECT_THAT(out, StrEq("stdout\n"));
1186 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1187}
1188
1189TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1190 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001191 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1192 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001193 EXPECT_THAT(out, IsEmpty());
1194 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1195}
1196
1197TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1198 CreateFd("RunCommandDryRun.txt");
1199 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001200 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1201 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1202 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1203 kSimpleCommand.c_str())));
1204 EXPECT_THAT(err, IsEmpty());
1205}
1206
1207TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1208 CreateFd("RunCommandDryRun.txt");
1209 SetDryRun(true);
1210 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001211 EXPECT_THAT(
1212 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1213 EXPECT_THAT(err, IsEmpty());
1214}
1215
1216TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1217 CreateFd("RunCommandDryRunAlways.txt");
1218 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001219 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001220 EXPECT_THAT(out, StrEq("stdout\n"));
1221 EXPECT_THAT(err, StrEq("stderr\n"));
1222}
1223
1224TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1225 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001226 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001227 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1228 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1229}
1230
1231TEST_F(DumpstateUtilTest, RunCommandFails) {
1232 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001233 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001234 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1235 " --exit 42' failed: exit code 42\n"));
1236 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1237 " --exit 42' failed: exit code 42\n"));
1238}
1239
1240TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1241 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001242 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001243 // We don't know the exit code, so check just the prefix.
1244 EXPECT_THAT(
1245 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1246 EXPECT_THAT(
1247 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1248}
1249
Vishnu Nair6921f802017-11-22 09:17:23 -08001250TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001251 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001252 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1253 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001254 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1255 " --sleep 2' timed out after 1"));
1256 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1257 " --sleep 2' timed out after 1"));
1258}
1259
Vishnu Nair6921f802017-11-22 09:17:23 -08001260TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1261 CreateFd("RunCommandTimesout.txt");
1262 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1263 CommandOptions::WithTimeoutInMs(1000).Build()));
1264 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1265 " --sleep 2' timed out after 1"));
1266 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1267 " --sleep 2' timed out after 1"));
1268}
1269
1270
Felipe Leme46b85da2016-11-21 17:40:45 -08001271TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1272 CreateFd("RunCommandIsKilled.txt");
1273 CaptureStderr();
1274
1275 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001276 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001277 CommandOptions::WithTimeout(100).Always().Build()));
1278 });
1279
1280 // Capture pid and pre-sleep output.
1281 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1282 std::string err = GetCapturedStderr();
1283 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1284
1285 CaptureFdOut();
1286 std::vector<std::string> lines = android::base::Split(out, "\n");
1287 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1288
1289 int pid = atoi(lines[0].c_str());
1290 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1291 EXPECT_THAT(lines[2], IsEmpty()); // \n
1292
1293 // Then kill the process.
1294 CaptureFdOut();
1295 CaptureStderr();
1296 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1297 t.join();
1298
1299 // Finally, check output after murder.
1300 CaptureFdOut();
1301 err = GetCapturedStderr();
1302
1303 // out starts with the pid, which is an unknown
1304 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1305 " --pid --sleep 20' failed: killed by signal 15\n"));
1306 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1307 " --pid --sleep 20' failed: killed by signal 15\n"));
1308}
1309
1310TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1311 if (!IsStandalone()) {
1312 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1313 // to Shell - need to refactor tests to avoid this problem)
1314 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1315 return;
1316 }
1317 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001318 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001319 // Emulates user build if necessarily.
1320 SetBuildType("user");
1321 }
1322
1323 DropRoot();
1324
Felipe Lemef0292972016-11-22 13:57:05 -08001325 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001326
1327 // We don't know the exact path of su, so we just check for the 'root ...' commands
1328 EXPECT_THAT(out, StartsWith("Skipping"));
1329 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1330 EXPECT_THAT(err, IsEmpty());
1331}
1332
1333TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1334 if (!IsStandalone()) {
1335 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1336 // to Shell - need to refactor tests to avoid this problem)
1337 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1338 return;
1339 }
1340 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001341 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001342 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1343 return;
1344 }
1345
1346 DropRoot();
1347
Felipe Lemef0292972016-11-22 13:57:05 -08001348 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1349 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001350
1351 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1352 EXPECT_THAT(err, StrEq("stderr\n"));
1353}
Felipe Leme46b85da2016-11-21 17:40:45 -08001354
Yifan Hong48e83a12017-10-03 14:10:07 -07001355
1356TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1357 if (!IsStandalone()) {
1358 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1359 // to Shell - need to refactor tests to avoid this problem)
1360 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1361 return;
1362 }
1363 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1364 if (!PropertiesHelper::IsUserBuild()) {
1365 // Emulates user build if necessarily.
1366 SetBuildType("user");
1367 }
1368
1369 DropRoot();
1370
1371 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1372 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1373
1374 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1375 EXPECT_THAT(err, StrEq("stderr\n"));
1376}
1377
1378TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1379 if (!IsStandalone()) {
1380 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1381 // to Shell - need to refactor tests to avoid this problem)
1382 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1383 return;
1384 }
1385 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1386 if (PropertiesHelper::IsUserBuild()) {
1387 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1388 return;
1389 }
1390
1391 DropRoot();
1392
1393 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1394 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1395
1396 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1397 EXPECT_THAT(err, StrEq("stderr\n"));
1398}
1399
Felipe Leme46b85da2016-11-21 17:40:45 -08001400TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1401 if (!IsStandalone()) {
1402 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1403 // to Shell - need to refactor tests to avoid this problem)
1404 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1405 return;
1406 }
1407 CreateFd("RunCommandDropRoot.txt");
1408 // First check root case - only available when running with 'adb root'.
1409 uid_t uid = getuid();
1410 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001411 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001412 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1413 EXPECT_THAT(err, StrEq("stderr\n"));
1414 return;
1415 }
1416 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001417 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001418 CommandOptions::WithTimeout(1).DropRoot().Build()));
1419 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1420 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1421}
1422
Felipe Lemef0292972016-11-22 13:57:05 -08001423TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001424 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001425 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001426 EXPECT_THAT(out,
1427 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1428 EXPECT_THAT(err, IsEmpty());
1429}
1430
Felipe Lemef0292972016-11-22 13:57:05 -08001431TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1432 CreateFd("DumpFileNotFound.txt");
1433 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1434 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1435 "file or directory\n"));
1436 EXPECT_THAT(err, IsEmpty());
1437}
1438
Felipe Leme46b85da2016-11-21 17:40:45 -08001439TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1440 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001441 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001442 EXPECT_THAT(err, IsEmpty());
1443 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1444}
1445
1446TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1447 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001448 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001449 EXPECT_THAT(err, IsEmpty());
1450 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1451}
1452
1453TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1454 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001455 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001456 EXPECT_THAT(err, IsEmpty());
1457 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1458}
1459
1460TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1461 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001462 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001463 EXPECT_THAT(err, IsEmpty());
1464 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1465}
1466
Felipe Lemef0292972016-11-22 13:57:05 -08001467TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1468 CreateFd("DumpFileOnDryRun.txt");
1469 SetDryRun(true);
1470 std::string path = kTestDataPath + "single-line.txt";
1471 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1472 EXPECT_THAT(err, IsEmpty());
1473 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1474}
1475
Felipe Leme46b85da2016-11-21 17:40:45 -08001476TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1477 CreateFd("DumpFileOnDryRun.txt");
1478 SetDryRun(true);
1479 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001480 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001481 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001482 EXPECT_THAT(
1483 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1484 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001485}
Ecco Park61ffcf72016-10-27 15:46:26 -07001486
1487TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
1488 // init process always has pid 1.
1489 EXPECT_EQ(1, FindPidOfProcess("init"));
1490 EXPECT_THAT(err, IsEmpty());
1491}
1492
1493TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
1494 // find the process with abnormal name.
1495 EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
1496 EXPECT_THAT(err, StrEq("can't find the pid\n"));
1497}
Felipe Leme47e9be22016-12-21 15:37:07 -08001498
1499} // namespace dumpstate
1500} // namespace os
1501} // namespace android