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