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