blob: 306069f9f49fec974a56f8197f9c6e42487af66a [file] [log] [blame]
Felipe Leme4c2d6632016-09-28 14:32:00 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dieter Hsu105ad0c2020-09-29 15:23:33 +080017#define LOG_TAG "dumpstate_test"
Felipe Leme75876a22016-10-27 16:31:27 -070018
Felipe Lemef0292972016-11-22 13:57:05 -080019#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070020#include "DumpstateService.h"
21#include "android/os/BnDumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070022#include "dumpstate.h"
Rhed Jao27077b12020-07-14 18:38:08 +080023#include "DumpPool.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070024
25#include <gmock/gmock.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080026#include <gmock/gmock-matchers.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070027#include <gtest/gtest.h>
28
Felipe Leme46b85da2016-11-21 17:40:45 -080029#include <fcntl.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070030#include <libgen.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070031#include <signal.h>
32#include <sys/types.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070033#include <unistd.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070034#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070035
36#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070037#include <android-base/properties.h>
38#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070039#include <android-base/strings.h>
Abhijeet Kaure370d682019-10-01 16:49:30 +010040#include <android-base/unique_fd.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080041#include <android/hardware/dumpstate/1.1/types.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080042#include <cutils/log.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080043#include <cutils/properties.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080044#include <ziparchive/zip_archive.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070045
Felipe Leme47e9be22016-12-21 15:37:07 -080046namespace android {
47namespace os {
48namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070049
Hunter Knepshield8540faf2020-02-04 19:47:20 -080050using ::android::hardware::dumpstate::V1_1::DumpstateMode;
Felipe Leme4c2d6632016-09-28 14:32:00 -070051using ::testing::EndsWith;
Rhed Jao27077b12020-07-14 18:38:08 +080052using ::testing::Eq;
Felipe Leme46b85da2016-11-21 17:40:45 -080053using ::testing::HasSubstr;
Felipe Leme4c2d6632016-09-28 14:32:00 -070054using ::testing::IsEmpty;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080055using ::testing::IsNull;
Felipe Leme009ecbb2016-11-07 10:18:44 -080056using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070057using ::testing::StartsWith;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080058using ::testing::StrEq;
Felipe Leme4c2d6632016-09-28 14:32:00 -070059using ::testing::Test;
60using ::testing::internal::CaptureStderr;
61using ::testing::internal::CaptureStdout;
62using ::testing::internal::GetCapturedStderr;
63using ::testing::internal::GetCapturedStdout;
64
Nandana Dutt3f8c7172018-09-25 12:01:54 +010065#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
66
Felipe Leme75876a22016-10-27 16:31:27 -070067class DumpstateListenerMock : public IDumpstateListener {
68 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000069 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
70 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Nandana Duttcc4ead82019-01-23 08:29:23 +000071 MOCK_METHOD0(onFinished, binder::Status());
Paul Chang0d2aad72020-02-13 20:04:03 +080072 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
Paul Changc490e662020-04-11 18:14:09 +080073 MOCK_METHOD1(onUiIntensiveBugreportDumpsFinished,
74 binder::Status(const android::String16& callingpackage));
Felipe Leme75876a22016-10-27 16:31:27 -070075
76 protected:
77 MOCK_METHOD0(onAsBinder, IBinder*());
78};
79
Felipe Leme46b85da2016-11-21 17:40:45 -080080static int calls_;
81
Felipe Leme7447d7c2016-11-03 18:12:22 -070082// Base class for all tests in this file
83class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080084 public:
85 virtual void SetUp() override {
86 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080087 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080088 }
89
Felipe Lemef0292972016-11-22 13:57:05 -080090 void SetDryRun(bool dry_run) const {
91 PropertiesHelper::dry_run_ = dry_run;
92 }
93
94 void SetBuildType(const std::string& build_type) const {
95 PropertiesHelper::build_type_ = build_type;
96 }
97
Nandana Dutt4b392be2018-11-02 16:17:05 +000098 void SetUnroot(bool unroot) const {
99 PropertiesHelper::unroot_ = unroot;
100 }
101
Rhed Jao1c855122020-07-16 17:37:39 +0800102 void SetParallelRun(bool parallel_run) const {
103 PropertiesHelper::parallel_run_ = parallel_run;
104 }
105
Felipe Lemef0292972016-11-22 13:57:05 -0800106 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -0800107 return calls_ == 1;
108 }
109
Felipe Lemef0292972016-11-22 13:57:05 -0800110 void DropRoot() const {
111 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -0800112 uid_t uid = getuid();
113 ASSERT_EQ(2000, (int)uid);
114 }
115
Felipe Leme7447d7c2016-11-03 18:12:22 -0700116 protected:
117 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700118 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
119 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700120 const std::string kEchoCommand = "/system/bin/echo";
121
122 /*
123 * Copies a text file fixture to a temporary file, returning it's path.
124 *
125 * Useful in cases where the test case changes the content of the tile.
126 */
127 std::string CopyTextFileFixture(const std::string& relative_name) {
128 std::string from = kTestDataPath + relative_name;
129 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
130 // around for poking when the test fails.
131 std::string to = kTestDataPath + relative_name + ".tmp";
132 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
133 android::base::RemoveFileIfExists(to);
134 CopyTextFile(from, to);
135 return to.c_str();
136 }
137
Felipe Leme46b85da2016-11-21 17:40:45 -0800138 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700139 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800140 void ReadFileToString(const std::string& path, std::string* content) {
141 ASSERT_TRUE(android::base::ReadFileToString(path, content))
142 << "could not read contents from " << path;
143 }
144 void WriteStringToFile(const std::string& content, const std::string& path) {
145 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
146 << "could not write contents to " << path;
147 }
148
149 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700150 void CopyTextFile(const std::string& from, const std::string& to) {
151 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800152 ReadFileToString(from, &content);
153 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700154 }
155};
156
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100157class DumpOptionsTest : public Test {
158 public:
159 virtual ~DumpOptionsTest() {
160 }
161 virtual void SetUp() {
162 options_ = Dumpstate::DumpOptions();
163 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000164 void TearDown() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000165 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100166 Dumpstate::DumpOptions options_;
Abhijeet Kaure370d682019-10-01 16:49:30 +0100167 android::base::unique_fd fd;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100168};
169
170TEST_F(DumpOptionsTest, InitializeNone) {
171 // clang-format off
172 char* argv[] = {
173 const_cast<char*>("dumpstate")
174 };
175 // clang-format on
176
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100177 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
178
179 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000180
mhasank3a4cfb42020-06-15 18:06:43 -0700181 EXPECT_EQ("", options_.out_dir);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800182 EXPECT_FALSE(options_.stream_to_socket);
183 EXPECT_FALSE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100184 EXPECT_FALSE(options_.show_header_only);
185 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800186 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100187 EXPECT_FALSE(options_.do_progress_updates);
188 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700189 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800190 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000191}
192
193TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
194 // clang-format off
195 char* argv[] = {
196 const_cast<char*>("dumpstatez"),
197 const_cast<char*>("-S"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000198 };
199 // clang-format on
200
201 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
202
203 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800204 EXPECT_TRUE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000205
206 // Other options retain default values
207 EXPECT_TRUE(options_.do_vibrate);
208 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800209 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000210 EXPECT_FALSE(options_.do_progress_updates);
211 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800212 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700213 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800214 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000215}
216
217TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
218 // clang-format off
219 char* argv[] = {
220 const_cast<char*>("dumpstate"),
221 const_cast<char*>("-s"),
222 };
223 // clang-format on
224
225 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
226
227 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800228 EXPECT_TRUE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000229
230 // Other options retain default values
231 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800232 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000233 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800234 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000235 EXPECT_FALSE(options_.do_progress_updates);
236 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700237 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800238 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000239}
240
241TEST_F(DumpOptionsTest, InitializeFullBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800242 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800243 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800244 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000245
246 // Other options retain default values
247 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800248 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000249 EXPECT_FALSE(options_.show_header_only);
250 EXPECT_FALSE(options_.do_progress_updates);
251 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800252 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700253 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000254}
255
256TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800257 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000258 EXPECT_TRUE(options_.do_progress_updates);
Paul Chang0d2aad72020-02-13 20:04:03 +0800259 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800260 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000261
262 // Other options retain default values
263 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800264 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000265 EXPECT_FALSE(options_.show_header_only);
266 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800267 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700268 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000269}
270
271TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800272 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000273 EXPECT_TRUE(options_.is_remote_mode);
274 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800275 EXPECT_FALSE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800276 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000277
278 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800279 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000280 EXPECT_FALSE(options_.show_header_only);
281 EXPECT_FALSE(options_.do_progress_updates);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800282 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700283 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000284}
285
286TEST_F(DumpOptionsTest, InitializeWearBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800287 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800288 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000289 EXPECT_TRUE(options_.do_progress_updates);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800290 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000291
292 // Other options retain default values
293 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800294 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000295 EXPECT_FALSE(options_.show_header_only);
296 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800297 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700298 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000299}
300
301TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800302 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800303 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000304 EXPECT_TRUE(options_.telephony_only);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800305 EXPECT_TRUE(options_.do_progress_updates);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800306 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000307
308 // Other options retain default values
309 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800310 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000311 EXPECT_FALSE(options_.show_header_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000312 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800313 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700314 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000315}
316
317TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800318 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800319 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000320 EXPECT_TRUE(options_.wifi_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800321 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000322
323 // Other options retain default values
324 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800325 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000326 EXPECT_FALSE(options_.show_header_only);
327 EXPECT_FALSE(options_.do_progress_updates);
328 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800329 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700330 EXPECT_FALSE(options_.limited_only);
331}
332
333TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
334 // clang-format off
335 char* argv[] = {
336 const_cast<char*>("dumpstatez"),
337 const_cast<char*>("-S"),
mhasankd451a472020-05-26 18:02:39 -0700338 const_cast<char*>("-q"),
mhasank2d75c442020-06-11 15:05:25 -0700339 const_cast<char*>("-L"),
340 const_cast<char*>("-o abc")
mhasankd451a472020-05-26 18:02:39 -0700341 };
342 // clang-format on
343
344 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
345
346 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800347 EXPECT_TRUE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700348 EXPECT_FALSE(options_.do_vibrate);
349 EXPECT_TRUE(options_.limited_only);
mhasank3a4cfb42020-06-15 18:06:43 -0700350 EXPECT_EQ(" abc", std::string(options_.out_dir));
mhasankd451a472020-05-26 18:02:39 -0700351
352 // Other options retain default values
353 EXPECT_FALSE(options_.show_header_only);
354 EXPECT_FALSE(options_.do_screenshot);
355 EXPECT_FALSE(options_.do_progress_updates);
356 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800357 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700358 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000359}
360
361TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
362 // default: commandline options are not overridden
363 // clang-format off
364 char* argv[] = {
365 const_cast<char*>("bugreport"),
366 const_cast<char*>("-d"),
367 const_cast<char*>("-p"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000368 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000369 };
370 // clang-format on
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000371 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
372
373 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Paul Chang0d2aad72020-02-13 20:04:03 +0800374 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800375 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000376
377 // Other options retain default values
378 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800379 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000380 EXPECT_FALSE(options_.show_header_only);
381 EXPECT_FALSE(options_.do_progress_updates);
382 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800383 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000384 EXPECT_FALSE(options_.wifi_only);
mhasankd451a472020-05-26 18:02:39 -0700385 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100386}
387
388TEST_F(DumpOptionsTest, InitializePartial1) {
389 // clang-format off
390 char* argv[] = {
391 const_cast<char*>("dumpstate"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100392 const_cast<char*>("-s"),
393 const_cast<char*>("-S"),
394
395 };
396 // clang-format on
397
398 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
399
400 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100401 // TODO: Maybe we should trim the filename
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800402 EXPECT_TRUE(options_.stream_to_socket);
403 EXPECT_TRUE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100404
405 // Other options retain default values
406 EXPECT_FALSE(options_.show_header_only);
407 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800408 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100409 EXPECT_FALSE(options_.do_progress_updates);
410 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700411 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800412 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100413}
414
415TEST_F(DumpOptionsTest, InitializePartial2) {
416 // clang-format off
417 char* argv[] = {
418 const_cast<char*>("dumpstate"),
419 const_cast<char*>("-v"),
420 const_cast<char*>("-q"),
421 const_cast<char*>("-p"),
422 const_cast<char*>("-P"),
423 const_cast<char*>("-R"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100424 };
425 // clang-format on
426
427 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
428
429 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
430 EXPECT_TRUE(options_.show_header_only);
431 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800432 EXPECT_TRUE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100433 EXPECT_TRUE(options_.do_progress_updates);
434 EXPECT_TRUE(options_.is_remote_mode);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100435
436 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800437 EXPECT_FALSE(options_.stream_to_socket);
438 EXPECT_FALSE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700439 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800440 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100441}
442
443TEST_F(DumpOptionsTest, InitializeHelp) {
444 // clang-format off
445 char* argv[] = {
446 const_cast<char*>("dumpstate"),
447 const_cast<char*>("-h")
448 };
449 // clang-format on
450
451 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
452
453 // -h is for help.
454 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
455}
456
457TEST_F(DumpOptionsTest, InitializeUnknown) {
458 // clang-format off
459 char* argv[] = {
460 const_cast<char*>("dumpstate"),
461 const_cast<char*>("-u") // unknown flag
462 };
463 // clang-format on
464
465 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
466
467 // -u is unknown.
468 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
469}
470
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800471TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage1) {
472 options_.progress_updates_to_socket = true;
473 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100474 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000475
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800476 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100477 EXPECT_TRUE(options_.ValidateOptions());
478}
479
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800480TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage2) {
Abhijeet Kaure370d682019-10-01 16:49:30 +0100481 options_.do_progress_updates = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000482 // Writing to socket = !writing to file.
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800483 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100484 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000485
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800486 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100487 EXPECT_TRUE(options_.ValidateOptions());
488}
489
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100490TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800491 options_.do_progress_updates = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100492 options_.is_remote_mode = true;
493 EXPECT_FALSE(options_.ValidateOptions());
494
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800495 options_.do_progress_updates = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100496 EXPECT_TRUE(options_.ValidateOptions());
497}
498
Felipe Leme7447d7c2016-11-03 18:12:22 -0700499class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700500 public:
501 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800502 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700503 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700504 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700505 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100506 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700507 }
508
Rhed Jao1c855122020-07-16 17:37:39 +0800509 void TearDown() {
510 ds.ShutdownDumpPool();
511 }
512
Felipe Leme4c2d6632016-09-28 14:32:00 -0700513 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700514 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700515 const CommandOptions& options = CommandOptions::DEFAULT) {
516 CaptureStdout();
517 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700518 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700519 out = GetCapturedStdout();
520 err = GetCapturedStderr();
521 return status;
522 }
523
Felipe Lemecef02982016-10-03 17:22:22 -0700524 // Dumps a file and capture `stdout` and `stderr`.
525 int DumpFile(const std::string& title, const std::string& path) {
526 CaptureStdout();
527 CaptureStderr();
528 int status = ds.DumpFile(title, path);
529 out = GetCapturedStdout();
530 err = GetCapturedStderr();
531 return status;
532 }
533
Nandana Dutt402a8392019-06-14 14:25:13 +0100534 void SetProgress(long progress, long initial_max) {
535 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100536 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700537 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
538 }
539
Rhed Jao1c855122020-07-16 17:37:39 +0800540 void EnableParallelRunIfNeeded() {
541 ds.EnableParallelRunIfNeeded();
542 }
543
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100544 std::string GetProgressMessage(int progress, int max,
545 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700546 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
547 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700548
Felipe Leme7447d7c2016-11-03 18:12:22 -0700549 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700550
Felipe Leme009ecbb2016-11-07 10:18:44 -0800551 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700552 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800553 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700554 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700555 }
556
Felipe Leme009ecbb2016-11-07 10:18:44 -0800557 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100558 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
559 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800560 }
561
562 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700563 }
564
Felipe Leme4c2d6632016-09-28 14:32:00 -0700565 // `stdout` and `stderr` from the last command ran.
566 std::string out, err;
567
Felipe Lemefd8affa2016-09-30 17:38:57 -0700568 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700569};
570
571TEST_F(DumpstateTest, RunCommandNoArgs) {
572 EXPECT_EQ(-1, RunCommand("", {}));
573}
574
575TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700576 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700577 EXPECT_THAT(out, StrEq("stdout\n"));
578 EXPECT_THAT(err, StrEq("stderr\n"));
579}
580
581TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700582 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700583 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700584 // The duration may not get output, depending on how long it takes,
585 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700586 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000587 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700588}
589
Felipe Lemefd8affa2016-09-30 17:38:57 -0700590TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700591 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700592 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700593 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
594 EXPECT_THAT(out, StrEq("stdout\n"));
595 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
596}
597
598TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700599 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700600 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700601 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700602 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700603}
604
605TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700606 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700607 EXPECT_THAT(err, IsEmpty());
608 EXPECT_THAT(out, StrEq("one\n"));
609}
610
Felipe Lemefd8affa2016-09-30 17:38:57 -0700611TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700612 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700613 EXPECT_THAT(err, IsEmpty());
614 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
615}
616
617TEST_F(DumpstateTest, RunCommandDryRun) {
618 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700619 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700620 // The duration may not get output, depending on how long it takes,
621 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700622 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000623 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700624 EXPECT_THAT(err, IsEmpty());
625}
626
627TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
628 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700629 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700630 EXPECT_THAT(out, IsEmpty());
631 EXPECT_THAT(err, IsEmpty());
632}
633
634TEST_F(DumpstateTest, RunCommandDryRunAlways) {
635 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700636 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700637 EXPECT_THAT(out, StrEq("stdout\n"));
638 EXPECT_THAT(err, StrEq("stderr\n"));
639}
640
Felipe Lemefd8affa2016-09-30 17:38:57 -0700641TEST_F(DumpstateTest, RunCommandNotFound) {
642 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
643 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
644 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
645}
646
647TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700648 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
649 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700650 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700651 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700652 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700653}
654
655TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700656 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700657 // We don't know the exit code, so check just the prefix.
658 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700659 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700660 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700661 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700662}
663
664TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700665 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700666 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700667 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700668 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700669 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700670 " --sleep 2' timed out after 1"));
671}
672
673TEST_F(DumpstateTest, RunCommandIsKilled) {
674 CaptureStdout();
675 CaptureStderr();
676
677 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700678 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700679 CommandOptions::WithTimeout(100).Always().Build()));
680 });
681
682 // Capture pid and pre-sleep output.
683 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
684 std::string err = GetCapturedStderr();
685 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
686
687 std::string out = GetCapturedStdout();
688 std::vector<std::string> lines = android::base::Split(out, "\n");
689 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
690
691 int pid = atoi(lines[0].c_str());
692 EXPECT_THAT(lines[1], StrEq("stdout line1"));
693 EXPECT_THAT(lines[2], IsEmpty()); // \n
694
695 // Then kill the process.
696 CaptureStdout();
697 CaptureStderr();
698 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
699 t.join();
700
701 // Finally, check output after murder.
702 out = GetCapturedStdout();
703 err = GetCapturedStderr();
704
Felipe Leme7447d7c2016-11-03 18:12:22 -0700705 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700706 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700707 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700708 " --pid --sleep 20' failed: killed by signal 15\n"));
709}
710
Felipe Leme75876a22016-10-27 16:31:27 -0700711TEST_F(DumpstateTest, RunCommandProgress) {
712 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
713 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700714 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700715
Nandana Duttbabf6c72019-01-15 14:11:12 +0000716 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700717 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100718 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700719 EXPECT_THAT(out, StrEq("stdout\n"));
720 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
721
Nandana Dutt402a8392019-06-14 14:25:13 +0100722 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
723 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100724 progress_message = GetProgressMessage(24, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700725 EXPECT_THAT(out, StrEq("stdout\n"));
726 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
727
728 // Make sure command ran while in dry_run is counted.
729 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100730 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
731 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100732 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700733 EXPECT_THAT(out, IsEmpty());
734 EXPECT_THAT(err, StrEq(progress_message));
735
Nandana Dutt402a8392019-06-14 14:25:13 +0100736 SetDryRun(false);
737 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
738 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100739 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800740 EXPECT_THAT(out, StrEq("stdout\n"));
741 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
742
Nandana Dutt402a8392019-06-14 14:25:13 +0100743 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800744 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100745 progress_message = GetProgressMessage(30, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800746 EXPECT_THAT(out, StrEq("stdout\n"));
747 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
748
749 ds.listener_.clear();
750}
751
Felipe Lemed80e6b62016-10-03 13:08:14 -0700752TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800753 if (!IsStandalone()) {
754 // TODO: temporarily disabled because it might cause other tests to fail after dropping
755 // to Shell - need to refactor tests to avoid this problem)
756 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
757 return;
758 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700759 // First check root case - only available when running with 'adb root'.
760 uid_t uid = getuid();
761 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700762 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700763 EXPECT_THAT(out, StrEq("0\nstdout\n"));
764 EXPECT_THAT(err, StrEq("stderr\n"));
765 return;
766 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700767 // Then run dropping root.
768 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700769 CommandOptions::WithTimeout(1).DropRoot().Build()));
770 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700771 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700772}
773
774TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800775 if (!IsStandalone()) {
776 // TODO: temporarily disabled because it might cause other tests to fail after dropping
777 // to Shell - need to refactor tests to avoid this problem)
778 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
779 return;
780 }
Felipe Lemef0292972016-11-22 13:57:05 -0800781 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700782 // Emulates user build if necessarily.
783 SetBuildType("user");
784 }
785
786 DropRoot();
787
Felipe Leme7447d7c2016-11-03 18:12:22 -0700788 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700789
790 // We don't know the exact path of su, so we just check for the 'root ...' commands
791 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700792 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700793 EXPECT_THAT(err, IsEmpty());
794}
795
Felipe Leme46b85da2016-11-21 17:40:45 -0800796TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
797 if (!IsStandalone()) {
798 // TODO: temporarily disabled because it might cause other tests to fail after dropping
799 // to Shell - need to refactor tests to avoid this problem)
800 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
801 return;
802 }
Felipe Lemef0292972016-11-22 13:57:05 -0800803 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800804 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
805 return;
806 }
807
808 DropRoot();
809
810 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
811 CommandOptions::WithTimeout(1).AsRoot().Build()));
812
813 EXPECT_THAT(out, StrEq("0\nstdout\n"));
814 EXPECT_THAT(err, StrEq("stderr\n"));
815}
816
Nandana Dutt4b392be2018-11-02 16:17:05 +0000817TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
818 if (!IsStandalone()) {
819 // TODO: temporarily disabled because it might cause other tests to fail after dropping
820 // to Shell - need to refactor tests to avoid this problem)
821 MYLOGE(
822 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
823 "on test suite\n")
824 return;
825 }
826 if (PropertiesHelper::IsUserBuild()) {
827 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
828 return;
829 }
830
831 // Same test as above, but with unroot property set, which will override su availability.
832 SetUnroot(true);
833 DropRoot();
834
835 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
836 CommandOptions::WithTimeout(1).AsRoot().Build()));
837
838 // AsRoot is ineffective.
839 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
840 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
841}
842
Yifan Hong48e83a12017-10-03 14:10:07 -0700843TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
844 if (!IsStandalone()) {
845 // TODO: temporarily disabled because it might cause other tests to fail after dropping
846 // to Shell - need to refactor tests to avoid this problem)
847 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
848 return;
849 }
850 if (!PropertiesHelper::IsUserBuild()) {
851 // Emulates user build if necessarily.
852 SetBuildType("user");
853 }
854
855 DropRoot();
856
857 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
858 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
859
860 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
861 EXPECT_THAT(err, StrEq("stderr\n"));
862}
863
864TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
865 if (!IsStandalone()) {
866 // TODO: temporarily disabled because it might cause other tests to fail after dropping
867 // to Shell - need to refactor tests to avoid this problem)
868 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
869 return;
870 }
871 if (PropertiesHelper::IsUserBuild()) {
872 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
873 return;
874 }
875
876 DropRoot();
877
878 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
879 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
880
881 EXPECT_THAT(out, StrEq("0\nstdout\n"));
882 EXPECT_THAT(err, StrEq("stderr\n"));
883}
884
Nandana Dutt4b392be2018-11-02 16:17:05 +0000885TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
886 if (!IsStandalone()) {
887 // TODO: temporarily disabled because it might cause other tests to fail after dropping
888 // to Shell - need to refactor tests to avoid this problem)
889 MYLOGE(
890 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
891 "on test suite\n")
892 return;
893 }
894 if (PropertiesHelper::IsUserBuild()) {
895 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
896 return;
897 }
898 // Same test as above, but with unroot property set, which will override su availability.
899 SetUnroot(true);
900
901 DropRoot();
902
903 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
904 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
905
906 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
907 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
908 EXPECT_THAT(err, StrEq("stderr\n"));
909}
910
Felipe Lemecef02982016-10-03 17:22:22 -0700911TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
912 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
913 EXPECT_THAT(out,
914 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
915 EXPECT_THAT(err, IsEmpty());
916}
917
918TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
919 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
920 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700921 // The duration may not get output, depending on how long it takes,
922 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700923 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
924 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700925}
926
927TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700928 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700929 EXPECT_THAT(err, IsEmpty());
930 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
931}
932
933TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700934 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700935 EXPECT_THAT(err, IsEmpty());
936 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
937}
938
939TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700940 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700941 EXPECT_THAT(err, IsEmpty());
942 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
943}
944
945TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700946 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700947 EXPECT_THAT(err, IsEmpty());
948 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
949}
950
951TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
952 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700953 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700954 EXPECT_THAT(err, IsEmpty());
955 EXPECT_THAT(out, IsEmpty());
956}
957
958TEST_F(DumpstateTest, DumpFileOnDryRun) {
959 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700960 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700961 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800962 EXPECT_THAT(
963 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +0000964 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700965}
966
Felipe Leme75876a22016-10-27 16:31:27 -0700967TEST_F(DumpstateTest, DumpFileUpdateProgress) {
968 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
969 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700970 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700971
Nandana Duttbabf6c72019-01-15 14:11:12 +0000972 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700973 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700974
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100975 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -0700976 EXPECT_THAT(err, StrEq(progress_message));
977 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
978
979 ds.listener_.clear();
980}
981
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800982TEST_F(DumpstateTest, DumpPool_withParallelRunEnabled_notNull) {
Rhed Jao1c855122020-07-16 17:37:39 +0800983 SetParallelRun(true);
984 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800985 EXPECT_TRUE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800986 EXPECT_TRUE(ds.dump_pool_);
987}
988
Rhed Jao1c855122020-07-16 17:37:39 +0800989TEST_F(DumpstateTest, DumpPool_withParallelRunDisabled_isNull) {
990 SetParallelRun(false);
991 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800992 EXPECT_FALSE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800993 EXPECT_FALSE(ds.dump_pool_);
994}
995
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800996class ZippedBugReportStreamTest : public DumpstateBaseTest {
997 public:
998 void SetUp() {
999 DumpstateBaseTest::SetUp();
1000 ds_.options_.reset(new Dumpstate::DumpOptions());
1001 }
1002 void TearDown() {
1003 CloseArchive(handle_);
1004 }
1005
1006 // Set bugreport mode and options before here.
1007 void GenerateBugreport() {
1008 ds_.Initialize();
1009 EXPECT_EQ(Dumpstate::RunStatus::OK, ds_.Run(/*calling_uid=*/-1, /*calling_package=*/""));
1010 }
1011
1012 // Most bugreports droproot, ensure the file can be opened by shell to verify file content.
1013 void CreateFd(const std::string& path, android::base::unique_fd* out_fd) {
1014 out_fd->reset(TEMP_FAILURE_RETRY(open(path.c_str(),
1015 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1016 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1017 ASSERT_GE(out_fd->get(), 0) << "could not create FD for path " << path;
1018 }
1019
1020 void VerifyEntry(const ZipArchiveHandle archive, const std::string_view entry_name,
1021 ZipEntry* data) {
1022 int32_t e = FindEntry(archive, entry_name, data);
1023 EXPECT_EQ(0, e) << ErrorCodeString(e) << " entry name: " << entry_name;
1024 }
1025
1026 // While testing dumpstate in process, using STDOUT may get confused about
1027 // the internal fd redirection. Redirect to a dedicate fd to save content.
1028 void RedirectOutputToFd(android::base::unique_fd& ufd) {
1029 ds_.open_socket_fn_ = [&](const char*) -> int { return ufd.release(); };
1030 };
1031
1032 Dumpstate& ds_ = Dumpstate::GetInstance();
1033 ZipArchiveHandle handle_;
1034};
1035
1036// Generate a quick wifi report redirected to a file, open it and verify entry exist.
1037TEST_F(ZippedBugReportStreamTest, StreamWifiReport) {
1038 std::string out_path = kTestDataPath + "out.zip";
1039 android::base::unique_fd out_fd;
1040 CreateFd(out_path, &out_fd);
1041 ds_.options_->wifi_only = true;
1042 ds_.options_->stream_to_socket = true;
1043 RedirectOutputToFd(out_fd);
1044
1045 GenerateBugreport();
1046 OpenArchive(out_path.c_str(), &handle_);
1047
1048 ZipEntry entry;
1049 VerifyEntry(handle_, "main_entry.txt", &entry);
1050 std::string bugreport_txt_name;
1051 bugreport_txt_name.resize(entry.uncompressed_length);
1052 ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
1053 entry.uncompressed_length);
1054 EXPECT_THAT(bugreport_txt_name,
1055 testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)"));
1056 VerifyEntry(handle_, bugreport_txt_name, &entry);
1057}
1058
Felipe Leme7447d7c2016-11-03 18:12:22 -07001059class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -07001060 public:
1061 DumpstateService dss;
1062};
1063
Felipe Leme7447d7c2016-11-03 18:12:22 -07001064class ProgressTest : public DumpstateBaseTest {
1065 public:
1066 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1067 return Progress(max, growth_factor, path);
1068 }
1069
1070 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1071 std::string expected_content =
1072 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1073 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001074 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001075 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1076 }
1077};
1078
1079TEST_F(ProgressTest, SimpleTest) {
1080 Progress progress;
1081 EXPECT_EQ(0, progress.Get());
1082 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1083 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1084
1085 bool max_increased = progress.Inc(1);
1086 EXPECT_EQ(1, progress.Get());
1087 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1088 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1089 EXPECT_FALSE(max_increased);
1090
1091 // Ignore negative increase.
1092 max_increased = progress.Inc(-1);
1093 EXPECT_EQ(1, progress.Get());
1094 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1095 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1096 EXPECT_FALSE(max_increased);
1097}
1098
1099TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1100 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1101 EXPECT_EQ(0, progress.Get());
1102 EXPECT_EQ(10, progress.GetInitialMax());
1103 EXPECT_EQ(10, progress.GetMax());
1104
1105 // No increase
1106 bool max_increased = progress.Inc(10);
1107 EXPECT_EQ(10, progress.Get());
1108 EXPECT_EQ(10, progress.GetMax());
1109 EXPECT_FALSE(max_increased);
1110
1111 // Increase, with new value < max*20%
1112 max_increased = progress.Inc(1);
1113 EXPECT_EQ(11, progress.Get());
1114 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1115 EXPECT_TRUE(max_increased);
1116}
1117
1118TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1119 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1120 EXPECT_EQ(0, progress.Get());
1121 EXPECT_EQ(10, progress.GetInitialMax());
1122 EXPECT_EQ(10, progress.GetMax());
1123
1124 // No increase
1125 bool max_increased = progress.Inc(10);
1126 EXPECT_EQ(10, progress.Get());
1127 EXPECT_EQ(10, progress.GetMax());
1128 EXPECT_FALSE(max_increased);
1129
1130 // Increase, with new value > max*20%
1131 max_increased = progress.Inc(5);
1132 EXPECT_EQ(15, progress.Get());
1133 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1134 EXPECT_TRUE(max_increased);
1135}
1136
1137TEST_F(ProgressTest, InvalidPath) {
1138 Progress progress("/devil/null");
1139 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1140}
1141
1142TEST_F(ProgressTest, EmptyFile) {
1143 Progress progress(CopyTextFileFixture("empty-file.txt"));
1144 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1145}
1146
1147TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1148 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1149 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1150}
1151
1152TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1153 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1154 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1155}
1156
1157TEST_F(ProgressTest, InvalidLineBothNAN) {
1158 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1159 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1160}
1161
1162TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1163 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1164 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1165}
1166
1167TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1168 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1169 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1170}
1171
1172TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1173 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1174 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1175}
1176
1177TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1178 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1179 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1180}
1181
1182// Tests stats are properly saved when the file does not exists.
1183TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001184 if (!IsStandalone()) {
1185 // TODO: temporarily disabled because it's failing when running as suite
1186 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1187 return;
1188 }
1189
Felipe Leme7447d7c2016-11-03 18:12:22 -07001190 std::string path = kTestDataPath + "FirstTime.txt";
1191 android::base::RemoveFileIfExists(path);
1192
1193 Progress run1(path);
1194 EXPECT_EQ(0, run1.Get());
1195 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1196 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1197
1198 bool max_increased = run1.Inc(20);
1199 EXPECT_EQ(20, run1.Get());
1200 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1201 EXPECT_FALSE(max_increased);
1202
1203 run1.Save();
1204 AssertStats(path, 1, 20);
1205}
1206
1207// Tests what happens when the persistent settings contains the average duration of 1 run.
1208// Data on file is 1 run and 109 average.
1209TEST_F(ProgressTest, SecondTime) {
1210 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1211
1212 Progress run1 = GetInstance(-42, 1.2, path);
1213 EXPECT_EQ(0, run1.Get());
1214 EXPECT_EQ(10, run1.GetInitialMax());
1215 EXPECT_EQ(10, run1.GetMax());
1216
1217 bool max_increased = run1.Inc(20);
1218 EXPECT_EQ(20, run1.Get());
1219 EXPECT_EQ(24, run1.GetMax());
1220 EXPECT_TRUE(max_increased);
1221
1222 // Average now is 2 runs and (10 + 20)/ 2 = 15
1223 run1.Save();
1224 AssertStats(path, 2, 15);
1225
1226 Progress run2 = GetInstance(-42, 1.2, path);
1227 EXPECT_EQ(0, run2.Get());
1228 EXPECT_EQ(15, run2.GetInitialMax());
1229 EXPECT_EQ(15, run2.GetMax());
1230
1231 max_increased = run2.Inc(25);
1232 EXPECT_EQ(25, run2.Get());
1233 EXPECT_EQ(30, run2.GetMax());
1234 EXPECT_TRUE(max_increased);
1235
1236 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1237 run2.Save();
1238 AssertStats(path, 3, 18);
1239
1240 Progress run3 = GetInstance(-42, 1.2, path);
1241 EXPECT_EQ(0, run3.Get());
1242 EXPECT_EQ(18, run3.GetInitialMax());
1243 EXPECT_EQ(18, run3.GetMax());
1244
1245 // Make sure average decreases as well
1246 max_increased = run3.Inc(5);
1247 EXPECT_EQ(5, run3.Get());
1248 EXPECT_EQ(18, run3.GetMax());
1249 EXPECT_FALSE(max_increased);
1250
1251 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1252 run3.Save();
1253 AssertStats(path, 4, 14);
1254}
1255
1256// Tests what happens when the persistent settings contains the average duration of 2 runs.
1257// Data on file is 2 runs and 15 average.
1258TEST_F(ProgressTest, ThirdTime) {
1259 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1260 AssertStats(path, 2, 15); // Sanity check
1261
1262 Progress run1 = GetInstance(-42, 1.2, path);
1263 EXPECT_EQ(0, run1.Get());
1264 EXPECT_EQ(15, run1.GetInitialMax());
1265 EXPECT_EQ(15, run1.GetMax());
1266
1267 bool max_increased = run1.Inc(20);
1268 EXPECT_EQ(20, run1.Get());
1269 EXPECT_EQ(24, run1.GetMax());
1270 EXPECT_TRUE(max_increased);
1271
1272 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1273 run1.Save();
1274 AssertStats(path, 3, 16);
1275}
1276
Felipe Leme46b85da2016-11-21 17:40:45 -08001277class DumpstateUtilTest : public DumpstateBaseTest {
1278 public:
1279 void SetUp() {
1280 DumpstateBaseTest::SetUp();
1281 SetDryRun(false);
1282 }
1283
Felipe Leme46b85da2016-11-21 17:40:45 -08001284 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001285 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001286 }
1287
1288 void CreateFd(const std::string& name) {
1289 path_ = kTestDataPath + name;
1290 MYLOGD("Creating fd for file %s\n", path_.c_str());
1291
1292 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1293 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1294 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1295 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1296 }
1297
1298 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001299 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001300 const CommandOptions& options = CommandOptions::DEFAULT) {
1301 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001302 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001303 close(fd);
1304
1305 CaptureFdOut();
1306 err = GetCapturedStderr();
1307 return status;
1308 }
1309
1310 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001311 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001312 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001313 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001314 close(fd);
1315
1316 CaptureFdOut();
1317 err = GetCapturedStderr();
1318 return status;
1319 }
1320
1321 int fd;
1322
1323 // 'fd` output and `stderr` from the last command ran.
1324 std::string out, err;
1325
1326 private:
1327 std::string path_;
1328};
1329
1330TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001331 CreateFd("RunCommandNoArgs.txt");
1332 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001333}
1334
Felipe Lemef0292972016-11-22 13:57:05 -08001335TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001336 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001337 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001338 EXPECT_THAT(out, StrEq("stdout\n"));
1339 EXPECT_THAT(err, StrEq("stderr\n"));
1340}
1341
Felipe Lemef0292972016-11-22 13:57:05 -08001342TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1343 CreateFd("RunCommandWithNoArgs.txt");
1344 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1345 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1346 EXPECT_THAT(err, StrEq("stderr\n"));
1347}
1348
Felipe Leme46b85da2016-11-21 17:40:45 -08001349TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1350 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001351 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001352 EXPECT_THAT(err, IsEmpty());
1353 EXPECT_THAT(out, StrEq("one\n"));
1354}
1355
1356TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1357 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001358 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001359 EXPECT_THAT(err, IsEmpty());
1360 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1361}
1362
1363TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1364 CreateFd("RunCommandWithLoggingMessage.txt");
1365 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001366 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001367 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1368 EXPECT_THAT(out, StrEq("stdout\n"));
1369 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1370}
1371
1372TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1373 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001374 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1375 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001376 EXPECT_THAT(out, IsEmpty());
1377 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1378}
1379
1380TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1381 CreateFd("RunCommandDryRun.txt");
1382 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001383 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1384 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1385 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1386 kSimpleCommand.c_str())));
1387 EXPECT_THAT(err, IsEmpty());
1388}
1389
1390TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1391 CreateFd("RunCommandDryRun.txt");
1392 SetDryRun(true);
1393 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001394 EXPECT_THAT(
1395 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1396 EXPECT_THAT(err, IsEmpty());
1397}
1398
1399TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1400 CreateFd("RunCommandDryRunAlways.txt");
1401 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001402 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001403 EXPECT_THAT(out, StrEq("stdout\n"));
1404 EXPECT_THAT(err, StrEq("stderr\n"));
1405}
1406
1407TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1408 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001409 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001410 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1411 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1412}
1413
1414TEST_F(DumpstateUtilTest, RunCommandFails) {
1415 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001416 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001417 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1418 " --exit 42' failed: exit code 42\n"));
1419 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1420 " --exit 42' failed: exit code 42\n"));
1421}
1422
1423TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1424 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001425 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001426 // We don't know the exit code, so check just the prefix.
1427 EXPECT_THAT(
1428 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1429 EXPECT_THAT(
1430 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1431}
1432
Vishnu Nair6921f802017-11-22 09:17:23 -08001433TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001434 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001435 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1436 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001437 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1438 " --sleep 2' timed out after 1"));
1439 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1440 " --sleep 2' timed out after 1"));
1441}
1442
Vishnu Nair6921f802017-11-22 09:17:23 -08001443TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1444 CreateFd("RunCommandTimesout.txt");
1445 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1446 CommandOptions::WithTimeoutInMs(1000).Build()));
1447 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1448 " --sleep 2' timed out after 1"));
1449 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1450 " --sleep 2' timed out after 1"));
1451}
1452
1453
Felipe Leme46b85da2016-11-21 17:40:45 -08001454TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1455 CreateFd("RunCommandIsKilled.txt");
1456 CaptureStderr();
1457
1458 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001459 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001460 CommandOptions::WithTimeout(100).Always().Build()));
1461 });
1462
1463 // Capture pid and pre-sleep output.
1464 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1465 std::string err = GetCapturedStderr();
1466 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1467
1468 CaptureFdOut();
1469 std::vector<std::string> lines = android::base::Split(out, "\n");
1470 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1471
1472 int pid = atoi(lines[0].c_str());
1473 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1474 EXPECT_THAT(lines[2], IsEmpty()); // \n
1475
1476 // Then kill the process.
1477 CaptureFdOut();
1478 CaptureStderr();
1479 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1480 t.join();
1481
1482 // Finally, check output after murder.
1483 CaptureFdOut();
1484 err = GetCapturedStderr();
1485
1486 // out starts with the pid, which is an unknown
1487 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1488 " --pid --sleep 20' failed: killed by signal 15\n"));
1489 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1490 " --pid --sleep 20' failed: killed by signal 15\n"));
1491}
1492
1493TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1494 if (!IsStandalone()) {
1495 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1496 // to Shell - need to refactor tests to avoid this problem)
1497 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1498 return;
1499 }
1500 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001501 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001502 // Emulates user build if necessarily.
1503 SetBuildType("user");
1504 }
1505
1506 DropRoot();
1507
Felipe Lemef0292972016-11-22 13:57:05 -08001508 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001509
1510 // We don't know the exact path of su, so we just check for the 'root ...' commands
1511 EXPECT_THAT(out, StartsWith("Skipping"));
1512 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1513 EXPECT_THAT(err, IsEmpty());
1514}
1515
1516TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1517 if (!IsStandalone()) {
1518 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1519 // to Shell - need to refactor tests to avoid this problem)
1520 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1521 return;
1522 }
1523 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001524 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001525 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1526 return;
1527 }
1528
1529 DropRoot();
1530
Felipe Lemef0292972016-11-22 13:57:05 -08001531 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1532 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001533
1534 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1535 EXPECT_THAT(err, StrEq("stderr\n"));
1536}
Felipe Leme46b85da2016-11-21 17:40:45 -08001537
Yifan Hong48e83a12017-10-03 14:10:07 -07001538
1539TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1540 if (!IsStandalone()) {
1541 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1542 // to Shell - need to refactor tests to avoid this problem)
1543 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1544 return;
1545 }
1546 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1547 if (!PropertiesHelper::IsUserBuild()) {
1548 // Emulates user build if necessarily.
1549 SetBuildType("user");
1550 }
1551
1552 DropRoot();
1553
1554 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1555 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1556
1557 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1558 EXPECT_THAT(err, StrEq("stderr\n"));
1559}
1560
1561TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1562 if (!IsStandalone()) {
1563 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1564 // to Shell - need to refactor tests to avoid this problem)
1565 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1566 return;
1567 }
1568 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1569 if (PropertiesHelper::IsUserBuild()) {
1570 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1571 return;
1572 }
1573
1574 DropRoot();
1575
1576 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1577 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1578
1579 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1580 EXPECT_THAT(err, StrEq("stderr\n"));
1581}
1582
Felipe Leme46b85da2016-11-21 17:40:45 -08001583TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1584 if (!IsStandalone()) {
1585 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1586 // to Shell - need to refactor tests to avoid this problem)
1587 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1588 return;
1589 }
1590 CreateFd("RunCommandDropRoot.txt");
1591 // First check root case - only available when running with 'adb root'.
1592 uid_t uid = getuid();
1593 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001594 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001595 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1596 EXPECT_THAT(err, StrEq("stderr\n"));
1597 return;
1598 }
1599 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001600 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001601 CommandOptions::WithTimeout(1).DropRoot().Build()));
1602 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1603 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1604}
1605
Felipe Lemef0292972016-11-22 13:57:05 -08001606TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001607 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001608 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001609 EXPECT_THAT(out,
1610 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1611 EXPECT_THAT(err, IsEmpty());
1612}
1613
Felipe Lemef0292972016-11-22 13:57:05 -08001614TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1615 CreateFd("DumpFileNotFound.txt");
1616 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1617 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1618 "file or directory\n"));
1619 EXPECT_THAT(err, IsEmpty());
1620}
1621
Felipe Leme46b85da2016-11-21 17:40:45 -08001622TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1623 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001624 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001625 EXPECT_THAT(err, IsEmpty());
1626 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1627}
1628
1629TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1630 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001631 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001632 EXPECT_THAT(err, IsEmpty());
1633 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1634}
1635
1636TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1637 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001638 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001639 EXPECT_THAT(err, IsEmpty());
1640 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1641}
1642
1643TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1644 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001645 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001646 EXPECT_THAT(err, IsEmpty());
1647 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1648}
1649
Felipe Lemef0292972016-11-22 13:57:05 -08001650TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1651 CreateFd("DumpFileOnDryRun.txt");
1652 SetDryRun(true);
1653 std::string path = kTestDataPath + "single-line.txt";
1654 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1655 EXPECT_THAT(err, IsEmpty());
1656 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1657}
1658
Felipe Leme46b85da2016-11-21 17:40:45 -08001659TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1660 CreateFd("DumpFileOnDryRun.txt");
1661 SetDryRun(true);
1662 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001663 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001664 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001665 EXPECT_THAT(
1666 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1667 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001668}
Ecco Park61ffcf72016-10-27 15:46:26 -07001669
Rhed Jao27077b12020-07-14 18:38:08 +08001670class DumpPoolTest : public DumpstateBaseTest {
1671 public:
1672 void SetUp() {
Rhed Jao1c855122020-07-16 17:37:39 +08001673 dump_pool_ = std::make_unique<DumpPool>(kTestDataPath);
Rhed Jao27077b12020-07-14 18:38:08 +08001674 DumpstateBaseTest::SetUp();
1675 CreateOutputFile();
1676 }
1677
1678 void CreateOutputFile() {
1679 out_path_ = kTestDataPath + "out.txt";
1680 out_fd_.reset(TEMP_FAILURE_RETRY(open(out_path_.c_str(),
1681 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1682 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1683 ASSERT_GE(out_fd_.get(), 0) << "could not create FD for path "
1684 << out_path_;
1685 }
1686
1687 int getTempFileCounts(const std::string& folder) {
1688 int count = 0;
1689 std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
1690 &closedir);
1691 if (!dir_ptr) {
1692 return -1;
1693 }
1694 int dir_fd = dirfd(dir_ptr.get());
1695 if (dir_fd < 0) {
1696 return -1;
1697 }
1698
1699 struct dirent* de;
1700 while ((de = readdir(dir_ptr.get()))) {
1701 if (de->d_type != DT_REG) {
1702 continue;
1703 }
1704 std::string file_name(de->d_name);
1705 if (file_name.find(DumpPool::PREFIX_TMPFILE_NAME) != 0) {
1706 continue;
1707 }
1708 count++;
1709 }
1710 return count;
1711 }
1712
Rhed Jao1c855122020-07-16 17:37:39 +08001713 void setLogDuration(bool log_duration) {
1714 dump_pool_->setLogDuration(log_duration);
1715 }
1716
1717 std::unique_ptr<DumpPool> dump_pool_;
Rhed Jao27077b12020-07-14 18:38:08 +08001718 android::base::unique_fd out_fd_;
1719 std::string out_path_;
1720};
1721
Rhed Jao1c855122020-07-16 17:37:39 +08001722TEST_F(DumpPoolTest, EnqueueTaskWithFd) {
Rhed Jao27077b12020-07-14 18:38:08 +08001723 auto dump_func_1 = [](int out_fd) {
1724 dprintf(out_fd, "A");
1725 };
1726 auto dump_func_2 = [](int out_fd) {
1727 dprintf(out_fd, "B");
1728 sleep(1);
1729 };
1730 auto dump_func_3 = [](int out_fd) {
1731 dprintf(out_fd, "C");
1732 };
Rhed Jao1c855122020-07-16 17:37:39 +08001733 setLogDuration(/* log_duration = */false);
1734 dump_pool_->enqueueTaskWithFd(/* task_name = */"1", dump_func_1, std::placeholders::_1);
1735 dump_pool_->enqueueTaskWithFd(/* task_name = */"2", dump_func_2, std::placeholders::_1);
1736 dump_pool_->enqueueTaskWithFd(/* task_name = */"3", dump_func_3, std::placeholders::_1);
Rhed Jao27077b12020-07-14 18:38:08 +08001737
Rhed Jao1c855122020-07-16 17:37:39 +08001738 dump_pool_->waitForTask("1", "", out_fd_.get());
1739 dump_pool_->waitForTask("2", "", out_fd_.get());
1740 dump_pool_->waitForTask("3", "", out_fd_.get());
1741 dump_pool_->shutdown();
Rhed Jao27077b12020-07-14 18:38:08 +08001742
1743 std::string result;
1744 ReadFileToString(out_path_, &result);
1745 EXPECT_THAT(result, StrEq("A\nB\nC\n"));
1746 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao1c855122020-07-16 17:37:39 +08001747}
1748
1749TEST_F(DumpPoolTest, EnqueueTask_withDurationLog) {
1750 bool run_1 = false;
1751 auto dump_func_1 = [&]() {
1752 run_1 = true;
1753 };
1754
1755 dump_pool_->enqueueTask(/* task_name = */"1", dump_func_1);
1756 dump_pool_->waitForTask("1", "", out_fd_.get());
1757 dump_pool_->shutdown();
1758
1759 std::string result;
1760 ReadFileToString(out_path_, &result);
1761 EXPECT_TRUE(run_1);
1762 EXPECT_THAT(result, StrEq("------ 0.000s was the duration of '1' ------\n"));
1763 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao27077b12020-07-14 18:38:08 +08001764}
1765
Rhed Jao4875aa62020-07-20 17:46:29 +08001766class TaskQueueTest : public DumpstateBaseTest {
1767public:
1768 void SetUp() {
1769 DumpstateBaseTest::SetUp();
1770 }
1771
1772 TaskQueue task_queue_;
1773};
1774
1775TEST_F(TaskQueueTest, runTask) {
1776 bool is_task1_run = false;
1777 bool is_task2_run = false;
1778 auto task_1 = [&](bool task_cancelled) {
1779 if (task_cancelled) {
1780 return;
1781 }
1782 is_task1_run = true;
1783 };
1784 auto task_2 = [&](bool task_cancelled) {
1785 if (task_cancelled) {
1786 return;
1787 }
1788 is_task2_run = true;
1789 };
1790 task_queue_.add(task_1, std::placeholders::_1);
1791 task_queue_.add(task_2, std::placeholders::_1);
1792
1793 task_queue_.run(/* do_cancel = */false);
1794
1795 EXPECT_TRUE(is_task1_run);
1796 EXPECT_TRUE(is_task2_run);
1797}
1798
1799TEST_F(TaskQueueTest, runTask_withCancelled) {
1800 bool is_task1_cancelled = false;
1801 bool is_task2_cancelled = false;
1802 auto task_1 = [&](bool task_cancelled) {
1803 is_task1_cancelled = task_cancelled;
1804 };
1805 auto task_2 = [&](bool task_cancelled) {
1806 is_task2_cancelled = task_cancelled;
1807 };
1808 task_queue_.add(task_1, std::placeholders::_1);
1809 task_queue_.add(task_2, std::placeholders::_1);
1810
1811 task_queue_.run(/* do_cancel = */true);
1812
1813 EXPECT_TRUE(is_task1_cancelled);
1814 EXPECT_TRUE(is_task2_cancelled);
1815}
1816
Rhed Jao27077b12020-07-14 18:38:08 +08001817
Felipe Leme47e9be22016-12-21 15:37:07 -08001818} // namespace dumpstate
1819} // namespace os
1820} // namespace android