blob: 1ffcafa54423f3caf9bd057d2417b3c17b500d88 [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>
Kean Mariotti306633e2022-09-05 16:30:47 +000034#include <filesystem>
Felipe Lemefd8affa2016-09-30 17:38:57 -070035#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070036
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000037#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070038#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070039#include <android-base/properties.h>
40#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070041#include <android-base/strings.h>
Abhijeet Kaure370d682019-10-01 16:49:30 +010042#include <android-base/unique_fd.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080043#include <android/hardware/dumpstate/1.1/types.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080044#include <cutils/log.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080045#include <cutils/properties.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080046#include <ziparchive/zip_archive.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070047
Felipe Leme47e9be22016-12-21 15:37:07 -080048namespace android {
49namespace os {
50namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070051
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000052using DumpstateDeviceAidl = ::aidl::android::hardware::dumpstate::IDumpstateDevice;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080053using ::android::hardware::dumpstate::V1_1::DumpstateMode;
Felipe Leme4c2d6632016-09-28 14:32:00 -070054using ::testing::EndsWith;
Rhed Jao27077b12020-07-14 18:38:08 +080055using ::testing::Eq;
Felipe Leme46b85da2016-11-21 17:40:45 -080056using ::testing::HasSubstr;
Felipe Leme4c2d6632016-09-28 14:32:00 -070057using ::testing::IsEmpty;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080058using ::testing::IsNull;
Felipe Leme009ecbb2016-11-07 10:18:44 -080059using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070060using ::testing::StartsWith;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080061using ::testing::StrEq;
Felipe Leme4c2d6632016-09-28 14:32:00 -070062using ::testing::Test;
63using ::testing::internal::CaptureStderr;
64using ::testing::internal::CaptureStdout;
65using ::testing::internal::GetCapturedStderr;
66using ::testing::internal::GetCapturedStdout;
67
Nandana Dutt3f8c7172018-09-25 12:01:54 +010068#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
69
Felipe Leme75876a22016-10-27 16:31:27 -070070class DumpstateListenerMock : public IDumpstateListener {
71 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000072 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
73 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Nandana Duttcc4ead82019-01-23 08:29:23 +000074 MOCK_METHOD0(onFinished, binder::Status());
Paul Chang0d2aad72020-02-13 20:04:03 +080075 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
Paul Chang5702b482020-05-28 22:05:47 +080076 MOCK_METHOD0(onUiIntensiveBugreportDumpsFinished, binder::Status());
Felipe Leme75876a22016-10-27 16:31:27 -070077
78 protected:
79 MOCK_METHOD0(onAsBinder, IBinder*());
80};
81
Felipe Leme46b85da2016-11-21 17:40:45 -080082static int calls_;
83
Felipe Leme7447d7c2016-11-03 18:12:22 -070084// Base class for all tests in this file
85class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080086 public:
87 virtual void SetUp() override {
88 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080089 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080090 }
91
Felipe Lemef0292972016-11-22 13:57:05 -080092 void SetDryRun(bool dry_run) const {
93 PropertiesHelper::dry_run_ = dry_run;
94 }
95
96 void SetBuildType(const std::string& build_type) const {
97 PropertiesHelper::build_type_ = build_type;
98 }
99
Nandana Dutt4b392be2018-11-02 16:17:05 +0000100 void SetUnroot(bool unroot) const {
101 PropertiesHelper::unroot_ = unroot;
102 }
103
Rhed Jao1c855122020-07-16 17:37:39 +0800104 void SetParallelRun(bool parallel_run) const {
105 PropertiesHelper::parallel_run_ = parallel_run;
106 }
107
Felipe Lemef0292972016-11-22 13:57:05 -0800108 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -0800109 return calls_ == 1;
110 }
111
Felipe Lemef0292972016-11-22 13:57:05 -0800112 void DropRoot() const {
113 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -0800114 uid_t uid = getuid();
115 ASSERT_EQ(2000, (int)uid);
116 }
117
Felipe Leme7447d7c2016-11-03 18:12:22 -0700118 protected:
119 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700120 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
121 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700122 const std::string kEchoCommand = "/system/bin/echo";
123
124 /*
125 * Copies a text file fixture to a temporary file, returning it's path.
126 *
127 * Useful in cases where the test case changes the content of the tile.
128 */
129 std::string CopyTextFileFixture(const std::string& relative_name) {
130 std::string from = kTestDataPath + relative_name;
131 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
132 // around for poking when the test fails.
133 std::string to = kTestDataPath + relative_name + ".tmp";
134 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
135 android::base::RemoveFileIfExists(to);
136 CopyTextFile(from, to);
137 return to.c_str();
138 }
139
Felipe Leme46b85da2016-11-21 17:40:45 -0800140 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700141 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800142 void ReadFileToString(const std::string& path, std::string* content) {
143 ASSERT_TRUE(android::base::ReadFileToString(path, content))
144 << "could not read contents from " << path;
145 }
146 void WriteStringToFile(const std::string& content, const std::string& path) {
147 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
148 << "could not write contents to " << path;
149 }
150
151 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700152 void CopyTextFile(const std::string& from, const std::string& to) {
153 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800154 ReadFileToString(from, &content);
155 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700156 }
157};
158
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100159class DumpOptionsTest : public Test {
160 public:
161 virtual ~DumpOptionsTest() {
162 }
163 virtual void SetUp() {
164 options_ = Dumpstate::DumpOptions();
165 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000166 void TearDown() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000167 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100168 Dumpstate::DumpOptions options_;
Abhijeet Kaure370d682019-10-01 16:49:30 +0100169 android::base::unique_fd fd;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100170};
171
172TEST_F(DumpOptionsTest, InitializeNone) {
173 // clang-format off
174 char* argv[] = {
175 const_cast<char*>("dumpstate")
176 };
177 // clang-format on
178
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100179 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
180
181 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000182
mhasank3a4cfb42020-06-15 18:06:43 -0700183 EXPECT_EQ("", options_.out_dir);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800184 EXPECT_FALSE(options_.stream_to_socket);
185 EXPECT_FALSE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100186 EXPECT_FALSE(options_.show_header_only);
187 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800188 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100189 EXPECT_FALSE(options_.do_progress_updates);
190 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700191 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000192}
193
194TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
195 // clang-format off
196 char* argv[] = {
197 const_cast<char*>("dumpstatez"),
198 const_cast<char*>("-S"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000199 };
200 // clang-format on
201
202 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
203
204 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800205 EXPECT_TRUE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000206
207 // Other options retain default values
208 EXPECT_TRUE(options_.do_vibrate);
209 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800210 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000211 EXPECT_FALSE(options_.do_progress_updates);
212 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800213 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700214 EXPECT_FALSE(options_.limited_only);
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);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000238}
239
240TEST_F(DumpOptionsTest, InitializeFullBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000241 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800242 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000243
244 // Other options retain default values
245 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800246 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000247 EXPECT_FALSE(options_.show_header_only);
248 EXPECT_FALSE(options_.do_progress_updates);
249 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800250 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700251 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000252}
253
254TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000255 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000256 EXPECT_TRUE(options_.do_progress_updates);
Paul Chang0d2aad72020-02-13 20:04:03 +0800257 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000258
259 // Other options retain default values
260 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800261 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000262 EXPECT_FALSE(options_.show_header_only);
263 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800264 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700265 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000266}
267
268TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000269 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000270 EXPECT_TRUE(options_.is_remote_mode);
271 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800272 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000273
274 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800275 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000276 EXPECT_FALSE(options_.show_header_only);
277 EXPECT_FALSE(options_.do_progress_updates);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800278 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700279 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000280}
281
282TEST_F(DumpOptionsTest, InitializeWearBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000283 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800284 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000285 EXPECT_TRUE(options_.do_progress_updates);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000286
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000287
288 // Other options retain default values
289 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800290 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000291 EXPECT_FALSE(options_.show_header_only);
292 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800293 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700294 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000295}
296
297TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000298 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800299 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000300 EXPECT_TRUE(options_.telephony_only);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800301 EXPECT_TRUE(options_.do_progress_updates);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000302
303 // Other options retain default values
304 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800305 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000306 EXPECT_FALSE(options_.show_header_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000307 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800308 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700309 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000310}
311
312TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000313 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800314 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000315 EXPECT_TRUE(options_.wifi_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000316
317 // Other options retain default values
318 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800319 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000320 EXPECT_FALSE(options_.show_header_only);
321 EXPECT_FALSE(options_.do_progress_updates);
322 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800323 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700324 EXPECT_FALSE(options_.limited_only);
325}
326
327TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
328 // clang-format off
329 char* argv[] = {
330 const_cast<char*>("dumpstatez"),
331 const_cast<char*>("-S"),
mhasankd451a472020-05-26 18:02:39 -0700332 const_cast<char*>("-q"),
mhasank2d75c442020-06-11 15:05:25 -0700333 const_cast<char*>("-L"),
334 const_cast<char*>("-o abc")
mhasankd451a472020-05-26 18:02:39 -0700335 };
336 // clang-format on
337
338 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
339
340 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800341 EXPECT_TRUE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700342 EXPECT_FALSE(options_.do_vibrate);
343 EXPECT_TRUE(options_.limited_only);
mhasank3a4cfb42020-06-15 18:06:43 -0700344 EXPECT_EQ(" abc", std::string(options_.out_dir));
mhasankd451a472020-05-26 18:02:39 -0700345
346 // Other options retain default values
347 EXPECT_FALSE(options_.show_header_only);
348 EXPECT_FALSE(options_.do_screenshot);
349 EXPECT_FALSE(options_.do_progress_updates);
350 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800351 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000352}
353
354TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
355 // default: commandline options are not overridden
356 // clang-format off
357 char* argv[] = {
358 const_cast<char*>("bugreport"),
359 const_cast<char*>("-d"),
360 const_cast<char*>("-p"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000361 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000362 };
363 // clang-format on
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000364 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
365
366 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Paul Chang0d2aad72020-02-13 20:04:03 +0800367 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000368
369 // Other options retain default values
370 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800371 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000372 EXPECT_FALSE(options_.show_header_only);
373 EXPECT_FALSE(options_.do_progress_updates);
374 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800375 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000376 EXPECT_FALSE(options_.wifi_only);
mhasankd451a472020-05-26 18:02:39 -0700377 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100378}
379
380TEST_F(DumpOptionsTest, InitializePartial1) {
381 // clang-format off
382 char* argv[] = {
383 const_cast<char*>("dumpstate"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100384 const_cast<char*>("-s"),
385 const_cast<char*>("-S"),
386
387 };
388 // clang-format on
389
390 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
391
392 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100393 // TODO: Maybe we should trim the filename
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800394 EXPECT_TRUE(options_.stream_to_socket);
395 EXPECT_TRUE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100396
397 // Other options retain default values
398 EXPECT_FALSE(options_.show_header_only);
399 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800400 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100401 EXPECT_FALSE(options_.do_progress_updates);
402 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700403 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100404}
405
406TEST_F(DumpOptionsTest, InitializePartial2) {
407 // clang-format off
408 char* argv[] = {
409 const_cast<char*>("dumpstate"),
410 const_cast<char*>("-v"),
411 const_cast<char*>("-q"),
412 const_cast<char*>("-p"),
413 const_cast<char*>("-P"),
414 const_cast<char*>("-R"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100415 };
416 // clang-format on
417
418 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
419
420 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
421 EXPECT_TRUE(options_.show_header_only);
422 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800423 EXPECT_TRUE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100424 EXPECT_TRUE(options_.do_progress_updates);
425 EXPECT_TRUE(options_.is_remote_mode);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100426
427 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800428 EXPECT_FALSE(options_.stream_to_socket);
429 EXPECT_FALSE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700430 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100431}
432
433TEST_F(DumpOptionsTest, InitializeHelp) {
434 // clang-format off
435 char* argv[] = {
436 const_cast<char*>("dumpstate"),
437 const_cast<char*>("-h")
438 };
439 // clang-format on
440
441 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
442
443 // -h is for help.
444 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
445}
446
447TEST_F(DumpOptionsTest, InitializeUnknown) {
448 // clang-format off
449 char* argv[] = {
450 const_cast<char*>("dumpstate"),
451 const_cast<char*>("-u") // unknown flag
452 };
453 // clang-format on
454
455 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
456
457 // -u is unknown.
458 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
459}
460
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800461TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage1) {
462 options_.progress_updates_to_socket = true;
463 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100464 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000465
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800466 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100467 EXPECT_TRUE(options_.ValidateOptions());
468}
469
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800470TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage2) {
Abhijeet Kaure370d682019-10-01 16:49:30 +0100471 options_.do_progress_updates = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000472 // Writing to socket = !writing to file.
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800473 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
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100480TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800481 options_.do_progress_updates = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100482 options_.is_remote_mode = true;
483 EXPECT_FALSE(options_.ValidateOptions());
484
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800485 options_.do_progress_updates = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100486 EXPECT_TRUE(options_.ValidateOptions());
487}
488
Felipe Leme7447d7c2016-11-03 18:12:22 -0700489class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700490 public:
491 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800492 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700493 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700494 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700495 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100496 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700497 }
498
Rhed Jao1c855122020-07-16 17:37:39 +0800499 void TearDown() {
500 ds.ShutdownDumpPool();
501 }
502
Felipe Leme4c2d6632016-09-28 14:32:00 -0700503 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700504 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700505 const CommandOptions& options = CommandOptions::DEFAULT) {
506 CaptureStdout();
507 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700508 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700509 out = GetCapturedStdout();
510 err = GetCapturedStderr();
511 return status;
512 }
513
Felipe Lemecef02982016-10-03 17:22:22 -0700514 // Dumps a file and capture `stdout` and `stderr`.
515 int DumpFile(const std::string& title, const std::string& path) {
516 CaptureStdout();
517 CaptureStderr();
518 int status = ds.DumpFile(title, path);
519 out = GetCapturedStdout();
520 err = GetCapturedStderr();
521 return status;
522 }
523
Nandana Dutt402a8392019-06-14 14:25:13 +0100524 void SetProgress(long progress, long initial_max) {
525 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100526 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700527 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
528 }
529
Rhed Jao1c855122020-07-16 17:37:39 +0800530 void EnableParallelRunIfNeeded() {
531 ds.EnableParallelRunIfNeeded();
532 }
533
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100534 std::string GetProgressMessage(int progress, int max,
535 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700536 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
537 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700538
Felipe Leme7447d7c2016-11-03 18:12:22 -0700539 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700540
Felipe Leme009ecbb2016-11-07 10:18:44 -0800541 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700542 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800543 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700544 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700545 }
546
Felipe Leme009ecbb2016-11-07 10:18:44 -0800547 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100548 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
549 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800550 }
551
552 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700553 }
554
Felipe Leme4c2d6632016-09-28 14:32:00 -0700555 // `stdout` and `stderr` from the last command ran.
556 std::string out, err;
557
Felipe Lemefd8affa2016-09-30 17:38:57 -0700558 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700559};
560
561TEST_F(DumpstateTest, RunCommandNoArgs) {
562 EXPECT_EQ(-1, RunCommand("", {}));
563}
564
565TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700566 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700567 EXPECT_THAT(out, StrEq("stdout\n"));
568 EXPECT_THAT(err, StrEq("stderr\n"));
569}
570
571TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700572 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700573 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700574 // The duration may not get output, depending on how long it takes,
575 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700576 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000577 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700578}
579
Felipe Lemefd8affa2016-09-30 17:38:57 -0700580TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700581 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700582 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700583 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
584 EXPECT_THAT(out, StrEq("stdout\n"));
585 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
586}
587
588TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700589 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700590 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700591 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700592 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700593}
594
595TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700596 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700597 EXPECT_THAT(err, IsEmpty());
598 EXPECT_THAT(out, StrEq("one\n"));
599}
600
Felipe Lemefd8affa2016-09-30 17:38:57 -0700601TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700602 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700603 EXPECT_THAT(err, IsEmpty());
604 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
605}
606
607TEST_F(DumpstateTest, RunCommandDryRun) {
608 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700609 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700610 // The duration may not get output, depending on how long it takes,
611 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700612 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000613 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700614 EXPECT_THAT(err, IsEmpty());
615}
616
617TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
618 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700619 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700620 EXPECT_THAT(out, IsEmpty());
621 EXPECT_THAT(err, IsEmpty());
622}
623
624TEST_F(DumpstateTest, RunCommandDryRunAlways) {
625 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700626 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700627 EXPECT_THAT(out, StrEq("stdout\n"));
628 EXPECT_THAT(err, StrEq("stderr\n"));
629}
630
Felipe Lemefd8affa2016-09-30 17:38:57 -0700631TEST_F(DumpstateTest, RunCommandNotFound) {
632 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
633 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
634 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
635}
636
637TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700638 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
639 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700640 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700641 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700642 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700643}
644
645TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700646 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700647 // We don't know the exit code, so check just the prefix.
648 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700649 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700650 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700651 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700652}
653
654TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700655 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700656 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700657 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700658 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700659 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700660 " --sleep 2' timed out after 1"));
661}
662
663TEST_F(DumpstateTest, RunCommandIsKilled) {
664 CaptureStdout();
665 CaptureStderr();
666
667 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700668 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700669 CommandOptions::WithTimeout(100).Always().Build()));
670 });
671
672 // Capture pid and pre-sleep output.
673 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
674 std::string err = GetCapturedStderr();
675 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
676
677 std::string out = GetCapturedStdout();
678 std::vector<std::string> lines = android::base::Split(out, "\n");
679 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
680
681 int pid = atoi(lines[0].c_str());
682 EXPECT_THAT(lines[1], StrEq("stdout line1"));
683 EXPECT_THAT(lines[2], IsEmpty()); // \n
684
685 // Then kill the process.
686 CaptureStdout();
687 CaptureStderr();
688 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
689 t.join();
690
691 // Finally, check output after murder.
692 out = GetCapturedStdout();
693 err = GetCapturedStderr();
694
Felipe Leme7447d7c2016-11-03 18:12:22 -0700695 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700696 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700697 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700698 " --pid --sleep 20' failed: killed by signal 15\n"));
699}
700
Felipe Leme75876a22016-10-27 16:31:27 -0700701TEST_F(DumpstateTest, RunCommandProgress) {
702 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
703 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700704 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700705
Nandana Duttbabf6c72019-01-15 14:11:12 +0000706 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700707 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100708 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700709 EXPECT_THAT(out, StrEq("stdout\n"));
710 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
711
Nandana Dutt402a8392019-06-14 14:25:13 +0100712 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
713 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100714 progress_message = GetProgressMessage(24, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700715 EXPECT_THAT(out, StrEq("stdout\n"));
716 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
717
718 // Make sure command ran while in dry_run is counted.
719 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100720 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
721 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100722 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700723 EXPECT_THAT(out, IsEmpty());
724 EXPECT_THAT(err, StrEq(progress_message));
725
Nandana Dutt402a8392019-06-14 14:25:13 +0100726 SetDryRun(false);
727 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
728 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100729 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800730 EXPECT_THAT(out, StrEq("stdout\n"));
731 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
732
Nandana Dutt402a8392019-06-14 14:25:13 +0100733 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800734 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100735 progress_message = GetProgressMessage(30, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800736 EXPECT_THAT(out, StrEq("stdout\n"));
737 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
738
739 ds.listener_.clear();
740}
741
Felipe Lemed80e6b62016-10-03 13:08:14 -0700742TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800743 if (!IsStandalone()) {
744 // TODO: temporarily disabled because it might cause other tests to fail after dropping
745 // to Shell - need to refactor tests to avoid this problem)
746 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
747 return;
748 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700749 // First check root case - only available when running with 'adb root'.
750 uid_t uid = getuid();
751 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700752 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700753 EXPECT_THAT(out, StrEq("0\nstdout\n"));
754 EXPECT_THAT(err, StrEq("stderr\n"));
755 return;
756 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700757 // Then run dropping root.
758 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700759 CommandOptions::WithTimeout(1).DropRoot().Build()));
760 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700761 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700762}
763
764TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800765 if (!IsStandalone()) {
766 // TODO: temporarily disabled because it might cause other tests to fail after dropping
767 // to Shell - need to refactor tests to avoid this problem)
768 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
769 return;
770 }
Felipe Lemef0292972016-11-22 13:57:05 -0800771 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700772 // Emulates user build if necessarily.
773 SetBuildType("user");
774 }
775
776 DropRoot();
777
Felipe Leme7447d7c2016-11-03 18:12:22 -0700778 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700779
780 // We don't know the exact path of su, so we just check for the 'root ...' commands
781 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700782 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700783 EXPECT_THAT(err, IsEmpty());
784}
785
Felipe Leme46b85da2016-11-21 17:40:45 -0800786TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
787 if (!IsStandalone()) {
788 // TODO: temporarily disabled because it might cause other tests to fail after dropping
789 // to Shell - need to refactor tests to avoid this problem)
790 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
791 return;
792 }
Felipe Lemef0292972016-11-22 13:57:05 -0800793 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800794 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
795 return;
796 }
797
798 DropRoot();
799
800 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
801 CommandOptions::WithTimeout(1).AsRoot().Build()));
802
803 EXPECT_THAT(out, StrEq("0\nstdout\n"));
804 EXPECT_THAT(err, StrEq("stderr\n"));
805}
806
Nandana Dutt4b392be2018-11-02 16:17:05 +0000807TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
808 if (!IsStandalone()) {
809 // TODO: temporarily disabled because it might cause other tests to fail after dropping
810 // to Shell - need to refactor tests to avoid this problem)
811 MYLOGE(
812 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
813 "on test suite\n")
814 return;
815 }
816 if (PropertiesHelper::IsUserBuild()) {
817 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
818 return;
819 }
820
821 // Same test as above, but with unroot property set, which will override su availability.
822 SetUnroot(true);
823 DropRoot();
824
825 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
826 CommandOptions::WithTimeout(1).AsRoot().Build()));
827
828 // AsRoot is ineffective.
829 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
830 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
831}
832
Yifan Hong48e83a12017-10-03 14:10:07 -0700833TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
834 if (!IsStandalone()) {
835 // TODO: temporarily disabled because it might cause other tests to fail after dropping
836 // to Shell - need to refactor tests to avoid this problem)
837 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
838 return;
839 }
840 if (!PropertiesHelper::IsUserBuild()) {
841 // Emulates user build if necessarily.
842 SetBuildType("user");
843 }
844
845 DropRoot();
846
847 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
848 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
849
850 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
851 EXPECT_THAT(err, StrEq("stderr\n"));
852}
853
854TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
855 if (!IsStandalone()) {
856 // TODO: temporarily disabled because it might cause other tests to fail after dropping
857 // to Shell - need to refactor tests to avoid this problem)
858 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
859 return;
860 }
861 if (PropertiesHelper::IsUserBuild()) {
862 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
863 return;
864 }
865
866 DropRoot();
867
868 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
869 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
870
871 EXPECT_THAT(out, StrEq("0\nstdout\n"));
872 EXPECT_THAT(err, StrEq("stderr\n"));
873}
874
Nandana Dutt4b392be2018-11-02 16:17:05 +0000875TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
876 if (!IsStandalone()) {
877 // TODO: temporarily disabled because it might cause other tests to fail after dropping
878 // to Shell - need to refactor tests to avoid this problem)
879 MYLOGE(
880 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
881 "on test suite\n")
882 return;
883 }
884 if (PropertiesHelper::IsUserBuild()) {
885 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
886 return;
887 }
888 // Same test as above, but with unroot property set, which will override su availability.
889 SetUnroot(true);
890
891 DropRoot();
892
893 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
894 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
895
896 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
897 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
898 EXPECT_THAT(err, StrEq("stderr\n"));
899}
900
Felipe Lemecef02982016-10-03 17:22:22 -0700901TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
902 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
903 EXPECT_THAT(out,
904 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
905 EXPECT_THAT(err, IsEmpty());
906}
907
908TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
909 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
910 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700911 // The duration may not get output, depending on how long it takes,
912 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700913 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
914 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700915}
916
917TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700918 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700919 EXPECT_THAT(err, IsEmpty());
920 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
921}
922
923TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700924 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700925 EXPECT_THAT(err, IsEmpty());
926 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
927}
928
929TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700930 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700931 EXPECT_THAT(err, IsEmpty());
932 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
933}
934
935TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700936 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700937 EXPECT_THAT(err, IsEmpty());
938 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
939}
940
941TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
942 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700943 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700944 EXPECT_THAT(err, IsEmpty());
945 EXPECT_THAT(out, IsEmpty());
946}
947
948TEST_F(DumpstateTest, DumpFileOnDryRun) {
949 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700950 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700951 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800952 EXPECT_THAT(
953 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +0000954 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700955}
956
Felipe Leme75876a22016-10-27 16:31:27 -0700957TEST_F(DumpstateTest, DumpFileUpdateProgress) {
958 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
959 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700960 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700961
Nandana Duttbabf6c72019-01-15 14:11:12 +0000962 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700963 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700964
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100965 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -0700966 EXPECT_THAT(err, StrEq(progress_message));
967 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
968
969 ds.listener_.clear();
970}
971
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800972TEST_F(DumpstateTest, DumpPool_withParallelRunEnabled_notNull) {
Rhed Jao1c855122020-07-16 17:37:39 +0800973 SetParallelRun(true);
974 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800975 EXPECT_TRUE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800976 EXPECT_TRUE(ds.dump_pool_);
977}
978
Rhed Jao1c855122020-07-16 17:37:39 +0800979TEST_F(DumpstateTest, DumpPool_withParallelRunDisabled_isNull) {
980 SetParallelRun(false);
981 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800982 EXPECT_FALSE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800983 EXPECT_FALSE(ds.dump_pool_);
984}
985
Kean Mariotti306633e2022-09-05 16:30:47 +0000986TEST_F(DumpstateBaseTest, PreDumpUiData) {
987 // SurfaceFlinger's transactions trace is always enabled, i.e. it is always pre-dumped
988 static const auto kTransactionsTrace =
989 std::filesystem::path {"/data/misc/wmtrace/transactions_trace.winscope"};
990
991 std::system(("rm " + kTransactionsTrace.string()).c_str());
992 EXPECT_FALSE(std::filesystem::exists(kTransactionsTrace));
993
994 Dumpstate& ds_ = Dumpstate::GetInstance();
995 ds_.PreDumpUiData();
996 EXPECT_TRUE(std::filesystem::exists(kTransactionsTrace));
997}
998
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800999class ZippedBugReportStreamTest : public DumpstateBaseTest {
1000 public:
1001 void SetUp() {
1002 DumpstateBaseTest::SetUp();
1003 ds_.options_.reset(new Dumpstate::DumpOptions());
1004 }
1005 void TearDown() {
1006 CloseArchive(handle_);
1007 }
1008
1009 // Set bugreport mode and options before here.
1010 void GenerateBugreport() {
1011 ds_.Initialize();
1012 EXPECT_EQ(Dumpstate::RunStatus::OK, ds_.Run(/*calling_uid=*/-1, /*calling_package=*/""));
1013 }
1014
1015 // Most bugreports droproot, ensure the file can be opened by shell to verify file content.
1016 void CreateFd(const std::string& path, android::base::unique_fd* out_fd) {
1017 out_fd->reset(TEMP_FAILURE_RETRY(open(path.c_str(),
1018 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1019 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1020 ASSERT_GE(out_fd->get(), 0) << "could not create FD for path " << path;
1021 }
1022
1023 void VerifyEntry(const ZipArchiveHandle archive, const std::string_view entry_name,
1024 ZipEntry* data) {
1025 int32_t e = FindEntry(archive, entry_name, data);
1026 EXPECT_EQ(0, e) << ErrorCodeString(e) << " entry name: " << entry_name;
1027 }
1028
1029 // While testing dumpstate in process, using STDOUT may get confused about
1030 // the internal fd redirection. Redirect to a dedicate fd to save content.
1031 void RedirectOutputToFd(android::base::unique_fd& ufd) {
1032 ds_.open_socket_fn_ = [&](const char*) -> int { return ufd.release(); };
1033 };
1034
1035 Dumpstate& ds_ = Dumpstate::GetInstance();
1036 ZipArchiveHandle handle_;
1037};
1038
Rhed Jaob8b56172021-04-08 20:14:27 +08001039// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
1040TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
1041 std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001042 android::base::unique_fd out_fd;
1043 CreateFd(out_path, &out_fd);
Rhed Jaob8b56172021-04-08 20:14:27 +08001044 ds_.options_->limited_only = true;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001045 ds_.options_->stream_to_socket = true;
1046 RedirectOutputToFd(out_fd);
1047
1048 GenerateBugreport();
1049 OpenArchive(out_path.c_str(), &handle_);
1050
1051 ZipEntry entry;
1052 VerifyEntry(handle_, "main_entry.txt", &entry);
1053 std::string bugreport_txt_name;
1054 bugreport_txt_name.resize(entry.uncompressed_length);
1055 ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
1056 entry.uncompressed_length);
1057 EXPECT_THAT(bugreport_txt_name,
Rhed Jaob8b56172021-04-08 20:14:27 +08001058 testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001059 VerifyEntry(handle_, bugreport_txt_name, &entry);
1060}
1061
Felipe Leme7447d7c2016-11-03 18:12:22 -07001062class ProgressTest : public DumpstateBaseTest {
1063 public:
1064 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1065 return Progress(max, growth_factor, path);
1066 }
1067
1068 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1069 std::string expected_content =
1070 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1071 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001072 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001073 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1074 }
1075};
1076
1077TEST_F(ProgressTest, SimpleTest) {
1078 Progress progress;
1079 EXPECT_EQ(0, progress.Get());
1080 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1081 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1082
1083 bool max_increased = progress.Inc(1);
1084 EXPECT_EQ(1, progress.Get());
1085 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1086 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1087 EXPECT_FALSE(max_increased);
1088
1089 // Ignore negative increase.
1090 max_increased = progress.Inc(-1);
1091 EXPECT_EQ(1, progress.Get());
1092 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1093 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1094 EXPECT_FALSE(max_increased);
1095}
1096
1097TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1098 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1099 EXPECT_EQ(0, progress.Get());
1100 EXPECT_EQ(10, progress.GetInitialMax());
1101 EXPECT_EQ(10, progress.GetMax());
1102
1103 // No increase
1104 bool max_increased = progress.Inc(10);
1105 EXPECT_EQ(10, progress.Get());
1106 EXPECT_EQ(10, progress.GetMax());
1107 EXPECT_FALSE(max_increased);
1108
1109 // Increase, with new value < max*20%
1110 max_increased = progress.Inc(1);
1111 EXPECT_EQ(11, progress.Get());
1112 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1113 EXPECT_TRUE(max_increased);
1114}
1115
1116TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1117 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1118 EXPECT_EQ(0, progress.Get());
1119 EXPECT_EQ(10, progress.GetInitialMax());
1120 EXPECT_EQ(10, progress.GetMax());
1121
1122 // No increase
1123 bool max_increased = progress.Inc(10);
1124 EXPECT_EQ(10, progress.Get());
1125 EXPECT_EQ(10, progress.GetMax());
1126 EXPECT_FALSE(max_increased);
1127
1128 // Increase, with new value > max*20%
1129 max_increased = progress.Inc(5);
1130 EXPECT_EQ(15, progress.Get());
1131 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1132 EXPECT_TRUE(max_increased);
1133}
1134
1135TEST_F(ProgressTest, InvalidPath) {
1136 Progress progress("/devil/null");
1137 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1138}
1139
1140TEST_F(ProgressTest, EmptyFile) {
1141 Progress progress(CopyTextFileFixture("empty-file.txt"));
1142 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1143}
1144
1145TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1146 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1147 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1148}
1149
1150TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1151 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1152 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1153}
1154
1155TEST_F(ProgressTest, InvalidLineBothNAN) {
1156 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1157 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1158}
1159
1160TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1161 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1162 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1163}
1164
1165TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1166 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1167 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1168}
1169
1170TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1171 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1172 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1173}
1174
1175TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1176 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1177 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1178}
1179
1180// Tests stats are properly saved when the file does not exists.
1181TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001182 if (!IsStandalone()) {
1183 // TODO: temporarily disabled because it's failing when running as suite
1184 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1185 return;
1186 }
1187
Felipe Leme7447d7c2016-11-03 18:12:22 -07001188 std::string path = kTestDataPath + "FirstTime.txt";
1189 android::base::RemoveFileIfExists(path);
1190
1191 Progress run1(path);
1192 EXPECT_EQ(0, run1.Get());
1193 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1194 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1195
1196 bool max_increased = run1.Inc(20);
1197 EXPECT_EQ(20, run1.Get());
1198 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1199 EXPECT_FALSE(max_increased);
1200
1201 run1.Save();
1202 AssertStats(path, 1, 20);
1203}
1204
1205// Tests what happens when the persistent settings contains the average duration of 1 run.
1206// Data on file is 1 run and 109 average.
1207TEST_F(ProgressTest, SecondTime) {
1208 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1209
1210 Progress run1 = GetInstance(-42, 1.2, path);
1211 EXPECT_EQ(0, run1.Get());
1212 EXPECT_EQ(10, run1.GetInitialMax());
1213 EXPECT_EQ(10, run1.GetMax());
1214
1215 bool max_increased = run1.Inc(20);
1216 EXPECT_EQ(20, run1.Get());
1217 EXPECT_EQ(24, run1.GetMax());
1218 EXPECT_TRUE(max_increased);
1219
1220 // Average now is 2 runs and (10 + 20)/ 2 = 15
1221 run1.Save();
1222 AssertStats(path, 2, 15);
1223
1224 Progress run2 = GetInstance(-42, 1.2, path);
1225 EXPECT_EQ(0, run2.Get());
1226 EXPECT_EQ(15, run2.GetInitialMax());
1227 EXPECT_EQ(15, run2.GetMax());
1228
1229 max_increased = run2.Inc(25);
1230 EXPECT_EQ(25, run2.Get());
1231 EXPECT_EQ(30, run2.GetMax());
1232 EXPECT_TRUE(max_increased);
1233
1234 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1235 run2.Save();
1236 AssertStats(path, 3, 18);
1237
1238 Progress run3 = GetInstance(-42, 1.2, path);
1239 EXPECT_EQ(0, run3.Get());
1240 EXPECT_EQ(18, run3.GetInitialMax());
1241 EXPECT_EQ(18, run3.GetMax());
1242
1243 // Make sure average decreases as well
1244 max_increased = run3.Inc(5);
1245 EXPECT_EQ(5, run3.Get());
1246 EXPECT_EQ(18, run3.GetMax());
1247 EXPECT_FALSE(max_increased);
1248
1249 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1250 run3.Save();
1251 AssertStats(path, 4, 14);
1252}
1253
1254// Tests what happens when the persistent settings contains the average duration of 2 runs.
1255// Data on file is 2 runs and 15 average.
1256TEST_F(ProgressTest, ThirdTime) {
1257 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1258 AssertStats(path, 2, 15); // Sanity check
1259
1260 Progress run1 = GetInstance(-42, 1.2, path);
1261 EXPECT_EQ(0, run1.Get());
1262 EXPECT_EQ(15, run1.GetInitialMax());
1263 EXPECT_EQ(15, run1.GetMax());
1264
1265 bool max_increased = run1.Inc(20);
1266 EXPECT_EQ(20, run1.Get());
1267 EXPECT_EQ(24, run1.GetMax());
1268 EXPECT_TRUE(max_increased);
1269
1270 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1271 run1.Save();
1272 AssertStats(path, 3, 16);
1273}
1274
Felipe Leme46b85da2016-11-21 17:40:45 -08001275class DumpstateUtilTest : public DumpstateBaseTest {
1276 public:
1277 void SetUp() {
1278 DumpstateBaseTest::SetUp();
1279 SetDryRun(false);
1280 }
1281
Felipe Leme46b85da2016-11-21 17:40:45 -08001282 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001283 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001284 }
1285
1286 void CreateFd(const std::string& name) {
1287 path_ = kTestDataPath + name;
1288 MYLOGD("Creating fd for file %s\n", path_.c_str());
1289
1290 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1291 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1293 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1294 }
1295
1296 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001297 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001298 const CommandOptions& options = CommandOptions::DEFAULT) {
1299 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001300 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001301 close(fd);
1302
1303 CaptureFdOut();
1304 err = GetCapturedStderr();
1305 return status;
1306 }
1307
1308 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001309 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001310 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001311 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001312 close(fd);
1313
1314 CaptureFdOut();
1315 err = GetCapturedStderr();
1316 return status;
1317 }
1318
1319 int fd;
1320
1321 // 'fd` output and `stderr` from the last command ran.
1322 std::string out, err;
1323
1324 private:
1325 std::string path_;
1326};
1327
1328TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001329 CreateFd("RunCommandNoArgs.txt");
1330 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001331}
1332
Felipe Lemef0292972016-11-22 13:57:05 -08001333TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001334 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001335 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001336 EXPECT_THAT(out, StrEq("stdout\n"));
1337 EXPECT_THAT(err, StrEq("stderr\n"));
1338}
1339
Felipe Lemef0292972016-11-22 13:57:05 -08001340TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1341 CreateFd("RunCommandWithNoArgs.txt");
1342 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1343 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1344 EXPECT_THAT(err, StrEq("stderr\n"));
1345}
1346
Felipe Leme46b85da2016-11-21 17:40:45 -08001347TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1348 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001349 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001350 EXPECT_THAT(err, IsEmpty());
1351 EXPECT_THAT(out, StrEq("one\n"));
1352}
1353
1354TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1355 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001356 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001357 EXPECT_THAT(err, IsEmpty());
1358 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1359}
1360
1361TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1362 CreateFd("RunCommandWithLoggingMessage.txt");
1363 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001364 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001365 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1366 EXPECT_THAT(out, StrEq("stdout\n"));
1367 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1368}
1369
1370TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1371 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001372 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1373 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001374 EXPECT_THAT(out, IsEmpty());
1375 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1376}
1377
1378TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1379 CreateFd("RunCommandDryRun.txt");
1380 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001381 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1382 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1383 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1384 kSimpleCommand.c_str())));
1385 EXPECT_THAT(err, IsEmpty());
1386}
1387
1388TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1389 CreateFd("RunCommandDryRun.txt");
1390 SetDryRun(true);
1391 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001392 EXPECT_THAT(
1393 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1394 EXPECT_THAT(err, IsEmpty());
1395}
1396
1397TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1398 CreateFd("RunCommandDryRunAlways.txt");
1399 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001400 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001401 EXPECT_THAT(out, StrEq("stdout\n"));
1402 EXPECT_THAT(err, StrEq("stderr\n"));
1403}
1404
1405TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1406 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001407 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001408 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1409 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1410}
1411
1412TEST_F(DumpstateUtilTest, RunCommandFails) {
1413 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001414 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001415 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1416 " --exit 42' failed: exit code 42\n"));
1417 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1418 " --exit 42' failed: exit code 42\n"));
1419}
1420
1421TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1422 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001423 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001424 // We don't know the exit code, so check just the prefix.
1425 EXPECT_THAT(
1426 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1427 EXPECT_THAT(
1428 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1429}
1430
Vishnu Nair6921f802017-11-22 09:17:23 -08001431TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001432 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001433 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1434 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001435 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1436 " --sleep 2' timed out after 1"));
1437 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1438 " --sleep 2' timed out after 1"));
1439}
1440
Vishnu Nair6921f802017-11-22 09:17:23 -08001441TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1442 CreateFd("RunCommandTimesout.txt");
1443 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1444 CommandOptions::WithTimeoutInMs(1000).Build()));
1445 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1446 " --sleep 2' timed out after 1"));
1447 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1448 " --sleep 2' timed out after 1"));
1449}
1450
1451
Felipe Leme46b85da2016-11-21 17:40:45 -08001452TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1453 CreateFd("RunCommandIsKilled.txt");
1454 CaptureStderr();
1455
1456 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001457 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001458 CommandOptions::WithTimeout(100).Always().Build()));
1459 });
1460
1461 // Capture pid and pre-sleep output.
1462 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1463 std::string err = GetCapturedStderr();
1464 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1465
1466 CaptureFdOut();
1467 std::vector<std::string> lines = android::base::Split(out, "\n");
1468 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1469
1470 int pid = atoi(lines[0].c_str());
1471 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1472 EXPECT_THAT(lines[2], IsEmpty()); // \n
1473
1474 // Then kill the process.
1475 CaptureFdOut();
1476 CaptureStderr();
1477 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1478 t.join();
1479
1480 // Finally, check output after murder.
1481 CaptureFdOut();
1482 err = GetCapturedStderr();
1483
1484 // out starts with the pid, which is an unknown
1485 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1486 " --pid --sleep 20' failed: killed by signal 15\n"));
1487 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1488 " --pid --sleep 20' failed: killed by signal 15\n"));
1489}
1490
1491TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1492 if (!IsStandalone()) {
1493 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1494 // to Shell - need to refactor tests to avoid this problem)
1495 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1496 return;
1497 }
1498 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001499 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001500 // Emulates user build if necessarily.
1501 SetBuildType("user");
1502 }
1503
1504 DropRoot();
1505
Felipe Lemef0292972016-11-22 13:57:05 -08001506 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001507
1508 // We don't know the exact path of su, so we just check for the 'root ...' commands
1509 EXPECT_THAT(out, StartsWith("Skipping"));
1510 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1511 EXPECT_THAT(err, IsEmpty());
1512}
1513
1514TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1515 if (!IsStandalone()) {
1516 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1517 // to Shell - need to refactor tests to avoid this problem)
1518 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1519 return;
1520 }
1521 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001522 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001523 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1524 return;
1525 }
1526
1527 DropRoot();
1528
Felipe Lemef0292972016-11-22 13:57:05 -08001529 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1530 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001531
1532 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1533 EXPECT_THAT(err, StrEq("stderr\n"));
1534}
Felipe Leme46b85da2016-11-21 17:40:45 -08001535
Yifan Hong48e83a12017-10-03 14:10:07 -07001536
1537TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1538 if (!IsStandalone()) {
1539 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1540 // to Shell - need to refactor tests to avoid this problem)
1541 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1542 return;
1543 }
1544 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1545 if (!PropertiesHelper::IsUserBuild()) {
1546 // Emulates user build if necessarily.
1547 SetBuildType("user");
1548 }
1549
1550 DropRoot();
1551
1552 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1553 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1554
1555 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1556 EXPECT_THAT(err, StrEq("stderr\n"));
1557}
1558
1559TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1560 if (!IsStandalone()) {
1561 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1562 // to Shell - need to refactor tests to avoid this problem)
1563 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1564 return;
1565 }
1566 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1567 if (PropertiesHelper::IsUserBuild()) {
1568 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1569 return;
1570 }
1571
1572 DropRoot();
1573
1574 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1575 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1576
1577 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1578 EXPECT_THAT(err, StrEq("stderr\n"));
1579}
1580
Felipe Leme46b85da2016-11-21 17:40:45 -08001581TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1582 if (!IsStandalone()) {
1583 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1584 // to Shell - need to refactor tests to avoid this problem)
1585 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1586 return;
1587 }
1588 CreateFd("RunCommandDropRoot.txt");
1589 // First check root case - only available when running with 'adb root'.
1590 uid_t uid = getuid();
1591 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001592 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001593 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1594 EXPECT_THAT(err, StrEq("stderr\n"));
1595 return;
1596 }
1597 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001598 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001599 CommandOptions::WithTimeout(1).DropRoot().Build()));
1600 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1601 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1602}
1603
Felipe Lemef0292972016-11-22 13:57:05 -08001604TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001605 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001606 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001607 EXPECT_THAT(out,
1608 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1609 EXPECT_THAT(err, IsEmpty());
1610}
1611
Felipe Lemef0292972016-11-22 13:57:05 -08001612TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1613 CreateFd("DumpFileNotFound.txt");
1614 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1615 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1616 "file or directory\n"));
1617 EXPECT_THAT(err, IsEmpty());
1618}
1619
Felipe Leme46b85da2016-11-21 17:40:45 -08001620TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1621 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001622 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001623 EXPECT_THAT(err, IsEmpty());
1624 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1625}
1626
1627TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1628 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001629 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001630 EXPECT_THAT(err, IsEmpty());
1631 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1632}
1633
1634TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1635 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001636 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001637 EXPECT_THAT(err, IsEmpty());
1638 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1639}
1640
1641TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1642 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001643 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001644 EXPECT_THAT(err, IsEmpty());
1645 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1646}
1647
Felipe Lemef0292972016-11-22 13:57:05 -08001648TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1649 CreateFd("DumpFileOnDryRun.txt");
1650 SetDryRun(true);
1651 std::string path = kTestDataPath + "single-line.txt";
1652 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1653 EXPECT_THAT(err, IsEmpty());
1654 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1655}
1656
Felipe Leme46b85da2016-11-21 17:40:45 -08001657TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1658 CreateFd("DumpFileOnDryRun.txt");
1659 SetDryRun(true);
1660 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001661 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001662 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001663 EXPECT_THAT(
1664 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1665 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001666}
Ecco Park61ffcf72016-10-27 15:46:26 -07001667
Rhed Jao27077b12020-07-14 18:38:08 +08001668class DumpPoolTest : public DumpstateBaseTest {
1669 public:
1670 void SetUp() {
Rhed Jao1c855122020-07-16 17:37:39 +08001671 dump_pool_ = std::make_unique<DumpPool>(kTestDataPath);
Rhed Jao27077b12020-07-14 18:38:08 +08001672 DumpstateBaseTest::SetUp();
1673 CreateOutputFile();
1674 }
1675
1676 void CreateOutputFile() {
1677 out_path_ = kTestDataPath + "out.txt";
1678 out_fd_.reset(TEMP_FAILURE_RETRY(open(out_path_.c_str(),
1679 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1680 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1681 ASSERT_GE(out_fd_.get(), 0) << "could not create FD for path "
1682 << out_path_;
1683 }
1684
1685 int getTempFileCounts(const std::string& folder) {
1686 int count = 0;
1687 std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
1688 &closedir);
1689 if (!dir_ptr) {
1690 return -1;
1691 }
1692 int dir_fd = dirfd(dir_ptr.get());
1693 if (dir_fd < 0) {
1694 return -1;
1695 }
1696
1697 struct dirent* de;
1698 while ((de = readdir(dir_ptr.get()))) {
1699 if (de->d_type != DT_REG) {
1700 continue;
1701 }
1702 std::string file_name(de->d_name);
1703 if (file_name.find(DumpPool::PREFIX_TMPFILE_NAME) != 0) {
1704 continue;
1705 }
1706 count++;
1707 }
1708 return count;
1709 }
1710
Rhed Jao1c855122020-07-16 17:37:39 +08001711 void setLogDuration(bool log_duration) {
1712 dump_pool_->setLogDuration(log_duration);
1713 }
1714
1715 std::unique_ptr<DumpPool> dump_pool_;
Rhed Jao27077b12020-07-14 18:38:08 +08001716 android::base::unique_fd out_fd_;
1717 std::string out_path_;
1718};
1719
Rhed Jao1c855122020-07-16 17:37:39 +08001720TEST_F(DumpPoolTest, EnqueueTaskWithFd) {
Rhed Jao27077b12020-07-14 18:38:08 +08001721 auto dump_func_1 = [](int out_fd) {
1722 dprintf(out_fd, "A");
1723 };
1724 auto dump_func_2 = [](int out_fd) {
1725 dprintf(out_fd, "B");
1726 sleep(1);
1727 };
1728 auto dump_func_3 = [](int out_fd) {
1729 dprintf(out_fd, "C");
1730 };
Rhed Jao1c855122020-07-16 17:37:39 +08001731 setLogDuration(/* log_duration = */false);
Chris Morinbc223142022-02-04 14:17:11 -08001732 auto t1 = dump_pool_->enqueueTaskWithFd("", dump_func_1, std::placeholders::_1);
1733 auto t2 = dump_pool_->enqueueTaskWithFd("", dump_func_2, std::placeholders::_1);
1734 auto t3 = dump_pool_->enqueueTaskWithFd("", dump_func_3, std::placeholders::_1);
Rhed Jao27077b12020-07-14 18:38:08 +08001735
Chris Morinbc223142022-02-04 14:17:11 -08001736 WaitForTask(std::move(t1), "", out_fd_.get());
1737 WaitForTask(std::move(t2), "", out_fd_.get());
1738 WaitForTask(std::move(t3), "", out_fd_.get());
Rhed Jao27077b12020-07-14 18:38:08 +08001739
1740 std::string result;
1741 ReadFileToString(out_path_, &result);
1742 EXPECT_THAT(result, StrEq("A\nB\nC\n"));
1743 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao1c855122020-07-16 17:37:39 +08001744}
1745
1746TEST_F(DumpPoolTest, EnqueueTask_withDurationLog) {
1747 bool run_1 = false;
1748 auto dump_func_1 = [&]() {
1749 run_1 = true;
1750 };
1751
Chris Morinbc223142022-02-04 14:17:11 -08001752 auto t1 = dump_pool_->enqueueTask(/* duration_title = */"1", dump_func_1);
1753 WaitForTask(std::move(t1), "", out_fd_.get());
Rhed Jao1c855122020-07-16 17:37:39 +08001754
1755 std::string result;
1756 ReadFileToString(out_path_, &result);
1757 EXPECT_TRUE(run_1);
1758 EXPECT_THAT(result, StrEq("------ 0.000s was the duration of '1' ------\n"));
1759 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao27077b12020-07-14 18:38:08 +08001760}
1761
Rhed Jao4875aa62020-07-20 17:46:29 +08001762class TaskQueueTest : public DumpstateBaseTest {
1763public:
1764 void SetUp() {
1765 DumpstateBaseTest::SetUp();
1766 }
1767
1768 TaskQueue task_queue_;
1769};
1770
1771TEST_F(TaskQueueTest, runTask) {
1772 bool is_task1_run = false;
1773 bool is_task2_run = false;
1774 auto task_1 = [&](bool task_cancelled) {
1775 if (task_cancelled) {
1776 return;
1777 }
1778 is_task1_run = true;
1779 };
1780 auto task_2 = [&](bool task_cancelled) {
1781 if (task_cancelled) {
1782 return;
1783 }
1784 is_task2_run = true;
1785 };
1786 task_queue_.add(task_1, std::placeholders::_1);
1787 task_queue_.add(task_2, std::placeholders::_1);
1788
1789 task_queue_.run(/* do_cancel = */false);
1790
1791 EXPECT_TRUE(is_task1_run);
1792 EXPECT_TRUE(is_task2_run);
1793}
1794
1795TEST_F(TaskQueueTest, runTask_withCancelled) {
1796 bool is_task1_cancelled = false;
1797 bool is_task2_cancelled = false;
1798 auto task_1 = [&](bool task_cancelled) {
1799 is_task1_cancelled = task_cancelled;
1800 };
1801 auto task_2 = [&](bool task_cancelled) {
1802 is_task2_cancelled = task_cancelled;
1803 };
1804 task_queue_.add(task_1, std::placeholders::_1);
1805 task_queue_.add(task_2, std::placeholders::_1);
1806
1807 task_queue_.run(/* do_cancel = */true);
1808
1809 EXPECT_TRUE(is_task1_cancelled);
1810 EXPECT_TRUE(is_task2_cancelled);
1811}
1812
Rhed Jao27077b12020-07-14 18:38:08 +08001813
Felipe Leme47e9be22016-12-21 15:37:07 -08001814} // namespace dumpstate
1815} // namespace os
1816} // namespace android