dumpstate_test.cpp revision 7447d7c3d74b28f1a071b1d3503212cc8ad08d68
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 2075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#include "DumpstateService.h" 2175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme#include "android/os/BnDumpstate.h" 224c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include "dumpstate.h" 234c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 244c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <gmock/gmock.h> 254c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <gtest/gtest.h> 264c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 274c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <libgen.h> 28fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <signal.h> 29fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <sys/types.h> 304c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <unistd.h> 31fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <thread> 324c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 334c2d66379753e2b7680811726424026b9e54b18aFelipe Leme#include <android-base/file.h> 34d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme#include <android-base/properties.h> 35d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme#include <android-base/stringprintf.h> 36fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme#include <android-base/strings.h> 374c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 3875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Lemeusing namespace android; 39d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 404c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::EndsWith; 414c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::IsEmpty; 424c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::StrEq; 434c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::StartsWith; 444c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::Test; 454c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::CaptureStderr; 464c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::CaptureStdout; 474c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::GetCapturedStderr; 484c2d66379753e2b7680811726424026b9e54b18aFelipe Lemeusing ::testing::internal::GetCapturedStdout; 494c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 5075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Lemeusing os::DumpstateService; 5175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Lemeusing os::IDumpstateListener; 5275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 534c2d66379753e2b7680811726424026b9e54b18aFelipe Leme// Not used on test cases yet... 544c2d66379753e2b7680811726424026b9e54b18aFelipe Lemevoid dumpstate_board(void) { 554c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 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 667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Base class for all tests in this file 677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateBaseTest : public Test { 687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme protected: 697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str()); 707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/"; 717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme const std::string kTestDataPath = kFixturesPath + "/testdata/"; 727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture"; 737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme const std::string kEchoCommand = "/system/bin/echo"; 747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme /* 767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme * Copies a text file fixture to a temporary file, returning it's path. 777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme * 787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme * Useful in cases where the test case changes the content of the tile. 797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme */ 807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string CopyTextFileFixture(const std::string& relative_name) { 817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string from = kTestDataPath + relative_name; 827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it 837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // around for poking when the test fails. 847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string to = kTestDataPath + relative_name + ".tmp"; 857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str()); 867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme android::base::RemoveFileIfExists(to); 877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme CopyTextFile(from, to); 887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme return to.c_str(); 897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme private: 927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Need a function that returns void to use assertions - 937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement 947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme void CopyTextFile(const std::string& from, const std::string& to) { 957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string content; 967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ASSERT_TRUE(android::base::ReadFileToString(from, &content)) << "could not read from " 977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme << from; 987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ASSERT_TRUE(android::base::WriteStringToFile(content, to)) << "could not write to " << to; 997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 1007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}; 1017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 1027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateTest : public DumpstateBaseTest { 1034c2d66379753e2b7680811726424026b9e54b18aFelipe Leme public: 1044c2d66379753e2b7680811726424026b9e54b18aFelipe Leme void SetUp() { 1054c2d66379753e2b7680811726424026b9e54b18aFelipe Leme SetDryRun(false); 106d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)")); 1077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ds.progress_.reset(new Progress()); 1089a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme ds.update_progress_ = false; 1094c2d66379753e2b7680811726424026b9e54b18aFelipe Leme } 1104c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 1114c2d66379753e2b7680811726424026b9e54b18aFelipe Leme // Runs a command and capture `stdout` and `stderr`. 1129a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme int RunCommand(const std::string& title, const std::vector<std::string>& full_command, 1134c2d66379753e2b7680811726424026b9e54b18aFelipe Leme const CommandOptions& options = CommandOptions::DEFAULT) { 1144c2d66379753e2b7680811726424026b9e54b18aFelipe Leme CaptureStdout(); 1154c2d66379753e2b7680811726424026b9e54b18aFelipe Leme CaptureStderr(); 1169a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme int status = ds.RunCommand(title, full_command, options); 1174c2d66379753e2b7680811726424026b9e54b18aFelipe Leme out = GetCapturedStdout(); 1184c2d66379753e2b7680811726424026b9e54b18aFelipe Leme err = GetCapturedStderr(); 1194c2d66379753e2b7680811726424026b9e54b18aFelipe Leme return status; 1204c2d66379753e2b7680811726424026b9e54b18aFelipe Leme } 1214c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 122cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme // Dumps a file and capture `stdout` and `stderr`. 123cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme int DumpFile(const std::string& title, const std::string& path) { 124cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme CaptureStdout(); 125cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme CaptureStderr(); 126cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme int status = ds.DumpFile(title, path); 127cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme out = GetCapturedStdout(); 128cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme err = GetCapturedStderr(); 129cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme return status; 130cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme } 131cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 1329a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme void SetDryRun(bool dry_run) { 1339a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme ALOGD("Setting dry_run_ to %s\n", dry_run ? "true" : "false"); 1349a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme ds.dry_run_ = dry_run; 135d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 136d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 1379a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme void SetBuildType(const std::string& build_type) { 1389a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme ALOGD("Setting build_type_ to '%s'\n", build_type.c_str()); 1399a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme ds.build_type_ = build_type; 140d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 141d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 142d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme bool IsUserBuild() { 143d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme return "user" == android::base::GetProperty("ro.build.type", "(unknown)"); 144d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 145d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 146d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme void DropRoot() { 147d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme drop_root_user(); 148d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme uid_t uid = getuid(); 149d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme ASSERT_EQ(2000, (int)uid); 150d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 151d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 1527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme void SetProgress(long progress, long initial_max) { 1537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ds.update_progress_ = true; 1547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ds.progress_.reset(new Progress(initial_max, progress, 1.2)); 1557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 1567447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 157d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme // TODO: remove when progress is set by Binder callbacks. 1589a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme void AssertSystemProperty(const std::string& key, const std::string& expected_value) { 159d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme std::string actualValue = android::base::GetProperty(key, "not set"); 1609a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(expected_value, StrEq(actualValue)) << "invalid value for property " << key; 161d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 162d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 16375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme // TODO: remove when progress is set by Binder callbacks. 1647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string GetProgressMessageAndAssertSystemProperties(int progress, int max, int old_max = 0) { 1657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress"; 1667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max"; 167d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 168d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme AssertSystemProperty(android::base::StringPrintf("dumpstate.%d.progress", getpid()), 169d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme std::to_string(progress)); 170d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 1717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = old_max > 0; 172d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 1739a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme std::string adjustment_message = ""; 1749a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme if (max_increased) { 175d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme AssertSystemProperty(android::base::StringPrintf("dumpstate.%d.max", getpid()), 1767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::to_string(max)); 1777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme adjustment_message = 1787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max); 179d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 180d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 181d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme return android::base::StringPrintf("%sSetting progress (dumpstate.%d.progress): %d/%d\n", 1827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme adjustment_message.c_str(), getpid(), progress, max); 18375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme } 18475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 1857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string GetProgressMessage(const std::string& listener_name, int progress, int max, 1867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme int old_max = 0) { 1877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress"; 1887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max"; 18975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 1907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = old_max > 0; 19175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 19275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme std::string adjustment_message = ""; 19375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme if (max_increased) { 1947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme adjustment_message = 1957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max); 19675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme } 19775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 19875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme return android::base::StringPrintf("%sSetting progress (%s): %d/%d\n", 19975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme adjustment_message.c_str(), listener_name.c_str(), 2007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme progress, max); 201d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 202d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 2034c2d66379753e2b7680811726424026b9e54b18aFelipe Leme // `stdout` and `stderr` from the last command ran. 2044c2d66379753e2b7680811726424026b9e54b18aFelipe Leme std::string out, err; 2054c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 206fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme Dumpstate& ds = Dumpstate::GetInstance(); 2074c2d66379753e2b7680811726424026b9e54b18aFelipe Leme}; 2084c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2094c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandNoArgs) { 2104c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_EQ(-1, RunCommand("", {})); 2114c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2124c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2134c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandNoTitle) { 2147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 2154c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 2164c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, StrEq("stderr\n")); 2174c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2184c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2194c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandWithTitle) { 2207447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 2214c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, StrEq("stderr\n")); 2224c2d66379753e2b7680811726424026b9e54b18aFelipe Leme // We don't know the exact duration, so we check the prefix and suffix 223fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(out, 2247447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------")); 2254c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); 2264c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2274c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 228fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandWithLoggingMessage) { 2294c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_EQ( 2307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 0, RunCommand("", {kSimpleCommand}, 231fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build())); 232fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 233fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n")); 234fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 235fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 236fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandRedirectStderr) { 2377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, 238fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CommandOptions::WithTimeout(10).RedirectStderr().Build())); 2394c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, IsEmpty()); 240fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(err, StrEq("stdout\nstderr\n")); 2414c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2424c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2434c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandWithOneArg) { 2447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"})); 2454c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, IsEmpty()); 2464c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, StrEq("one\n")); 2474c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2484c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 249fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandWithMultipleArgs) { 2507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"})); 2514c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, IsEmpty()); 2524c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, StrEq("one is the loniest number\n")); 2534c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2544c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2554c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRun) { 2564c2d66379753e2b7680811726424026b9e54b18aFelipe Leme SetDryRun(true); 2577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 2584c2d66379753e2b7680811726424026b9e54b18aFelipe Leme // We don't know the exact duration, so we check the prefix and suffix 2597447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand + 2604c2d66379753e2b7680811726424026b9e54b18aFelipe Leme ") ------\n\t(skipped on dry run)\n------")); 2614c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); 2624c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, IsEmpty()); 2634c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2644c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2654c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRunNoTitle) { 2664c2d66379753e2b7680811726424026b9e54b18aFelipe Leme SetDryRun(true); 2677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 2684c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, IsEmpty()); 2694c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, IsEmpty()); 2704c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2714c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 2724c2d66379753e2b7680811726424026b9e54b18aFelipe LemeTEST_F(DumpstateTest, RunCommandDryRunAlways) { 2734c2d66379753e2b7680811726424026b9e54b18aFelipe Leme SetDryRun(true); 2747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build())); 2754c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 2764c2d66379753e2b7680811726424026b9e54b18aFelipe Leme EXPECT_THAT(err, StrEq("stderr\n")); 2774c2d66379753e2b7680811726424026b9e54b18aFelipe Leme} 2784c2d66379753e2b7680811726424026b9e54b18aFelipe Leme 279fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandNotFound) { 280fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"})); 281fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code")); 282fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed")); 283fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 284fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 285fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandFails) { 2867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"})); 2877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand + 2889a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme " --exit 42' failed: exit code 42\n")); 2897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand + 2909a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme " --exit 42' failed: exit code 42\n")); 291fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 292fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 293fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandCrashes) { 2947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"})); 295fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme // We don't know the exit code, so check just the prefix. 296fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT( 2977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 298fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT( 2997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 300fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 301fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 302fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandTimesout) { 3037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"}, 304fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CommandOptions::WithTimeout(1).Build())); 3057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand + 306fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme " --sleep 2' timed out after 1")); 3077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand + 308fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme " --sleep 2' timed out after 1")); 309fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 310fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 311fd8affa8840d2d9f7f320201521a702919c677ffFelipe LemeTEST_F(DumpstateTest, RunCommandIsKilled) { 312fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CaptureStdout(); 313fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CaptureStderr(); 314fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 315fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme std::thread t([=]() { 3167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"}, 317fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CommandOptions::WithTimeout(100).Always().Build())); 318fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme }); 319fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 320fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme // Capture pid and pre-sleep output. 321fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme sleep(1); // Wait a little bit to make sure pid and 1st line were printed. 322fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme std::string err = GetCapturedStderr(); 323fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(err, StrEq("sleeping for 20s\n")); 324fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 325fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme std::string out = GetCapturedStdout(); 326fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme std::vector<std::string> lines = android::base::Split(out, "\n"); 327fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out; 328fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 329fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme int pid = atoi(lines[0].c_str()); 330fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(lines[1], StrEq("stdout line1")); 331fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme EXPECT_THAT(lines[2], IsEmpty()); // \n 332fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 333fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme // Then kill the process. 334fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CaptureStdout(); 335fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme CaptureStderr(); 336fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid; 337fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme t.join(); 338fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 339fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme // Finally, check output after murder. 340fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme out = GetCapturedStdout(); 341fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme err = GetCapturedStderr(); 342fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 3437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand + 344fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme " --pid --sleep 20' failed: killed by signal 15\n")); 3457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand + 346fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme " --pid --sleep 20' failed: killed by signal 15\n")); 347fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme} 348fd8affa8840d2d9f7f320201521a702919c677ffFelipe Leme 34975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateTest, RunCommandProgressNoListener) { 3507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme SetProgress(0, 30); 35175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 3527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); 35375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme std::string progress_message = GetProgressMessageAndAssertSystemProperties(20, 30); 35475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 35575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 35675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 3577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build())); 35875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme progress_message = GetProgressMessageAndAssertSystemProperties(30, 30); 35975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 36075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 36175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 36275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme // Run a command that will increase maximum timeout. 3637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); 3647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme progress_message = GetProgressMessageAndAssertSystemProperties(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); 3707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); 3717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme progress_message = GetProgressMessageAndAssertSystemProperties(35, 37); 37275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(out, IsEmpty()); 37375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(err, StrEq(progress_message)); 37475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme} 37575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 376d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe LemeTEST_F(DumpstateTest, RunCommandProgress) { 37775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 37875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_ = listener; 37975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_name_ = "FoxMulder"; 3807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme SetProgress(0, 30); 381d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 38275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_CALL(*listener, onProgressUpdated(20)); 3837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); 38475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30); 385d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 3869a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 387d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 38875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_CALL(*listener, onProgressUpdated(30)); 3897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build())); 39075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme progress_message = GetProgressMessage(ds.listener_name_, 30, 30); 391d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 3929a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 393d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 394d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme // Run a command that will increase maximum timeout. 39575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_CALL(*listener, onProgressUpdated(31)); 3967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_CALL(*listener, onMaxProgressUpdated(37)); 3977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); 3987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase 399d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StrEq("stdout\n")); 4009a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 401d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 4029a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme // Make sure command ran while in dry_run is counted. 403d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme SetDryRun(true); 40475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_CALL(*listener, onProgressUpdated(35)); 4057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); 4067447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme progress_message = GetProgressMessage(ds.listener_name_, 35, 37); 407d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, IsEmpty()); 4089a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(err, StrEq(progress_message)); 40975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 41075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_.clear(); 411d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme} 412d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 413d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe LemeTEST_F(DumpstateTest, RunCommandDropRoot) { 414d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme // First check root case - only available when running with 'adb root'. 415d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme uid_t uid = getuid(); 416d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme if (uid == 0) { 4177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"})); 418d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StrEq("0\nstdout\n")); 419d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(err, StrEq("stderr\n")); 420d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme return; 421d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 4227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Then run dropping root. 4237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 424d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme CommandOptions::WithTimeout(1).DropRoot().Build())); 425d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StrEq("2000\nstdout\n")); 42626c4157a0823688ba78bf29d93fbce0def3a0fa6Felipe Leme EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n")); 427d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme} 428d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 429d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe LemeTEST_F(DumpstateTest, RunCommandAsRootUserBuild) { 430d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme if (!IsUserBuild()) { 431d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme // Emulates user build if necessarily. 432d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme SetBuildType("user"); 433d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme } 434d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 435d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme DropRoot(); 436d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 4377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build())); 438d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 439d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme // We don't know the exact path of su, so we just check for the 'root ...' commands 440d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(out, StartsWith("Skipping")); 4417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n")); 442d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme EXPECT_THAT(err, IsEmpty()); 443d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme} 444d80e6b6109c52d57ebba675c1f97fcb2ca1d93c5Felipe Leme 445cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileNotFoundNoTitle) { 446cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist")); 447cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, 448cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n")); 449cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 450cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 451cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 452cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileNotFoundWithTitle) { 453cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); 454cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 455cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme // We don't know the exact duration, so we check the prefix and suffix 456cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No " 457cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme "such file or directory\n")); 458cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n")); 459cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 460cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 461cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileSingleLine) { 4627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 463cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 464cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 465cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 466cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 467cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) { 4687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt")); 469cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 470cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\n")); 471cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 472cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 473cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileMultipleLines) { 4747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt")); 475cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 476cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 477cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 478cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 479cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) { 4807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt")); 481cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 482cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 483cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 484cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 485cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) { 486cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme SetDryRun(true); 4877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 488cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 489cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, IsEmpty()); 490cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 491cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 492cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe LemeTEST_F(DumpstateTest, DumpFileOnDryRun) { 493cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme SetDryRun(true); 4947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt")); 495cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 4967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + 497cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme "single-line.txt) ------\n\t(skipped on dry run)\n------")); 498cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n")); 499cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(err, IsEmpty()); 500cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 501cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 50275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateTest, DumpFileUpdateProgressNoListener) { 5037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme SetProgress(0, 30); 504cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 5057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 506cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 50775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme std::string progress_message = 50875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme GetProgressMessageAndAssertSystemProperties(5, 30); // TODO: unhardcode WEIGHT_FILE (5)? 509cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme 5109a523aed06ef962f67385ac88191b08dc91059f4Felipe Leme EXPECT_THAT(err, StrEq(progress_message)); 511cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 512cef0298e2540e6ad8c2728e6fcc007247c68aac0Felipe Leme} 51375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 51475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateTest, DumpFileUpdateProgress) { 51575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 51675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_ = listener; 51775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_name_ = "FoxMulder"; 5187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme SetProgress(0, 30); 51975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 52075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_CALL(*listener, onProgressUpdated(5)); 5217447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 52275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 52375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme std::string progress_message = 52475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme GetProgressMessage(ds.listener_name_, 5, 30); // TODO: unhardcode WEIGHT_FILE (5)? 52575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(err, StrEq(progress_message)); 52675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 52775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 52875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme ds.listener_.clear(); 52975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme} 53075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 5317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass DumpstateServiceTest : public DumpstateBaseTest { 53275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme public: 53375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme DumpstateService dss; 53475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme}; 53575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 53675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerNoName) { 53775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 53875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme bool result; 53975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_TRUE(dss.setListener("", listener, &result).isOk()); 54075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_FALSE(result); 54175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme} 54275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 54375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerNoPointer) { 54475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme bool result; 54575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_TRUE(dss.setListener("whatever", nullptr, &result).isOk()); 54675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_FALSE(result); 54775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme} 54875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 54975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe LemeTEST_F(DumpstateServiceTest, SetListenerTwice) { 55075876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 55175876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme bool result; 55275876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_TRUE(dss.setListener("whatever", listener, &result).isOk()); 55375876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_TRUE(result); 55475876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 55575876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); 55675876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme 55775876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_TRUE(dss.setListener("whatever", listener, &result).isOk()); 55875876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme EXPECT_FALSE(result); 55975876a2c0649b8cde36329ca0a1dc6e349af6493Felipe Leme} 5607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5617447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Lemeclass ProgressTest : public DumpstateBaseTest { 5627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme public: 5637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { 5647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme return Progress(max, growth_factor, path); 5657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 5667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) { 5687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string expected_content = 5697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme android::base::StringPrintf("%d %d\n", expected_runs, expected_average); 5707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string actual_content; 5717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ASSERT_TRUE(android::base::ReadFileToString(path, &actual_content)) 5727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme << "could not read statsfrom" << path; 5737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path; 5747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 5757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme}; 5767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, SimpleTest) { 5787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress; 5797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, progress.Get()); 5807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 5817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 5827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = progress.Inc(1); 5847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(1, progress.Get()); 5857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 5867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 5877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 5887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Ignore negative increase. 5907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme max_increased = progress.Inc(-1); 5917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(1, progress.Get()); 5927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 5937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 5947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 5957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 5967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 5977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, MaxGrowsInsideNewRange) { 5987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress = GetInstance(10, 1.2); // 20% growth factor 5997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, progress.Get()); 6007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetInitialMax()); 6017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetMax()); 6027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // No increase 6047447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = progress.Inc(10); 6057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.Get()); 6067447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetMax()); 6077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 6087447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Increase, with new value < max*20% 6107447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme max_increased = progress.Inc(1); 6117447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(11, progress.Get()); 6127447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13 6137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_TRUE(max_increased); 6147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, MaxGrowsOutsideNewRange) { 6177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress = GetInstance(10, 1.2); // 20% growth factor 6187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, progress.Get()); 6197447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetInitialMax()); 6207447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetMax()); 6217447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // No increase 6237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = progress.Inc(10); 6247447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.Get()); 6257447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, progress.GetMax()); 6267447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 6277447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6287447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Increase, with new value > max*20% 6297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme max_increased = progress.Inc(5); 6307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(15, progress.Get()); 6317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18 6327447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_TRUE(max_increased); 6337447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6347447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6357447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidPath) { 6367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress("/devil/null"); 6377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6387447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6397447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6407447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, EmptyFile) { 6417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("empty-file.txt")); 6427447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryNAN) { 6467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt")); 6477447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6487447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6497447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryNAN) { 6517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt")); 6527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLineBothNAN) { 6567447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt")); 6577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6587447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6597447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryNegative) { 6617447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt")); 6627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryNegative) { 6667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt")); 6677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine1stEntryTooBig) { 6717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt")); 6727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, InvalidLine2ndEntryTooBig) { 6767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt")); 6777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 6787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests stats are properly saved when the file does not exists. 6817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, FirstTime) { 6827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string path = kTestDataPath + "FirstTime.txt"; 6837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme android::base::RemoveFileIfExists(path); 6847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress run1(path); 6867447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, run1.Get()); 6877447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax()); 6887447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); 6897447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6907447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = run1.Inc(20); 6917447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(20, run1.Get()); 6927447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); 6937447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 6947447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6957447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme run1.Save(); 6967447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 1, 20); 6977447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 6987447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 6997447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests what happens when the persistent settings contains the average duration of 1 run. 7007447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Data on file is 1 run and 109 average. 7017447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, SecondTime) { 7027447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt"); 7037447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7047447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress run1 = GetInstance(-42, 1.2, path); 7057447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, run1.Get()); 7067447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, run1.GetInitialMax()); 7077447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(10, run1.GetMax()); 7087447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7097447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = run1.Inc(20); 7107447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(20, run1.Get()); 7117447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(24, run1.GetMax()); 7127447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_TRUE(max_increased); 7137447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7147447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Average now is 2 runs and (10 + 20)/ 2 = 15 7157447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme run1.Save(); 7167447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 2, 15); 7177447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7187447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress run2 = GetInstance(-42, 1.2, path); 7197447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, run2.Get()); 7207447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(15, run2.GetInitialMax()); 7217447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(15, run2.GetMax()); 7227447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7237447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme max_increased = run2.Inc(25); 7247447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(25, run2.Get()); 7257447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(30, run2.GetMax()); 7267447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_TRUE(max_increased); 7277447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7287447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18 7297447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme run2.Save(); 7307447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 3, 18); 7317447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7327447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress run3 = GetInstance(-42, 1.2, path); 7337447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, run3.Get()); 7347447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(18, run3.GetInitialMax()); 7357447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(18, run3.GetMax()); 7367447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7377447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Make sure average decreases as well 7387447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme max_increased = run3.Inc(5); 7397447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(5, run3.Get()); 7407447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(18, run3.GetMax()); 7417447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_FALSE(max_increased); 7427447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7437447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14 7447447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme run3.Save(); 7457447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 4, 14); 7467447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 7477447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7487447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Tests what happens when the persistent settings contains the average duration of 2 runs. 7497447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// Data on file is 2 runs and 15 average. 7507447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(ProgressTest, ThirdTime) { 7517447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme std::string path = CopyTextFileFixture("stats-two-runs.txt"); 7527447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 2, 15); // Sanity check 7537447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7547447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme Progress run1 = GetInstance(-42, 1.2, path); 7557447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, run1.Get()); 7567447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(15, run1.GetInitialMax()); 7577447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(15, run1.GetMax()); 7587447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7597447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme bool max_increased = run1.Inc(20); 7607447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(20, run1.Get()); 7617447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(24, run1.GetMax()); 7627447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_TRUE(max_increased); 7637447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7647447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16 7657447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme run1.Save(); 7667447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme AssertStats(path, 3, 16); 7677447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 7687447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7697447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// TODO: RunCommandAsRootNonUserBuild must be the last test because it drops root, which could cause 7707447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// other tests to fail if they're relyin on the process running as root. 7717447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme// For now this is fine, but eventually it might need to be moved to its own test case / process. 7727447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe LemeTEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) { 7737447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme if (IsUserBuild()) { 7747447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n"); 7757447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme return; 7767447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme } 7777447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7787447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme DropRoot(); 7797447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7807447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 7817447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme CommandOptions::WithTimeout(1).AsRoot().Build())); 7827447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme 7837447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(out, StrEq("0\nstdout\n")); 7847447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme EXPECT_THAT(err, StrEq("stderr\n")); 7857447d7c3d74b28f1a071b1d3503212cc8ad08d68Felipe Leme} 786