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