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