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
17 #define LOG_TAG "dumpstate"
18 #include <cutils/log.h>
19
20 #include "DumpstateInternal.h"
21 #include "DumpstateService.h"
22 #include "android/os/BnDumpstate.h"
23 #include "dumpstate.h"
24
25 #include <gmock/gmock.h>
26 #include <gtest/gtest.h>
27
28 #include <fcntl.h>
29 #include <libgen.h>
30 #include <signal.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33 #include <thread>
34
35 #include <android-base/file.h>
36 #include <android-base/properties.h>
37 #include <android-base/stringprintf.h>
38 #include <android-base/strings.h>
39 #include <android-base/unique_fd.h>
40 #include <android/hardware/dumpstate/1.1/types.h>
41 #include <cutils/properties.h>
42
43 namespace android {
44 namespace os {
45 namespace dumpstate {
46
47 using ::android::hardware::dumpstate::V1_1::DumpstateMode;
48 using ::testing::EndsWith;
49 using ::testing::HasSubstr;
50 using ::testing::IsEmpty;
51 using ::testing::IsNull;
52 using ::testing::NotNull;
53 using ::testing::StartsWith;
54 using ::testing::StrEq;
55 using ::testing::Test;
56 using ::testing::internal::CaptureStderr;
57 using ::testing::internal::CaptureStdout;
58 using ::testing::internal::GetCapturedStderr;
59 using ::testing::internal::GetCapturedStdout;
60
61 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
62
63 class DumpstateListenerMock : public IDumpstateListener {
64 public:
65 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
66 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
67 MOCK_METHOD0(onFinished, binder::Status());
68 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
69 MOCK_METHOD1(onUiIntensiveBugreportDumpsFinished,
70 binder::Status(const android::String16& callingpackage));
71
72 protected:
73 MOCK_METHOD0(onAsBinder, IBinder*());
74 };
75
76 static int calls_;
77
78 // Base class for all tests in this file
79 class DumpstateBaseTest : public Test {
80 public:
SetUp()81 virtual void SetUp() override {
82 calls_++;
83 SetDryRun(false);
84 }
85
SetDryRun(bool dry_run) const86 void SetDryRun(bool dry_run) const {
87 PropertiesHelper::dry_run_ = dry_run;
88 }
89
SetBuildType(const std::string & build_type) const90 void SetBuildType(const std::string& build_type) const {
91 PropertiesHelper::build_type_ = build_type;
92 }
93
SetUnroot(bool unroot) const94 void SetUnroot(bool unroot) const {
95 PropertiesHelper::unroot_ = unroot;
96 }
97
IsStandalone() const98 bool IsStandalone() const {
99 return calls_ == 1;
100 }
101
DropRoot() const102 void DropRoot() const {
103 DropRootUser();
104 uid_t uid = getuid();
105 ASSERT_EQ(2000, (int)uid);
106 }
107
108 protected:
109 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
110 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
111 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
112 const std::string kEchoCommand = "/system/bin/echo";
113
114 /*
115 * Copies a text file fixture to a temporary file, returning it's path.
116 *
117 * Useful in cases where the test case changes the content of the tile.
118 */
CopyTextFileFixture(const std::string & relative_name)119 std::string CopyTextFileFixture(const std::string& relative_name) {
120 std::string from = kTestDataPath + relative_name;
121 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
122 // around for poking when the test fails.
123 std::string to = kTestDataPath + relative_name + ".tmp";
124 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
125 android::base::RemoveFileIfExists(to);
126 CopyTextFile(from, to);
127 return to.c_str();
128 }
129
130 // Need functions that returns void to use assertions -
131 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
ReadFileToString(const std::string & path,std::string * content)132 void ReadFileToString(const std::string& path, std::string* content) {
133 ASSERT_TRUE(android::base::ReadFileToString(path, content))
134 << "could not read contents from " << path;
135 }
WriteStringToFile(const std::string & content,const std::string & path)136 void WriteStringToFile(const std::string& content, const std::string& path) {
137 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
138 << "could not write contents to " << path;
139 }
140
141 private:
CopyTextFile(const std::string & from,const std::string & to)142 void CopyTextFile(const std::string& from, const std::string& to) {
143 std::string content;
144 ReadFileToString(from, &content);
145 WriteStringToFile(content, to);
146 }
147 };
148
149 class DumpOptionsTest : public Test {
150 public:
~DumpOptionsTest()151 virtual ~DumpOptionsTest() {
152 }
SetUp()153 virtual void SetUp() {
154 options_ = Dumpstate::DumpOptions();
155 }
TearDown()156 void TearDown() {
157 }
158 Dumpstate::DumpOptions options_;
159 android::base::unique_fd fd;
160 };
161
TEST_F(DumpOptionsTest,InitializeNone)162 TEST_F(DumpOptionsTest, InitializeNone) {
163 // clang-format off
164 char* argv[] = {
165 const_cast<char*>("dumpstate")
166 };
167 // clang-format on
168
169 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
170
171 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
172
173 EXPECT_FALSE(options_.do_add_date);
174 EXPECT_FALSE(options_.do_zip_file);
175 EXPECT_EQ("", options_.out_dir);
176 EXPECT_FALSE(options_.use_socket);
177 EXPECT_FALSE(options_.use_control_socket);
178 EXPECT_FALSE(options_.show_header_only);
179 EXPECT_TRUE(options_.do_vibrate);
180 EXPECT_FALSE(options_.do_screenshot);
181 EXPECT_FALSE(options_.do_progress_updates);
182 EXPECT_FALSE(options_.is_remote_mode);
183 EXPECT_FALSE(options_.limited_only);
184 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
185 }
186
TEST_F(DumpOptionsTest,InitializeAdbBugreport)187 TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
188 // clang-format off
189 char* argv[] = {
190 const_cast<char*>("dumpstatez"),
191 const_cast<char*>("-S"),
192 const_cast<char*>("-d"),
193 const_cast<char*>("-z"),
194 };
195 // clang-format on
196
197 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
198
199 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
200 EXPECT_TRUE(options_.do_add_date);
201 EXPECT_TRUE(options_.do_zip_file);
202 EXPECT_TRUE(options_.use_control_socket);
203
204 // Other options retain default values
205 EXPECT_TRUE(options_.do_vibrate);
206 EXPECT_FALSE(options_.show_header_only);
207 EXPECT_FALSE(options_.do_screenshot);
208 EXPECT_FALSE(options_.do_progress_updates);
209 EXPECT_FALSE(options_.is_remote_mode);
210 EXPECT_FALSE(options_.use_socket);
211 EXPECT_FALSE(options_.limited_only);
212 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
213 }
214
TEST_F(DumpOptionsTest,InitializeAdbShellBugreport)215 TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
216 // clang-format off
217 char* argv[] = {
218 const_cast<char*>("dumpstate"),
219 const_cast<char*>("-s"),
220 };
221 // clang-format on
222
223 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
224
225 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
226 EXPECT_TRUE(options_.use_socket);
227
228 // Other options retain default values
229 EXPECT_TRUE(options_.do_vibrate);
230 EXPECT_FALSE(options_.do_add_date);
231 EXPECT_FALSE(options_.do_zip_file);
232 EXPECT_FALSE(options_.use_control_socket);
233 EXPECT_FALSE(options_.show_header_only);
234 EXPECT_FALSE(options_.do_screenshot);
235 EXPECT_FALSE(options_.do_progress_updates);
236 EXPECT_FALSE(options_.is_remote_mode);
237 EXPECT_FALSE(options_.limited_only);
238 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
239 }
240
TEST_F(DumpOptionsTest,InitializeFullBugReport)241 TEST_F(DumpOptionsTest, InitializeFullBugReport) {
242 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
243 EXPECT_TRUE(options_.do_add_date);
244 EXPECT_TRUE(options_.do_screenshot);
245 EXPECT_TRUE(options_.do_zip_file);
246 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
247
248 // Other options retain default values
249 EXPECT_TRUE(options_.do_vibrate);
250 EXPECT_FALSE(options_.use_control_socket);
251 EXPECT_FALSE(options_.show_header_only);
252 EXPECT_FALSE(options_.do_progress_updates);
253 EXPECT_FALSE(options_.is_remote_mode);
254 EXPECT_FALSE(options_.use_socket);
255 EXPECT_FALSE(options_.do_start_service);
256 EXPECT_FALSE(options_.limited_only);
257 }
258
TEST_F(DumpOptionsTest,InitializeInteractiveBugReport)259 TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
260 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
261 EXPECT_TRUE(options_.do_add_date);
262 EXPECT_TRUE(options_.do_zip_file);
263 EXPECT_TRUE(options_.do_progress_updates);
264 EXPECT_TRUE(options_.do_start_service);
265 EXPECT_TRUE(options_.do_screenshot);
266 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
267
268 // Other options retain default values
269 EXPECT_TRUE(options_.do_vibrate);
270 EXPECT_FALSE(options_.use_control_socket);
271 EXPECT_FALSE(options_.show_header_only);
272 EXPECT_FALSE(options_.is_remote_mode);
273 EXPECT_FALSE(options_.use_socket);
274 EXPECT_FALSE(options_.limited_only);
275 }
276
TEST_F(DumpOptionsTest,InitializeRemoteBugReport)277 TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
278 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
279 EXPECT_TRUE(options_.do_add_date);
280 EXPECT_TRUE(options_.do_zip_file);
281 EXPECT_TRUE(options_.is_remote_mode);
282 EXPECT_FALSE(options_.do_vibrate);
283 EXPECT_FALSE(options_.do_screenshot);
284 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
285
286 // Other options retain default values
287 EXPECT_FALSE(options_.use_control_socket);
288 EXPECT_FALSE(options_.show_header_only);
289 EXPECT_FALSE(options_.do_progress_updates);
290 EXPECT_FALSE(options_.use_socket);
291 EXPECT_FALSE(options_.limited_only);
292 }
293
TEST_F(DumpOptionsTest,InitializeWearBugReport)294 TEST_F(DumpOptionsTest, InitializeWearBugReport) {
295 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
296 EXPECT_TRUE(options_.do_add_date);
297 EXPECT_TRUE(options_.do_screenshot);
298 EXPECT_TRUE(options_.do_zip_file);
299 EXPECT_TRUE(options_.do_progress_updates);
300 EXPECT_TRUE(options_.do_start_service);
301 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
302
303 // Other options retain default values
304 EXPECT_TRUE(options_.do_vibrate);
305 EXPECT_FALSE(options_.use_control_socket);
306 EXPECT_FALSE(options_.show_header_only);
307 EXPECT_FALSE(options_.is_remote_mode);
308 EXPECT_FALSE(options_.use_socket);
309 EXPECT_FALSE(options_.limited_only);
310 }
311
TEST_F(DumpOptionsTest,InitializeTelephonyBugReport)312 TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
313 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
314 EXPECT_TRUE(options_.do_add_date);
315 EXPECT_FALSE(options_.do_screenshot);
316 EXPECT_TRUE(options_.do_zip_file);
317 EXPECT_TRUE(options_.telephony_only);
318 EXPECT_TRUE(options_.do_progress_updates);
319 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
320
321 // Other options retain default values
322 EXPECT_TRUE(options_.do_vibrate);
323 EXPECT_FALSE(options_.use_control_socket);
324 EXPECT_FALSE(options_.show_header_only);
325 EXPECT_FALSE(options_.is_remote_mode);
326 EXPECT_FALSE(options_.use_socket);
327 EXPECT_FALSE(options_.limited_only);
328 }
329
TEST_F(DumpOptionsTest,InitializeWifiBugReport)330 TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
331 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
332 EXPECT_TRUE(options_.do_add_date);
333 EXPECT_FALSE(options_.do_screenshot);
334 EXPECT_TRUE(options_.do_zip_file);
335 EXPECT_TRUE(options_.wifi_only);
336 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
337
338 // Other options retain default values
339 EXPECT_TRUE(options_.do_vibrate);
340 EXPECT_FALSE(options_.use_control_socket);
341 EXPECT_FALSE(options_.show_header_only);
342 EXPECT_FALSE(options_.do_progress_updates);
343 EXPECT_FALSE(options_.is_remote_mode);
344 EXPECT_FALSE(options_.use_socket);
345 EXPECT_FALSE(options_.limited_only);
346 }
347
TEST_F(DumpOptionsTest,InitializeLimitedOnlyBugreport)348 TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
349 // clang-format off
350 char* argv[] = {
351 const_cast<char*>("dumpstatez"),
352 const_cast<char*>("-S"),
353 const_cast<char*>("-d"),
354 const_cast<char*>("-z"),
355 const_cast<char*>("-q"),
356 const_cast<char*>("-L"),
357 const_cast<char*>("-o abc")
358 };
359 // clang-format on
360
361 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
362
363 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
364 EXPECT_TRUE(options_.do_add_date);
365 EXPECT_TRUE(options_.do_zip_file);
366 EXPECT_TRUE(options_.use_control_socket);
367 EXPECT_FALSE(options_.do_vibrate);
368 EXPECT_TRUE(options_.limited_only);
369 EXPECT_EQ(" abc", std::string(options_.out_dir));
370
371 // Other options retain default values
372 EXPECT_FALSE(options_.show_header_only);
373 EXPECT_FALSE(options_.do_screenshot);
374 EXPECT_FALSE(options_.do_progress_updates);
375 EXPECT_FALSE(options_.is_remote_mode);
376 EXPECT_FALSE(options_.use_socket);
377 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
378 }
379
TEST_F(DumpOptionsTest,InitializeDefaultBugReport)380 TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
381 // default: commandline options are not overridden
382 // clang-format off
383 char* argv[] = {
384 const_cast<char*>("bugreport"),
385 const_cast<char*>("-d"),
386 const_cast<char*>("-p"),
387 const_cast<char*>("-z"),
388 };
389 // clang-format on
390 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
391
392 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
393 EXPECT_TRUE(options_.do_add_date);
394 EXPECT_TRUE(options_.do_screenshot);
395 EXPECT_TRUE(options_.do_zip_file);
396 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
397
398 // Other options retain default values
399 EXPECT_TRUE(options_.do_vibrate);
400 EXPECT_FALSE(options_.use_control_socket);
401 EXPECT_FALSE(options_.show_header_only);
402 EXPECT_FALSE(options_.do_progress_updates);
403 EXPECT_FALSE(options_.is_remote_mode);
404 EXPECT_FALSE(options_.use_socket);
405 EXPECT_FALSE(options_.wifi_only);
406 EXPECT_FALSE(options_.limited_only);
407 }
408
TEST_F(DumpOptionsTest,InitializePartial1)409 TEST_F(DumpOptionsTest, InitializePartial1) {
410 // clang-format off
411 char* argv[] = {
412 const_cast<char*>("dumpstate"),
413 const_cast<char*>("-d"),
414 const_cast<char*>("-z"),
415 const_cast<char*>("-s"),
416 const_cast<char*>("-S"),
417
418 };
419 // clang-format on
420
421 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
422
423 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
424 EXPECT_TRUE(options_.do_add_date);
425 EXPECT_TRUE(options_.do_zip_file);
426 // TODO: Maybe we should trim the filename
427 EXPECT_TRUE(options_.use_socket);
428 EXPECT_TRUE(options_.use_control_socket);
429
430 // Other options retain default values
431 EXPECT_FALSE(options_.show_header_only);
432 EXPECT_TRUE(options_.do_vibrate);
433 EXPECT_FALSE(options_.do_screenshot);
434 EXPECT_FALSE(options_.do_progress_updates);
435 EXPECT_FALSE(options_.is_remote_mode);
436 EXPECT_FALSE(options_.limited_only);
437 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
438 }
439
TEST_F(DumpOptionsTest,InitializePartial2)440 TEST_F(DumpOptionsTest, InitializePartial2) {
441 // clang-format off
442 char* argv[] = {
443 const_cast<char*>("dumpstate"),
444 const_cast<char*>("-v"),
445 const_cast<char*>("-q"),
446 const_cast<char*>("-p"),
447 const_cast<char*>("-P"),
448 const_cast<char*>("-R"),
449 };
450 // clang-format on
451
452 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
453
454 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
455 EXPECT_TRUE(options_.show_header_only);
456 EXPECT_FALSE(options_.do_vibrate);
457 EXPECT_TRUE(options_.do_screenshot);
458 EXPECT_TRUE(options_.do_progress_updates);
459 EXPECT_TRUE(options_.is_remote_mode);
460
461 // Other options retain default values
462 EXPECT_FALSE(options_.do_add_date);
463 EXPECT_FALSE(options_.do_zip_file);
464 EXPECT_FALSE(options_.use_socket);
465 EXPECT_FALSE(options_.use_control_socket);
466 EXPECT_FALSE(options_.limited_only);
467 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
468 }
469
TEST_F(DumpOptionsTest,InitializeHelp)470 TEST_F(DumpOptionsTest, InitializeHelp) {
471 // clang-format off
472 char* argv[] = {
473 const_cast<char*>("dumpstate"),
474 const_cast<char*>("-h")
475 };
476 // clang-format on
477
478 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
479
480 // -h is for help.
481 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
482 }
483
TEST_F(DumpOptionsTest,InitializeUnknown)484 TEST_F(DumpOptionsTest, InitializeUnknown) {
485 // clang-format off
486 char* argv[] = {
487 const_cast<char*>("dumpstate"),
488 const_cast<char*>("-u") // unknown flag
489 };
490 // clang-format on
491
492 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
493
494 // -u is unknown.
495 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
496 }
497
TEST_F(DumpOptionsTest,ValidateOptionsNeedOutfile1)498 TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
499 options_.do_zip_file = true;
500 // Writing to socket = !writing to file.
501 options_.use_socket = true;
502 EXPECT_FALSE(options_.ValidateOptions());
503
504 options_.use_socket = false;
505 EXPECT_TRUE(options_.ValidateOptions());
506 }
507
TEST_F(DumpOptionsTest,ValidateOptionsNeedOutfile2)508 TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
509 options_.do_progress_updates = true;
510 // Writing to socket = !writing to file.
511 options_.use_socket = true;
512 EXPECT_FALSE(options_.ValidateOptions());
513
514 options_.use_socket = false;
515 EXPECT_TRUE(options_.ValidateOptions());
516 }
517
TEST_F(DumpOptionsTest,ValidateOptionsNeedZipfile)518 TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) {
519 options_.use_control_socket = true;
520 EXPECT_FALSE(options_.ValidateOptions());
521
522 options_.do_zip_file = true;
523 EXPECT_TRUE(options_.ValidateOptions());
524 }
525
TEST_F(DumpOptionsTest,ValidateOptionsRemoteMode)526 TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
527 options_.is_remote_mode = true;
528 EXPECT_FALSE(options_.ValidateOptions());
529
530 options_.do_zip_file = true;
531 options_.do_add_date = true;
532 EXPECT_TRUE(options_.ValidateOptions());
533 }
534
535 class DumpstateTest : public DumpstateBaseTest {
536 public:
SetUp()537 void SetUp() {
538 DumpstateBaseTest::SetUp();
539 SetDryRun(false);
540 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
541 ds.progress_.reset(new Progress());
542 ds.options_.reset(new Dumpstate::DumpOptions());
543 }
544
545 // Runs a command and capture `stdout` and `stderr`.
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options=CommandOptions::DEFAULT)546 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
547 const CommandOptions& options = CommandOptions::DEFAULT) {
548 CaptureStdout();
549 CaptureStderr();
550 int status = ds.RunCommand(title, full_command, options);
551 out = GetCapturedStdout();
552 err = GetCapturedStderr();
553 return status;
554 }
555
556 // Dumps a file and capture `stdout` and `stderr`.
DumpFile(const std::string & title,const std::string & path)557 int DumpFile(const std::string& title, const std::string& path) {
558 CaptureStdout();
559 CaptureStderr();
560 int status = ds.DumpFile(title, path);
561 out = GetCapturedStdout();
562 err = GetCapturedStderr();
563 return status;
564 }
565
SetProgress(long progress,long initial_max)566 void SetProgress(long progress, long initial_max) {
567 ds.last_reported_percent_progress_ = 0;
568 ds.options_->do_progress_updates = true;
569 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
570 }
571
GetProgressMessage(int progress,int max,int old_max=0,bool update_progress=true)572 std::string GetProgressMessage(int progress, int max,
573 int old_max = 0, bool update_progress = true) {
574 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
575 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
576
577 bool max_increased = old_max > 0;
578
579 std::string message = "";
580 if (max_increased) {
581 message =
582 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
583 }
584
585 if (update_progress) {
586 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
587 progress, max, (100 * progress / max));
588 }
589
590 return message;
591 }
592
593 // `stdout` and `stderr` from the last command ran.
594 std::string out, err;
595
596 Dumpstate& ds = Dumpstate::GetInstance();
597 };
598
TEST_F(DumpstateTest,RunCommandNoArgs)599 TEST_F(DumpstateTest, RunCommandNoArgs) {
600 EXPECT_EQ(-1, RunCommand("", {}));
601 }
602
TEST_F(DumpstateTest,RunCommandNoTitle)603 TEST_F(DumpstateTest, RunCommandNoTitle) {
604 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
605 EXPECT_THAT(out, StrEq("stdout\n"));
606 EXPECT_THAT(err, StrEq("stderr\n"));
607 }
608
TEST_F(DumpstateTest,RunCommandWithTitle)609 TEST_F(DumpstateTest, RunCommandWithTitle) {
610 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
611 EXPECT_THAT(err, StrEq("stderr\n"));
612 // The duration may not get output, depending on how long it takes,
613 // so we just check the prefix.
614 EXPECT_THAT(out,
615 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
616 }
617
TEST_F(DumpstateTest,RunCommandWithLoggingMessage)618 TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
619 EXPECT_EQ(
620 0, RunCommand("", {kSimpleCommand},
621 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
622 EXPECT_THAT(out, StrEq("stdout\n"));
623 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
624 }
625
TEST_F(DumpstateTest,RunCommandRedirectStderr)626 TEST_F(DumpstateTest, RunCommandRedirectStderr) {
627 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
628 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
629 EXPECT_THAT(out, IsEmpty());
630 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
631 }
632
TEST_F(DumpstateTest,RunCommandWithOneArg)633 TEST_F(DumpstateTest, RunCommandWithOneArg) {
634 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
635 EXPECT_THAT(err, IsEmpty());
636 EXPECT_THAT(out, StrEq("one\n"));
637 }
638
TEST_F(DumpstateTest,RunCommandWithMultipleArgs)639 TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
640 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
641 EXPECT_THAT(err, IsEmpty());
642 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
643 }
644
TEST_F(DumpstateTest,RunCommandDryRun)645 TEST_F(DumpstateTest, RunCommandDryRun) {
646 SetDryRun(true);
647 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
648 // The duration may not get output, depending on how long it takes,
649 // so we just check the prefix.
650 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
651 ") ------\n\t(skipped on dry run)\n"));
652 EXPECT_THAT(err, IsEmpty());
653 }
654
TEST_F(DumpstateTest,RunCommandDryRunNoTitle)655 TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
656 SetDryRun(true);
657 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
658 EXPECT_THAT(out, IsEmpty());
659 EXPECT_THAT(err, IsEmpty());
660 }
661
TEST_F(DumpstateTest,RunCommandDryRunAlways)662 TEST_F(DumpstateTest, RunCommandDryRunAlways) {
663 SetDryRun(true);
664 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
665 EXPECT_THAT(out, StrEq("stdout\n"));
666 EXPECT_THAT(err, StrEq("stderr\n"));
667 }
668
TEST_F(DumpstateTest,RunCommandNotFound)669 TEST_F(DumpstateTest, RunCommandNotFound) {
670 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
671 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
672 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
673 }
674
TEST_F(DumpstateTest,RunCommandFails)675 TEST_F(DumpstateTest, RunCommandFails) {
676 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
677 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
678 " --exit 42' failed: exit code 42\n"));
679 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
680 " --exit 42' failed: exit code 42\n"));
681 }
682
TEST_F(DumpstateTest,RunCommandCrashes)683 TEST_F(DumpstateTest, RunCommandCrashes) {
684 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
685 // We don't know the exit code, so check just the prefix.
686 EXPECT_THAT(
687 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
688 EXPECT_THAT(
689 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
690 }
691
TEST_F(DumpstateTest,RunCommandTimesout)692 TEST_F(DumpstateTest, RunCommandTimesout) {
693 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
694 CommandOptions::WithTimeout(1).Build()));
695 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
696 " --sleep 2' timed out after 1"));
697 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
698 " --sleep 2' timed out after 1"));
699 }
700
TEST_F(DumpstateTest,RunCommandIsKilled)701 TEST_F(DumpstateTest, RunCommandIsKilled) {
702 CaptureStdout();
703 CaptureStderr();
704
705 std::thread t([=]() {
706 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
707 CommandOptions::WithTimeout(100).Always().Build()));
708 });
709
710 // Capture pid and pre-sleep output.
711 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
712 std::string err = GetCapturedStderr();
713 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
714
715 std::string out = GetCapturedStdout();
716 std::vector<std::string> lines = android::base::Split(out, "\n");
717 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
718
719 int pid = atoi(lines[0].c_str());
720 EXPECT_THAT(lines[1], StrEq("stdout line1"));
721 EXPECT_THAT(lines[2], IsEmpty()); // \n
722
723 // Then kill the process.
724 CaptureStdout();
725 CaptureStderr();
726 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
727 t.join();
728
729 // Finally, check output after murder.
730 out = GetCapturedStdout();
731 err = GetCapturedStderr();
732
733 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
734 " --pid --sleep 20' failed: killed by signal 15\n"));
735 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
736 " --pid --sleep 20' failed: killed by signal 15\n"));
737 }
738
TEST_F(DumpstateTest,RunCommandProgress)739 TEST_F(DumpstateTest, RunCommandProgress) {
740 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
741 ds.listener_ = listener;
742 SetProgress(0, 30);
743
744 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
745 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
746 std::string progress_message = GetProgressMessage(20, 30);
747 EXPECT_THAT(out, StrEq("stdout\n"));
748 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
749
750 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
751 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
752 progress_message = GetProgressMessage(24, 30);
753 EXPECT_THAT(out, StrEq("stdout\n"));
754 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
755
756 // Make sure command ran while in dry_run is counted.
757 SetDryRun(true);
758 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
759 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
760 progress_message = GetProgressMessage(27, 30);
761 EXPECT_THAT(out, IsEmpty());
762 EXPECT_THAT(err, StrEq(progress_message));
763
764 SetDryRun(false);
765 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
766 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
767 progress_message = GetProgressMessage(29, 30);
768 EXPECT_THAT(out, StrEq("stdout\n"));
769 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
770
771 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
772 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
773 progress_message = GetProgressMessage(30, 30);
774 EXPECT_THAT(out, StrEq("stdout\n"));
775 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
776
777 ds.listener_.clear();
778 }
779
TEST_F(DumpstateTest,RunCommandDropRoot)780 TEST_F(DumpstateTest, RunCommandDropRoot) {
781 if (!IsStandalone()) {
782 // TODO: temporarily disabled because it might cause other tests to fail after dropping
783 // to Shell - need to refactor tests to avoid this problem)
784 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
785 return;
786 }
787 // First check root case - only available when running with 'adb root'.
788 uid_t uid = getuid();
789 if (uid == 0) {
790 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
791 EXPECT_THAT(out, StrEq("0\nstdout\n"));
792 EXPECT_THAT(err, StrEq("stderr\n"));
793 return;
794 }
795 // Then run dropping root.
796 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
797 CommandOptions::WithTimeout(1).DropRoot().Build()));
798 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
799 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
800 }
801
TEST_F(DumpstateTest,RunCommandAsRootUserBuild)802 TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
803 if (!IsStandalone()) {
804 // TODO: temporarily disabled because it might cause other tests to fail after dropping
805 // to Shell - need to refactor tests to avoid this problem)
806 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
807 return;
808 }
809 if (!PropertiesHelper::IsUserBuild()) {
810 // Emulates user build if necessarily.
811 SetBuildType("user");
812 }
813
814 DropRoot();
815
816 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
817
818 // We don't know the exact path of su, so we just check for the 'root ...' commands
819 EXPECT_THAT(out, StartsWith("Skipping"));
820 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
821 EXPECT_THAT(err, IsEmpty());
822 }
823
TEST_F(DumpstateTest,RunCommandAsRootNonUserBuild)824 TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
825 if (!IsStandalone()) {
826 // TODO: temporarily disabled because it might cause other tests to fail after dropping
827 // to Shell - need to refactor tests to avoid this problem)
828 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
829 return;
830 }
831 if (PropertiesHelper::IsUserBuild()) {
832 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
833 return;
834 }
835
836 DropRoot();
837
838 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
839 CommandOptions::WithTimeout(1).AsRoot().Build()));
840
841 EXPECT_THAT(out, StrEq("0\nstdout\n"));
842 EXPECT_THAT(err, StrEq("stderr\n"));
843 }
844
TEST_F(DumpstateTest,RunCommandAsRootNonUserBuild_withUnroot)845 TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
846 if (!IsStandalone()) {
847 // TODO: temporarily disabled because it might cause other tests to fail after dropping
848 // to Shell - need to refactor tests to avoid this problem)
849 MYLOGE(
850 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
851 "on test suite\n")
852 return;
853 }
854 if (PropertiesHelper::IsUserBuild()) {
855 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
856 return;
857 }
858
859 // Same test as above, but with unroot property set, which will override su availability.
860 SetUnroot(true);
861 DropRoot();
862
863 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
864 CommandOptions::WithTimeout(1).AsRoot().Build()));
865
866 // AsRoot is ineffective.
867 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
868 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
869 }
870
TEST_F(DumpstateTest,RunCommandAsRootIfAvailableOnUserBuild)871 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
872 if (!IsStandalone()) {
873 // TODO: temporarily disabled because it might cause other tests to fail after dropping
874 // to Shell - need to refactor tests to avoid this problem)
875 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
876 return;
877 }
878 if (!PropertiesHelper::IsUserBuild()) {
879 // Emulates user build if necessarily.
880 SetBuildType("user");
881 }
882
883 DropRoot();
884
885 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
886 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
887
888 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
889 EXPECT_THAT(err, StrEq("stderr\n"));
890 }
891
TEST_F(DumpstateTest,RunCommandAsRootIfAvailableOnDebugBuild)892 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
893 if (!IsStandalone()) {
894 // TODO: temporarily disabled because it might cause other tests to fail after dropping
895 // to Shell - need to refactor tests to avoid this problem)
896 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
897 return;
898 }
899 if (PropertiesHelper::IsUserBuild()) {
900 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
901 return;
902 }
903
904 DropRoot();
905
906 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
907 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
908
909 EXPECT_THAT(out, StrEq("0\nstdout\n"));
910 EXPECT_THAT(err, StrEq("stderr\n"));
911 }
912
TEST_F(DumpstateTest,RunCommandAsRootIfAvailableOnDebugBuild_withUnroot)913 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
914 if (!IsStandalone()) {
915 // TODO: temporarily disabled because it might cause other tests to fail after dropping
916 // to Shell - need to refactor tests to avoid this problem)
917 MYLOGE(
918 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
919 "on test suite\n")
920 return;
921 }
922 if (PropertiesHelper::IsUserBuild()) {
923 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
924 return;
925 }
926 // Same test as above, but with unroot property set, which will override su availability.
927 SetUnroot(true);
928
929 DropRoot();
930
931 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
932 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
933
934 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
935 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
936 EXPECT_THAT(err, StrEq("stderr\n"));
937 }
938
TEST_F(DumpstateTest,DumpFileNotFoundNoTitle)939 TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
940 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
941 EXPECT_THAT(out,
942 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
943 EXPECT_THAT(err, IsEmpty());
944 }
945
TEST_F(DumpstateTest,DumpFileNotFoundWithTitle)946 TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
947 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
948 EXPECT_THAT(err, IsEmpty());
949 // The duration may not get output, depending on how long it takes,
950 // so we just check the prefix.
951 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
952 "such file or directory\n"));
953 }
954
TEST_F(DumpstateTest,DumpFileSingleLine)955 TEST_F(DumpstateTest, DumpFileSingleLine) {
956 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
957 EXPECT_THAT(err, IsEmpty());
958 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
959 }
960
TEST_F(DumpstateTest,DumpFileSingleLineWithNewLine)961 TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
962 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
963 EXPECT_THAT(err, IsEmpty());
964 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
965 }
966
TEST_F(DumpstateTest,DumpFileMultipleLines)967 TEST_F(DumpstateTest, DumpFileMultipleLines) {
968 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
969 EXPECT_THAT(err, IsEmpty());
970 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
971 }
972
TEST_F(DumpstateTest,DumpFileMultipleLinesWithNewLine)973 TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
974 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
975 EXPECT_THAT(err, IsEmpty());
976 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
977 }
978
TEST_F(DumpstateTest,DumpFileOnDryRunNoTitle)979 TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
980 SetDryRun(true);
981 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
982 EXPECT_THAT(err, IsEmpty());
983 EXPECT_THAT(out, IsEmpty());
984 }
985
TEST_F(DumpstateTest,DumpFileOnDryRun)986 TEST_F(DumpstateTest, DumpFileOnDryRun) {
987 SetDryRun(true);
988 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
989 EXPECT_THAT(err, IsEmpty());
990 EXPECT_THAT(
991 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
992 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
993 }
994
TEST_F(DumpstateTest,DumpFileUpdateProgress)995 TEST_F(DumpstateTest, DumpFileUpdateProgress) {
996 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
997 ds.listener_ = listener;
998 SetProgress(0, 30);
999
1000 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
1001 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1002
1003 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
1004 EXPECT_THAT(err, StrEq(progress_message));
1005 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1006
1007 ds.listener_.clear();
1008 }
1009
1010 class DumpstateServiceTest : public DumpstateBaseTest {
1011 public:
1012 DumpstateService dss;
1013 };
1014
1015 class ProgressTest : public DumpstateBaseTest {
1016 public:
GetInstance(int32_t max,double growth_factor,const std::string & path="")1017 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1018 return Progress(max, growth_factor, path);
1019 }
1020
AssertStats(const std::string & path,int32_t expected_runs,int32_t expected_average)1021 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1022 std::string expected_content =
1023 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1024 std::string actual_content;
1025 ReadFileToString(path, &actual_content);
1026 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1027 }
1028 };
1029
TEST_F(ProgressTest,SimpleTest)1030 TEST_F(ProgressTest, SimpleTest) {
1031 Progress progress;
1032 EXPECT_EQ(0, progress.Get());
1033 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1034 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1035
1036 bool max_increased = progress.Inc(1);
1037 EXPECT_EQ(1, progress.Get());
1038 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1039 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1040 EXPECT_FALSE(max_increased);
1041
1042 // Ignore negative increase.
1043 max_increased = progress.Inc(-1);
1044 EXPECT_EQ(1, progress.Get());
1045 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1046 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1047 EXPECT_FALSE(max_increased);
1048 }
1049
TEST_F(ProgressTest,MaxGrowsInsideNewRange)1050 TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1051 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1052 EXPECT_EQ(0, progress.Get());
1053 EXPECT_EQ(10, progress.GetInitialMax());
1054 EXPECT_EQ(10, progress.GetMax());
1055
1056 // No increase
1057 bool max_increased = progress.Inc(10);
1058 EXPECT_EQ(10, progress.Get());
1059 EXPECT_EQ(10, progress.GetMax());
1060 EXPECT_FALSE(max_increased);
1061
1062 // Increase, with new value < max*20%
1063 max_increased = progress.Inc(1);
1064 EXPECT_EQ(11, progress.Get());
1065 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1066 EXPECT_TRUE(max_increased);
1067 }
1068
TEST_F(ProgressTest,MaxGrowsOutsideNewRange)1069 TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1070 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1071 EXPECT_EQ(0, progress.Get());
1072 EXPECT_EQ(10, progress.GetInitialMax());
1073 EXPECT_EQ(10, progress.GetMax());
1074
1075 // No increase
1076 bool max_increased = progress.Inc(10);
1077 EXPECT_EQ(10, progress.Get());
1078 EXPECT_EQ(10, progress.GetMax());
1079 EXPECT_FALSE(max_increased);
1080
1081 // Increase, with new value > max*20%
1082 max_increased = progress.Inc(5);
1083 EXPECT_EQ(15, progress.Get());
1084 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1085 EXPECT_TRUE(max_increased);
1086 }
1087
TEST_F(ProgressTest,InvalidPath)1088 TEST_F(ProgressTest, InvalidPath) {
1089 Progress progress("/devil/null");
1090 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1091 }
1092
TEST_F(ProgressTest,EmptyFile)1093 TEST_F(ProgressTest, EmptyFile) {
1094 Progress progress(CopyTextFileFixture("empty-file.txt"));
1095 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1096 }
1097
TEST_F(ProgressTest,InvalidLine1stEntryNAN)1098 TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1099 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1100 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1101 }
1102
TEST_F(ProgressTest,InvalidLine2ndEntryNAN)1103 TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1104 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1105 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1106 }
1107
TEST_F(ProgressTest,InvalidLineBothNAN)1108 TEST_F(ProgressTest, InvalidLineBothNAN) {
1109 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1110 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1111 }
1112
TEST_F(ProgressTest,InvalidLine1stEntryNegative)1113 TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1114 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1115 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1116 }
1117
TEST_F(ProgressTest,InvalidLine2ndEntryNegative)1118 TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1119 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1120 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1121 }
1122
TEST_F(ProgressTest,InvalidLine1stEntryTooBig)1123 TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1124 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1125 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1126 }
1127
TEST_F(ProgressTest,InvalidLine2ndEntryTooBig)1128 TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1129 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1130 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1131 }
1132
1133 // Tests stats are properly saved when the file does not exists.
TEST_F(ProgressTest,FirstTime)1134 TEST_F(ProgressTest, FirstTime) {
1135 if (!IsStandalone()) {
1136 // TODO: temporarily disabled because it's failing when running as suite
1137 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1138 return;
1139 }
1140
1141 std::string path = kTestDataPath + "FirstTime.txt";
1142 android::base::RemoveFileIfExists(path);
1143
1144 Progress run1(path);
1145 EXPECT_EQ(0, run1.Get());
1146 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1147 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1148
1149 bool max_increased = run1.Inc(20);
1150 EXPECT_EQ(20, run1.Get());
1151 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1152 EXPECT_FALSE(max_increased);
1153
1154 run1.Save();
1155 AssertStats(path, 1, 20);
1156 }
1157
1158 // Tests what happens when the persistent settings contains the average duration of 1 run.
1159 // Data on file is 1 run and 109 average.
TEST_F(ProgressTest,SecondTime)1160 TEST_F(ProgressTest, SecondTime) {
1161 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1162
1163 Progress run1 = GetInstance(-42, 1.2, path);
1164 EXPECT_EQ(0, run1.Get());
1165 EXPECT_EQ(10, run1.GetInitialMax());
1166 EXPECT_EQ(10, run1.GetMax());
1167
1168 bool max_increased = run1.Inc(20);
1169 EXPECT_EQ(20, run1.Get());
1170 EXPECT_EQ(24, run1.GetMax());
1171 EXPECT_TRUE(max_increased);
1172
1173 // Average now is 2 runs and (10 + 20)/ 2 = 15
1174 run1.Save();
1175 AssertStats(path, 2, 15);
1176
1177 Progress run2 = GetInstance(-42, 1.2, path);
1178 EXPECT_EQ(0, run2.Get());
1179 EXPECT_EQ(15, run2.GetInitialMax());
1180 EXPECT_EQ(15, run2.GetMax());
1181
1182 max_increased = run2.Inc(25);
1183 EXPECT_EQ(25, run2.Get());
1184 EXPECT_EQ(30, run2.GetMax());
1185 EXPECT_TRUE(max_increased);
1186
1187 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1188 run2.Save();
1189 AssertStats(path, 3, 18);
1190
1191 Progress run3 = GetInstance(-42, 1.2, path);
1192 EXPECT_EQ(0, run3.Get());
1193 EXPECT_EQ(18, run3.GetInitialMax());
1194 EXPECT_EQ(18, run3.GetMax());
1195
1196 // Make sure average decreases as well
1197 max_increased = run3.Inc(5);
1198 EXPECT_EQ(5, run3.Get());
1199 EXPECT_EQ(18, run3.GetMax());
1200 EXPECT_FALSE(max_increased);
1201
1202 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1203 run3.Save();
1204 AssertStats(path, 4, 14);
1205 }
1206
1207 // Tests what happens when the persistent settings contains the average duration of 2 runs.
1208 // Data on file is 2 runs and 15 average.
TEST_F(ProgressTest,ThirdTime)1209 TEST_F(ProgressTest, ThirdTime) {
1210 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1211 AssertStats(path, 2, 15); // Sanity check
1212
1213 Progress run1 = GetInstance(-42, 1.2, path);
1214 EXPECT_EQ(0, run1.Get());
1215 EXPECT_EQ(15, run1.GetInitialMax());
1216 EXPECT_EQ(15, run1.GetMax());
1217
1218 bool max_increased = run1.Inc(20);
1219 EXPECT_EQ(20, run1.Get());
1220 EXPECT_EQ(24, run1.GetMax());
1221 EXPECT_TRUE(max_increased);
1222
1223 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1224 run1.Save();
1225 AssertStats(path, 3, 16);
1226 }
1227
1228 class DumpstateUtilTest : public DumpstateBaseTest {
1229 public:
SetUp()1230 void SetUp() {
1231 DumpstateBaseTest::SetUp();
1232 SetDryRun(false);
1233 }
1234
CaptureFdOut()1235 void CaptureFdOut() {
1236 ReadFileToString(path_, &out);
1237 }
1238
CreateFd(const std::string & name)1239 void CreateFd(const std::string& name) {
1240 path_ = kTestDataPath + name;
1241 MYLOGD("Creating fd for file %s\n", path_.c_str());
1242
1243 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1244 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1245 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1246 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1247 }
1248
1249 // Runs a command into the `fd` and capture `stderr`.
RunCommand(const std::string & title,const std::vector<std::string> & full_command,const CommandOptions & options=CommandOptions::DEFAULT)1250 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
1251 const CommandOptions& options = CommandOptions::DEFAULT) {
1252 CaptureStderr();
1253 int status = RunCommandToFd(fd, title, full_command, options);
1254 close(fd);
1255
1256 CaptureFdOut();
1257 err = GetCapturedStderr();
1258 return status;
1259 }
1260
1261 // Dumps a file and into the `fd` and `stderr`.
DumpFile(const std::string & title,const std::string & path)1262 int DumpFile(const std::string& title, const std::string& path) {
1263 CaptureStderr();
1264 int status = DumpFileToFd(fd, title, path);
1265 close(fd);
1266
1267 CaptureFdOut();
1268 err = GetCapturedStderr();
1269 return status;
1270 }
1271
1272 int fd;
1273
1274 // 'fd` output and `stderr` from the last command ran.
1275 std::string out, err;
1276
1277 private:
1278 std::string path_;
1279 };
1280
TEST_F(DumpstateUtilTest,RunCommandNoArgs)1281 TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
1282 CreateFd("RunCommandNoArgs.txt");
1283 EXPECT_EQ(-1, RunCommand("", {}));
1284 }
1285
TEST_F(DumpstateUtilTest,RunCommandNoTitle)1286 TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
1287 CreateFd("RunCommandWithNoArgs.txt");
1288 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
1289 EXPECT_THAT(out, StrEq("stdout\n"));
1290 EXPECT_THAT(err, StrEq("stderr\n"));
1291 }
1292
TEST_F(DumpstateUtilTest,RunCommandWithTitle)1293 TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1294 CreateFd("RunCommandWithNoArgs.txt");
1295 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1296 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1297 EXPECT_THAT(err, StrEq("stderr\n"));
1298 }
1299
TEST_F(DumpstateUtilTest,RunCommandWithOneArg)1300 TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1301 CreateFd("RunCommandWithOneArg.txt");
1302 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
1303 EXPECT_THAT(err, IsEmpty());
1304 EXPECT_THAT(out, StrEq("one\n"));
1305 }
1306
TEST_F(DumpstateUtilTest,RunCommandWithMultipleArgs)1307 TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1308 CreateFd("RunCommandWithMultipleArgs.txt");
1309 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
1310 EXPECT_THAT(err, IsEmpty());
1311 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1312 }
1313
TEST_F(DumpstateUtilTest,RunCommandWithLoggingMessage)1314 TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1315 CreateFd("RunCommandWithLoggingMessage.txt");
1316 EXPECT_EQ(
1317 0, RunCommand("", {kSimpleCommand},
1318 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1319 EXPECT_THAT(out, StrEq("stdout\n"));
1320 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1321 }
1322
TEST_F(DumpstateUtilTest,RunCommandRedirectStderr)1323 TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1324 CreateFd("RunCommandRedirectStderr.txt");
1325 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1326 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
1327 EXPECT_THAT(out, IsEmpty());
1328 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1329 }
1330
TEST_F(DumpstateUtilTest,RunCommandDryRun)1331 TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1332 CreateFd("RunCommandDryRun.txt");
1333 SetDryRun(true);
1334 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1335 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1336 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1337 kSimpleCommand.c_str())));
1338 EXPECT_THAT(err, IsEmpty());
1339 }
1340
TEST_F(DumpstateUtilTest,RunCommandDryRunNoTitle)1341 TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1342 CreateFd("RunCommandDryRun.txt");
1343 SetDryRun(true);
1344 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
1345 EXPECT_THAT(
1346 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1347 EXPECT_THAT(err, IsEmpty());
1348 }
1349
TEST_F(DumpstateUtilTest,RunCommandDryRunAlways)1350 TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1351 CreateFd("RunCommandDryRunAlways.txt");
1352 SetDryRun(true);
1353 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
1354 EXPECT_THAT(out, StrEq("stdout\n"));
1355 EXPECT_THAT(err, StrEq("stderr\n"));
1356 }
1357
TEST_F(DumpstateUtilTest,RunCommandNotFound)1358 TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1359 CreateFd("RunCommandNotFound.txt");
1360 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
1361 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1362 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1363 }
1364
TEST_F(DumpstateUtilTest,RunCommandFails)1365 TEST_F(DumpstateUtilTest, RunCommandFails) {
1366 CreateFd("RunCommandFails.txt");
1367 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
1368 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1369 " --exit 42' failed: exit code 42\n"));
1370 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1371 " --exit 42' failed: exit code 42\n"));
1372 }
1373
TEST_F(DumpstateUtilTest,RunCommandCrashes)1374 TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1375 CreateFd("RunCommandCrashes.txt");
1376 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
1377 // We don't know the exit code, so check just the prefix.
1378 EXPECT_THAT(
1379 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1380 EXPECT_THAT(
1381 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1382 }
1383
TEST_F(DumpstateUtilTest,RunCommandTimesoutWithSec)1384 TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
1385 CreateFd("RunCommandTimesout.txt");
1386 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1387 CommandOptions::WithTimeout(1).Build()));
1388 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1389 " --sleep 2' timed out after 1"));
1390 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1391 " --sleep 2' timed out after 1"));
1392 }
1393
TEST_F(DumpstateUtilTest,RunCommandTimesoutWithMsec)1394 TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1395 CreateFd("RunCommandTimesout.txt");
1396 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1397 CommandOptions::WithTimeoutInMs(1000).Build()));
1398 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1399 " --sleep 2' timed out after 1"));
1400 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1401 " --sleep 2' timed out after 1"));
1402 }
1403
1404
TEST_F(DumpstateUtilTest,RunCommandIsKilled)1405 TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1406 CreateFd("RunCommandIsKilled.txt");
1407 CaptureStderr();
1408
1409 std::thread t([=]() {
1410 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
1411 CommandOptions::WithTimeout(100).Always().Build()));
1412 });
1413
1414 // Capture pid and pre-sleep output.
1415 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1416 std::string err = GetCapturedStderr();
1417 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1418
1419 CaptureFdOut();
1420 std::vector<std::string> lines = android::base::Split(out, "\n");
1421 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1422
1423 int pid = atoi(lines[0].c_str());
1424 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1425 EXPECT_THAT(lines[2], IsEmpty()); // \n
1426
1427 // Then kill the process.
1428 CaptureFdOut();
1429 CaptureStderr();
1430 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1431 t.join();
1432
1433 // Finally, check output after murder.
1434 CaptureFdOut();
1435 err = GetCapturedStderr();
1436
1437 // out starts with the pid, which is an unknown
1438 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1439 " --pid --sleep 20' failed: killed by signal 15\n"));
1440 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1441 " --pid --sleep 20' failed: killed by signal 15\n"));
1442 }
1443
TEST_F(DumpstateUtilTest,RunCommandAsRootUserBuild)1444 TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1445 if (!IsStandalone()) {
1446 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1447 // to Shell - need to refactor tests to avoid this problem)
1448 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1449 return;
1450 }
1451 CreateFd("RunCommandAsRootUserBuild.txt");
1452 if (!PropertiesHelper::IsUserBuild()) {
1453 // Emulates user build if necessarily.
1454 SetBuildType("user");
1455 }
1456
1457 DropRoot();
1458
1459 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
1460
1461 // We don't know the exact path of su, so we just check for the 'root ...' commands
1462 EXPECT_THAT(out, StartsWith("Skipping"));
1463 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1464 EXPECT_THAT(err, IsEmpty());
1465 }
1466
TEST_F(DumpstateUtilTest,RunCommandAsRootNonUserBuild)1467 TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1468 if (!IsStandalone()) {
1469 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1470 // to Shell - need to refactor tests to avoid this problem)
1471 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1472 return;
1473 }
1474 CreateFd("RunCommandAsRootNonUserBuild.txt");
1475 if (PropertiesHelper::IsUserBuild()) {
1476 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1477 return;
1478 }
1479
1480 DropRoot();
1481
1482 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1483 CommandOptions::WithTimeout(1).AsRoot().Build()));
1484
1485 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1486 EXPECT_THAT(err, StrEq("stderr\n"));
1487 }
1488
1489
TEST_F(DumpstateUtilTest,RunCommandAsRootIfAvailableOnUserBuild)1490 TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1491 if (!IsStandalone()) {
1492 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1493 // to Shell - need to refactor tests to avoid this problem)
1494 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1495 return;
1496 }
1497 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1498 if (!PropertiesHelper::IsUserBuild()) {
1499 // Emulates user build if necessarily.
1500 SetBuildType("user");
1501 }
1502
1503 DropRoot();
1504
1505 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1506 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1507
1508 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1509 EXPECT_THAT(err, StrEq("stderr\n"));
1510 }
1511
TEST_F(DumpstateUtilTest,RunCommandAsRootIfAvailableOnDebugBuild)1512 TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1513 if (!IsStandalone()) {
1514 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1515 // to Shell - need to refactor tests to avoid this problem)
1516 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1517 return;
1518 }
1519 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1520 if (PropertiesHelper::IsUserBuild()) {
1521 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1522 return;
1523 }
1524
1525 DropRoot();
1526
1527 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1528 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1529
1530 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1531 EXPECT_THAT(err, StrEq("stderr\n"));
1532 }
1533
TEST_F(DumpstateUtilTest,RunCommandDropRoot)1534 TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1535 if (!IsStandalone()) {
1536 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1537 // to Shell - need to refactor tests to avoid this problem)
1538 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1539 return;
1540 }
1541 CreateFd("RunCommandDropRoot.txt");
1542 // First check root case - only available when running with 'adb root'.
1543 uid_t uid = getuid();
1544 if (uid == 0) {
1545 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
1546 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1547 EXPECT_THAT(err, StrEq("stderr\n"));
1548 return;
1549 }
1550 // Then run dropping root.
1551 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1552 CommandOptions::WithTimeout(1).DropRoot().Build()));
1553 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1554 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1555 }
1556
TEST_F(DumpstateUtilTest,DumpFileNotFoundNoTitle)1557 TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
1558 CreateFd("DumpFileNotFound.txt");
1559 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
1560 EXPECT_THAT(out,
1561 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1562 EXPECT_THAT(err, IsEmpty());
1563 }
1564
TEST_F(DumpstateUtilTest,DumpFileNotFoundWithTitle)1565 TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1566 CreateFd("DumpFileNotFound.txt");
1567 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1568 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1569 "file or directory\n"));
1570 EXPECT_THAT(err, IsEmpty());
1571 }
1572
TEST_F(DumpstateUtilTest,DumpFileSingleLine)1573 TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1574 CreateFd("DumpFileSingleLine.txt");
1575 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1576 EXPECT_THAT(err, IsEmpty());
1577 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1578 }
1579
TEST_F(DumpstateUtilTest,DumpFileSingleLineWithNewLine)1580 TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1581 CreateFd("DumpFileSingleLineWithNewLine.txt");
1582 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
1583 EXPECT_THAT(err, IsEmpty());
1584 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1585 }
1586
TEST_F(DumpstateUtilTest,DumpFileMultipleLines)1587 TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1588 CreateFd("DumpFileMultipleLines.txt");
1589 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
1590 EXPECT_THAT(err, IsEmpty());
1591 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1592 }
1593
TEST_F(DumpstateUtilTest,DumpFileMultipleLinesWithNewLine)1594 TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1595 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
1596 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
1597 EXPECT_THAT(err, IsEmpty());
1598 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1599 }
1600
TEST_F(DumpstateUtilTest,DumpFileOnDryRunNoTitle)1601 TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1602 CreateFd("DumpFileOnDryRun.txt");
1603 SetDryRun(true);
1604 std::string path = kTestDataPath + "single-line.txt";
1605 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1606 EXPECT_THAT(err, IsEmpty());
1607 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1608 }
1609
TEST_F(DumpstateUtilTest,DumpFileOnDryRun)1610 TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1611 CreateFd("DumpFileOnDryRun.txt");
1612 SetDryRun(true);
1613 std::string path = kTestDataPath + "single-line.txt";
1614 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
1615 EXPECT_THAT(err, IsEmpty());
1616 EXPECT_THAT(
1617 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1618 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
1619 }
1620
1621 } // namespace dumpstate
1622 } // namespace os
1623 } // namespace android
1624