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