blob: db508b52bd728ae9f09bafa1cfd35c1808bc3c3a [file] [log] [blame]
Felipe Leme4c2d6632016-09-28 14:32:00 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dieter Hsu105ad0c2020-09-29 15:23:33 +080017#define LOG_TAG "dumpstate_test"
Felipe Leme75876a22016-10-27 16:31:27 -070018
Felipe Lemef0292972016-11-22 13:57:05 -080019#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070020#include "DumpstateService.h"
21#include "android/os/BnDumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070022#include "dumpstate.h"
Rhed Jao27077b12020-07-14 18:38:08 +080023#include "DumpPool.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070024
25#include <gmock/gmock.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080026#include <gmock/gmock-matchers.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070027#include <gtest/gtest.h>
28
Felipe Leme46b85da2016-11-21 17:40:45 -080029#include <fcntl.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070030#include <libgen.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070031#include <signal.h>
32#include <sys/types.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070033#include <unistd.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070034#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070035
36#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070037#include <android-base/properties.h>
38#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070039#include <android-base/strings.h>
Abhijeet Kaure370d682019-10-01 16:49:30 +010040#include <android-base/unique_fd.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080041#include <android/hardware/dumpstate/1.1/types.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080042#include <cutils/log.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080043#include <cutils/properties.h>
Dieter Hsu105ad0c2020-09-29 15:23:33 +080044#include <ziparchive/zip_archive.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070045
Felipe Leme47e9be22016-12-21 15:37:07 -080046namespace android {
47namespace os {
48namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070049
Hunter Knepshield8540faf2020-02-04 19:47:20 -080050using ::android::hardware::dumpstate::V1_1::DumpstateMode;
Felipe Leme4c2d6632016-09-28 14:32:00 -070051using ::testing::EndsWith;
Rhed Jao27077b12020-07-14 18:38:08 +080052using ::testing::Eq;
Felipe Leme46b85da2016-11-21 17:40:45 -080053using ::testing::HasSubstr;
Felipe Leme4c2d6632016-09-28 14:32:00 -070054using ::testing::IsEmpty;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080055using ::testing::IsNull;
Felipe Leme009ecbb2016-11-07 10:18:44 -080056using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070057using ::testing::StartsWith;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080058using ::testing::StrEq;
Felipe Leme4c2d6632016-09-28 14:32:00 -070059using ::testing::Test;
60using ::testing::internal::CaptureStderr;
61using ::testing::internal::CaptureStdout;
62using ::testing::internal::GetCapturedStderr;
63using ::testing::internal::GetCapturedStdout;
64
Nandana Dutt3f8c7172018-09-25 12:01:54 +010065#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
66
Felipe Leme75876a22016-10-27 16:31:27 -070067class DumpstateListenerMock : public IDumpstateListener {
68 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000069 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
70 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Nandana Duttcc4ead82019-01-23 08:29:23 +000071 MOCK_METHOD0(onFinished, binder::Status());
Paul Chang0d2aad72020-02-13 20:04:03 +080072 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
Paul Chang5702b482020-05-28 22:05:47 +080073 MOCK_METHOD0(onUiIntensiveBugreportDumpsFinished, binder::Status());
Felipe Leme75876a22016-10-27 16:31:27 -070074
75 protected:
76 MOCK_METHOD0(onAsBinder, IBinder*());
77};
78
Felipe Leme46b85da2016-11-21 17:40:45 -080079static int calls_;
80
Felipe Leme7447d7c2016-11-03 18:12:22 -070081// Base class for all tests in this file
82class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080083 public:
84 virtual void SetUp() override {
85 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080086 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080087 }
88
Felipe Lemef0292972016-11-22 13:57:05 -080089 void SetDryRun(bool dry_run) const {
90 PropertiesHelper::dry_run_ = dry_run;
91 }
92
93 void SetBuildType(const std::string& build_type) const {
94 PropertiesHelper::build_type_ = build_type;
95 }
96
Nandana Dutt4b392be2018-11-02 16:17:05 +000097 void SetUnroot(bool unroot) const {
98 PropertiesHelper::unroot_ = unroot;
99 }
100
Rhed Jao1c855122020-07-16 17:37:39 +0800101 void SetParallelRun(bool parallel_run) const {
102 PropertiesHelper::parallel_run_ = parallel_run;
103 }
104
Felipe Lemef0292972016-11-22 13:57:05 -0800105 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -0800106 return calls_ == 1;
107 }
108
Felipe Lemef0292972016-11-22 13:57:05 -0800109 void DropRoot() const {
110 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -0800111 uid_t uid = getuid();
112 ASSERT_EQ(2000, (int)uid);
113 }
114
Felipe Leme7447d7c2016-11-03 18:12:22 -0700115 protected:
116 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700117 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
118 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700119 const std::string kEchoCommand = "/system/bin/echo";
120
121 /*
122 * Copies a text file fixture to a temporary file, returning it's path.
123 *
124 * Useful in cases where the test case changes the content of the tile.
125 */
126 std::string CopyTextFileFixture(const std::string& relative_name) {
127 std::string from = kTestDataPath + relative_name;
128 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
129 // around for poking when the test fails.
130 std::string to = kTestDataPath + relative_name + ".tmp";
131 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
132 android::base::RemoveFileIfExists(to);
133 CopyTextFile(from, to);
134 return to.c_str();
135 }
136
Felipe Leme46b85da2016-11-21 17:40:45 -0800137 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700138 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800139 void ReadFileToString(const std::string& path, std::string* content) {
140 ASSERT_TRUE(android::base::ReadFileToString(path, content))
141 << "could not read contents from " << path;
142 }
143 void WriteStringToFile(const std::string& content, const std::string& path) {
144 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
145 << "could not write contents to " << path;
146 }
147
148 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700149 void CopyTextFile(const std::string& from, const std::string& to) {
150 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800151 ReadFileToString(from, &content);
152 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700153 }
154};
155
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100156class DumpOptionsTest : public Test {
157 public:
158 virtual ~DumpOptionsTest() {
159 }
160 virtual void SetUp() {
161 options_ = Dumpstate::DumpOptions();
162 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000163 void TearDown() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000164 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100165 Dumpstate::DumpOptions options_;
Abhijeet Kaure370d682019-10-01 16:49:30 +0100166 android::base::unique_fd fd;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100167};
168
169TEST_F(DumpOptionsTest, InitializeNone) {
170 // clang-format off
171 char* argv[] = {
172 const_cast<char*>("dumpstate")
173 };
174 // clang-format on
175
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100176 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
177
178 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000179
mhasank3a4cfb42020-06-15 18:06:43 -0700180 EXPECT_EQ("", options_.out_dir);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800181 EXPECT_FALSE(options_.stream_to_socket);
182 EXPECT_FALSE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100183 EXPECT_FALSE(options_.show_header_only);
184 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800185 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100186 EXPECT_FALSE(options_.do_progress_updates);
187 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700188 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800189 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000190}
191
192TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
193 // clang-format off
194 char* argv[] = {
195 const_cast<char*>("dumpstatez"),
196 const_cast<char*>("-S"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000197 };
198 // clang-format on
199
200 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
201
202 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800203 EXPECT_TRUE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000204
205 // Other options retain default values
206 EXPECT_TRUE(options_.do_vibrate);
207 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800208 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000209 EXPECT_FALSE(options_.do_progress_updates);
210 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800211 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700212 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800213 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000214}
215
216TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
217 // clang-format off
218 char* argv[] = {
219 const_cast<char*>("dumpstate"),
220 const_cast<char*>("-s"),
221 };
222 // clang-format on
223
224 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
225
226 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800227 EXPECT_TRUE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000228
229 // Other options retain default values
230 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800231 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000232 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800233 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000234 EXPECT_FALSE(options_.do_progress_updates);
235 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700236 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800237 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000238}
239
240TEST_F(DumpOptionsTest, InitializeFullBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800241 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800242 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800243 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
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) {
Paul Changf59c2b72020-03-10 02:08:55 +0800256 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, 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);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800259 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000260
261 // Other options retain default values
262 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800263 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000264 EXPECT_FALSE(options_.show_header_only);
265 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800266 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700267 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000268}
269
270TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800271 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000272 EXPECT_TRUE(options_.is_remote_mode);
273 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800274 EXPECT_FALSE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800275 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000276
277 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800278 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000279 EXPECT_FALSE(options_.show_header_only);
280 EXPECT_FALSE(options_.do_progress_updates);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800281 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700282 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000283}
284
285TEST_F(DumpOptionsTest, InitializeWearBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800286 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
Paul Chang0d2aad72020-02-13 20:04:03 +0800287 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000288 EXPECT_TRUE(options_.do_progress_updates);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800289 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000290
291 // Other options retain default values
292 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800293 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000294 EXPECT_FALSE(options_.show_header_only);
295 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800296 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700297 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000298}
299
300TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800301 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800302 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000303 EXPECT_TRUE(options_.telephony_only);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800304 EXPECT_TRUE(options_.do_progress_updates);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800305 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000306
307 // Other options retain default values
308 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800309 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000310 EXPECT_FALSE(options_.show_header_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000311 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800312 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700313 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000314}
315
316TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800317 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
Paul Chang0d2aad72020-02-13 20:04:03 +0800318 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000319 EXPECT_TRUE(options_.wifi_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800320 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000321
322 // Other options retain default values
323 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800324 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000325 EXPECT_FALSE(options_.show_header_only);
326 EXPECT_FALSE(options_.do_progress_updates);
327 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800328 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700329 EXPECT_FALSE(options_.limited_only);
330}
331
332TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
333 // clang-format off
334 char* argv[] = {
335 const_cast<char*>("dumpstatez"),
336 const_cast<char*>("-S"),
mhasankd451a472020-05-26 18:02:39 -0700337 const_cast<char*>("-q"),
mhasank2d75c442020-06-11 15:05:25 -0700338 const_cast<char*>("-L"),
339 const_cast<char*>("-o abc")
mhasankd451a472020-05-26 18:02:39 -0700340 };
341 // clang-format on
342
343 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
344
345 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800346 EXPECT_TRUE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700347 EXPECT_FALSE(options_.do_vibrate);
348 EXPECT_TRUE(options_.limited_only);
mhasank3a4cfb42020-06-15 18:06:43 -0700349 EXPECT_EQ(" abc", std::string(options_.out_dir));
mhasankd451a472020-05-26 18:02:39 -0700350
351 // Other options retain default values
352 EXPECT_FALSE(options_.show_header_only);
353 EXPECT_FALSE(options_.do_screenshot);
354 EXPECT_FALSE(options_.do_progress_updates);
355 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800356 EXPECT_FALSE(options_.stream_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700357 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000358}
359
360TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
361 // default: commandline options are not overridden
362 // clang-format off
363 char* argv[] = {
364 const_cast<char*>("bugreport"),
365 const_cast<char*>("-d"),
366 const_cast<char*>("-p"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000367 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000368 };
369 // clang-format on
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000370 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
371
372 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Paul Chang0d2aad72020-02-13 20:04:03 +0800373 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800374 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000375
376 // Other options retain default values
377 EXPECT_TRUE(options_.do_vibrate);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800378 EXPECT_FALSE(options_.progress_updates_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000379 EXPECT_FALSE(options_.show_header_only);
380 EXPECT_FALSE(options_.do_progress_updates);
381 EXPECT_FALSE(options_.is_remote_mode);
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800382 EXPECT_FALSE(options_.stream_to_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000383 EXPECT_FALSE(options_.wifi_only);
mhasankd451a472020-05-26 18:02:39 -0700384 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100385}
386
387TEST_F(DumpOptionsTest, InitializePartial1) {
388 // clang-format off
389 char* argv[] = {
390 const_cast<char*>("dumpstate"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100391 const_cast<char*>("-s"),
392 const_cast<char*>("-S"),
393
394 };
395 // clang-format on
396
397 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
398
399 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100400 // TODO: Maybe we should trim the filename
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800401 EXPECT_TRUE(options_.stream_to_socket);
402 EXPECT_TRUE(options_.progress_updates_to_socket);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100403
404 // Other options retain default values
405 EXPECT_FALSE(options_.show_header_only);
406 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800407 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100408 EXPECT_FALSE(options_.do_progress_updates);
409 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700410 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800411 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100412}
413
414TEST_F(DumpOptionsTest, InitializePartial2) {
415 // clang-format off
416 char* argv[] = {
417 const_cast<char*>("dumpstate"),
418 const_cast<char*>("-v"),
419 const_cast<char*>("-q"),
420 const_cast<char*>("-p"),
421 const_cast<char*>("-P"),
422 const_cast<char*>("-R"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100423 };
424 // clang-format on
425
426 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
427
428 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
429 EXPECT_TRUE(options_.show_header_only);
430 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800431 EXPECT_TRUE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100432 EXPECT_TRUE(options_.do_progress_updates);
433 EXPECT_TRUE(options_.is_remote_mode);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100434
435 // Other options retain default values
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800436 EXPECT_FALSE(options_.stream_to_socket);
437 EXPECT_FALSE(options_.progress_updates_to_socket);
mhasankd451a472020-05-26 18:02:39 -0700438 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800439 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100440}
441
442TEST_F(DumpOptionsTest, InitializeHelp) {
443 // clang-format off
444 char* argv[] = {
445 const_cast<char*>("dumpstate"),
446 const_cast<char*>("-h")
447 };
448 // clang-format on
449
450 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
451
452 // -h is for help.
453 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
454}
455
456TEST_F(DumpOptionsTest, InitializeUnknown) {
457 // clang-format off
458 char* argv[] = {
459 const_cast<char*>("dumpstate"),
460 const_cast<char*>("-u") // unknown flag
461 };
462 // clang-format on
463
464 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
465
466 // -u is unknown.
467 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
468}
469
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800470TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage1) {
471 options_.progress_updates_to_socket = true;
472 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100473 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000474
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800475 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100476 EXPECT_TRUE(options_.ValidateOptions());
477}
478
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800479TEST_F(DumpOptionsTest, ValidateOptionsSocketUsage2) {
Abhijeet Kaure370d682019-10-01 16:49:30 +0100480 options_.do_progress_updates = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000481 // Writing to socket = !writing to file.
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800482 options_.stream_to_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100483 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000484
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800485 options_.stream_to_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100486 EXPECT_TRUE(options_.ValidateOptions());
487}
488
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100489TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800490 options_.do_progress_updates = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100491 options_.is_remote_mode = true;
492 EXPECT_FALSE(options_.ValidateOptions());
493
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800494 options_.do_progress_updates = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100495 EXPECT_TRUE(options_.ValidateOptions());
496}
497
Felipe Leme7447d7c2016-11-03 18:12:22 -0700498class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700499 public:
500 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800501 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700502 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700503 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700504 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100505 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700506 }
507
Rhed Jao1c855122020-07-16 17:37:39 +0800508 void TearDown() {
509 ds.ShutdownDumpPool();
510 }
511
Felipe Leme4c2d6632016-09-28 14:32:00 -0700512 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700513 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700514 const CommandOptions& options = CommandOptions::DEFAULT) {
515 CaptureStdout();
516 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700517 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700518 out = GetCapturedStdout();
519 err = GetCapturedStderr();
520 return status;
521 }
522
Felipe Lemecef02982016-10-03 17:22:22 -0700523 // Dumps a file and capture `stdout` and `stderr`.
524 int DumpFile(const std::string& title, const std::string& path) {
525 CaptureStdout();
526 CaptureStderr();
527 int status = ds.DumpFile(title, path);
528 out = GetCapturedStdout();
529 err = GetCapturedStderr();
530 return status;
531 }
532
Nandana Dutt402a8392019-06-14 14:25:13 +0100533 void SetProgress(long progress, long initial_max) {
534 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100535 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700536 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
537 }
538
Rhed Jao1c855122020-07-16 17:37:39 +0800539 void EnableParallelRunIfNeeded() {
540 ds.EnableParallelRunIfNeeded();
541 }
542
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100543 std::string GetProgressMessage(int progress, int max,
544 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700545 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
546 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700547
Felipe Leme7447d7c2016-11-03 18:12:22 -0700548 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700549
Felipe Leme009ecbb2016-11-07 10:18:44 -0800550 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700551 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800552 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700553 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700554 }
555
Felipe Leme009ecbb2016-11-07 10:18:44 -0800556 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100557 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
558 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800559 }
560
561 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700562 }
563
Felipe Leme4c2d6632016-09-28 14:32:00 -0700564 // `stdout` and `stderr` from the last command ran.
565 std::string out, err;
566
Felipe Lemefd8affa2016-09-30 17:38:57 -0700567 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700568};
569
570TEST_F(DumpstateTest, RunCommandNoArgs) {
571 EXPECT_EQ(-1, RunCommand("", {}));
572}
573
574TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700575 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700576 EXPECT_THAT(out, StrEq("stdout\n"));
577 EXPECT_THAT(err, StrEq("stderr\n"));
578}
579
580TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700581 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700582 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700583 // The duration may not get output, depending on how long it takes,
584 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700585 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000586 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700587}
588
Felipe Lemefd8affa2016-09-30 17:38:57 -0700589TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700590 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700591 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700592 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
593 EXPECT_THAT(out, StrEq("stdout\n"));
594 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
595}
596
597TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700598 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700599 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700600 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700601 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700602}
603
604TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700605 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700606 EXPECT_THAT(err, IsEmpty());
607 EXPECT_THAT(out, StrEq("one\n"));
608}
609
Felipe Lemefd8affa2016-09-30 17:38:57 -0700610TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700611 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700612 EXPECT_THAT(err, IsEmpty());
613 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
614}
615
616TEST_F(DumpstateTest, RunCommandDryRun) {
617 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700618 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700619 // The duration may not get output, depending on how long it takes,
620 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700621 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000622 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700623 EXPECT_THAT(err, IsEmpty());
624}
625
626TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
627 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700628 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700629 EXPECT_THAT(out, IsEmpty());
630 EXPECT_THAT(err, IsEmpty());
631}
632
633TEST_F(DumpstateTest, RunCommandDryRunAlways) {
634 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700635 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700636 EXPECT_THAT(out, StrEq("stdout\n"));
637 EXPECT_THAT(err, StrEq("stderr\n"));
638}
639
Felipe Lemefd8affa2016-09-30 17:38:57 -0700640TEST_F(DumpstateTest, RunCommandNotFound) {
641 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
642 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
643 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
644}
645
646TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700647 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
648 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700649 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700650 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700651 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700652}
653
654TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700655 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700656 // We don't know the exit code, so check just the prefix.
657 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700658 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700659 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700660 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700661}
662
663TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700664 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700665 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700666 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700667 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700668 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700669 " --sleep 2' timed out after 1"));
670}
671
672TEST_F(DumpstateTest, RunCommandIsKilled) {
673 CaptureStdout();
674 CaptureStderr();
675
676 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700677 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700678 CommandOptions::WithTimeout(100).Always().Build()));
679 });
680
681 // Capture pid and pre-sleep output.
682 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
683 std::string err = GetCapturedStderr();
684 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
685
686 std::string out = GetCapturedStdout();
687 std::vector<std::string> lines = android::base::Split(out, "\n");
688 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
689
690 int pid = atoi(lines[0].c_str());
691 EXPECT_THAT(lines[1], StrEq("stdout line1"));
692 EXPECT_THAT(lines[2], IsEmpty()); // \n
693
694 // Then kill the process.
695 CaptureStdout();
696 CaptureStderr();
697 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
698 t.join();
699
700 // Finally, check output after murder.
701 out = GetCapturedStdout();
702 err = GetCapturedStderr();
703
Felipe Leme7447d7c2016-11-03 18:12:22 -0700704 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700705 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700706 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700707 " --pid --sleep 20' failed: killed by signal 15\n"));
708}
709
Felipe Leme75876a22016-10-27 16:31:27 -0700710TEST_F(DumpstateTest, RunCommandProgress) {
711 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
712 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700713 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700714
Nandana Duttbabf6c72019-01-15 14:11:12 +0000715 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700716 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100717 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700718 EXPECT_THAT(out, StrEq("stdout\n"));
719 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
720
Nandana Dutt402a8392019-06-14 14:25:13 +0100721 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
722 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100723 progress_message = GetProgressMessage(24, 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
727 // Make sure command ran while in dry_run is counted.
728 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100729 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
730 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100731 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700732 EXPECT_THAT(out, IsEmpty());
733 EXPECT_THAT(err, StrEq(progress_message));
734
Nandana Dutt402a8392019-06-14 14:25:13 +0100735 SetDryRun(false);
736 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
737 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100738 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800739 EXPECT_THAT(out, StrEq("stdout\n"));
740 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
741
Nandana Dutt402a8392019-06-14 14:25:13 +0100742 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800743 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100744 progress_message = GetProgressMessage(30, 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
748 ds.listener_.clear();
749}
750
Felipe Lemed80e6b62016-10-03 13:08:14 -0700751TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800752 if (!IsStandalone()) {
753 // TODO: temporarily disabled because it might cause other tests to fail after dropping
754 // to Shell - need to refactor tests to avoid this problem)
755 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
756 return;
757 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700758 // First check root case - only available when running with 'adb root'.
759 uid_t uid = getuid();
760 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700761 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700762 EXPECT_THAT(out, StrEq("0\nstdout\n"));
763 EXPECT_THAT(err, StrEq("stderr\n"));
764 return;
765 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700766 // Then run dropping root.
767 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700768 CommandOptions::WithTimeout(1).DropRoot().Build()));
769 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700770 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700771}
772
773TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800774 if (!IsStandalone()) {
775 // TODO: temporarily disabled because it might cause other tests to fail after dropping
776 // to Shell - need to refactor tests to avoid this problem)
777 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
778 return;
779 }
Felipe Lemef0292972016-11-22 13:57:05 -0800780 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700781 // Emulates user build if necessarily.
782 SetBuildType("user");
783 }
784
785 DropRoot();
786
Felipe Leme7447d7c2016-11-03 18:12:22 -0700787 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700788
789 // We don't know the exact path of su, so we just check for the 'root ...' commands
790 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700791 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700792 EXPECT_THAT(err, IsEmpty());
793}
794
Felipe Leme46b85da2016-11-21 17:40:45 -0800795TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
796 if (!IsStandalone()) {
797 // TODO: temporarily disabled because it might cause other tests to fail after dropping
798 // to Shell - need to refactor tests to avoid this problem)
799 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
800 return;
801 }
Felipe Lemef0292972016-11-22 13:57:05 -0800802 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800803 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
804 return;
805 }
806
807 DropRoot();
808
809 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
810 CommandOptions::WithTimeout(1).AsRoot().Build()));
811
812 EXPECT_THAT(out, StrEq("0\nstdout\n"));
813 EXPECT_THAT(err, StrEq("stderr\n"));
814}
815
Nandana Dutt4b392be2018-11-02 16:17:05 +0000816TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
817 if (!IsStandalone()) {
818 // TODO: temporarily disabled because it might cause other tests to fail after dropping
819 // to Shell - need to refactor tests to avoid this problem)
820 MYLOGE(
821 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
822 "on test suite\n")
823 return;
824 }
825 if (PropertiesHelper::IsUserBuild()) {
826 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
827 return;
828 }
829
830 // Same test as above, but with unroot property set, which will override su availability.
831 SetUnroot(true);
832 DropRoot();
833
834 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
835 CommandOptions::WithTimeout(1).AsRoot().Build()));
836
837 // AsRoot is ineffective.
838 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
839 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
840}
841
Yifan Hong48e83a12017-10-03 14:10:07 -0700842TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
843 if (!IsStandalone()) {
844 // TODO: temporarily disabled because it might cause other tests to fail after dropping
845 // to Shell - need to refactor tests to avoid this problem)
846 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
847 return;
848 }
849 if (!PropertiesHelper::IsUserBuild()) {
850 // Emulates user build if necessarily.
851 SetBuildType("user");
852 }
853
854 DropRoot();
855
856 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
857 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
858
859 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
860 EXPECT_THAT(err, StrEq("stderr\n"));
861}
862
863TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
864 if (!IsStandalone()) {
865 // TODO: temporarily disabled because it might cause other tests to fail after dropping
866 // to Shell - need to refactor tests to avoid this problem)
867 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
868 return;
869 }
870 if (PropertiesHelper::IsUserBuild()) {
871 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
872 return;
873 }
874
875 DropRoot();
876
877 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
878 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
879
880 EXPECT_THAT(out, StrEq("0\nstdout\n"));
881 EXPECT_THAT(err, StrEq("stderr\n"));
882}
883
Nandana Dutt4b392be2018-11-02 16:17:05 +0000884TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
885 if (!IsStandalone()) {
886 // TODO: temporarily disabled because it might cause other tests to fail after dropping
887 // to Shell - need to refactor tests to avoid this problem)
888 MYLOGE(
889 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
890 "on test suite\n")
891 return;
892 }
893 if (PropertiesHelper::IsUserBuild()) {
894 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
895 return;
896 }
897 // Same test as above, but with unroot property set, which will override su availability.
898 SetUnroot(true);
899
900 DropRoot();
901
902 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
903 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
904
905 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
906 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
907 EXPECT_THAT(err, StrEq("stderr\n"));
908}
909
Felipe Lemecef02982016-10-03 17:22:22 -0700910TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
911 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
912 EXPECT_THAT(out,
913 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
914 EXPECT_THAT(err, IsEmpty());
915}
916
917TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
918 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
919 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700920 // The duration may not get output, depending on how long it takes,
921 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700922 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
923 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700924}
925
926TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700927 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700928 EXPECT_THAT(err, IsEmpty());
929 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
930}
931
932TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700933 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700934 EXPECT_THAT(err, IsEmpty());
935 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
936}
937
938TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700939 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700940 EXPECT_THAT(err, IsEmpty());
941 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
942}
943
944TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700945 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.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, DumpFileOnDryRunNoTitle) {
951 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700952 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700953 EXPECT_THAT(err, IsEmpty());
954 EXPECT_THAT(out, IsEmpty());
955}
956
957TEST_F(DumpstateTest, DumpFileOnDryRun) {
958 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700959 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700960 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800961 EXPECT_THAT(
962 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +0000963 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700964}
965
Felipe Leme75876a22016-10-27 16:31:27 -0700966TEST_F(DumpstateTest, DumpFileUpdateProgress) {
967 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
968 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700969 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700970
Nandana Duttbabf6c72019-01-15 14:11:12 +0000971 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700972 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -0700973
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100974 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -0700975 EXPECT_THAT(err, StrEq(progress_message));
976 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
977
978 ds.listener_.clear();
979}
980
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800981TEST_F(DumpstateTest, DumpPool_withParallelRunEnabled_notNull) {
Rhed Jao1c855122020-07-16 17:37:39 +0800982 SetParallelRun(true);
983 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800984 EXPECT_TRUE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800985 EXPECT_TRUE(ds.dump_pool_);
986}
987
Rhed Jao1c855122020-07-16 17:37:39 +0800988TEST_F(DumpstateTest, DumpPool_withParallelRunDisabled_isNull) {
989 SetParallelRun(false);
990 EnableParallelRunIfNeeded();
Rhed Jao4875aa62020-07-20 17:46:29 +0800991 EXPECT_FALSE(ds.zip_entry_tasks_);
Rhed Jao1c855122020-07-16 17:37:39 +0800992 EXPECT_FALSE(ds.dump_pool_);
993}
994
Dieter Hsu105ad0c2020-09-29 15:23:33 +0800995class ZippedBugReportStreamTest : public DumpstateBaseTest {
996 public:
997 void SetUp() {
998 DumpstateBaseTest::SetUp();
999 ds_.options_.reset(new Dumpstate::DumpOptions());
1000 }
1001 void TearDown() {
1002 CloseArchive(handle_);
1003 }
1004
1005 // Set bugreport mode and options before here.
1006 void GenerateBugreport() {
1007 ds_.Initialize();
1008 EXPECT_EQ(Dumpstate::RunStatus::OK, ds_.Run(/*calling_uid=*/-1, /*calling_package=*/""));
1009 }
1010
1011 // Most bugreports droproot, ensure the file can be opened by shell to verify file content.
1012 void CreateFd(const std::string& path, android::base::unique_fd* out_fd) {
1013 out_fd->reset(TEMP_FAILURE_RETRY(open(path.c_str(),
1014 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1015 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1016 ASSERT_GE(out_fd->get(), 0) << "could not create FD for path " << path;
1017 }
1018
1019 void VerifyEntry(const ZipArchiveHandle archive, const std::string_view entry_name,
1020 ZipEntry* data) {
1021 int32_t e = FindEntry(archive, entry_name, data);
1022 EXPECT_EQ(0, e) << ErrorCodeString(e) << " entry name: " << entry_name;
1023 }
1024
1025 // While testing dumpstate in process, using STDOUT may get confused about
1026 // the internal fd redirection. Redirect to a dedicate fd to save content.
1027 void RedirectOutputToFd(android::base::unique_fd& ufd) {
1028 ds_.open_socket_fn_ = [&](const char*) -> int { return ufd.release(); };
1029 };
1030
1031 Dumpstate& ds_ = Dumpstate::GetInstance();
1032 ZipArchiveHandle handle_;
1033};
1034
Rhed Jaob8b56172021-04-08 20:14:27 +08001035// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
1036TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
1037 std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001038 android::base::unique_fd out_fd;
1039 CreateFd(out_path, &out_fd);
Rhed Jaob8b56172021-04-08 20:14:27 +08001040 ds_.options_->limited_only = true;
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001041 ds_.options_->stream_to_socket = true;
1042 RedirectOutputToFd(out_fd);
1043
1044 GenerateBugreport();
1045 OpenArchive(out_path.c_str(), &handle_);
1046
1047 ZipEntry entry;
1048 VerifyEntry(handle_, "main_entry.txt", &entry);
1049 std::string bugreport_txt_name;
1050 bugreport_txt_name.resize(entry.uncompressed_length);
1051 ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
1052 entry.uncompressed_length);
1053 EXPECT_THAT(bugreport_txt_name,
Rhed Jaob8b56172021-04-08 20:14:27 +08001054 testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
Dieter Hsu105ad0c2020-09-29 15:23:33 +08001055 VerifyEntry(handle_, bugreport_txt_name, &entry);
1056}
1057
Felipe Leme7447d7c2016-11-03 18:12:22 -07001058class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -07001059 public:
1060 DumpstateService dss;
1061};
1062
Felipe Leme7447d7c2016-11-03 18:12:22 -07001063class ProgressTest : public DumpstateBaseTest {
1064 public:
1065 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1066 return Progress(max, growth_factor, path);
1067 }
1068
1069 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1070 std::string expected_content =
1071 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1072 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001073 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001074 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1075 }
1076};
1077
1078TEST_F(ProgressTest, SimpleTest) {
1079 Progress progress;
1080 EXPECT_EQ(0, progress.Get());
1081 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1082 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1083
1084 bool max_increased = progress.Inc(1);
1085 EXPECT_EQ(1, progress.Get());
1086 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1087 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1088 EXPECT_FALSE(max_increased);
1089
1090 // Ignore negative increase.
1091 max_increased = progress.Inc(-1);
1092 EXPECT_EQ(1, progress.Get());
1093 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1094 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1095 EXPECT_FALSE(max_increased);
1096}
1097
1098TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1099 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1100 EXPECT_EQ(0, progress.Get());
1101 EXPECT_EQ(10, progress.GetInitialMax());
1102 EXPECT_EQ(10, progress.GetMax());
1103
1104 // No increase
1105 bool max_increased = progress.Inc(10);
1106 EXPECT_EQ(10, progress.Get());
1107 EXPECT_EQ(10, progress.GetMax());
1108 EXPECT_FALSE(max_increased);
1109
1110 // Increase, with new value < max*20%
1111 max_increased = progress.Inc(1);
1112 EXPECT_EQ(11, progress.Get());
1113 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1114 EXPECT_TRUE(max_increased);
1115}
1116
1117TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1118 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1119 EXPECT_EQ(0, progress.Get());
1120 EXPECT_EQ(10, progress.GetInitialMax());
1121 EXPECT_EQ(10, progress.GetMax());
1122
1123 // No increase
1124 bool max_increased = progress.Inc(10);
1125 EXPECT_EQ(10, progress.Get());
1126 EXPECT_EQ(10, progress.GetMax());
1127 EXPECT_FALSE(max_increased);
1128
1129 // Increase, with new value > max*20%
1130 max_increased = progress.Inc(5);
1131 EXPECT_EQ(15, progress.Get());
1132 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1133 EXPECT_TRUE(max_increased);
1134}
1135
1136TEST_F(ProgressTest, InvalidPath) {
1137 Progress progress("/devil/null");
1138 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1139}
1140
1141TEST_F(ProgressTest, EmptyFile) {
1142 Progress progress(CopyTextFileFixture("empty-file.txt"));
1143 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1144}
1145
1146TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1147 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1148 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1149}
1150
1151TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1152 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1153 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1154}
1155
1156TEST_F(ProgressTest, InvalidLineBothNAN) {
1157 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1158 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1159}
1160
1161TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1162 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1163 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1164}
1165
1166TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1167 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1168 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1169}
1170
1171TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1172 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1173 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1174}
1175
1176TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1177 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1178 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1179}
1180
1181// Tests stats are properly saved when the file does not exists.
1182TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001183 if (!IsStandalone()) {
1184 // TODO: temporarily disabled because it's failing when running as suite
1185 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1186 return;
1187 }
1188
Felipe Leme7447d7c2016-11-03 18:12:22 -07001189 std::string path = kTestDataPath + "FirstTime.txt";
1190 android::base::RemoveFileIfExists(path);
1191
1192 Progress run1(path);
1193 EXPECT_EQ(0, run1.Get());
1194 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1195 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1196
1197 bool max_increased = run1.Inc(20);
1198 EXPECT_EQ(20, run1.Get());
1199 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1200 EXPECT_FALSE(max_increased);
1201
1202 run1.Save();
1203 AssertStats(path, 1, 20);
1204}
1205
1206// Tests what happens when the persistent settings contains the average duration of 1 run.
1207// Data on file is 1 run and 109 average.
1208TEST_F(ProgressTest, SecondTime) {
1209 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1210
1211 Progress run1 = GetInstance(-42, 1.2, path);
1212 EXPECT_EQ(0, run1.Get());
1213 EXPECT_EQ(10, run1.GetInitialMax());
1214 EXPECT_EQ(10, run1.GetMax());
1215
1216 bool max_increased = run1.Inc(20);
1217 EXPECT_EQ(20, run1.Get());
1218 EXPECT_EQ(24, run1.GetMax());
1219 EXPECT_TRUE(max_increased);
1220
1221 // Average now is 2 runs and (10 + 20)/ 2 = 15
1222 run1.Save();
1223 AssertStats(path, 2, 15);
1224
1225 Progress run2 = GetInstance(-42, 1.2, path);
1226 EXPECT_EQ(0, run2.Get());
1227 EXPECT_EQ(15, run2.GetInitialMax());
1228 EXPECT_EQ(15, run2.GetMax());
1229
1230 max_increased = run2.Inc(25);
1231 EXPECT_EQ(25, run2.Get());
1232 EXPECT_EQ(30, run2.GetMax());
1233 EXPECT_TRUE(max_increased);
1234
1235 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1236 run2.Save();
1237 AssertStats(path, 3, 18);
1238
1239 Progress run3 = GetInstance(-42, 1.2, path);
1240 EXPECT_EQ(0, run3.Get());
1241 EXPECT_EQ(18, run3.GetInitialMax());
1242 EXPECT_EQ(18, run3.GetMax());
1243
1244 // Make sure average decreases as well
1245 max_increased = run3.Inc(5);
1246 EXPECT_EQ(5, run3.Get());
1247 EXPECT_EQ(18, run3.GetMax());
1248 EXPECT_FALSE(max_increased);
1249
1250 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1251 run3.Save();
1252 AssertStats(path, 4, 14);
1253}
1254
1255// Tests what happens when the persistent settings contains the average duration of 2 runs.
1256// Data on file is 2 runs and 15 average.
1257TEST_F(ProgressTest, ThirdTime) {
1258 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1259 AssertStats(path, 2, 15); // Sanity check
1260
1261 Progress run1 = GetInstance(-42, 1.2, path);
1262 EXPECT_EQ(0, run1.Get());
1263 EXPECT_EQ(15, run1.GetInitialMax());
1264 EXPECT_EQ(15, run1.GetMax());
1265
1266 bool max_increased = run1.Inc(20);
1267 EXPECT_EQ(20, run1.Get());
1268 EXPECT_EQ(24, run1.GetMax());
1269 EXPECT_TRUE(max_increased);
1270
1271 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1272 run1.Save();
1273 AssertStats(path, 3, 16);
1274}
1275
Felipe Leme46b85da2016-11-21 17:40:45 -08001276class DumpstateUtilTest : public DumpstateBaseTest {
1277 public:
1278 void SetUp() {
1279 DumpstateBaseTest::SetUp();
1280 SetDryRun(false);
1281 }
1282
Felipe Leme46b85da2016-11-21 17:40:45 -08001283 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001284 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001285 }
1286
1287 void CreateFd(const std::string& name) {
1288 path_ = kTestDataPath + name;
1289 MYLOGD("Creating fd for file %s\n", path_.c_str());
1290
1291 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1292 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1293 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1294 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1295 }
1296
1297 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001298 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001299 const CommandOptions& options = CommandOptions::DEFAULT) {
1300 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001301 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001302 close(fd);
1303
1304 CaptureFdOut();
1305 err = GetCapturedStderr();
1306 return status;
1307 }
1308
1309 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001310 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001311 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001312 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001313 close(fd);
1314
1315 CaptureFdOut();
1316 err = GetCapturedStderr();
1317 return status;
1318 }
1319
1320 int fd;
1321
1322 // 'fd` output and `stderr` from the last command ran.
1323 std::string out, err;
1324
1325 private:
1326 std::string path_;
1327};
1328
1329TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001330 CreateFd("RunCommandNoArgs.txt");
1331 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001332}
1333
Felipe Lemef0292972016-11-22 13:57:05 -08001334TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001335 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001336 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001337 EXPECT_THAT(out, StrEq("stdout\n"));
1338 EXPECT_THAT(err, StrEq("stderr\n"));
1339}
1340
Felipe Lemef0292972016-11-22 13:57:05 -08001341TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1342 CreateFd("RunCommandWithNoArgs.txt");
1343 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1344 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1345 EXPECT_THAT(err, StrEq("stderr\n"));
1346}
1347
Felipe Leme46b85da2016-11-21 17:40:45 -08001348TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1349 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001350 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001351 EXPECT_THAT(err, IsEmpty());
1352 EXPECT_THAT(out, StrEq("one\n"));
1353}
1354
1355TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1356 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001357 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001358 EXPECT_THAT(err, IsEmpty());
1359 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1360}
1361
1362TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1363 CreateFd("RunCommandWithLoggingMessage.txt");
1364 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001365 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001366 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1367 EXPECT_THAT(out, StrEq("stdout\n"));
1368 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1369}
1370
1371TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1372 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001373 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1374 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001375 EXPECT_THAT(out, IsEmpty());
1376 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1377}
1378
1379TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1380 CreateFd("RunCommandDryRun.txt");
1381 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001382 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1383 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1384 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1385 kSimpleCommand.c_str())));
1386 EXPECT_THAT(err, IsEmpty());
1387}
1388
1389TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1390 CreateFd("RunCommandDryRun.txt");
1391 SetDryRun(true);
1392 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001393 EXPECT_THAT(
1394 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1395 EXPECT_THAT(err, IsEmpty());
1396}
1397
1398TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1399 CreateFd("RunCommandDryRunAlways.txt");
1400 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001401 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001402 EXPECT_THAT(out, StrEq("stdout\n"));
1403 EXPECT_THAT(err, StrEq("stderr\n"));
1404}
1405
1406TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1407 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001408 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001409 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1410 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1411}
1412
1413TEST_F(DumpstateUtilTest, RunCommandFails) {
1414 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001415 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001416 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1417 " --exit 42' failed: exit code 42\n"));
1418 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1419 " --exit 42' failed: exit code 42\n"));
1420}
1421
1422TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1423 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001424 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001425 // We don't know the exit code, so check just the prefix.
1426 EXPECT_THAT(
1427 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1428 EXPECT_THAT(
1429 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1430}
1431
Vishnu Nair6921f802017-11-22 09:17:23 -08001432TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001433 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001434 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1435 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001436 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1437 " --sleep 2' timed out after 1"));
1438 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1439 " --sleep 2' timed out after 1"));
1440}
1441
Vishnu Nair6921f802017-11-22 09:17:23 -08001442TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1443 CreateFd("RunCommandTimesout.txt");
1444 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1445 CommandOptions::WithTimeoutInMs(1000).Build()));
1446 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1447 " --sleep 2' timed out after 1"));
1448 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1449 " --sleep 2' timed out after 1"));
1450}
1451
1452
Felipe Leme46b85da2016-11-21 17:40:45 -08001453TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1454 CreateFd("RunCommandIsKilled.txt");
1455 CaptureStderr();
1456
1457 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001458 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001459 CommandOptions::WithTimeout(100).Always().Build()));
1460 });
1461
1462 // Capture pid and pre-sleep output.
1463 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1464 std::string err = GetCapturedStderr();
1465 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1466
1467 CaptureFdOut();
1468 std::vector<std::string> lines = android::base::Split(out, "\n");
1469 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1470
1471 int pid = atoi(lines[0].c_str());
1472 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1473 EXPECT_THAT(lines[2], IsEmpty()); // \n
1474
1475 // Then kill the process.
1476 CaptureFdOut();
1477 CaptureStderr();
1478 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1479 t.join();
1480
1481 // Finally, check output after murder.
1482 CaptureFdOut();
1483 err = GetCapturedStderr();
1484
1485 // out starts with the pid, which is an unknown
1486 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1487 " --pid --sleep 20' failed: killed by signal 15\n"));
1488 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1489 " --pid --sleep 20' failed: killed by signal 15\n"));
1490}
1491
1492TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1493 if (!IsStandalone()) {
1494 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1495 // to Shell - need to refactor tests to avoid this problem)
1496 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1497 return;
1498 }
1499 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001500 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001501 // Emulates user build if necessarily.
1502 SetBuildType("user");
1503 }
1504
1505 DropRoot();
1506
Felipe Lemef0292972016-11-22 13:57:05 -08001507 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001508
1509 // We don't know the exact path of su, so we just check for the 'root ...' commands
1510 EXPECT_THAT(out, StartsWith("Skipping"));
1511 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1512 EXPECT_THAT(err, IsEmpty());
1513}
1514
1515TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1516 if (!IsStandalone()) {
1517 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1518 // to Shell - need to refactor tests to avoid this problem)
1519 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1520 return;
1521 }
1522 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001523 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001524 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1525 return;
1526 }
1527
1528 DropRoot();
1529
Felipe Lemef0292972016-11-22 13:57:05 -08001530 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1531 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001532
1533 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1534 EXPECT_THAT(err, StrEq("stderr\n"));
1535}
Felipe Leme46b85da2016-11-21 17:40:45 -08001536
Yifan Hong48e83a12017-10-03 14:10:07 -07001537
1538TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1539 if (!IsStandalone()) {
1540 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1541 // to Shell - need to refactor tests to avoid this problem)
1542 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1543 return;
1544 }
1545 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1546 if (!PropertiesHelper::IsUserBuild()) {
1547 // Emulates user build if necessarily.
1548 SetBuildType("user");
1549 }
1550
1551 DropRoot();
1552
1553 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1554 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1555
1556 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1557 EXPECT_THAT(err, StrEq("stderr\n"));
1558}
1559
1560TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
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.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1565 return;
1566 }
1567 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1568 if (PropertiesHelper::IsUserBuild()) {
1569 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1570 return;
1571 }
1572
1573 DropRoot();
1574
1575 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1576 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1577
1578 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1579 EXPECT_THAT(err, StrEq("stderr\n"));
1580}
1581
Felipe Leme46b85da2016-11-21 17:40:45 -08001582TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
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.RunCommandDropRoot() on test suite\n")
1587 return;
1588 }
1589 CreateFd("RunCommandDropRoot.txt");
1590 // First check root case - only available when running with 'adb root'.
1591 uid_t uid = getuid();
1592 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001593 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001594 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1595 EXPECT_THAT(err, StrEq("stderr\n"));
1596 return;
1597 }
1598 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001599 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001600 CommandOptions::WithTimeout(1).DropRoot().Build()));
1601 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1602 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1603}
1604
Felipe Lemef0292972016-11-22 13:57:05 -08001605TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001606 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001607 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001608 EXPECT_THAT(out,
1609 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1610 EXPECT_THAT(err, IsEmpty());
1611}
1612
Felipe Lemef0292972016-11-22 13:57:05 -08001613TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1614 CreateFd("DumpFileNotFound.txt");
1615 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1616 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1617 "file or directory\n"));
1618 EXPECT_THAT(err, IsEmpty());
1619}
1620
Felipe Leme46b85da2016-11-21 17:40:45 -08001621TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1622 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001623 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001624 EXPECT_THAT(err, IsEmpty());
1625 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1626}
1627
1628TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1629 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001630 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001631 EXPECT_THAT(err, IsEmpty());
1632 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1633}
1634
1635TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1636 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001637 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001638 EXPECT_THAT(err, IsEmpty());
1639 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1640}
1641
1642TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1643 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001644 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001645 EXPECT_THAT(err, IsEmpty());
1646 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1647}
1648
Felipe Lemef0292972016-11-22 13:57:05 -08001649TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1650 CreateFd("DumpFileOnDryRun.txt");
1651 SetDryRun(true);
1652 std::string path = kTestDataPath + "single-line.txt";
1653 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1654 EXPECT_THAT(err, IsEmpty());
1655 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1656}
1657
Felipe Leme46b85da2016-11-21 17:40:45 -08001658TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1659 CreateFd("DumpFileOnDryRun.txt");
1660 SetDryRun(true);
1661 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001662 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001663 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001664 EXPECT_THAT(
1665 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1666 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001667}
Ecco Park61ffcf72016-10-27 15:46:26 -07001668
Rhed Jao27077b12020-07-14 18:38:08 +08001669class DumpPoolTest : public DumpstateBaseTest {
1670 public:
1671 void SetUp() {
Rhed Jao1c855122020-07-16 17:37:39 +08001672 dump_pool_ = std::make_unique<DumpPool>(kTestDataPath);
Rhed Jao27077b12020-07-14 18:38:08 +08001673 DumpstateBaseTest::SetUp();
1674 CreateOutputFile();
1675 }
1676
1677 void CreateOutputFile() {
1678 out_path_ = kTestDataPath + "out.txt";
1679 out_fd_.reset(TEMP_FAILURE_RETRY(open(out_path_.c_str(),
1680 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1681 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)));
1682 ASSERT_GE(out_fd_.get(), 0) << "could not create FD for path "
1683 << out_path_;
1684 }
1685
1686 int getTempFileCounts(const std::string& folder) {
1687 int count = 0;
1688 std::unique_ptr<DIR, decltype(&closedir)> dir_ptr(opendir(folder.c_str()),
1689 &closedir);
1690 if (!dir_ptr) {
1691 return -1;
1692 }
1693 int dir_fd = dirfd(dir_ptr.get());
1694 if (dir_fd < 0) {
1695 return -1;
1696 }
1697
1698 struct dirent* de;
1699 while ((de = readdir(dir_ptr.get()))) {
1700 if (de->d_type != DT_REG) {
1701 continue;
1702 }
1703 std::string file_name(de->d_name);
1704 if (file_name.find(DumpPool::PREFIX_TMPFILE_NAME) != 0) {
1705 continue;
1706 }
1707 count++;
1708 }
1709 return count;
1710 }
1711
Rhed Jao1c855122020-07-16 17:37:39 +08001712 void setLogDuration(bool log_duration) {
1713 dump_pool_->setLogDuration(log_duration);
1714 }
1715
1716 std::unique_ptr<DumpPool> dump_pool_;
Rhed Jao27077b12020-07-14 18:38:08 +08001717 android::base::unique_fd out_fd_;
1718 std::string out_path_;
1719};
1720
Rhed Jao1c855122020-07-16 17:37:39 +08001721TEST_F(DumpPoolTest, EnqueueTaskWithFd) {
Rhed Jao27077b12020-07-14 18:38:08 +08001722 auto dump_func_1 = [](int out_fd) {
1723 dprintf(out_fd, "A");
1724 };
1725 auto dump_func_2 = [](int out_fd) {
1726 dprintf(out_fd, "B");
1727 sleep(1);
1728 };
1729 auto dump_func_3 = [](int out_fd) {
1730 dprintf(out_fd, "C");
1731 };
Rhed Jao1c855122020-07-16 17:37:39 +08001732 setLogDuration(/* log_duration = */false);
1733 dump_pool_->enqueueTaskWithFd(/* task_name = */"1", dump_func_1, std::placeholders::_1);
1734 dump_pool_->enqueueTaskWithFd(/* task_name = */"2", dump_func_2, std::placeholders::_1);
1735 dump_pool_->enqueueTaskWithFd(/* task_name = */"3", dump_func_3, std::placeholders::_1);
Rhed Jao27077b12020-07-14 18:38:08 +08001736
Rhed Jao1c855122020-07-16 17:37:39 +08001737 dump_pool_->waitForTask("1", "", out_fd_.get());
1738 dump_pool_->waitForTask("2", "", out_fd_.get());
1739 dump_pool_->waitForTask("3", "", out_fd_.get());
1740 dump_pool_->shutdown();
Rhed Jao27077b12020-07-14 18:38:08 +08001741
1742 std::string result;
1743 ReadFileToString(out_path_, &result);
1744 EXPECT_THAT(result, StrEq("A\nB\nC\n"));
1745 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao1c855122020-07-16 17:37:39 +08001746}
1747
1748TEST_F(DumpPoolTest, EnqueueTask_withDurationLog) {
1749 bool run_1 = false;
1750 auto dump_func_1 = [&]() {
1751 run_1 = true;
1752 };
1753
1754 dump_pool_->enqueueTask(/* task_name = */"1", dump_func_1);
1755 dump_pool_->waitForTask("1", "", out_fd_.get());
1756 dump_pool_->shutdown();
1757
1758 std::string result;
1759 ReadFileToString(out_path_, &result);
1760 EXPECT_TRUE(run_1);
1761 EXPECT_THAT(result, StrEq("------ 0.000s was the duration of '1' ------\n"));
1762 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
Rhed Jao27077b12020-07-14 18:38:08 +08001763}
1764
Rhed Jao34b041f2021-03-17 18:53:39 +08001765TEST_F(DumpPoolTest, Shutdown_withoutCrash) {
1766 bool run_1 = false;
1767 auto dump_func_1 = [&]() {
1768 run_1 = true;
1769 };
1770 auto dump_func = []() {
1771 sleep(1);
1772 };
1773
1774 dump_pool_->start(/* thread_counts = */1);
1775 dump_pool_->enqueueTask(/* task_name = */"1", dump_func_1);
1776 dump_pool_->enqueueTask(/* task_name = */"2", dump_func);
1777 dump_pool_->enqueueTask(/* task_name = */"3", dump_func);
1778 dump_pool_->enqueueTask(/* task_name = */"4", dump_func);
1779 dump_pool_->waitForTask("1", "", out_fd_.get());
1780 dump_pool_->shutdown();
1781
1782 EXPECT_TRUE(run_1);
1783 EXPECT_THAT(getTempFileCounts(kTestDataPath), Eq(0));
1784}
1785
Rhed Jao4875aa62020-07-20 17:46:29 +08001786class TaskQueueTest : public DumpstateBaseTest {
1787public:
1788 void SetUp() {
1789 DumpstateBaseTest::SetUp();
1790 }
1791
1792 TaskQueue task_queue_;
1793};
1794
1795TEST_F(TaskQueueTest, runTask) {
1796 bool is_task1_run = false;
1797 bool is_task2_run = false;
1798 auto task_1 = [&](bool task_cancelled) {
1799 if (task_cancelled) {
1800 return;
1801 }
1802 is_task1_run = true;
1803 };
1804 auto task_2 = [&](bool task_cancelled) {
1805 if (task_cancelled) {
1806 return;
1807 }
1808 is_task2_run = true;
1809 };
1810 task_queue_.add(task_1, std::placeholders::_1);
1811 task_queue_.add(task_2, std::placeholders::_1);
1812
1813 task_queue_.run(/* do_cancel = */false);
1814
1815 EXPECT_TRUE(is_task1_run);
1816 EXPECT_TRUE(is_task2_run);
1817}
1818
1819TEST_F(TaskQueueTest, runTask_withCancelled) {
1820 bool is_task1_cancelled = false;
1821 bool is_task2_cancelled = false;
1822 auto task_1 = [&](bool task_cancelled) {
1823 is_task1_cancelled = task_cancelled;
1824 };
1825 auto task_2 = [&](bool task_cancelled) {
1826 is_task2_cancelled = task_cancelled;
1827 };
1828 task_queue_.add(task_1, std::placeholders::_1);
1829 task_queue_.add(task_2, std::placeholders::_1);
1830
1831 task_queue_.run(/* do_cancel = */true);
1832
1833 EXPECT_TRUE(is_task1_cancelled);
1834 EXPECT_TRUE(is_task2_cancelled);
1835}
1836
Rhed Jao27077b12020-07-14 18:38:08 +08001837
Felipe Leme47e9be22016-12-21 15:37:07 -08001838} // namespace dumpstate
1839} // namespace os
1840} // namespace android