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