blob: 2afabed813c36120f00b37757dd0678f92e984fc [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 Leme4c2d6632016-09-28 14:32:00 -070019#include "dumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070020
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000021#include <aidl/android/hardware/dumpstate/IDumpstateDevice.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070022#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070023#include <android-base/properties.h>
24#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070025#include <android-base/strings.h>
Abhijeet Kaure370d682019-10-01 16:49:30 +010026#include <android-base/unique_fd.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080027#include <android/hardware/dumpstate/1.1/types.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000028#include <android_tracing.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080029#include <cutils/log.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080030#include <cutils/properties.h>
Pablo Gamito654831c2024-02-16 16:47:48 +000031#include <fcntl.h>
32#include <gmock/gmock-matchers.h>
33#include <gmock/gmock.h>
34#include <gtest/gtest.h>
35#include <libgen.h>
36#include <signal.h>
37#include <sys/types.h>
38#include <unistd.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080039#include <ziparchive/zip_archive.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070040
Pablo Gamito654831c2024-02-16 16:47:48 +000041#include <filesystem>
42#include <thread>
43
44#include "DumpPool.h"
45#include "DumpstateInternal.h"
46#include "DumpstateService.h"
47#include "android/os/BnDumpstate.h"
48
Felipe Leme47e9be22016-12-21 15:37:07 -080049namespace android {
50namespace os {
51namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070052
Kedar Chitnis9fd8c052021-11-16 09:09:22 +000053using DumpstateDeviceAidl = ::aidl::android::hardware::dumpstate::IDumpstateDevice;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080054using ::android::hardware::dumpstate::V1_1::DumpstateMode;
Felipe Leme4c2d6632016-09-28 14:32:00 -070055using ::testing::EndsWith;
Rhed Jao27077b12020-07-14 18:38:08 +080056using ::testing::Eq;
Felipe Leme46b85da2016-11-21 17:40:45 -080057using ::testing::HasSubstr;
Felipe Leme4c2d6632016-09-28 14:32:00 -070058using ::testing::IsEmpty;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080059using ::testing::IsNull;
Felipe Leme009ecbb2016-11-07 10:18:44 -080060using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070061using ::testing::StartsWith;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080062using ::testing::StrEq;
Felipe Leme4c2d6632016-09-28 14:32:00 -070063using ::testing::Test;
64using ::testing::internal::CaptureStderr;
65using ::testing::internal::CaptureStdout;
66using ::testing::internal::GetCapturedStderr;
67using ::testing::internal::GetCapturedStdout;
68
Nandana Dutt3f8c7172018-09-25 12:01:54 +010069#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
70
Felipe Leme75876a22016-10-27 16:31:27 -070071class DumpstateListenerMock : public IDumpstateListener {
72 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000073 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
74 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Gavin Corkerya44686c2022-11-23 18:16:51 +000075 MOCK_METHOD1(onFinished, binder::Status(const std::string& bugreport_file));
Paul Chang0d2aad72020-02-13 20:04:03 +080076 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
Paul Chang5702b482020-05-28 22:05:47 +080077 MOCK_METHOD0(onUiIntensiveBugreportDumpsFinished, binder::Status());
Felipe Leme75876a22016-10-27 16:31:27 -070078
79 protected:
80 MOCK_METHOD0(onAsBinder, IBinder*());
81};
82
Felipe Leme46b85da2016-11-21 17:40:45 -080083static int calls_;
84
Felipe Leme7447d7c2016-11-03 18:12:22 -070085// Base class for all tests in this file
86class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080087 public:
88 virtual void SetUp() override {
89 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080090 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080091 }
92
Felipe Lemef0292972016-11-22 13:57:05 -080093 void SetDryRun(bool dry_run) const {
94 PropertiesHelper::dry_run_ = dry_run;
95 }
96
97 void SetBuildType(const std::string& build_type) const {
98 PropertiesHelper::build_type_ = build_type;
99 }
100
Nandana Dutt4b392be2018-11-02 16:17:05 +0000101 void SetUnroot(bool unroot) const {
102 PropertiesHelper::unroot_ = unroot;
103 }
104
Rhed Jao1c855122020-07-16 17:37:39 +0800105 void SetParallelRun(bool parallel_run) const {
106 PropertiesHelper::parallel_run_ = parallel_run;
107 }
108
Felipe Lemef0292972016-11-22 13:57:05 -0800109 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -0800110 return calls_ == 1;
111 }
112
Felipe Lemef0292972016-11-22 13:57:05 -0800113 void DropRoot() const {
114 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -0800115 uid_t uid = getuid();
116 ASSERT_EQ(2000, (int)uid);
117 }
118
Felipe Leme7447d7c2016-11-03 18:12:22 -0700119 protected:
120 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700121 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
122 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700123 const std::string kEchoCommand = "/system/bin/echo";
124
125 /*
126 * Copies a text file fixture to a temporary file, returning it's path.
127 *
128 * Useful in cases where the test case changes the content of the tile.
129 */
130 std::string CopyTextFileFixture(const std::string& relative_name) {
131 std::string from = kTestDataPath + relative_name;
132 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
133 // around for poking when the test fails.
134 std::string to = kTestDataPath + relative_name + ".tmp";
135 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
136 android::base::RemoveFileIfExists(to);
137 CopyTextFile(from, to);
138 return to.c_str();
139 }
140
Felipe Leme46b85da2016-11-21 17:40:45 -0800141 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700142 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800143 void ReadFileToString(const std::string& path, std::string* content) {
144 ASSERT_TRUE(android::base::ReadFileToString(path, content))
145 << "could not read contents from " << path;
146 }
147 void WriteStringToFile(const std::string& content, const std::string& path) {
148 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
149 << "could not write contents to " << path;
150 }
151
152 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700153 void CopyTextFile(const std::string& from, const std::string& to) {
154 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800155 ReadFileToString(from, &content);
156 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700157 }
158};
159
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100160class DumpOptionsTest : public Test {
161 public:
162 virtual ~DumpOptionsTest() {
163 }
164 virtual void SetUp() {
165 options_ = Dumpstate::DumpOptions();
166 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000167 void TearDown() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000168 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100169 Dumpstate::DumpOptions options_;
Abhijeet Kaure370d682019-10-01 16:49:30 +0100170 android::base::unique_fd fd;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100171};
172
173TEST_F(DumpOptionsTest, InitializeNone) {
174 // clang-format off
175 char* argv[] = {
176 const_cast<char*>("dumpstate")
177 };
178 // clang-format on
179
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100180 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
181
182 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000183
mhasank3a4cfb42020-06-15 18:06:43 -0700184 EXPECT_EQ("", options_.out_dir);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800185 EXPECT_FALSE(options_.stream_to_socket);
186 EXPECT_FALSE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100187 EXPECT_FALSE(options_.show_header_only);
188 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800189 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100190 EXPECT_FALSE(options_.do_progress_updates);
191 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700192 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000193}
194
195TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
196 // clang-format off
197 char* argv[] = {
198 const_cast<char*>("dumpstatez"),
199 const_cast<char*>("-S"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000200 };
201 // clang-format on
202
203 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
204
205 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800206 EXPECT_TRUE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000207
208 // Other options retain default values
209 EXPECT_TRUE(options_.do_vibrate);
210 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800211 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000212 EXPECT_FALSE(options_.do_progress_updates);
213 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800214 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700215 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000216}
217
218TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
219 // clang-format off
220 char* argv[] = {
221 const_cast<char*>("dumpstate"),
222 const_cast<char*>("-s"),
223 };
224 // clang-format on
225
226 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
227
228 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800229 EXPECT_TRUE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000230
231 // Other options retain default values
232 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800233 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000234 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800235 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000236 EXPECT_FALSE(options_.do_progress_updates);
237 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700238 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000239}
240
241TEST_F(DumpOptionsTest, InitializeFullBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000242 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800243 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000244
245 // Other options retain default values
246 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800247 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000248 EXPECT_FALSE(options_.show_header_only);
249 EXPECT_FALSE(options_.do_progress_updates);
250 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800251 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700252 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000253}
254
255TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000256 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 0, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000257 EXPECT_TRUE(options_.do_progress_updates);
Paul Chang0d2aad72020-02-13 20:04:03 +0800258 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000259
260 // Other options retain default values
261 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800262 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000263 EXPECT_FALSE(options_.show_header_only);
264 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800265 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700266 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000267}
268
269TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000270 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, 0, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000271 EXPECT_TRUE(options_.is_remote_mode);
272 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800273 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000274
275 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800276 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000277 EXPECT_FALSE(options_.show_header_only);
278 EXPECT_FALSE(options_.do_progress_updates);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800279 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700280 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000281}
282
283TEST_F(DumpOptionsTest, InitializeWearBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000284 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, 0, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800285 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000286 EXPECT_TRUE(options_.do_progress_updates);
Kedar Chitnis9fd8c052021-11-16 09:09:22 +0000287
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000288
289 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800290 EXPECT_FALSE(options_.progress_updates_to_socket);
Robert Gindada7d6702023-04-03 22:53:20 +0000291 EXPECT_FALSE(options_.do_vibrate);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000292 EXPECT_FALSE(options_.show_header_only);
293 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800294 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700295 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000296}
297
298TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000299 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, 0, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800300 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000301 EXPECT_TRUE(options_.telephony_only);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800302 EXPECT_TRUE(options_.do_progress_updates);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000303
304 // Other options retain default values
305 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800306 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000307 EXPECT_FALSE(options_.show_header_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000308 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800309 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700310 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000311}
312
313TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
Kean Mariotti306633e2022-09-05 16:30:47 +0000314 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, 0, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800315 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000316 EXPECT_TRUE(options_.wifi_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000317
318 // Other options retain default values
319 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800320 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000321 EXPECT_FALSE(options_.show_header_only);
322 EXPECT_FALSE(options_.do_progress_updates);
323 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800324 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700325 EXPECT_FALSE(options_.limited_only);
326}
327
328TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
329 // clang-format off
330 char* argv[] = {
331 const_cast<char*>("dumpstatez"),
332 const_cast<char*>("-S"),
mhasankd451a472020-05-26 18:02:39 -0700333 const_cast<char*>("-q"),
mhasank2d75c442020-06-11 15:05:25 -0700334 const_cast<char*>("-L"),
335 const_cast<char*>("-o abc")
mhasankd451a472020-05-26 18:02:39 -0700336 };
337 // clang-format on
338
339 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
340
341 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800342 EXPECT_TRUE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700343 EXPECT_FALSE(options_.do_vibrate);
344 EXPECT_TRUE(options_.limited_only);
mhasank3a4cfb42020-06-15 18:06:43 -0700345 EXPECT_EQ(" abc", std::string(options_.out_dir));
mhasankd451a472020-05-26 18:02:39 -0700346
347 // Other options retain default values
348 EXPECT_FALSE(options_.show_header_only);
349 EXPECT_FALSE(options_.do_screenshot);
350 EXPECT_FALSE(options_.do_progress_updates);
351 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800352 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000353}
354
355TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
356 // default: commandline options are not overridden
357 // clang-format off
358 char* argv[] = {
359 const_cast<char*>("bugreport"),
360 const_cast<char*>("-d"),
361 const_cast<char*>("-p"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000362 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000363 };
364 // clang-format on
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000365 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
366
367 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Paul Chang0d2aad72020-02-13 20:04:03 +0800368 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000369
370 // Other options retain default values
371 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800372 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000373 EXPECT_FALSE(options_.show_header_only);
374 EXPECT_FALSE(options_.do_progress_updates);
375 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800376 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000377 EXPECT_FALSE(options_.wifi_only);
mhasankd451a472020-05-26 18:02:39 -0700378 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100379}
380
381TEST_F(DumpOptionsTest, InitializePartial1) {
382 // clang-format off
383 char* argv[] = {
384 const_cast<char*>("dumpstate"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100385 const_cast<char*>("-s"),
386 const_cast<char*>("-S"),
387
388 };
389 // clang-format on
390
391 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
392
393 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100394 // TODO: Maybe we should trim the filename
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800395 EXPECT_TRUE(options_.stream_to_socket);
396 EXPECT_TRUE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100397
398 // Other options retain default values
399 EXPECT_FALSE(options_.show_header_only);
400 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800401 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100402 EXPECT_FALSE(options_.do_progress_updates);
403 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700404 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100405}
406
407TEST_F(DumpOptionsTest, InitializePartial2) {
408 // clang-format off
409 char* argv[] = {
410 const_cast<char*>("dumpstate"),
411 const_cast<char*>("-v"),
412 const_cast<char*>("-q"),
413 const_cast<char*>("-p"),
414 const_cast<char*>("-P"),
415 const_cast<char*>("-R"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100416 };
417 // clang-format on
418
419 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
420
421 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
422 EXPECT_TRUE(options_.show_header_only);
423 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800424 EXPECT_TRUE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100425 EXPECT_TRUE(options_.do_progress_updates);
426 EXPECT_TRUE(options_.is_remote_mode);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100427
428 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800429 EXPECT_FALSE(options_.stream_to_socket);
430 EXPECT_FALSE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700431 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100432}
433
434TEST_F(DumpOptionsTest, InitializeHelp) {
435 // clang-format off
436 char* argv[] = {
437 const_cast<char*>("dumpstate"),
438 const_cast<char*>("-h")
439 };
440 // clang-format on
441
442 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
443
444 // -h is for help.
445 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
446}
447
448TEST_F(DumpOptionsTest, InitializeUnknown) {
449 // clang-format off
450 char* argv[] = {
451 const_cast<char*>("dumpstate"),
452 const_cast<char*>("-u") // unknown flag
453 };
454 // clang-format on
455
456 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
457
458 // -u is unknown.
459 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
460}
461
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800462TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage1) {
463 options_.progress_updates_to_socket = true;
464 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100465 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000466
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800467 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100468 EXPECT_TRUE(options_.ValidateOptions());
469}
470
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800471TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage2) {
Abhijeet Kaure370d682019-10-01 16:49:30 +0100472 options_.do_progress_updates = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000473 // Writing to socket = !writing to file.
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800474 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100475 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000476
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800477 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100478 EXPECT_TRUE(options_.ValidateOptions());
479}
480
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100481TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800482 options_.do_progress_updates = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100483 options_.is_remote_mode = true;
484 EXPECT_FALSE(options_.ValidateOptions());
485
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800486 options_.do_progress_updates = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100487 EXPECT_TRUE(options_.ValidateOptions());
488}
489
Gavin Corkerya44686c2022-11-23 18:16:51 +0000490TEST_F(DumpOptionsTest, InitializeBugreportFlags) {
491 int flags = Dumpstate::BugreportFlag::BUGREPORT_USE_PREDUMPED_UI_DATA |
492 Dumpstate::BugreportFlag::BUGREPORT_FLAG_DEFER_CONSENT;
493 options_.Initialize(
494 Dumpstate::BugreportMode::BUGREPORT_FULL, flags, fd, fd, true);
495 EXPECT_TRUE(options_.is_consent_deferred);
496 EXPECT_TRUE(options_.use_predumped_ui_data);
497
498 options_.Initialize(
499 Dumpstate::BugreportMode::BUGREPORT_FULL, 0, fd, fd, true);
500 EXPECT_FALSE(options_.is_consent_deferred);
501 EXPECT_FALSE(options_.use_predumped_ui_data);
502}
503
Felipe Leme7447d7c2016-11-03 18:12:22 -0700504class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700505 public:
506 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800507 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700508 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700509 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700510 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100511 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700512 }
513
Rhed Jao1c855122020-07-16 17:37:39 +0800514 void TearDown() {
515 ds.ShutdownDumpPool();
516 }
517
Felipe Leme4c2d6632016-09-28 14:32:00 -0700518 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700519 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700520 const CommandOptions& options = CommandOptions::DEFAULT) {
521 CaptureStdout();
522 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700523 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700524 out = GetCapturedStdout();
525 err = GetCapturedStderr();
526 return status;
527 }
528
Felipe Lemecef02982016-10-03 17:22:22 -0700529 // Dumps a file and capture `stdout` and `stderr`.
530 int DumpFile(const std::string& title, const std::string& path) {
531 CaptureStdout();
532 CaptureStderr();
533 int status = ds.DumpFile(title, path);
534 out = GetCapturedStdout();
535 err = GetCapturedStderr();
536 return status;
537 }
538
Nandana Dutt402a8392019-06-14 14:25:13 +0100539 void SetProgress(long progress, long initial_max) {
540 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100541 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700542 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
543 }
544
Rhed Jao1c855122020-07-16 17:37:39 +0800545 void EnableParallelRunIfNeeded() {
546 ds.EnableParallelRunIfNeeded();
547 }
548
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100549 std::string GetProgressMessage(int progress, int max,
550 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700551 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
552 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700553
Felipe Leme7447d7c2016-11-03 18:12:22 -0700554 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700555
Felipe Leme009ecbb2016-11-07 10:18:44 -0800556 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700557 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800558 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700559 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700560 }
561
Felipe Leme009ecbb2016-11-07 10:18:44 -0800562 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100563 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
564 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800565 }
566
567 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700568 }
569
Felipe Leme4c2d6632016-09-28 14:32:00 -0700570 // `stdout` and `stderr` from the last command ran.
571 std::string out, err;
572
Felipe Lemefd8affa2016-09-30 17:38:57 -0700573 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700574};
575
576TEST_F(DumpstateTest, RunCommandNoArgs) {
577 EXPECT_EQ(-1, RunCommand("", {}));
578}
579
580TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700581 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700582 EXPECT_THAT(out, StrEq("stdout\n"));
583 EXPECT_THAT(err, StrEq("stderr\n"));
584}
585
586TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700587 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700588 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700589 // The duration may not get output, depending on how long it takes,
590 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700591 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000592 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700593}
594
Felipe Lemefd8affa2016-09-30 17:38:57 -0700595TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700596 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700597 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700598 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
599 EXPECT_THAT(out, StrEq("stdout\n"));
600 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
601}
602
603TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700604 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700605 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700606 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700607 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700608}
609
610TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700611 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700612 EXPECT_THAT(err, IsEmpty());
613 EXPECT_THAT(out, StrEq("one\n"));
614}
615
Felipe Lemefd8affa2016-09-30 17:38:57 -0700616TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700617 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700618 EXPECT_THAT(err, IsEmpty());
619 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
620}
621
622TEST_F(DumpstateTest, RunCommandDryRun) {
623 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700624 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700625 // The duration may not get output, depending on how long it takes,
626 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700627 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000628 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700629 EXPECT_THAT(err, IsEmpty());
630}
631
632TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
633 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700634 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700635 EXPECT_THAT(out, IsEmpty());
636 EXPECT_THAT(err, IsEmpty());
637}
638
639TEST_F(DumpstateTest, RunCommandDryRunAlways) {
640 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700641 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700642 EXPECT_THAT(out, StrEq("stdout\n"));
643 EXPECT_THAT(err, StrEq("stderr\n"));
644}
645
Felipe Lemefd8affa2016-09-30 17:38:57 -0700646TEST_F(DumpstateTest, RunCommandNotFound) {
647 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
648 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
649 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
650}
651
652TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700653 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
654 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700655 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700656 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700657 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700658}
659
660TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700661 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700662 // We don't know the exit code, so check just the prefix.
663 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700664 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700665 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700666 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700667}
668
669TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700670 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700671 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700672 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700673 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700674 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700675 " --sleep 2' timed out after 1"));
676}
677
678TEST_F(DumpstateTest, RunCommandIsKilled) {
679 CaptureStdout();
680 CaptureStderr();
681
682 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700683 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700684 CommandOptions::WithTimeout(100).Always().Build()));
685 });
686
687 // Capture pid and pre-sleep output.
688 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
689 std::string err = GetCapturedStderr();
690 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
691
692 std::string out = GetCapturedStdout();
693 std::vector<std::string> lines = android::base::Split(out, "\n");
694 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
695
696 int pid = atoi(lines[0].c_str());
697 EXPECT_THAT(lines[1], StrEq("stdout line1"));
698 EXPECT_THAT(lines[2], IsEmpty()); // \n
699
700 // Then kill the process.
701 CaptureStdout();
702 CaptureStderr();
703 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
704 t.join();
705
706 // Finally, check output after murder.
707 out = GetCapturedStdout();
708 err = GetCapturedStderr();
709
Felipe Leme7447d7c2016-11-03 18:12:22 -0700710 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700711 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700712 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700713 " --pid --sleep 20' failed: killed by signal 15\n"));
714}
715
Felipe Leme75876a22016-10-27 16:31:27 -0700716TEST_F(DumpstateTest, RunCommandProgress) {
717 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
718 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700719 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700720
Nandana Duttbabf6c72019-01-15 14:11:12 +0000721 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700722 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100723 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700724 EXPECT_THAT(out, StrEq("stdout\n"));
725 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
726
Nandana Dutt402a8392019-06-14 14:25:13 +0100727 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
728 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100729 progress_message = GetProgressMessage(24, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700730 EXPECT_THAT(out, StrEq("stdout\n"));
731 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
732
733 // Make sure command ran while in dry_run is counted.
734 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100735 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
736 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100737 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700738 EXPECT_THAT(out, IsEmpty());
739 EXPECT_THAT(err, StrEq(progress_message));
740
Nandana Dutt402a8392019-06-14 14:25:13 +0100741 SetDryRun(false);
742 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
743 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100744 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800745 EXPECT_THAT(out, StrEq("stdout\n"));
746 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
747
Nandana Dutt402a8392019-06-14 14:25:13 +0100748 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800749 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100750 progress_message = GetProgressMessage(30, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800751 EXPECT_THAT(out, StrEq("stdout\n"));
752 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
753
754 ds.listener_.clear();
755}
756
Felipe Lemed80e6b62016-10-03 13:08:14 -0700757TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800758 if (!IsStandalone()) {
759 // TODO: temporarily disabled because it might cause other tests to fail after dropping
760 // to Shell - need to refactor tests to avoid this problem)
761 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
762 return;
763 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700764 // First check root case - only available when running with 'adb root'.
765 uid_t uid = getuid();
766 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700767 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700768 EXPECT_THAT(out, StrEq("0\nstdout\n"));
769 EXPECT_THAT(err, StrEq("stderr\n"));
770 return;
771 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700772 // Then run dropping root.
773 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700774 CommandOptions::WithTimeout(1).DropRoot().Build()));
775 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700776 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700777}
778
779TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800780 if (!IsStandalone()) {
781 // TODO: temporarily disabled because it might cause other tests to fail after dropping
782 // to Shell - need to refactor tests to avoid this problem)
783 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
784 return;
785 }
Felipe Lemef0292972016-11-22 13:57:05 -0800786 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700787 // Emulates user build if necessarily.
788 SetBuildType("user");
789 }
790
791 DropRoot();
792
Felipe Leme7447d7c2016-11-03 18:12:22 -0700793 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700794
795 // We don't know the exact path of su, so we just check for the 'root ...' commands
796 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700797 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700798 EXPECT_THAT(err, IsEmpty());
799}
800
Felipe Leme46b85da2016-11-21 17:40:45 -0800801TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
802 if (!IsStandalone()) {
803 // TODO: temporarily disabled because it might cause other tests to fail after dropping
804 // to Shell - need to refactor tests to avoid this problem)
805 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
806 return;
807 }
Felipe Lemef0292972016-11-22 13:57:05 -0800808 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800809 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
810 return;
811 }
812
813 DropRoot();
814
815 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
816 CommandOptions::WithTimeout(1).AsRoot().Build()));
817
818 EXPECT_THAT(out, StrEq("0\nstdout\n"));
819 EXPECT_THAT(err, StrEq("stderr\n"));
820}
821
Nandana Dutt4b392be2018-11-02 16:17:05 +0000822TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
823 if (!IsStandalone()) {
824 // TODO: temporarily disabled because it might cause other tests to fail after dropping
825 // to Shell - need to refactor tests to avoid this problem)
826 MYLOGE(
827 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
828 "on test suite\n")
829 return;
830 }
831 if (PropertiesHelper::IsUserBuild()) {
832 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
833 return;
834 }
835
836 // Same test as above, but with unroot property set, which will override su availability.
837 SetUnroot(true);
838 DropRoot();
839
840 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
841 CommandOptions::WithTimeout(1).AsRoot().Build()));
842
843 // AsRoot is ineffective.
844 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
845 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
846}
847
Yifan Hong48e83a12017-10-03 14:10:07 -0700848TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
849 if (!IsStandalone()) {
850 // TODO: temporarily disabled because it might cause other tests to fail after dropping
851 // to Shell - need to refactor tests to avoid this problem)
852 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
853 return;
854 }
855 if (!PropertiesHelper::IsUserBuild()) {
856 // Emulates user build if necessarily.
857 SetBuildType("user");
858 }
859
860 DropRoot();
861
862 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
863 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
864
865 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
866 EXPECT_THAT(err, StrEq("stderr\n"));
867}
868
869TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
870 if (!IsStandalone()) {
871 // TODO: temporarily disabled because it might cause other tests to fail after dropping
872 // to Shell - need to refactor tests to avoid this problem)
873 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
874 return;
875 }
876 if (PropertiesHelper::IsUserBuild()) {
877 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
878 return;
879 }
880
881 DropRoot();
882
883 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
884 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
885
886 EXPECT_THAT(out, StrEq("0\nstdout\n"));
887 EXPECT_THAT(err, StrEq("stderr\n"));
888}
889
Nandana Dutt4b392be2018-11-02 16:17:05 +0000890TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
891 if (!IsStandalone()) {
892 // TODO: temporarily disabled because it might cause other tests to fail after dropping
893 // to Shell - need to refactor tests to avoid this problem)
894 MYLOGE(
895 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
896 "on test suite\n")
897 return;
898 }
899 if (PropertiesHelper::IsUserBuild()) {
900 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
901 return;
902 }
903 // Same test as above, but with unroot property set, which will override su availability.
904 SetUnroot(true);
905
906 DropRoot();
907
908 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
909 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
910
911 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
912 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
913 EXPECT_THAT(err, StrEq("stderr\n"));
914}
915
Felipe Lemecef02982016-10-03 17:22:22 -0700916TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
917 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
918 EXPECT_THAT(out,
919 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
920 EXPECT_THAT(err, IsEmpty());
921}
922
923TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
924 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
925 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700926 // The duration may not get output, depending on how long it takes,
927 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700928 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
929 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700930}
931
932TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700933 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700934 EXPECT_THAT(err, IsEmpty());
935 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
936}
937
938TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700939 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700940 EXPECT_THAT(err, IsEmpty());
941 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
942}
943
944TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700945 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700946 EXPECT_THAT(err, IsEmpty());
947 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
948}
949
950TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700951 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700952 EXPECT_THAT(err, IsEmpty());
953 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
954}
955
956TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
957 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700958 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700959 EXPECT_THAT(err, IsEmpty());
960 EXPECT_THAT(out, IsEmpty());
961}
962
963TEST_F(DumpstateTest, DumpFileOnDryRun) {
964 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700965 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700966 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800967 EXPECT_THAT(
968 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +0000969 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700970}
971
Felipe Leme75876a22016-10-27 16:31:27 -0700972TEST_F(DumpstateTest, DumpFileUpdateProgress) {
973 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
974 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700975 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700976
Nandana Duttbabf6c72019-01-15 14:11:12 +0000977 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700978 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700979
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100980 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -0700981 EXPECT_THAT(err, StrEq(progress_message));
982 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
983
984 ds.listener_.clear();
985}
986
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800987TEST_F(DumpstateTest, DumpPool_withParallelRunEnabled_notNull) {
Rhed Jao1c855122020-07-16 17:37:39 +0800988 SetParallelRun(true);
989 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800990 EXPECT_TRUE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800991 EXPECT_TRUE(ds.dump_pool_);
992}
993
Rhed Jao1c855122020-07-16 17:37:39 +0800994TEST_F(DumpstateTest, DumpPool_withParallelRunDisabled_isNull) {
995 SetParallelRun(false);
996 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800997 EXPECT_FALSE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800998 EXPECT_FALSE(ds.dump_pool_);
999}
1000
Pablo Gamitoefdc5922023-04-19 09:44:47 +00001001TEST_F(DumpstateTest, PreDumpUiData) {
1002 // These traces are always enabled, i.e. they are always pre-dumped
Pablo Gamito654831c2024-02-16 16:47:48 +00001003 std::vector<std::filesystem::path> uiTraces;
1004 if (!android_tracing_perfetto_transition_tracing()) {
1005 uiTraces.push_back(
1006 std::filesystem::path{"/data/misc/wmtrace/wm_transition_trace.winscope"});
1007 uiTraces.push_back(
1008 std::filesystem::path{"/data/misc/wmtrace/shell_transition_trace.winscope"});
1009 }
Kean Mariotti306633e2022-09-05 16:30:47 +00001010
Pablo Gamitoefdc5922023-04-19 09:44:47 +00001011 for (const auto traceFile : uiTraces) {
1012 std::system(("rm -f " + traceFile.string()).c_str());
1013 EXPECT_FALSE(std::filesystem::exists(traceFile)) << traceFile << " was not deleted.";
Kean Mariotti306633e2022-09-05 16:30:47 +00001014
Pablo Gamitoefdc5922023-04-19 09:44:47 +00001015 Dumpstate& ds_ = Dumpstate::GetInstance();
1016 ds_.PreDumpUiData();
1017 EXPECT_TRUE(std::filesystem::exists(traceFile)) << traceFile << " was not created.";
1018 }
Kean Mariotti306633e2022-09-05 16:30:47 +00001019}
1020
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001021class ZippedBugReportStreamTest : public DumpstateBaseTest {
1022 public:
1023 void SetUp() {
1024 DumpstateBaseTest::SetUp();
1025 ds_.options_.reset(new Dumpstate::DumpOptions());
1026 }
1027 void TearDown() {
1028 CloseArchive(handle_);
1029 }
1030
1031 // Set bugreport mode and options before here.
1032 void GenerateBugreport() {
1033 ds_.Initialize();
1034 EXPECT_EQ(Dumpstate::RunStatus::OK, ds_.Run(/*calling_uid=*/-1, /*calling_package=*/""));
1035 }
1036
1037 // Most bugreports droproot, ensure the file can be opened by shell to verify file content.
1038 void CreateFd(const std::string& path, android::base::unique_fd* out_fd) {
1039 out_fd->reset(TEMP_FAILURE_RETRY(open(path.c_str(),
1040 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1041 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1042 ASSERT_GE(out_fd->get(), 0) << "could not create FD for path " << path;
1043 }
1044
1045 void VerifyEntry(const ZipArchiveHandle archive, const std::string_view entry_name,
1046 ZipEntry* data) {
1047 int32_t e = FindEntry(archive, entry_name, data);
1048 EXPECT_EQ(0, e) << ErrorCodeString(e) << " entry name: " << entry_name;
1049 }
1050
1051 // While testing dumpstate in process, using STDOUT may get confused about
1052 // the internal fd redirection. Redirect to a dedicate fd to save content.
1053 void RedirectOutputToFd(android::base::unique_fd& ufd) {
1054 ds_.open_socket_fn_ = [&](const char*) -> int { return ufd.release(); };
1055 };
1056
1057 Dumpstate& ds_ = Dumpstate::GetInstance();
1058 ZipArchiveHandle handle_;
1059};
1060
Rhed Jaob8b56172021-04-08 20:14:27 +08001061// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
Jeff Sharkey9df29d52023-02-06 14:26:30 -07001062// TODO: broken test tracked in b/249983726
1063TEST_F(ZippedBugReportStreamTest, DISABLED_StreamLimitedOnlyReport) {
Rhed Jaob8b56172021-04-08 20:14:27 +08001064 std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001065 android::base::unique_fd out_fd;
1066 CreateFd(out_path, &out_fd);
Rhed Jaob8b56172021-04-08 20:14:27 +08001067 ds_.options_->limited_only = true;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001068 ds_.options_->stream_to_socket = true;
1069 RedirectOutputToFd(out_fd);
1070
1071 GenerateBugreport();
1072 OpenArchive(out_path.c_str(), &handle_);
1073
1074 ZipEntry entry;
1075 VerifyEntry(handle_, "main_entry.txt", &entry);
1076 std::string bugreport_txt_name;
1077 bugreport_txt_name.resize(entry.uncompressed_length);
1078 ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
1079 entry.uncompressed_length);
1080 EXPECT_THAT(bugreport_txt_name,
Rhed Jaob8b56172021-04-08 20:14:27 +08001081 testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001082 VerifyEntry(handle_, bugreport_txt_name, &entry);
1083}
1084
Felipe Leme7447d7c2016-11-03 18:12:22 -07001085class ProgressTest : public DumpstateBaseTest {
1086 public:
1087 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1088 return Progress(max, growth_factor, path);
1089 }
1090
1091 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1092 std::string expected_content =
1093 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1094 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001095 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001096 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1097 }
1098};
1099
1100TEST_F(ProgressTest, SimpleTest) {
1101 Progress progress;
1102 EXPECT_EQ(0, progress.Get());
1103 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1104 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1105
1106 bool max_increased = progress.Inc(1);
1107 EXPECT_EQ(1, progress.Get());
1108 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1109 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1110 EXPECT_FALSE(max_increased);
1111
1112 // Ignore negative increase.
1113 max_increased = progress.Inc(-1);
1114 EXPECT_EQ(1, progress.Get());
1115 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1116 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1117 EXPECT_FALSE(max_increased);
1118}
1119
1120TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1121 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1122 EXPECT_EQ(0, progress.Get());
1123 EXPECT_EQ(10, progress.GetInitialMax());
1124 EXPECT_EQ(10, progress.GetMax());
1125
1126 // No increase
1127 bool max_increased = progress.Inc(10);
1128 EXPECT_EQ(10, progress.Get());
1129 EXPECT_EQ(10, progress.GetMax());
1130 EXPECT_FALSE(max_increased);
1131
1132 // Increase, with new value < max*20%
1133 max_increased = progress.Inc(1);
1134 EXPECT_EQ(11, progress.Get());
1135 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1136 EXPECT_TRUE(max_increased);
1137}
1138
1139TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1140 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1141 EXPECT_EQ(0, progress.Get());
1142 EXPECT_EQ(10, progress.GetInitialMax());
1143 EXPECT_EQ(10, progress.GetMax());
1144
1145 // No increase
1146 bool max_increased = progress.Inc(10);
1147 EXPECT_EQ(10, progress.Get());
1148 EXPECT_EQ(10, progress.GetMax());
1149 EXPECT_FALSE(max_increased);
1150
1151 // Increase, with new value > max*20%
1152 max_increased = progress.Inc(5);
1153 EXPECT_EQ(15, progress.Get());
1154 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1155 EXPECT_TRUE(max_increased);
1156}
1157
1158TEST_F(ProgressTest, InvalidPath) {
1159 Progress progress("/devil/null");
1160 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1161}
1162
1163TEST_F(ProgressTest, EmptyFile) {
1164 Progress progress(CopyTextFileFixture("empty-file.txt"));
1165 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1166}
1167
1168TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1169 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1170 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1171}
1172
1173TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1174 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1175 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1176}
1177
1178TEST_F(ProgressTest, InvalidLineBothNAN) {
1179 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1180 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1181}
1182
1183TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1184 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1185 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1186}
1187
1188TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1189 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1190 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1191}
1192
1193TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1194 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1195 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1196}
1197
1198TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1199 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1200 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1201}
1202
1203// Tests stats are properly saved when the file does not exists.
1204TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001205 if (!IsStandalone()) {
1206 // TODO: temporarily disabled because it's failing when running as suite
1207 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1208 return;
1209 }
1210
Felipe Leme7447d7c2016-11-03 18:12:22 -07001211 std::string path = kTestDataPath + "FirstTime.txt";
1212 android::base::RemoveFileIfExists(path);
1213
1214 Progress run1(path);
1215 EXPECT_EQ(0, run1.Get());
1216 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1217 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1218
1219 bool max_increased = run1.Inc(20);
1220 EXPECT_EQ(20, run1.Get());
1221 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1222 EXPECT_FALSE(max_increased);
1223
1224 run1.Save();
1225 AssertStats(path, 1, 20);
1226}
1227
1228// Tests what happens when the persistent settings contains the average duration of 1 run.
1229// Data on file is 1 run and 109 average.
1230TEST_F(ProgressTest, SecondTime) {
1231 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1232
1233 Progress run1 = GetInstance(-42, 1.2, path);
1234 EXPECT_EQ(0, run1.Get());
1235 EXPECT_EQ(10, run1.GetInitialMax());
1236 EXPECT_EQ(10, run1.GetMax());
1237
1238 bool max_increased = run1.Inc(20);
1239 EXPECT_EQ(20, run1.Get());
1240 EXPECT_EQ(24, run1.GetMax());
1241 EXPECT_TRUE(max_increased);
1242
1243 // Average now is 2 runs and (10 + 20)/ 2 = 15
1244 run1.Save();
1245 AssertStats(path, 2, 15);
1246
1247 Progress run2 = GetInstance(-42, 1.2, path);
1248 EXPECT_EQ(0, run2.Get());
1249 EXPECT_EQ(15, run2.GetInitialMax());
1250 EXPECT_EQ(15, run2.GetMax());
1251
1252 max_increased = run2.Inc(25);
1253 EXPECT_EQ(25, run2.Get());
1254 EXPECT_EQ(30, run2.GetMax());
1255 EXPECT_TRUE(max_increased);
1256
1257 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1258 run2.Save();
1259 AssertStats(path, 3, 18);
1260
1261 Progress run3 = GetInstance(-42, 1.2, path);
1262 EXPECT_EQ(0, run3.Get());
1263 EXPECT_EQ(18, run3.GetInitialMax());
1264 EXPECT_EQ(18, run3.GetMax());
1265
1266 // Make sure average decreases as well
1267 max_increased = run3.Inc(5);
1268 EXPECT_EQ(5, run3.Get());
1269 EXPECT_EQ(18, run3.GetMax());
1270 EXPECT_FALSE(max_increased);
1271
1272 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1273 run3.Save();
1274 AssertStats(path, 4, 14);
1275}
1276
1277// Tests what happens when the persistent settings contains the average duration of 2 runs.
1278// Data on file is 2 runs and 15 average.
1279TEST_F(ProgressTest, ThirdTime) {
1280 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1281 AssertStats(path, 2, 15); // Sanity check
1282
1283 Progress run1 = GetInstance(-42, 1.2, path);
1284 EXPECT_EQ(0, run1.Get());
1285 EXPECT_EQ(15, run1.GetInitialMax());
1286 EXPECT_EQ(15, run1.GetMax());
1287
1288 bool max_increased = run1.Inc(20);
1289 EXPECT_EQ(20, run1.Get());
1290 EXPECT_EQ(24, run1.GetMax());
1291 EXPECT_TRUE(max_increased);
1292
1293 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1294 run1.Save();
1295 AssertStats(path, 3, 16);
1296}
1297
Felipe Leme46b85da2016-11-21 17:40:45 -08001298class DumpstateUtilTest : public DumpstateBaseTest {
1299 public:
1300 void SetUp() {
1301 DumpstateBaseTest::SetUp();
1302 SetDryRun(false);
1303 }
1304
Felipe Leme46b85da2016-11-21 17:40:45 -08001305 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001306 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001307 }
1308
1309 void CreateFd(const std::string& name) {
1310 path_ = kTestDataPath + name;
1311 MYLOGD("Creating fd for file %s\n", path_.c_str());
1312
1313 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1314 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1315 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1316 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1317 }
1318
1319 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001320 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001321 const CommandOptions& options = CommandOptions::DEFAULT) {
1322 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001323 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001324 close(fd);
1325
1326 CaptureFdOut();
1327 err = GetCapturedStderr();
1328 return status;
1329 }
1330
1331 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001332 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001333 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001334 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001335 close(fd);
1336
1337 CaptureFdOut();
1338 err = GetCapturedStderr();
1339 return status;
1340 }
1341
1342 int fd;
1343
1344 // 'fd` output and `stderr` from the last command ran.
1345 std::string out, err;
1346
1347 private:
1348 std::string path_;
1349};
1350
1351TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001352 CreateFd("RunCommandNoArgs.txt");
1353 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001354}
1355
Felipe Lemef0292972016-11-22 13:57:05 -08001356TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001357 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001358 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001359 EXPECT_THAT(out, StrEq("stdout\n"));
1360 EXPECT_THAT(err, StrEq("stderr\n"));
1361}
1362
Felipe Lemef0292972016-11-22 13:57:05 -08001363TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1364 CreateFd("RunCommandWithNoArgs.txt");
1365 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1366 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1367 EXPECT_THAT(err, StrEq("stderr\n"));
1368}
1369
Felipe Leme46b85da2016-11-21 17:40:45 -08001370TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1371 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001372 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001373 EXPECT_THAT(err, IsEmpty());
1374 EXPECT_THAT(out, StrEq("one\n"));
1375}
1376
1377TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1378 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001379 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001380 EXPECT_THAT(err, IsEmpty());
1381 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1382}
1383
1384TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1385 CreateFd("RunCommandWithLoggingMessage.txt");
1386 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001387 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001388 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1389 EXPECT_THAT(out, StrEq("stdout\n"));
1390 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1391}
1392
1393TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1394 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001395 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1396 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001397 EXPECT_THAT(out, IsEmpty());
1398 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1399}
1400
1401TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1402 CreateFd("RunCommandDryRun.txt");
1403 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001404 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1405 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1406 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1407 kSimpleCommand.c_str())));
1408 EXPECT_THAT(err, IsEmpty());
1409}
1410
1411TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1412 CreateFd("RunCommandDryRun.txt");
1413 SetDryRun(true);
1414 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001415 EXPECT_THAT(
1416 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1417 EXPECT_THAT(err, IsEmpty());
1418}
1419
1420TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1421 CreateFd("RunCommandDryRunAlways.txt");
1422 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001423 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001424 EXPECT_THAT(out, StrEq("stdout\n"));
1425 EXPECT_THAT(err, StrEq("stderr\n"));
1426}
1427
1428TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1429 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001430 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001431 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1432 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1433}
1434
1435TEST_F(DumpstateUtilTest, RunCommandFails) {
1436 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001437 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001438 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1439 " --exit 42' failed: exit code 42\n"));
1440 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1441 " --exit 42' failed: exit code 42\n"));
1442}
1443
1444TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1445 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001446 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001447 // We don't know the exit code, so check just the prefix.
1448 EXPECT_THAT(
1449 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1450 EXPECT_THAT(
1451 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1452}
1453
Vishnu Nair6921f802017-11-22 09:17:23 -08001454TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001455 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001456 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1457 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001458 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1459 " --sleep 2' timed out after 1"));
1460 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1461 " --sleep 2' timed out after 1"));
1462}
1463
Vishnu Nair6921f802017-11-22 09:17:23 -08001464TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1465 CreateFd("RunCommandTimesout.txt");
1466 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1467 CommandOptions::WithTimeoutInMs(1000).Build()));
1468 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1469 " --sleep 2' timed out after 1"));
1470 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1471 " --sleep 2' timed out after 1"));
1472}
1473
1474
Felipe Leme46b85da2016-11-21 17:40:45 -08001475TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1476 CreateFd("RunCommandIsKilled.txt");
1477 CaptureStderr();
1478
1479 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001480 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001481 CommandOptions::WithTimeout(100).Always().Build()));
1482 });
1483
1484 // Capture pid and pre-sleep output.
1485 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1486 std::string err = GetCapturedStderr();
1487 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1488
1489 CaptureFdOut();
1490 std::vector<std::string> lines = android::base::Split(out, "\n");
1491 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1492
1493 int pid = atoi(lines[0].c_str());
1494 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1495 EXPECT_THAT(lines[2], IsEmpty()); // \n
1496
1497 // Then kill the process.
1498 CaptureFdOut();
1499 CaptureStderr();
1500 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1501 t.join();
1502
1503 // Finally, check output after murder.
1504 CaptureFdOut();
1505 err = GetCapturedStderr();
1506
1507 // out starts with the pid, which is an unknown
1508 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1509 " --pid --sleep 20' failed: killed by signal 15\n"));
1510 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1511 " --pid --sleep 20' failed: killed by signal 15\n"));
1512}
1513
1514TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
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.RunCommandAsRootUserBuild() on test suite\n")
1519 return;
1520 }
1521 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001522 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001523 // Emulates user build if necessarily.
1524 SetBuildType("user");
1525 }
1526
1527 DropRoot();
1528
Felipe Lemef0292972016-11-22 13:57:05 -08001529 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001530
1531 // We don't know the exact path of su, so we just check for the 'root ...' commands
1532 EXPECT_THAT(out, StartsWith("Skipping"));
1533 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1534 EXPECT_THAT(err, IsEmpty());
1535}
1536
1537TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
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.RunCommandAsRootNonUserBuild() on test suite\n")
1542 return;
1543 }
1544 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001545 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001546 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1547 return;
1548 }
1549
1550 DropRoot();
1551
Felipe Lemef0292972016-11-22 13:57:05 -08001552 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1553 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001554
1555 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1556 EXPECT_THAT(err, StrEq("stderr\n"));
1557}
Felipe Leme46b85da2016-11-21 17:40:45 -08001558
Yifan Hong48e83a12017-10-03 14:10:07 -07001559
1560TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1561 if (!IsStandalone()) {
1562 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1563 // to Shell - need to refactor tests to avoid this problem)
1564 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1565 return;
1566 }
1567 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1568 if (!PropertiesHelper::IsUserBuild()) {
1569 // Emulates user build if necessarily.
1570 SetBuildType("user");
1571 }
1572
1573 DropRoot();
1574
1575 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1576 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1577
1578 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1579 EXPECT_THAT(err, StrEq("stderr\n"));
1580}
1581
1582TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1583 if (!IsStandalone()) {
1584 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1585 // to Shell - need to refactor tests to avoid this problem)
1586 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1587 return;
1588 }
1589 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1590 if (PropertiesHelper::IsUserBuild()) {
1591 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1592 return;
1593 }
1594
1595 DropRoot();
1596
1597 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1598 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1599
1600 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1601 EXPECT_THAT(err, StrEq("stderr\n"));
1602}
1603
Felipe Leme46b85da2016-11-21 17:40:45 -08001604TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1605 if (!IsStandalone()) {
1606 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1607 // to Shell - need to refactor tests to avoid this problem)
1608 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1609 return;
1610 }
1611 CreateFd("RunCommandDropRoot.txt");
1612 // First check root case - only available when running with 'adb root'.
1613 uid_t uid = getuid();
1614 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001615 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001616 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1617 EXPECT_THAT(err, StrEq("stderr\n"));
1618 return;
1619 }
1620 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001621 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001622 CommandOptions::WithTimeout(1).DropRoot().Build()));
1623 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1624 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1625}
1626
Felipe Lemef0292972016-11-22 13:57:05 -08001627TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001628 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001629 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001630 EXPECT_THAT(out,
1631 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1632 EXPECT_THAT(err, IsEmpty());
1633}
1634
Felipe Lemef0292972016-11-22 13:57:05 -08001635TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1636 CreateFd("DumpFileNotFound.txt");
1637 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1638 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1639 "file or directory\n"));
1640 EXPECT_THAT(err, IsEmpty());
1641}
1642
Felipe Leme46b85da2016-11-21 17:40:45 -08001643TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1644 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001645 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001646 EXPECT_THAT(err, IsEmpty());
1647 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1648}
1649
1650TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1651 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001652 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001653 EXPECT_THAT(err, IsEmpty());
1654 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1655}
1656
1657TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1658 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001659 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001660 EXPECT_THAT(err, IsEmpty());
1661 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1662}
1663
1664TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1665 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001666 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001667 EXPECT_THAT(err, IsEmpty());
1668 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1669}
1670
Felipe Lemef0292972016-11-22 13:57:05 -08001671TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1672 CreateFd("DumpFileOnDryRun.txt");
1673 SetDryRun(true);
1674 std::string path = kTestDataPath + "single-line.txt";
1675 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1676 EXPECT_THAT(err, IsEmpty());
1677 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1678}
1679
Felipe Leme46b85da2016-11-21 17:40:45 -08001680TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1681 CreateFd("DumpFileOnDryRun.txt");
1682 SetDryRun(true);
1683 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001684 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001685 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001686 EXPECT_THAT(
1687 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1688 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001689}
Ecco Park61ffcf72016-10-27 15:46:26 -07001690
Rhed Jao27077b12020-07-14 18:38:08 +08001691class DumpPoolTest : public DumpstateBaseTest {
1692 public:
1693 void SetUp() {
Rhed Jao1c855122020-07-16 17:37:39 +08001694 dump_pool_ = std::make_unique<DumpPool>(kTestDataPath);
Rhed Jao27077b12020-07-14 18:38:08 +08001695 DumpstateBaseTest::SetUp();
1696 CreateOutputFile();
1697 }
1698
1699 void CreateOutputFile() {
1700 out_path_ = kTestDataPath + "out.txt";
1701 out_fd_.reset(TEMP_FAILURE_RETRY(open(out_path_.c_str(),
1702 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1703 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1704 ASSERT_GE(out_fd_.get(), 0) << "could not create FD for path "
1705 << out_path_;
1706 }
1707
1708 int getTempFileCounts(const std::string& folder) {
1709 int count = 0;
1710 std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
1711 &closedir);
1712 if (!dir_ptr) {
1713 return -1;
1714 }
1715 int dir_fd = dirfd(dir_ptr.get());
1716 if (dir_fd < 0) {
1717 return -1;
1718 }
1719
1720 struct dirent* de;
1721 while ((de = readdir(dir_ptr.get()))) {
1722 if (de->d_type != DT_REG) {
1723 continue;
1724 }
1725 std::string file_name(de->d_name);
1726 if (file_name.find(DumpPool::PREFIX_TMPFILE_NAME) != 0) {
1727 continue;
1728 }
1729 count++;
1730 }
1731 return count;
1732 }
1733
Rhed Jao1c855122020-07-16 17:37:39 +08001734 void setLogDuration(bool log_duration) {
1735 dump_pool_->setLogDuration(log_duration);
1736 }
1737
1738 std::unique_ptr<DumpPool> dump_pool_;
Rhed Jao27077b12020-07-14 18:38:08 +08001739 android::base::unique_fd out_fd_;
1740 std::string out_path_;
1741};
1742
Rhed Jao1c855122020-07-16 17:37:39 +08001743TEST_F(DumpPoolTest, EnqueueTaskWithFd) {
Rhed Jao27077b12020-07-14 18:38:08 +08001744 auto dump_func_1 = [](int out_fd) {
1745 dprintf(out_fd, "A");
1746 };
1747 auto dump_func_2 = [](int out_fd) {
1748 dprintf(out_fd, "B");
1749 sleep(1);
1750 };
1751 auto dump_func_3 = [](int out_fd) {
1752 dprintf(out_fd, "C");
1753 };
Rhed Jao1c855122020-07-16 17:37:39 +08001754 setLogDuration(/* log_duration = */false);
Chris Morinbc223142022-02-04 14:17:11 -08001755 auto t1 = dump_pool_->enqueueTaskWithFd("", dump_func_1, std::placeholders::_1);
1756 auto t2 = dump_pool_->enqueueTaskWithFd("", dump_func_2, std::placeholders::_1);
1757 auto t3 = dump_pool_->enqueueTaskWithFd("", dump_func_3, std::placeholders::_1);
Rhed Jao27077b12020-07-14 18:38:08 +08001758
Chris Morinbc223142022-02-04 14:17:11 -08001759 WaitForTask(std::move(t1), "", out_fd_.get());
1760 WaitForTask(std::move(t2), "", out_fd_.get());
1761 WaitForTask(std::move(t3), "", out_fd_.get());
Rhed Jao27077b12020-07-14 18:38:08 +08001762
1763 std::string result;
1764 ReadFileToString(out_path_, &result);
1765 EXPECT_THAT(result, StrEq("A\nB\nC\n"));
1766 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao1c855122020-07-16 17:37:39 +08001767}
1768
1769TEST_F(DumpPoolTest, EnqueueTask_withDurationLog) {
1770 bool run_1 = false;
1771 auto dump_func_1 = [&]() {
1772 run_1 = true;
1773 };
1774
Chris Morinbc223142022-02-04 14:17:11 -08001775 auto t1 = dump_pool_->enqueueTask(/* duration_title = */"1", dump_func_1);
1776 WaitForTask(std::move(t1), "", out_fd_.get());
Rhed Jao1c855122020-07-16 17:37:39 +08001777
1778 std::string result;
1779 ReadFileToString(out_path_, &result);
1780 EXPECT_TRUE(run_1);
1781 EXPECT_THAT(result, StrEq("------ 0.000s was the duration of '1' ------\n"));
1782 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao27077b12020-07-14 18:38:08 +08001783}
1784
Rhed Jao4875aa62020-07-20 17:46:29 +08001785class TaskQueueTest : public DumpstateBaseTest {
1786public:
1787 void SetUp() {
1788 DumpstateBaseTest::SetUp();
1789 }
1790
1791 TaskQueue task_queue_;
1792};
1793
1794TEST_F(TaskQueueTest, runTask) {
1795 bool is_task1_run = false;
1796 bool is_task2_run = false;
1797 auto task_1 = [&](bool task_cancelled) {
1798 if (task_cancelled) {
1799 return;
1800 }
1801 is_task1_run = true;
1802 };
1803 auto task_2 = [&](bool task_cancelled) {
1804 if (task_cancelled) {
1805 return;
1806 }
1807 is_task2_run = true;
1808 };
1809 task_queue_.add(task_1, std::placeholders::_1);
1810 task_queue_.add(task_2, std::placeholders::_1);
1811
1812 task_queue_.run(/* do_cancel = */false);
1813
1814 EXPECT_TRUE(is_task1_run);
1815 EXPECT_TRUE(is_task2_run);
1816}
1817
1818TEST_F(TaskQueueTest, runTask_withCancelled) {
1819 bool is_task1_cancelled = false;
1820 bool is_task2_cancelled = false;
1821 auto task_1 = [&](bool task_cancelled) {
1822 is_task1_cancelled = task_cancelled;
1823 };
1824 auto task_2 = [&](bool task_cancelled) {
1825 is_task2_cancelled = task_cancelled;
1826 };
1827 task_queue_.add(task_1, std::placeholders::_1);
1828 task_queue_.add(task_2, std::placeholders::_1);
1829
1830 task_queue_.run(/* do_cancel = */true);
1831
1832 EXPECT_TRUE(is_task1_cancelled);
1833 EXPECT_TRUE(is_task2_cancelled);
1834}
1835
Rhed Jao27077b12020-07-14 18:38:08 +08001836
Felipe Leme47e9be22016-12-21 15:37:07 -08001837} // namespace dumpstate
1838} // namespace os
1839} // namespace android