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 
40 namespace android {
41 namespace os {
42 namespace dumpstate {
43 
44 using ::testing::EndsWith;
45 using ::testing::HasSubstr;
46 using ::testing::IsNull;
47 using ::testing::IsEmpty;
48 using ::testing::NotNull;
49 using ::testing::StrEq;
50 using ::testing::StartsWith;
51 using ::testing::Test;
52 using ::testing::internal::CaptureStderr;
53 using ::testing::internal::CaptureStdout;
54 using ::testing::internal::GetCapturedStderr;
55 using ::testing::internal::GetCapturedStdout;
56 
57 class DumpstateListenerMock : public IDumpstateListener {
58   public:
59     MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
60     MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
61     MOCK_METHOD4(onSectionComplete, binder::Status(const ::std::string& name, int32_t status,
62                                                    int32_t size, int32_t durationMs));
63 
64   protected:
65     MOCK_METHOD0(onAsBinder, IBinder*());
66 };
67 
68 static int calls_;
69 
70 // Base class for all tests in this file
71 class DumpstateBaseTest : public Test {
72   public:
SetUp()73     virtual void SetUp() override {
74         calls_++;
75         SetDryRun(false);
76     }
77 
SetDryRun(bool dry_run) const78     void SetDryRun(bool dry_run) const {
79         PropertiesHelper::dry_run_ = dry_run;
80     }
81 
SetBuildType(const std::string & build_type) const82     void SetBuildType(const std::string& build_type) const {
83         PropertiesHelper::build_type_ = build_type;
84     }
85 
IsStandalone() const86     bool IsStandalone() const {
87         return calls_ == 1;
88     }
89 
DropRoot() const90     void DropRoot() const {
91         DropRootUser();
92         uid_t uid = getuid();
93         ASSERT_EQ(2000, (int)uid);
94     }
95 
96   protected:
97     const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
98     const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
99     const std::string kTestDataPath = kFixturesPath + "tests/testdata/";
100     const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
101     const std::string kEchoCommand = "/system/bin/echo";
102 
103     /*
104      * Copies a text file fixture to a temporary file, returning it's path.
105      *
106      * Useful in cases where the test case changes the content of the tile.
107      */
CopyTextFileFixture(const std::string & relative_name)108     std::string CopyTextFileFixture(const std::string& relative_name) {
109         std::string from = kTestDataPath + relative_name;
110         // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
111         // around for poking when the test fails.
112         std::string to = kTestDataPath + relative_name + ".tmp";
113         ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
114         android::base::RemoveFileIfExists(to);
115         CopyTextFile(from, to);
116         return to.c_str();
117     }
118 
119     // Need functions that returns void to use assertions -
120     // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
ReadFileToString(const std::string & path,std::string * content)121     void ReadFileToString(const std::string& path, std::string* content) {
122         ASSERT_TRUE(android::base::ReadFileToString(path, content))
123             << "could not read contents from " << path;
124     }
WriteStringToFile(const std::string & content,const std::string & path)125     void WriteStringToFile(const std::string& content, const std::string& path) {
126         ASSERT_TRUE(android::base::WriteStringToFile(content, path))
127             << "could not write contents to " << path;
128     }
129 
130   private:
CopyTextFile(const std::string & from,const std::string & to)131     void CopyTextFile(const std::string& from, const std::string& to) {
132         std::string content;
133         ReadFileToString(from, &content);
134         WriteStringToFile(content, to);
135     }
136 };
137 
138 class DumpstateTest : public DumpstateBaseTest {
139   public:
SetUp()140     void SetUp() {
141         DumpstateBaseTest::SetUp();
142         SetDryRun(false);
143         SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
144         ds.progress_.reset(new Progress());
145         ds.update_progress_ = false;
146         ds.update_progress_threshold_ = 0;
147     }
148 
149     // 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)150     int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
151                    const CommandOptions& options = CommandOptions::DEFAULT) {
152         CaptureStdout();
153         CaptureStderr();
154         int status = ds.RunCommand(title, full_command, options);
155         out = GetCapturedStdout();
156         err = GetCapturedStderr();
157         return status;
158     }
159 
160     // Dumps a file and capture `stdout` and `stderr`.
DumpFile(const std::string & title,const std::string & path)161     int DumpFile(const std::string& title, const std::string& path) {
162         CaptureStdout();
163         CaptureStderr();
164         int status = ds.DumpFile(title, path);
165         out = GetCapturedStdout();
166         err = GetCapturedStderr();
167         return status;
168     }
169 
SetProgress(long progress,long initial_max,long threshold=0)170     void SetProgress(long progress, long initial_max, long threshold = 0) {
171         ds.update_progress_ = true;
172         ds.update_progress_threshold_ = threshold;
173         ds.last_updated_progress_ = 0;
174         ds.progress_.reset(new Progress(initial_max, progress, 1.2));
175     }
176 
GetProgressMessage(const std::string & listener_name,int progress,int max,int old_max=0,bool update_progress=true)177     std::string GetProgressMessage(const std::string& listener_name, int progress, int max,
178                                    int old_max = 0, bool update_progress = true) {
179         EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
180         EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
181 
182         bool max_increased = old_max > 0;
183 
184         std::string message = "";
185         if (max_increased) {
186             message =
187                 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
188         }
189 
190         if (update_progress) {
191             message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
192                                                    listener_name.c_str(), progress, max);
193         }
194 
195         return message;
196     }
197 
198     // `stdout` and `stderr` from the last command ran.
199     std::string out, err;
200 
201     Dumpstate& ds = Dumpstate::GetInstance();
202 };
203 
TEST_F(DumpstateTest,RunCommandNoArgs)204 TEST_F(DumpstateTest, RunCommandNoArgs) {
205     EXPECT_EQ(-1, RunCommand("", {}));
206 }
207 
TEST_F(DumpstateTest,RunCommandNoTitle)208 TEST_F(DumpstateTest, RunCommandNoTitle) {
209     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
210     EXPECT_THAT(out, StrEq("stdout\n"));
211     EXPECT_THAT(err, StrEq("stderr\n"));
212 }
213 
TEST_F(DumpstateTest,RunCommandWithTitle)214 TEST_F(DumpstateTest, RunCommandWithTitle) {
215     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
216     EXPECT_THAT(err, StrEq("stderr\n"));
217     // We don't know the exact duration, so we check the prefix and suffix
218     EXPECT_THAT(out,
219                 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------"));
220     EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
221 }
222 
TEST_F(DumpstateTest,RunCommandWithLoggingMessage)223 TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
224     EXPECT_EQ(
225         0, RunCommand("", {kSimpleCommand},
226                       CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
227     EXPECT_THAT(out, StrEq("stdout\n"));
228     EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
229 }
230 
TEST_F(DumpstateTest,RunCommandRedirectStderr)231 TEST_F(DumpstateTest, RunCommandRedirectStderr) {
232     EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
233                             CommandOptions::WithTimeout(10).RedirectStderr().Build()));
234     EXPECT_THAT(out, IsEmpty());
235     EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
236 }
237 
TEST_F(DumpstateTest,RunCommandWithOneArg)238 TEST_F(DumpstateTest, RunCommandWithOneArg) {
239     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
240     EXPECT_THAT(err, IsEmpty());
241     EXPECT_THAT(out, StrEq("one\n"));
242 }
243 
TEST_F(DumpstateTest,RunCommandWithMultipleArgs)244 TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
245     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
246     EXPECT_THAT(err, IsEmpty());
247     EXPECT_THAT(out, StrEq("one is the loniest number\n"));
248 }
249 
TEST_F(DumpstateTest,RunCommandDryRun)250 TEST_F(DumpstateTest, RunCommandDryRun) {
251     SetDryRun(true);
252     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
253     // We don't know the exact duration, so we check the prefix and suffix
254     EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
255                                 ") ------\n\t(skipped on dry run)\n------"));
256     EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
257     EXPECT_THAT(err, IsEmpty());
258 }
259 
TEST_F(DumpstateTest,RunCommandDryRunNoTitle)260 TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
261     SetDryRun(true);
262     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
263     EXPECT_THAT(out, IsEmpty());
264     EXPECT_THAT(err, IsEmpty());
265 }
266 
TEST_F(DumpstateTest,RunCommandDryRunAlways)267 TEST_F(DumpstateTest, RunCommandDryRunAlways) {
268     SetDryRun(true);
269     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
270     EXPECT_THAT(out, StrEq("stdout\n"));
271     EXPECT_THAT(err, StrEq("stderr\n"));
272 }
273 
TEST_F(DumpstateTest,RunCommandNotFound)274 TEST_F(DumpstateTest, RunCommandNotFound) {
275     EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
276     EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
277     EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
278 }
279 
TEST_F(DumpstateTest,RunCommandFails)280 TEST_F(DumpstateTest, RunCommandFails) {
281     EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
282     EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
283                            " --exit 42' failed: exit code 42\n"));
284     EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
285                            " --exit 42' failed: exit code 42\n"));
286 }
287 
TEST_F(DumpstateTest,RunCommandCrashes)288 TEST_F(DumpstateTest, RunCommandCrashes) {
289     EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
290     // We don't know the exit code, so check just the prefix.
291     EXPECT_THAT(
292         out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
293     EXPECT_THAT(
294         err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
295 }
296 
TEST_F(DumpstateTest,RunCommandTimesout)297 TEST_F(DumpstateTest, RunCommandTimesout) {
298     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
299                              CommandOptions::WithTimeout(1).Build()));
300     EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
301                                 " --sleep 2' timed out after 1"));
302     EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
303                                 " --sleep 2' timed out after 1"));
304 }
305 
TEST_F(DumpstateTest,RunCommandIsKilled)306 TEST_F(DumpstateTest, RunCommandIsKilled) {
307     CaptureStdout();
308     CaptureStderr();
309 
310     std::thread t([=]() {
311         EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
312                                          CommandOptions::WithTimeout(100).Always().Build()));
313     });
314 
315     // Capture pid and pre-sleep output.
316     sleep(1);  // Wait a little bit to make sure pid and 1st line were printed.
317     std::string err = GetCapturedStderr();
318     EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
319 
320     std::string out = GetCapturedStdout();
321     std::vector<std::string> lines = android::base::Split(out, "\n");
322     ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
323 
324     int pid = atoi(lines[0].c_str());
325     EXPECT_THAT(lines[1], StrEq("stdout line1"));
326     EXPECT_THAT(lines[2], IsEmpty());  // \n
327 
328     // Then kill the process.
329     CaptureStdout();
330     CaptureStderr();
331     ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
332     t.join();
333 
334     // Finally, check output after murder.
335     out = GetCapturedStdout();
336     err = GetCapturedStderr();
337 
338     EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
339                            " --pid --sleep 20' failed: killed by signal 15\n"));
340     EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
341                            " --pid --sleep 20' failed: killed by signal 15\n"));
342 }
343 
TEST_F(DumpstateTest,RunCommandProgress)344 TEST_F(DumpstateTest, RunCommandProgress) {
345     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
346     ds.listener_ = listener;
347     ds.listener_name_ = "FoxMulder";
348     SetProgress(0, 30);
349 
350     EXPECT_CALL(*listener, onProgressUpdated(20));
351     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
352     std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
353     EXPECT_THAT(out, StrEq("stdout\n"));
354     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
355 
356     EXPECT_CALL(*listener, onProgressUpdated(30));
357     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
358     progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
359     EXPECT_THAT(out, StrEq("stdout\n"));
360     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
361 
362     // Run a command that will increase maximum timeout.
363     EXPECT_CALL(*listener, onProgressUpdated(31));
364     EXPECT_CALL(*listener, onMaxProgressUpdated(37));
365     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
366     progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase
367     EXPECT_THAT(out, StrEq("stdout\n"));
368     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
369 
370     // Make sure command ran while in dry_run is counted.
371     SetDryRun(true);
372     EXPECT_CALL(*listener, onProgressUpdated(35));
373     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
374     progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
375     EXPECT_THAT(out, IsEmpty());
376     EXPECT_THAT(err, StrEq(progress_message));
377 
378     ds.listener_.clear();
379 }
380 
TEST_F(DumpstateTest,RunCommandProgressIgnoreThreshold)381 TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
382     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
383     ds.listener_ = listener;
384     ds.listener_name_ = "FoxMulder";
385     SetProgress(0, 8, 5);  // 8 max, 5 threshold
386 
387     // First update should always be sent.
388     EXPECT_CALL(*listener, onProgressUpdated(1));
389     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
390     std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
391     EXPECT_THAT(out, StrEq("stdout\n"));
392     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
393 
394     // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
395     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
396     EXPECT_THAT(out, StrEq("stdout\n"));
397     EXPECT_THAT(err, StrEq("stderr\n"));
398 
399     // Third update should be sent because it reaches threshold (6 - 1 = 5).
400     EXPECT_CALL(*listener, onProgressUpdated(6));
401     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
402     progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
403     EXPECT_THAT(out, StrEq("stdout\n"));
404     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
405 
406     // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
407     // But max update should be sent.
408     EXPECT_CALL(*listener, onMaxProgressUpdated(10));  // 9 * 120% = 10.8 = 10
409     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
410     progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
411     EXPECT_THAT(out, StrEq("stdout\n"));
412     EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
413 
414     ds.listener_.clear();
415 }
416 
TEST_F(DumpstateTest,RunCommandDropRoot)417 TEST_F(DumpstateTest, RunCommandDropRoot) {
418     if (!IsStandalone()) {
419         // TODO: temporarily disabled because it might cause other tests to fail after dropping
420         // to Shell - need to refactor tests to avoid this problem)
421         MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
422         return;
423     }
424     // First check root case - only available when running with 'adb root'.
425     uid_t uid = getuid();
426     if (uid == 0) {
427         EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
428         EXPECT_THAT(out, StrEq("0\nstdout\n"));
429         EXPECT_THAT(err, StrEq("stderr\n"));
430         return;
431     }
432     // Then run dropping root.
433     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
434                             CommandOptions::WithTimeout(1).DropRoot().Build()));
435     EXPECT_THAT(out, StrEq("2000\nstdout\n"));
436     EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
437 }
438 
TEST_F(DumpstateTest,RunCommandAsRootUserBuild)439 TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
440     if (!IsStandalone()) {
441         // TODO: temporarily disabled because it might cause other tests to fail after dropping
442         // to Shell - need to refactor tests to avoid this problem)
443         MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
444         return;
445     }
446     if (!PropertiesHelper::IsUserBuild()) {
447         // Emulates user build if necessarily.
448         SetBuildType("user");
449     }
450 
451     DropRoot();
452 
453     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
454 
455     // We don't know the exact path of su, so we just check for the 'root ...' commands
456     EXPECT_THAT(out, StartsWith("Skipping"));
457     EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
458     EXPECT_THAT(err, IsEmpty());
459 }
460 
TEST_F(DumpstateTest,RunCommandAsRootNonUserBuild)461 TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
462     if (!IsStandalone()) {
463         // TODO: temporarily disabled because it might cause other tests to fail after dropping
464         // to Shell - need to refactor tests to avoid this problem)
465         MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
466         return;
467     }
468     if (PropertiesHelper::IsUserBuild()) {
469         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
470         return;
471     }
472 
473     DropRoot();
474 
475     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
476                             CommandOptions::WithTimeout(1).AsRoot().Build()));
477 
478     EXPECT_THAT(out, StrEq("0\nstdout\n"));
479     EXPECT_THAT(err, StrEq("stderr\n"));
480 }
481 
TEST_F(DumpstateTest,RunCommandAsRootIfAvailableOnUserBuild)482 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
483     if (!IsStandalone()) {
484         // TODO: temporarily disabled because it might cause other tests to fail after dropping
485         // to Shell - need to refactor tests to avoid this problem)
486         MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
487         return;
488     }
489     if (!PropertiesHelper::IsUserBuild()) {
490         // Emulates user build if necessarily.
491         SetBuildType("user");
492     }
493 
494     DropRoot();
495 
496     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
497                             CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
498 
499     EXPECT_THAT(out, StrEq("2000\nstdout\n"));
500     EXPECT_THAT(err, StrEq("stderr\n"));
501 }
502 
TEST_F(DumpstateTest,RunCommandAsRootIfAvailableOnDebugBuild)503 TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
504     if (!IsStandalone()) {
505         // TODO: temporarily disabled because it might cause other tests to fail after dropping
506         // to Shell - need to refactor tests to avoid this problem)
507         MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
508         return;
509     }
510     if (PropertiesHelper::IsUserBuild()) {
511         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
512         return;
513     }
514 
515     DropRoot();
516 
517     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
518                             CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
519 
520     EXPECT_THAT(out, StrEq("0\nstdout\n"));
521     EXPECT_THAT(err, StrEq("stderr\n"));
522 }
523 
TEST_F(DumpstateTest,DumpFileNotFoundNoTitle)524 TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
525     EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
526     EXPECT_THAT(out,
527                 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
528     EXPECT_THAT(err, IsEmpty());
529 }
530 
TEST_F(DumpstateTest,DumpFileNotFoundWithTitle)531 TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
532     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
533     EXPECT_THAT(err, IsEmpty());
534     // We don't know the exact duration, so we check the prefix and suffix
535     EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
536                                 "such file or directory\n"));
537     EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n"));
538 }
539 
TEST_F(DumpstateTest,DumpFileSingleLine)540 TEST_F(DumpstateTest, DumpFileSingleLine) {
541     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
542     EXPECT_THAT(err, IsEmpty());
543     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
544 }
545 
TEST_F(DumpstateTest,DumpFileSingleLineWithNewLine)546 TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
547     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
548     EXPECT_THAT(err, IsEmpty());
549     EXPECT_THAT(out, StrEq("I AM LINE1\n"));
550 }
551 
TEST_F(DumpstateTest,DumpFileMultipleLines)552 TEST_F(DumpstateTest, DumpFileMultipleLines) {
553     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
554     EXPECT_THAT(err, IsEmpty());
555     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
556 }
557 
TEST_F(DumpstateTest,DumpFileMultipleLinesWithNewLine)558 TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
559     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
560     EXPECT_THAT(err, IsEmpty());
561     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
562 }
563 
TEST_F(DumpstateTest,DumpFileOnDryRunNoTitle)564 TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
565     SetDryRun(true);
566     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
567     EXPECT_THAT(err, IsEmpty());
568     EXPECT_THAT(out, IsEmpty());
569 }
570 
TEST_F(DumpstateTest,DumpFileOnDryRun)571 TEST_F(DumpstateTest, DumpFileOnDryRun) {
572     SetDryRun(true);
573     EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
574     EXPECT_THAT(err, IsEmpty());
575     EXPECT_THAT(
576         out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
577     EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------"));
578     EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n"));
579 }
580 
TEST_F(DumpstateTest,DumpFileUpdateProgress)581 TEST_F(DumpstateTest, DumpFileUpdateProgress) {
582     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
583     ds.listener_ = listener;
584     ds.listener_name_ = "FoxMulder";
585     SetProgress(0, 30);
586 
587     EXPECT_CALL(*listener, onProgressUpdated(5));
588     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
589 
590     std::string progress_message =
591         GetProgressMessage(ds.listener_name_, 5, 30);  // TODO: unhardcode WEIGHT_FILE (5)?
592     EXPECT_THAT(err, StrEq(progress_message));
593     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
594 
595     ds.listener_.clear();
596 }
597 
598 class DumpstateServiceTest : public DumpstateBaseTest {
599   public:
600     DumpstateService dss;
601 };
602 
TEST_F(DumpstateServiceTest,SetListenerNoName)603 TEST_F(DumpstateServiceTest, SetListenerNoName) {
604     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
605     sp<IDumpstateToken> token;
606     EXPECT_TRUE(dss.setListener("", listener, /* getSectionDetails = */ false, &token).isOk());
607     ASSERT_THAT(token, IsNull());
608 }
609 
TEST_F(DumpstateServiceTest,SetListenerNoPointer)610 TEST_F(DumpstateServiceTest, SetListenerNoPointer) {
611     sp<IDumpstateToken> token;
612     EXPECT_TRUE(
613         dss.setListener("whatever", nullptr, /* getSectionDetails = */ false, &token).isOk());
614     ASSERT_THAT(token, IsNull());
615 }
616 
TEST_F(DumpstateServiceTest,SetListenerTwice)617 TEST_F(DumpstateServiceTest, SetListenerTwice) {
618     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
619     sp<IDumpstateToken> token;
620     EXPECT_TRUE(
621         dss.setListener("whatever", listener, /* getSectionDetails = */ false, &token).isOk());
622     ASSERT_THAT(token, NotNull());
623     EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
624     EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
625 
626     token.clear();
627     EXPECT_TRUE(
628         dss.setListener("whatsoever", listener, /* getSectionDetails = */ false, &token).isOk());
629     ASSERT_THAT(token, IsNull());
630     EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
631     EXPECT_FALSE(Dumpstate::GetInstance().report_section_);
632 }
633 
TEST_F(DumpstateServiceTest,SetListenerWithSectionDetails)634 TEST_F(DumpstateServiceTest, SetListenerWithSectionDetails) {
635     sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
636     sp<IDumpstateToken> token;
637     Dumpstate::GetInstance().listener_ = nullptr;
638     EXPECT_TRUE(
639         dss.setListener("whatever", listener, /* getSectionDetails = */ true, &token).isOk());
640     ASSERT_THAT(token, NotNull());
641     EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
642     EXPECT_TRUE(Dumpstate::GetInstance().report_section_);
643 }
644 
645 class ProgressTest : public DumpstateBaseTest {
646   public:
GetInstance(int32_t max,double growth_factor,const std::string & path="")647     Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
648         return Progress(max, growth_factor, path);
649     }
650 
AssertStats(const std::string & path,int32_t expected_runs,int32_t expected_average)651     void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
652         std::string expected_content =
653             android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
654         std::string actual_content;
655         ReadFileToString(path, &actual_content);
656         ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
657     }
658 };
659 
TEST_F(ProgressTest,SimpleTest)660 TEST_F(ProgressTest, SimpleTest) {
661     Progress progress;
662     EXPECT_EQ(0, progress.Get());
663     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
664     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
665 
666     bool max_increased = progress.Inc(1);
667     EXPECT_EQ(1, progress.Get());
668     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
669     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
670     EXPECT_FALSE(max_increased);
671 
672     // Ignore negative increase.
673     max_increased = progress.Inc(-1);
674     EXPECT_EQ(1, progress.Get());
675     EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
676     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
677     EXPECT_FALSE(max_increased);
678 }
679 
TEST_F(ProgressTest,MaxGrowsInsideNewRange)680 TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
681     Progress progress = GetInstance(10, 1.2);  // 20% growth factor
682     EXPECT_EQ(0, progress.Get());
683     EXPECT_EQ(10, progress.GetInitialMax());
684     EXPECT_EQ(10, progress.GetMax());
685 
686     // No increase
687     bool max_increased = progress.Inc(10);
688     EXPECT_EQ(10, progress.Get());
689     EXPECT_EQ(10, progress.GetMax());
690     EXPECT_FALSE(max_increased);
691 
692     // Increase, with new value < max*20%
693     max_increased = progress.Inc(1);
694     EXPECT_EQ(11, progress.Get());
695     EXPECT_EQ(13, progress.GetMax());  // 11 average * 20% growth = 13.2 = 13
696     EXPECT_TRUE(max_increased);
697 }
698 
TEST_F(ProgressTest,MaxGrowsOutsideNewRange)699 TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
700     Progress progress = GetInstance(10, 1.2);  // 20% growth factor
701     EXPECT_EQ(0, progress.Get());
702     EXPECT_EQ(10, progress.GetInitialMax());
703     EXPECT_EQ(10, progress.GetMax());
704 
705     // No increase
706     bool max_increased = progress.Inc(10);
707     EXPECT_EQ(10, progress.Get());
708     EXPECT_EQ(10, progress.GetMax());
709     EXPECT_FALSE(max_increased);
710 
711     // Increase, with new value > max*20%
712     max_increased = progress.Inc(5);
713     EXPECT_EQ(15, progress.Get());
714     EXPECT_EQ(18, progress.GetMax());  // 15 average * 20% growth = 18
715     EXPECT_TRUE(max_increased);
716 }
717 
TEST_F(ProgressTest,InvalidPath)718 TEST_F(ProgressTest, InvalidPath) {
719     Progress progress("/devil/null");
720     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
721 }
722 
TEST_F(ProgressTest,EmptyFile)723 TEST_F(ProgressTest, EmptyFile) {
724     Progress progress(CopyTextFileFixture("empty-file.txt"));
725     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
726 }
727 
TEST_F(ProgressTest,InvalidLine1stEntryNAN)728 TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
729     Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
730     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
731 }
732 
TEST_F(ProgressTest,InvalidLine2ndEntryNAN)733 TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
734     Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
735     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
736 }
737 
TEST_F(ProgressTest,InvalidLineBothNAN)738 TEST_F(ProgressTest, InvalidLineBothNAN) {
739     Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
740     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
741 }
742 
TEST_F(ProgressTest,InvalidLine1stEntryNegative)743 TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
744     Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
745     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
746 }
747 
TEST_F(ProgressTest,InvalidLine2ndEntryNegative)748 TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
749     Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
750     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
751 }
752 
TEST_F(ProgressTest,InvalidLine1stEntryTooBig)753 TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
754     Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
755     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
756 }
757 
TEST_F(ProgressTest,InvalidLine2ndEntryTooBig)758 TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
759     Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
760     EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
761 }
762 
763 // Tests stats are properly saved when the file does not exists.
TEST_F(ProgressTest,FirstTime)764 TEST_F(ProgressTest, FirstTime) {
765     if (!IsStandalone()) {
766         // TODO: temporarily disabled because it's failing when running as suite
767         MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
768         return;
769     }
770 
771     std::string path = kTestDataPath + "FirstTime.txt";
772     android::base::RemoveFileIfExists(path);
773 
774     Progress run1(path);
775     EXPECT_EQ(0, run1.Get());
776     EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
777     EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
778 
779     bool max_increased = run1.Inc(20);
780     EXPECT_EQ(20, run1.Get());
781     EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
782     EXPECT_FALSE(max_increased);
783 
784     run1.Save();
785     AssertStats(path, 1, 20);
786 }
787 
788 // Tests what happens when the persistent settings contains the average duration of 1 run.
789 // Data on file is 1 run and 109 average.
TEST_F(ProgressTest,SecondTime)790 TEST_F(ProgressTest, SecondTime) {
791     std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
792 
793     Progress run1 = GetInstance(-42, 1.2, path);
794     EXPECT_EQ(0, run1.Get());
795     EXPECT_EQ(10, run1.GetInitialMax());
796     EXPECT_EQ(10, run1.GetMax());
797 
798     bool max_increased = run1.Inc(20);
799     EXPECT_EQ(20, run1.Get());
800     EXPECT_EQ(24, run1.GetMax());
801     EXPECT_TRUE(max_increased);
802 
803     // Average now is 2 runs and (10 + 20)/ 2 = 15
804     run1.Save();
805     AssertStats(path, 2, 15);
806 
807     Progress run2 = GetInstance(-42, 1.2, path);
808     EXPECT_EQ(0, run2.Get());
809     EXPECT_EQ(15, run2.GetInitialMax());
810     EXPECT_EQ(15, run2.GetMax());
811 
812     max_increased = run2.Inc(25);
813     EXPECT_EQ(25, run2.Get());
814     EXPECT_EQ(30, run2.GetMax());
815     EXPECT_TRUE(max_increased);
816 
817     // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
818     run2.Save();
819     AssertStats(path, 3, 18);
820 
821     Progress run3 = GetInstance(-42, 1.2, path);
822     EXPECT_EQ(0, run3.Get());
823     EXPECT_EQ(18, run3.GetInitialMax());
824     EXPECT_EQ(18, run3.GetMax());
825 
826     // Make sure average decreases as well
827     max_increased = run3.Inc(5);
828     EXPECT_EQ(5, run3.Get());
829     EXPECT_EQ(18, run3.GetMax());
830     EXPECT_FALSE(max_increased);
831 
832     // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
833     run3.Save();
834     AssertStats(path, 4, 14);
835 }
836 
837 // Tests what happens when the persistent settings contains the average duration of 2 runs.
838 // Data on file is 2 runs and 15 average.
TEST_F(ProgressTest,ThirdTime)839 TEST_F(ProgressTest, ThirdTime) {
840     std::string path = CopyTextFileFixture("stats-two-runs.txt");
841     AssertStats(path, 2, 15);  // Sanity check
842 
843     Progress run1 = GetInstance(-42, 1.2, path);
844     EXPECT_EQ(0, run1.Get());
845     EXPECT_EQ(15, run1.GetInitialMax());
846     EXPECT_EQ(15, run1.GetMax());
847 
848     bool max_increased = run1.Inc(20);
849     EXPECT_EQ(20, run1.Get());
850     EXPECT_EQ(24, run1.GetMax());
851     EXPECT_TRUE(max_increased);
852 
853     // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
854     run1.Save();
855     AssertStats(path, 3, 16);
856 }
857 
858 class DumpstateUtilTest : public DumpstateBaseTest {
859   public:
SetUp()860     void SetUp() {
861         DumpstateBaseTest::SetUp();
862         SetDryRun(false);
863     }
864 
CaptureFdOut()865     void CaptureFdOut() {
866         ReadFileToString(path_, &out);
867     }
868 
CreateFd(const std::string & name)869     void CreateFd(const std::string& name) {
870         path_ = kTestDataPath + name;
871         MYLOGD("Creating fd for file %s\n", path_.c_str());
872 
873         fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
874                                      O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
875                                      S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
876         ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
877     }
878 
879     // 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)880     int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
881                    const CommandOptions& options = CommandOptions::DEFAULT) {
882         CaptureStderr();
883         int status = RunCommandToFd(fd, title, full_command, options);
884         close(fd);
885 
886         CaptureFdOut();
887         err = GetCapturedStderr();
888         return status;
889     }
890 
891     // Dumps a file and into the `fd` and `stderr`.
DumpFile(const std::string & title,const std::string & path)892     int DumpFile(const std::string& title, const std::string& path) {
893         CaptureStderr();
894         int status = DumpFileToFd(fd, title, path);
895         close(fd);
896 
897         CaptureFdOut();
898         err = GetCapturedStderr();
899         return status;
900     }
901 
902     // Find out the pid of the process_name
FindPidOfProcess(const std::string & process_name)903     int FindPidOfProcess(const std::string& process_name) {
904         CaptureStderr();
905         int status = GetPidByName(process_name);
906         err = GetCapturedStderr();
907         return status;
908     }
909 
910     int fd;
911 
912     // 'fd` output and `stderr` from the last command ran.
913     std::string out, err;
914 
915   private:
916     std::string path_;
917 };
918 
TEST_F(DumpstateUtilTest,RunCommandNoArgs)919 TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
920     CreateFd("RunCommandNoArgs.txt");
921     EXPECT_EQ(-1, RunCommand("", {}));
922 }
923 
TEST_F(DumpstateUtilTest,RunCommandNoTitle)924 TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
925     CreateFd("RunCommandWithNoArgs.txt");
926     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
927     EXPECT_THAT(out, StrEq("stdout\n"));
928     EXPECT_THAT(err, StrEq("stderr\n"));
929 }
930 
TEST_F(DumpstateUtilTest,RunCommandWithTitle)931 TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
932     CreateFd("RunCommandWithNoArgs.txt");
933     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
934     EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
935     EXPECT_THAT(err, StrEq("stderr\n"));
936 }
937 
TEST_F(DumpstateUtilTest,RunCommandWithOneArg)938 TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
939     CreateFd("RunCommandWithOneArg.txt");
940     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
941     EXPECT_THAT(err, IsEmpty());
942     EXPECT_THAT(out, StrEq("one\n"));
943 }
944 
TEST_F(DumpstateUtilTest,RunCommandWithMultipleArgs)945 TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
946     CreateFd("RunCommandWithMultipleArgs.txt");
947     EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
948     EXPECT_THAT(err, IsEmpty());
949     EXPECT_THAT(out, StrEq("one is the loniest number\n"));
950 }
951 
TEST_F(DumpstateUtilTest,RunCommandWithLoggingMessage)952 TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
953     CreateFd("RunCommandWithLoggingMessage.txt");
954     EXPECT_EQ(
955         0, RunCommand("", {kSimpleCommand},
956                       CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
957     EXPECT_THAT(out, StrEq("stdout\n"));
958     EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
959 }
960 
TEST_F(DumpstateUtilTest,RunCommandRedirectStderr)961 TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
962     CreateFd("RunCommandRedirectStderr.txt");
963     EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
964                             CommandOptions::WithTimeout(10).RedirectStderr().Build()));
965     EXPECT_THAT(out, IsEmpty());
966     EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
967 }
968 
TEST_F(DumpstateUtilTest,RunCommandDryRun)969 TEST_F(DumpstateUtilTest, RunCommandDryRun) {
970     CreateFd("RunCommandDryRun.txt");
971     SetDryRun(true);
972     EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
973     EXPECT_THAT(out, StrEq(android::base::StringPrintf(
974                          "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
975                          kSimpleCommand.c_str())));
976     EXPECT_THAT(err, IsEmpty());
977 }
978 
TEST_F(DumpstateUtilTest,RunCommandDryRunNoTitle)979 TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
980     CreateFd("RunCommandDryRun.txt");
981     SetDryRun(true);
982     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
983     EXPECT_THAT(
984         out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
985     EXPECT_THAT(err, IsEmpty());
986 }
987 
TEST_F(DumpstateUtilTest,RunCommandDryRunAlways)988 TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
989     CreateFd("RunCommandDryRunAlways.txt");
990     SetDryRun(true);
991     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
992     EXPECT_THAT(out, StrEq("stdout\n"));
993     EXPECT_THAT(err, StrEq("stderr\n"));
994 }
995 
TEST_F(DumpstateUtilTest,RunCommandNotFound)996 TEST_F(DumpstateUtilTest, RunCommandNotFound) {
997     CreateFd("RunCommandNotFound.txt");
998     EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
999     EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1000     EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1001 }
1002 
TEST_F(DumpstateUtilTest,RunCommandFails)1003 TEST_F(DumpstateUtilTest, RunCommandFails) {
1004     CreateFd("RunCommandFails.txt");
1005     EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
1006     EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1007                            " --exit 42' failed: exit code 42\n"));
1008     EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1009                            " --exit 42' failed: exit code 42\n"));
1010 }
1011 
TEST_F(DumpstateUtilTest,RunCommandCrashes)1012 TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1013     CreateFd("RunCommandCrashes.txt");
1014     EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
1015     // We don't know the exit code, so check just the prefix.
1016     EXPECT_THAT(
1017         out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1018     EXPECT_THAT(
1019         err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1020 }
1021 
TEST_F(DumpstateUtilTest,RunCommandTimesoutWithSec)1022 TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
1023     CreateFd("RunCommandTimesout.txt");
1024     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1025                              CommandOptions::WithTimeout(1).Build()));
1026     EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1027                                 " --sleep 2' timed out after 1"));
1028     EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1029                                 " --sleep 2' timed out after 1"));
1030 }
1031 
TEST_F(DumpstateUtilTest,RunCommandTimesoutWithMsec)1032 TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1033     CreateFd("RunCommandTimesout.txt");
1034     EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1035                              CommandOptions::WithTimeoutInMs(1000).Build()));
1036     EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1037                                 " --sleep 2' timed out after 1"));
1038     EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1039                                 " --sleep 2' timed out after 1"));
1040 }
1041 
1042 
TEST_F(DumpstateUtilTest,RunCommandIsKilled)1043 TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1044     CreateFd("RunCommandIsKilled.txt");
1045     CaptureStderr();
1046 
1047     std::thread t([=]() {
1048         EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
1049                                           CommandOptions::WithTimeout(100).Always().Build()));
1050     });
1051 
1052     // Capture pid and pre-sleep output.
1053     sleep(1);  // Wait a little bit to make sure pid and 1st line were printed.
1054     std::string err = GetCapturedStderr();
1055     EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1056 
1057     CaptureFdOut();
1058     std::vector<std::string> lines = android::base::Split(out, "\n");
1059     ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1060 
1061     int pid = atoi(lines[0].c_str());
1062     EXPECT_THAT(lines[1], StrEq("stdout line1"));
1063     EXPECT_THAT(lines[2], IsEmpty());  // \n
1064 
1065     // Then kill the process.
1066     CaptureFdOut();
1067     CaptureStderr();
1068     ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1069     t.join();
1070 
1071     // Finally, check output after murder.
1072     CaptureFdOut();
1073     err = GetCapturedStderr();
1074 
1075     // out starts with the pid, which is an unknown
1076     EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1077                               " --pid --sleep 20' failed: killed by signal 15\n"));
1078     EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1079                            " --pid --sleep 20' failed: killed by signal 15\n"));
1080 }
1081 
TEST_F(DumpstateUtilTest,RunCommandAsRootUserBuild)1082 TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1083     if (!IsStandalone()) {
1084         // TODO: temporarily disabled because it might cause other tests to fail after dropping
1085         // to Shell - need to refactor tests to avoid this problem)
1086         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1087         return;
1088     }
1089     CreateFd("RunCommandAsRootUserBuild.txt");
1090     if (!PropertiesHelper::IsUserBuild()) {
1091         // Emulates user build if necessarily.
1092         SetBuildType("user");
1093     }
1094 
1095     DropRoot();
1096 
1097     EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
1098 
1099     // We don't know the exact path of su, so we just check for the 'root ...' commands
1100     EXPECT_THAT(out, StartsWith("Skipping"));
1101     EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1102     EXPECT_THAT(err, IsEmpty());
1103 }
1104 
TEST_F(DumpstateUtilTest,RunCommandAsRootNonUserBuild)1105 TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1106     if (!IsStandalone()) {
1107         // TODO: temporarily disabled because it might cause other tests to fail after dropping
1108         // to Shell - need to refactor tests to avoid this problem)
1109         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1110         return;
1111     }
1112     CreateFd("RunCommandAsRootNonUserBuild.txt");
1113     if (PropertiesHelper::IsUserBuild()) {
1114         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1115         return;
1116     }
1117 
1118     DropRoot();
1119 
1120     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1121                             CommandOptions::WithTimeout(1).AsRoot().Build()));
1122 
1123     EXPECT_THAT(out, StrEq("0\nstdout\n"));
1124     EXPECT_THAT(err, StrEq("stderr\n"));
1125 }
1126 
1127 
TEST_F(DumpstateUtilTest,RunCommandAsRootIfAvailableOnUserBuild)1128 TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1129     if (!IsStandalone()) {
1130         // TODO: temporarily disabled because it might cause other tests to fail after dropping
1131         // to Shell - need to refactor tests to avoid this problem)
1132         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1133         return;
1134     }
1135     CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1136     if (!PropertiesHelper::IsUserBuild()) {
1137         // Emulates user build if necessarily.
1138         SetBuildType("user");
1139     }
1140 
1141     DropRoot();
1142 
1143     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1144                             CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1145 
1146     EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1147     EXPECT_THAT(err, StrEq("stderr\n"));
1148 }
1149 
TEST_F(DumpstateUtilTest,RunCommandAsRootIfAvailableOnDebugBuild)1150 TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1151     if (!IsStandalone()) {
1152         // TODO: temporarily disabled because it might cause other tests to fail after dropping
1153         // to Shell - need to refactor tests to avoid this problem)
1154         MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1155         return;
1156     }
1157     CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1158     if (PropertiesHelper::IsUserBuild()) {
1159         ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1160         return;
1161     }
1162 
1163     DropRoot();
1164 
1165     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1166                             CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1167 
1168     EXPECT_THAT(out, StrEq("0\nstdout\n"));
1169     EXPECT_THAT(err, StrEq("stderr\n"));
1170 }
1171 
TEST_F(DumpstateUtilTest,RunCommandDropRoot)1172 TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1173     if (!IsStandalone()) {
1174         // TODO: temporarily disabled because it might cause other tests to fail after dropping
1175         // to Shell - need to refactor tests to avoid this problem)
1176         MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1177         return;
1178     }
1179     CreateFd("RunCommandDropRoot.txt");
1180     // First check root case - only available when running with 'adb root'.
1181     uid_t uid = getuid();
1182     if (uid == 0) {
1183         EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
1184         EXPECT_THAT(out, StrEq("0\nstdout\n"));
1185         EXPECT_THAT(err, StrEq("stderr\n"));
1186         return;
1187     }
1188     // Then run dropping root.
1189     EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1190                             CommandOptions::WithTimeout(1).DropRoot().Build()));
1191     EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1192     EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1193 }
1194 
TEST_F(DumpstateUtilTest,DumpFileNotFoundNoTitle)1195 TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
1196     CreateFd("DumpFileNotFound.txt");
1197     EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
1198     EXPECT_THAT(out,
1199                 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1200     EXPECT_THAT(err, IsEmpty());
1201 }
1202 
TEST_F(DumpstateUtilTest,DumpFileNotFoundWithTitle)1203 TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1204     CreateFd("DumpFileNotFound.txt");
1205     EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1206     EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1207                            "file or directory\n"));
1208     EXPECT_THAT(err, IsEmpty());
1209 }
1210 
TEST_F(DumpstateUtilTest,DumpFileSingleLine)1211 TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1212     CreateFd("DumpFileSingleLine.txt");
1213     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1214     EXPECT_THAT(err, IsEmpty());
1215     EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
1216 }
1217 
TEST_F(DumpstateUtilTest,DumpFileSingleLineWithNewLine)1218 TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1219     CreateFd("DumpFileSingleLineWithNewLine.txt");
1220     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
1221     EXPECT_THAT(err, IsEmpty());
1222     EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1223 }
1224 
TEST_F(DumpstateUtilTest,DumpFileMultipleLines)1225 TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1226     CreateFd("DumpFileMultipleLines.txt");
1227     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
1228     EXPECT_THAT(err, IsEmpty());
1229     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1230 }
1231 
TEST_F(DumpstateUtilTest,DumpFileMultipleLinesWithNewLine)1232 TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1233     CreateFd("DumpFileMultipleLinesWithNewLine.txt");
1234     EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
1235     EXPECT_THAT(err, IsEmpty());
1236     EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1237 }
1238 
TEST_F(DumpstateUtilTest,DumpFileOnDryRunNoTitle)1239 TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1240     CreateFd("DumpFileOnDryRun.txt");
1241     SetDryRun(true);
1242     std::string path = kTestDataPath + "single-line.txt";
1243     EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1244     EXPECT_THAT(err, IsEmpty());
1245     EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1246 }
1247 
TEST_F(DumpstateUtilTest,DumpFileOnDryRun)1248 TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1249     CreateFd("DumpFileOnDryRun.txt");
1250     SetDryRun(true);
1251     std::string path = kTestDataPath + "single-line.txt";
1252     EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
1253     EXPECT_THAT(err, IsEmpty());
1254     EXPECT_THAT(
1255         out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1256     EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
1257 }
1258 
TEST_F(DumpstateUtilTest,FindingPidWithExistingProcess)1259 TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
1260     // init process always has pid 1.
1261     EXPECT_EQ(1, FindPidOfProcess("init"));
1262     EXPECT_THAT(err, IsEmpty());
1263 }
1264 
TEST_F(DumpstateUtilTest,FindingPidWithNotExistingProcess)1265 TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
1266     // find the process with abnormal name.
1267     EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
1268     EXPECT_THAT(err, StrEq("can't find the pid\n"));
1269 }
1270 
1271 }  // namespace dumpstate
1272 }  // namespace os
1273 }  // namespace android
1274