14c2d66379753e2b7680811726424026b9e54b18aFelipe Leme/*
24c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * Copyright (C) 2016 The Android Open Source Project
34c2d66379753e2b7680811726424026b9e54b18aFelipe Leme *
44c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * Licensed under the Apache License, Version 2.0 (the "License");
54c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * you may not use this file except in compliance with the License.
64c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * You may obtain a copy of the License at
74c2d66379753e2b7680811726424026b9e54b18aFelipe Leme *
84c2d66379753e2b7680811726424026b9e54b18aFelipe Leme *      http://www.apache.org/licenses/LICENSE-2.0
94c2d66379753e2b7680811726424026b9e54b18aFelipe Leme *
104c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * Unless required by applicable law or agreed to in writing, software
114c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * distributed under the License is distributed on an "AS IS" BASIS,
124c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * See the License for the specific language governing permissions and
144c2d66379753e2b7680811726424026b9e54b18aFelipe Leme * limitations under the License.
154c2d66379753e2b7680811726424026b9e54b18aFelipe Leme */
164c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
1775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#define LOG_TAG "dumpstate"
1875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#include <cutils/log.h>
1975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
20f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme#include "DumpstateInternal.h"
2175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#include "DumpstateService.h"
2275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#include "android/os/BnDumpstate.h"
234c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include "dumpstate.h"
244c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
254c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <gmock/gmock.h>
264c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <gtest/gtest.h>
274c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme#include <fcntl.h>
294c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <libgen.h>
30fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <signal.h>
31fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <sys/types.h>
324c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <unistd.h>
33fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <thread>
344c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
354c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <android-base/file.h>
36d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme#include <android-base/properties.h>
37d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme#include <android-base/stringprintf.h>
38fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <android-base/strings.h>
394c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
4047e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Lemenamespace android {
4147e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Lemenamespace os {
4247e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Lemenamespace dumpstate {
43d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
444c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::EndsWith;
4546b85da716a32f285fe1222e9978beacc8697d09Felipe Lemeusing ::testing::HasSubstr;
46009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Lemeusing ::testing::IsNull;
474c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::IsEmpty;
48009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Lemeusing ::testing::NotNull;
494c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::StrEq;
504c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::StartsWith;
514c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::Test;
524c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::CaptureStderr;
534c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::CaptureStdout;
544c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::GetCapturedStderr;
554c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::GetCapturedStdout;
564c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
5775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Lemeclass DumpstateListenerMock : public IDumpstateListener {
5875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme  public:
5975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress));
6075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress));
6175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
6275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme  protected:
6375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    MOCK_METHOD0(onAsBinder, IBinder*());
6475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme};
6575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
6646b85da716a32f285fe1222e9978beacc8697d09Felipe Lemestatic int calls_;
6746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Base class for all tests in this file
697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateBaseTest : public Test {
7046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme  public:
7146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    virtual void SetUp() override {
7246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        calls_++;
73f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        SetDryRun(false);
7446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
7546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
76f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    void SetDryRun(bool dry_run) const {
77f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        PropertiesHelper::dry_run_ = dry_run;
7846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
7946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
80f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    void SetBuildType(const std::string& build_type) const {
81f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        PropertiesHelper::build_type_ = build_type;
82f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    }
83f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme
84f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    bool IsStandalone() const {
85f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        return calls_ == 1;
8646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
8746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
88f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    void DropRoot() const {
89f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        DropRootUser();
9046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        uid_t uid = getuid();
9146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ASSERT_EQ(2000, (int)uid);
9246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
9346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme  protected:
957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/";
977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    const std::string kTestDataPath = kFixturesPath + "/testdata/";
987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture";
997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    const std::string kEchoCommand = "/system/bin/echo";
1007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
1017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    /*
1027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme     * Copies a text file fixture to a temporary file, returning it's path.
1037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme     *
1047447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme     * Useful in cases where the test case changes the content of the tile.
1057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme     */
1067447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    std::string CopyTextFileFixture(const std::string& relative_name) {
1077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        std::string from = kTestDataPath + relative_name;
1087447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
1097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        // around for poking when the test fails.
1107447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        std::string to = kTestDataPath + relative_name + ".tmp";
1117447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
1127447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        android::base::RemoveFileIfExists(to);
1137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        CopyTextFile(from, to);
1147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        return to.c_str();
1157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
1167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
11746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Need functions that returns void to use assertions -
1187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
11946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    void ReadFileToString(const std::string& path, std::string* content) {
12046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ASSERT_TRUE(android::base::ReadFileToString(path, content))
12146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme            << "could not read contents from " << path;
12246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
12346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    void WriteStringToFile(const std::string& content, const std::string& path) {
12446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ASSERT_TRUE(android::base::WriteStringToFile(content, path))
12546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme            << "could not write contents to " << path;
12646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
12746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
12846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme  private:
1297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    void CopyTextFile(const std::string& from, const std::string& to) {
1307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        std::string content;
13146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ReadFileToString(from, &content);
13246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        WriteStringToFile(content, to);
1337447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
1347447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme};
1357447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
1367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateTest : public DumpstateBaseTest {
1374c2d66379753e2b7680811726424026b9e54b18aFelipe Leme  public:
1384c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    void SetUp() {
13946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        DumpstateBaseTest::SetUp();
1404c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        SetDryRun(false);
141d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
1427447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ds.progress_.reset(new Progress());
1439a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme        ds.update_progress_ = false;
144009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        ds.update_progress_threshold_ = 0;
1454c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    }
1464c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
1474c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    // Runs a command and capture `stdout` and `stderr`.
1489a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme    int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
1494c2d66379753e2b7680811726424026b9e54b18aFelipe Leme                   const CommandOptions& options = CommandOptions::DEFAULT) {
1504c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        CaptureStdout();
1514c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        CaptureStderr();
1529a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme        int status = ds.RunCommand(title, full_command, options);
1534c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        out = GetCapturedStdout();
1544c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        err = GetCapturedStderr();
1554c2d66379753e2b7680811726424026b9e54b18aFelipe Leme        return status;
1564c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    }
1574c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
158cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    // Dumps a file and capture `stdout` and `stderr`.
159cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    int DumpFile(const std::string& title, const std::string& path) {
160cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        CaptureStdout();
161cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        CaptureStderr();
162cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        int status = ds.DumpFile(title, path);
163cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        out = GetCapturedStdout();
164cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        err = GetCapturedStderr();
165cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme        return status;
166cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    }
167cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
168009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    void SetProgress(long progress, long initial_max, long threshold = 0) {
1697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ds.update_progress_ = true;
170009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        ds.update_progress_threshold_ = threshold;
171009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        ds.last_updated_progress_ = 0;
1727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ds.progress_.reset(new Progress(initial_max, progress, 1.2));
1737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
1747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
175009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    std::string GetProgressMessage(const std::string& listener_name, int progress, int max,
176009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme                                   int old_max = 0, bool update_progress = true) {
1777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
1787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
179d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
1807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        bool max_increased = old_max > 0;
181d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
182009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        std::string message = "";
1839a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme        if (max_increased) {
184009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme            message =
1857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme                android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
186d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        }
187d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
188009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        if (update_progress) {
189009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme            message += android::base::StringPrintf("Setting progress (%s): %d/%d\n",
190009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme                                                   listener_name.c_str(), progress, max);
19175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme        }
19275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
193009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme        return message;
194d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    }
195d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
1964c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    // `stdout` and `stderr` from the last command ran.
1974c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    std::string out, err;
1984c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
199fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    Dumpstate& ds = Dumpstate::GetInstance();
2004c2d66379753e2b7680811726424026b9e54b18aFelipe Leme};
2014c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2024c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandNoArgs) {
2034c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_EQ(-1, RunCommand("", {}));
2044c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2054c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2064c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandNoTitle) {
2077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
2084c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
2094c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
2104c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2114c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2124c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandWithTitle) {
2137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
2144c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
2154c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    // We don't know the exact duration, so we check the prefix and suffix
216fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(out,
2177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme                StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------"));
2184c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
2194c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2204c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
221fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
2224c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_EQ(
2237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        0, RunCommand("", {kSimpleCommand},
224fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                      CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
225fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
226fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
227fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
228fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
229fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandRedirectStderr) {
2307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
231fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                            CommandOptions::WithTimeout(10).RedirectStderr().Build()));
2324c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, IsEmpty());
233fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
2344c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2354c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2364c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandWithOneArg) {
2377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
2384c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, IsEmpty());
2394c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, StrEq("one\n"));
2404c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2414c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
242fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
2437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
2444c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, IsEmpty());
2454c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, StrEq("one is the loniest number\n"));
2464c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2474c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2484c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRun) {
2494c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    SetDryRun(true);
2507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
2514c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    // We don't know the exact duration, so we check the prefix and suffix
2527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
2534c2d66379753e2b7680811726424026b9e54b18aFelipe Leme                                ") ------\n\t(skipped on dry run)\n------"));
2544c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n"));
2554c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, IsEmpty());
2564c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2574c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2584c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
2594c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    SetDryRun(true);
2607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
2614c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, IsEmpty());
2624c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, IsEmpty());
2634c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2644c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
2654c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRunAlways) {
2664c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    SetDryRun(true);
2677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
2684c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
2694c2d66379753e2b7680811726424026b9e54b18aFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
2704c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}
2714c2d66379753e2b7680811726424026b9e54b18aFelipe Leme
272fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandNotFound) {
273fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
274fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
275fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
276fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
277fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
278fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandFails) {
2797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
2807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
2819a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme                           " --exit 42' failed: exit code 42\n"));
2827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
2839a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme                           " --exit 42' failed: exit code 42\n"));
284fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
285fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
286fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandCrashes) {
2877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
288fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    // We don't know the exit code, so check just the prefix.
289fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(
2907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
291fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(
2927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
293fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
294fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
295fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandTimesout) {
2967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
297fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                             CommandOptions::WithTimeout(1).Build()));
2987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
299fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                                " --sleep 2' timed out after 1"));
3007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
301fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                                " --sleep 2' timed out after 1"));
302fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
303fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
304fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandIsKilled) {
305fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    CaptureStdout();
306fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    CaptureStderr();
307fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
308fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    std::thread t([=]() {
3097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
310fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                                         CommandOptions::WithTimeout(100).Always().Build()));
311fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    });
312fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
313fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    // Capture pid and pre-sleep output.
314fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    sleep(1);  // Wait a little bit to make sure pid and 1st line were printed.
315fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    std::string err = GetCapturedStderr();
316fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
317fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
318fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    std::string out = GetCapturedStdout();
319fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    std::vector<std::string> lines = android::base::Split(out, "\n");
320fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
321fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
322fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    int pid = atoi(lines[0].c_str());
323fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(lines[1], StrEq("stdout line1"));
324fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    EXPECT_THAT(lines[2], IsEmpty());  // \n
325fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
326fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    // Then kill the process.
327fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    CaptureStdout();
328fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    CaptureStderr();
329fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
330fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    t.join();
331fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
332fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    // Finally, check output after murder.
333fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    out = GetCapturedStdout();
334fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme    err = GetCapturedStderr();
335fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
3367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
337fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                           " --pid --sleep 20' failed: killed by signal 15\n"));
3387447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
339fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme                           " --pid --sleep 20' failed: killed by signal 15\n"));
340fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme}
341fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme
342009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe LemeTEST_F(DumpstateTest, RunCommandProgress) {
343009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
344009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ds.listener_ = listener;
345009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ds.listener_name_ = "FoxMulder";
3467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    SetProgress(0, 30);
34775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
348009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(20));
3497447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
350009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30);
35175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
35275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
35375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
354009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(30));
3557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build()));
356009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    progress_message = GetProgressMessage(ds.listener_name_, 30, 30);
35775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
35875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
35975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
36075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    // Run a command that will increase maximum timeout.
361009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(31));
362009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onMaxProgressUpdated(37));
3637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
364009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30);  // 20% increase
36575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
36675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
36775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
36875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    // Make sure command ran while in dry_run is counted.
36975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    SetDryRun(true);
370009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(35));
3717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
372009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    progress_message = GetProgressMessage(ds.listener_name_, 35, 37);
37375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(out, IsEmpty());
37475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(err, StrEq(progress_message));
375009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme
376009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ds.listener_.clear();
37775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}
37875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
379009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe LemeTEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) {
38075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
38175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_ = listener;
38275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_name_ = "FoxMulder";
383009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    SetProgress(0, 8, 5);  // 8 max, 5 threshold
384d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
385009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    // First update should always be sent.
386009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(1));
387009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
388009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8);
389d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
3909a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
391d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
392009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5).
393009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
394d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
395009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
396d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
397009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    // Third update should be sent because it reaches threshold (6 - 1 = 5).
398009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onProgressUpdated(6));
3997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
400009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    progress_message = GetProgressMessage(ds.listener_name_, 6, 8);
401d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
4029a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
403d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
404009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5).
405009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    // But max update should be sent.
406009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_CALL(*listener, onMaxProgressUpdated(10));  // 9 * 120% = 10.8 = 10
407009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
408009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false);
409009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
410009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
41175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
41275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_.clear();
413d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme}
414d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
415d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe LemeTEST_F(DumpstateTest, RunCommandDropRoot) {
41646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
41746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
41846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
41946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
42046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
42146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
422d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    // First check root case - only available when running with 'adb root'.
423d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    uid_t uid = getuid();
424d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    if (uid == 0) {
4257447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
426d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        EXPECT_THAT(out, StrEq("0\nstdout\n"));
427d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        EXPECT_THAT(err, StrEq("stderr\n"));
428d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        return;
429d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    }
4307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Then run dropping root.
4317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
432d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme                            CommandOptions::WithTimeout(1).DropRoot().Build()));
433d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(out, StrEq("2000\nstdout\n"));
43426c4157a0823688ba78bf29d93fbce0def3a0fa6Felipe Leme    EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
435d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme}
436d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
437d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe LemeTEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
43846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
43946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
44046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
44146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
44246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
44346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
444f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    if (!PropertiesHelper::IsUserBuild()) {
445d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        // Emulates user build if necessarily.
446d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme        SetBuildType("user");
447d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    }
448d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
449d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    DropRoot();
450d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
4517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
452d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
453d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    // We don't know the exact path of su, so we just check for the 'root ...' commands
454d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(out, StartsWith("Skipping"));
4557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
456d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme    EXPECT_THAT(err, IsEmpty());
457d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme}
458d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme
45946b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
46046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
46146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
46246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
46346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
46446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
46546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
466f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    if (PropertiesHelper::IsUserBuild()) {
46746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
46846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
46946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
47046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
47146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    DropRoot();
47246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
47346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
47446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                            CommandOptions::WithTimeout(1).AsRoot().Build()));
47546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
47646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("0\nstdout\n"));
47746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
47846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
47946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
480cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
481cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
482cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out,
483cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme                StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
484cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
485cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
486cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
487cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
488cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
489cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
490cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    // We don't know the exact duration, so we check the prefix and suffix
491cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
492cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme                                "such file or directory\n"));
493cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n"));
494cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
495cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
496cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileSingleLine) {
4977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
498cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
499cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
500cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
501cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
502cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
5037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
504cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
505cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\n"));
506cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
507cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
508cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileMultipleLines) {
5097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
510cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
511cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
512cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
513cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
514cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
5157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
516cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
517cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
518cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
519cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
520cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
521cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    SetDryRun(true);
5227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
523cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
524cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, IsEmpty());
525cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
526cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
527cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileOnDryRun) {
528cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    SetDryRun(true);
5297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
530cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(err, IsEmpty());
53146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(
53246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
53346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------"));
534cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme    EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n"));
535cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme}
536cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme
53775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateTest, DumpFileUpdateProgress) {
53875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
53975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_ = listener;
54075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_name_ = "FoxMulder";
5417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    SetProgress(0, 30);
54275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
54375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_CALL(*listener, onProgressUpdated(5));
5447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
54575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
54675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    std::string progress_message =
54775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme        GetProgressMessage(ds.listener_name_, 5, 30);  // TODO: unhardcode WEIGHT_FILE (5)?
54875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(err, StrEq(progress_message));
54975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
55075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
55175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    ds.listener_.clear();
55275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}
55375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
5547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateServiceTest : public DumpstateBaseTest {
55575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme  public:
55675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    DumpstateService dss;
55775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme};
55875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
55975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerNoName) {
56075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
561009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    sp<IDumpstateToken> token;
562009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_TRUE(dss.setListener("", listener, &token).isOk());
563009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ASSERT_THAT(token, IsNull());
56475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}
56575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
56675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerNoPointer) {
567009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    sp<IDumpstateToken> token;
568009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_TRUE(dss.setListener("whatever", nullptr, &token).isOk());
569009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ASSERT_THAT(token, IsNull());
57075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}
57175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
57275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerTwice) {
57375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
574009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    sp<IDumpstateToken> token;
575009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_TRUE(dss.setListener("whatever", listener, &token).isOk());
576009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ASSERT_THAT(token, NotNull());
57775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme    EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
57875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme
579009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    token.clear();
580009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_TRUE(dss.setListener("whatsoever", listener, &token).isOk());
581009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    ASSERT_THAT(token, IsNull());
582009ecbbd3fcfd06735b0102f0342fc7e60166d9bFelipe Leme    EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever"));
58375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}
5847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
5857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass ProgressTest : public DumpstateBaseTest {
5867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme  public:
5877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
5887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        return Progress(max, growth_factor, path);
5897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
5907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
5917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
5927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        std::string expected_content =
5937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme            android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
5947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        std::string actual_content;
59546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ReadFileToString(path, &actual_content);
5967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
5977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
5987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme};
5997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, SimpleTest) {
6017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress;
6027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, progress.Get());
6037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
6047447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6067447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = progress.Inc(1);
6077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(1, progress.Get());
6087447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
6097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6107447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
6117447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6127447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Ignore negative increase.
6137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    max_increased = progress.Inc(-1);
6147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(1, progress.Get());
6157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
6167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
6187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6197447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6207447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, MaxGrowsInsideNewRange) {
6217447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress = GetInstance(10, 1.2);  // 20% growth factor
6227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, progress.Get());
6237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetInitialMax());
6247447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetMax());
6257447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6267447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // No increase
6277447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = progress.Inc(10);
6287447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.Get());
6297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetMax());
6307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
6317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6327447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Increase, with new value < max*20%
6337447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    max_increased = progress.Inc(1);
6347447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(11, progress.Get());
6357447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(13, progress.GetMax());  // 11 average * 20% growth = 13.2 = 13
6367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_TRUE(max_increased);
6377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6387447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6397447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
6407447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress = GetInstance(10, 1.2);  // 20% growth factor
6417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, progress.Get());
6427447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetInitialMax());
6437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetMax());
6447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // No increase
6467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = progress.Inc(10);
6477447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.Get());
6487447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, progress.GetMax());
6497447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
6507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Increase, with new value > max*20%
6527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    max_increased = progress.Inc(5);
6537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(15, progress.Get());
6547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(18, progress.GetMax());  // 15 average * 20% growth = 18
6557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_TRUE(max_increased);
6567447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6587447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidPath) {
6597447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress("/devil/null");
6607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6617447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, EmptyFile) {
6647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("empty-file.txt"));
6657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryNAN) {
6697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
6707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
6747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
6757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLineBothNAN) {
6797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
6807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryNegative) {
6847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
6857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
6897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
6907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
6947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
6957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
6967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
6977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
6987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
6997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
7007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
7017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
7027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests stats are properly saved when the file does not exists.
7047447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, FirstTime) {
70546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
70646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it's failing when running as suite
70746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
70846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
70946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
71046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
7117447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    std::string path = kTestDataPath + "FirstTime.txt";
7127447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    android::base::RemoveFileIfExists(path);
7137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress run1(path);
7157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, run1.Get());
7167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
7177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
7187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7197447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = run1.Inc(20);
7207447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(20, run1.Get());
7217447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
7227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
7237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7247447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    run1.Save();
7257447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 1, 20);
7267447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
7277447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7287447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests what happens when the persistent settings contains the average duration of 1 run.
7297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Data on file is 1 run and 109 average.
7307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, SecondTime) {
7317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
7327447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7337447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress run1 = GetInstance(-42, 1.2, path);
7347447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, run1.Get());
7357447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, run1.GetInitialMax());
7367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(10, run1.GetMax());
7377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7387447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = run1.Inc(20);
7397447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(20, run1.Get());
7407447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(24, run1.GetMax());
7417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_TRUE(max_increased);
7427447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Average now is 2 runs and (10 + 20)/ 2 = 15
7447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    run1.Save();
7457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 2, 15);
7467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7477447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress run2 = GetInstance(-42, 1.2, path);
7487447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, run2.Get());
7497447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(15, run2.GetInitialMax());
7507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(15, run2.GetMax());
7517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    max_increased = run2.Inc(25);
7537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(25, run2.Get());
7547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(30, run2.GetMax());
7557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_TRUE(max_increased);
7567447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
7587447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    run2.Save();
7597447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 3, 18);
7607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7617447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress run3 = GetInstance(-42, 1.2, path);
7627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, run3.Get());
7637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(18, run3.GetInitialMax());
7647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(18, run3.GetMax());
7657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Make sure average decreases as well
7677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    max_increased = run3.Inc(5);
7687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(5, run3.Get());
7697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(18, run3.GetMax());
7707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_FALSE(max_increased);
7717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
7737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    run3.Save();
7747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 4, 14);
7757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
7767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests what happens when the persistent settings contains the average duration of 2 runs.
7787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Data on file is 2 runs and 15 average.
7797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, ThirdTime) {
7807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    std::string path = CopyTextFileFixture("stats-two-runs.txt");
7817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 2, 15);  // Sanity check
7827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    Progress run1 = GetInstance(-42, 1.2, path);
7847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(0, run1.Get());
7857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(15, run1.GetInitialMax());
7867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(15, run1.GetMax());
7877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    bool max_increased = run1.Inc(20);
7897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(20, run1.Get());
7907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_EQ(24, run1.GetMax());
7917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_TRUE(max_increased);
7927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
7937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
7947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    run1.Save();
7957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    AssertStats(path, 3, 16);
7967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
7977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
79846b85da716a32f285fe1222e9978beacc8697d09Felipe Lemeclass DumpstateUtilTest : public DumpstateBaseTest {
79946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme  public:
80046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    void SetUp() {
80146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        DumpstateBaseTest::SetUp();
80246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        SetDryRun(false);
80346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
80446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
80546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    void CaptureFdOut() {
806f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        ReadFileToString(path_, &out);
80746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
80846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
80946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    void CreateFd(const std::string& name) {
81046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        path_ = kTestDataPath + name;
81146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGD("Creating fd for file %s\n", path_.c_str());
81246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
81346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
81446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                                     O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
81546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                                     S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
81646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
81746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
81846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
81946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Runs a command into the `fd` and capture `stderr`.
820f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
82146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                   const CommandOptions& options = CommandOptions::DEFAULT) {
82246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        CaptureStderr();
823f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        int status = RunCommandToFd(fd, title, full_command, options);
82446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        close(fd);
82546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
82646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        CaptureFdOut();
82746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        err = GetCapturedStderr();
82846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return status;
82946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
83046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
83146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Dumps a file and into the `fd` and `stderr`.
832f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    int DumpFile(const std::string& title, const std::string& path) {
83346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        CaptureStderr();
834f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        int status = DumpFileToFd(fd, title, path);
83546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        close(fd);
83646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
83746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        CaptureFdOut();
83846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        err = GetCapturedStderr();
83946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return status;
84046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
84146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
84261ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    // Find out the pid of the process_name
84361ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    int FindPidOfProcess(const std::string& process_name) {
84461ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park        CaptureStderr();
84561ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park        int status = GetPidByName(process_name);
84661ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park        err = GetCapturedStderr();
84761ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park        return status;
84861ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    }
84961ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park
85046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    int fd;
85146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
85246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // 'fd` output and `stderr` from the last command ran.
85346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::string out, err;
85446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
85546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme  private:
85646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::string path_;
85746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme};
85846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
85946b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandNoArgs) {
860f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    CreateFd("RunCommandNoArgs.txt");
861f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(-1, RunCommand("", {}));
86246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
86346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
864f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, RunCommandNoTitle) {
86546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandWithNoArgs.txt");
866f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
86746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
86846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
86946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
87046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
871f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, RunCommandWithTitle) {
872f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    CreateFd("RunCommandWithNoArgs.txt");
873f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
874f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
875f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
876f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme}
877f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme
87846b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
87946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandWithOneArg.txt");
880f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
88146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
88246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("one\n"));
88346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
88446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
88546b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
88646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandWithMultipleArgs.txt");
887f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
88846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
88946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("one is the loniest number\n"));
89046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
89146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
89246b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
89346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandWithLoggingMessage.txt");
89446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_EQ(
895f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        0, RunCommand("", {kSimpleCommand},
89646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                      CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
89746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
89846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
89946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
90046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
90146b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
90246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandRedirectStderr.txt");
903f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
904f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                            CommandOptions::WithTimeout(10).RedirectStderr().Build()));
90546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, IsEmpty());
90646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
90746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
90846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
90946b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandDryRun) {
91046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandDryRun.txt");
91146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    SetDryRun(true);
912f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
913f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(out, StrEq(android::base::StringPrintf(
914f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                         "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
915f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                         kSimpleCommand.c_str())));
916f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(err, IsEmpty());
917f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme}
918f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme
919f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
920f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    CreateFd("RunCommandDryRun.txt");
921f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    SetDryRun(true);
922f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
92346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(
92446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
92546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
92646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
92746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
92846b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
92946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandDryRunAlways.txt");
93046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    SetDryRun(true);
931f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
93246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n"));
93346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
93446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
93546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
93646b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandNotFound) {
93746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandNotFound.txt");
938f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
93946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
94046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
94146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
94246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
94346b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandFails) {
94446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandFails.txt");
945f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
94646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
94746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                           " --exit 42' failed: exit code 42\n"));
94846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
94946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                           " --exit 42' failed: exit code 42\n"));
95046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
95146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
95246b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandCrashes) {
95346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandCrashes.txt");
954f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
95546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // We don't know the exit code, so check just the prefix.
95646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(
95746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
95846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(
95946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
96046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
96146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
96246b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandTimesout) {
96346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandTimesout.txt");
964f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
965f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                             CommandOptions::WithTimeout(1).Build()));
96646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
96746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                                " --sleep 2' timed out after 1"));
96846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
96946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                                " --sleep 2' timed out after 1"));
97046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
97146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
97246b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandIsKilled) {
97346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandIsKilled.txt");
97446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CaptureStderr();
97546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
97646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::thread t([=]() {
977f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
97846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                                          CommandOptions::WithTimeout(100).Always().Build()));
97946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    });
98046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
98146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Capture pid and pre-sleep output.
98246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    sleep(1);  // Wait a little bit to make sure pid and 1st line were printed.
98346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::string err = GetCapturedStderr();
98446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
98546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
98646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CaptureFdOut();
98746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::vector<std::string> lines = android::base::Split(out, "\n");
98846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
98946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
99046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    int pid = atoi(lines[0].c_str());
99146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(lines[1], StrEq("stdout line1"));
99246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(lines[2], IsEmpty());  // \n
99346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
99446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Then kill the process.
99546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CaptureFdOut();
99646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CaptureStderr();
99746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
99846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    t.join();
99946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
100046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Finally, check output after murder.
100146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CaptureFdOut();
100246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    err = GetCapturedStderr();
100346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
100446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // out starts with the pid, which is an unknown
100546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
100646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                              " --pid --sleep 20' failed: killed by signal 15\n"));
100746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
100846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                           " --pid --sleep 20' failed: killed by signal 15\n"));
100946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
101046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
101146b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
101246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
101346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
101446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
101546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
101646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
101746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
101846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandAsRootUserBuild.txt");
1019f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    if (!PropertiesHelper::IsUserBuild()) {
102046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // Emulates user build if necessarily.
102146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        SetBuildType("user");
102246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
102346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
102446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    DropRoot();
102546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
1026f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
102746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
102846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // We don't know the exact path of su, so we just check for the 'root ...' commands
102946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StartsWith("Skipping"));
103046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
103146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
103246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
103346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
103446b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
103546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
103646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
103746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
103846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
103946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
104046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
104146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandAsRootNonUserBuild.txt");
1042f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    if (PropertiesHelper::IsUserBuild()) {
10437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
10447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme        return;
10457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    }
10467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
10477447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    DropRoot();
10487447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
1049f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1050f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                            CommandOptions::WithTimeout(1).AsRoot().Build()));
10517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme
10527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(out, StrEq("0\nstdout\n"));
10537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme    EXPECT_THAT(err, StrEq("stderr\n"));
10547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}
105546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
105646b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, RunCommandDropRoot) {
105746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (!IsStandalone()) {
105846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // TODO: temporarily disabled because it might cause other tests to fail after dropping
105946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        // to Shell - need to refactor tests to avoid this problem)
106046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
106146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
106246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
106346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("RunCommandDropRoot.txt");
106446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // First check root case - only available when running with 'adb root'.
106546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    uid_t uid = getuid();
106646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    if (uid == 0) {
1067f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
106846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        EXPECT_THAT(out, StrEq("0\nstdout\n"));
106946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        EXPECT_THAT(err, StrEq("stderr\n"));
107046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme        return;
107146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    }
107246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    // Then run dropping root.
1073f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
107446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                            CommandOptions::WithTimeout(1).DropRoot().Build()));
107546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("2000\nstdout\n"));
107646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
107746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
107846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
1079f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
108046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileNotFound.txt");
1081f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
108246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out,
108346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme                StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
108446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
108546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
108646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
1087f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1088f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    CreateFd("DumpFileNotFound.txt");
1089f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1090f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1091f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme                           "file or directory\n"));
1092f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(err, IsEmpty());
1093f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme}
1094f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme
109546b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, DumpFileSingleLine) {
109646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileSingleLine.txt");
1097f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
109846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
109946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\n"));  // dumpstate adds missing newline
110046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
110146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
110246b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
110346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileSingleLineWithNewLine.txt");
1104f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
110546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
110646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\n"));
110746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
110846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
110946b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
111046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileMultipleLines.txt");
1111f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
111246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
111346b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
111446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
111546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
111646b85da716a32f285fe1222e9978beacc8697d09Felipe LemeTEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
111746b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileMultipleLinesWithNewLine.txt");
1118f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
111946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
112046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
112146b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
112246b85da716a32f285fe1222e9978beacc8697d09Felipe Leme
1123f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
112446b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    CreateFd("DumpFileOnDryRun.txt");
112546b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    SetDryRun(true);
112646b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    std::string path = kTestDataPath + "single-line.txt";
1127f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
112846b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(err, IsEmpty());
112946b85da716a32f285fe1222e9978beacc8697d09Felipe Leme    EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
113046b85da716a32f285fe1222e9978beacc8697d09Felipe Leme}
1131f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme
1132f029297f673ae06d219bd727a318a48b885db6fdFelipe LemeTEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1133f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    CreateFd("DumpFileOnDryRun.txt");
1134f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    SetDryRun(true);
1135f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    std::string path = kTestDataPath + "single-line.txt";
1136f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
1137f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(err, IsEmpty());
1138f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(
1139f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme        out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1140f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme    EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
1141f029297f673ae06d219bd727a318a48b885db6fdFelipe Leme}
114261ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park
114361ffcf73d50dbed5b52265e79bb73abf1849324dEcco ParkTEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) {
114461ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    // init process always has pid 1.
114561ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    EXPECT_EQ(1, FindPidOfProcess("init"));
114661ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    EXPECT_THAT(err, IsEmpty());
114761ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park}
114861ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park
114961ffcf73d50dbed5b52265e79bb73abf1849324dEcco ParkTEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) {
115061ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    // find the process with abnormal name.
115161ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543"));
115261ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park    EXPECT_THAT(err, StrEq("can't find the pid\n"));
115361ffcf73d50dbed5b52265e79bb73abf1849324dEcco Park}
115447e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Leme
115547e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Leme}  // namespace dumpstate
115647e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Leme}  // namespace os
115747e9be2d71c5eca9002e289c98e8bbc20dffc073Felipe Leme}  // namespace android
1158