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