blob: c7df1bb6a34363a257cfff888622373752f5cfe7 [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
Felipe Leme75876a22016-10-27 16:31:27 -070017#define LOG_TAG "dumpstate"
18#include <cutils/log.h>
19
Felipe Lemef0292972016-11-22 13:57:05 -080020#include "DumpstateInternal.h"
Felipe Leme75876a22016-10-27 16:31:27 -070021#include "DumpstateService.h"
22#include "android/os/BnDumpstate.h"
Felipe Leme4c2d6632016-09-28 14:32:00 -070023#include "dumpstate.h"
24
25#include <gmock/gmock.h>
26#include <gtest/gtest.h>
27
Felipe Leme46b85da2016-11-21 17:40:45 -080028#include <fcntl.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070029#include <libgen.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070030#include <signal.h>
31#include <sys/types.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070032#include <unistd.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070033#include <thread>
Felipe Leme4c2d6632016-09-28 14:32:00 -070034
35#include <android-base/file.h>
Felipe Lemed80e6b62016-10-03 13:08:14 -070036#include <android-base/properties.h>
37#include <android-base/stringprintf.h>
Felipe Lemefd8affa2016-09-30 17:38:57 -070038#include <android-base/strings.h>
Abhijeet Kaure370d682019-10-01 16:49:30 +010039#include <android-base/unique_fd.h>
Hunter Knepshield8540faf2020-02-04 19:47:20 -080040#include <android/hardware/dumpstate/1.1/types.h>
41#include <cutils/properties.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070042
Felipe Leme47e9be22016-12-21 15:37:07 -080043namespace android {
44namespace os {
45namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070046
Hunter Knepshield8540faf2020-02-04 19:47:20 -080047using ::android::hardware::dumpstate::V1_1::DumpstateMode;
Felipe Leme4c2d6632016-09-28 14:32:00 -070048using ::testing::EndsWith;
Felipe Leme46b85da2016-11-21 17:40:45 -080049using ::testing::HasSubstr;
Felipe Leme4c2d6632016-09-28 14:32:00 -070050using ::testing::IsEmpty;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080051using ::testing::IsNull;
Felipe Leme009ecbb2016-11-07 10:18:44 -080052using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070053using ::testing::StartsWith;
Hunter Knepshield8540faf2020-02-04 19:47:20 -080054using ::testing::StrEq;
Felipe Leme4c2d6632016-09-28 14:32:00 -070055using ::testing::Test;
56using ::testing::internal::CaptureStderr;
57using ::testing::internal::CaptureStdout;
58using ::testing::internal::GetCapturedStderr;
59using ::testing::internal::GetCapturedStdout;
60
Nandana Dutt3f8c7172018-09-25 12:01:54 +010061#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
62
Felipe Leme75876a22016-10-27 16:31:27 -070063class DumpstateListenerMock : public IDumpstateListener {
64 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000065 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
66 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Nandana Duttcc4ead82019-01-23 08:29:23 +000067 MOCK_METHOD0(onFinished, binder::Status());
Paul Chang0d2aad72020-02-13 20:04:03 +080068 MOCK_METHOD1(onScreenshotTaken, binder::Status(bool success));
Paul Changc490e662020-04-11 18:14:09 +080069 MOCK_METHOD1(onUiIntensiveBugreportDumpsFinished,
70 binder::Status(const android::String16& callingpackage));
Felipe Leme75876a22016-10-27 16:31:27 -070071
72 protected:
73 MOCK_METHOD0(onAsBinder, IBinder*());
74};
75
Felipe Leme46b85da2016-11-21 17:40:45 -080076static int calls_;
77
Felipe Leme7447d7c2016-11-03 18:12:22 -070078// Base class for all tests in this file
79class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080080 public:
81 virtual void SetUp() override {
82 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080083 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080084 }
85
Felipe Lemef0292972016-11-22 13:57:05 -080086 void SetDryRun(bool dry_run) const {
87 PropertiesHelper::dry_run_ = dry_run;
88 }
89
90 void SetBuildType(const std::string& build_type) const {
91 PropertiesHelper::build_type_ = build_type;
92 }
93
Nandana Dutt4b392be2018-11-02 16:17:05 +000094 void SetUnroot(bool unroot) const {
95 PropertiesHelper::unroot_ = unroot;
96 }
97
Felipe Lemef0292972016-11-22 13:57:05 -080098 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -080099 return calls_ == 1;
100 }
101
Felipe Lemef0292972016-11-22 13:57:05 -0800102 void DropRoot() const {
103 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -0800104 uid_t uid = getuid();
105 ASSERT_EQ(2000, (int)uid);
106 }
107
Felipe Leme7447d7c2016-11-03 18:12:22 -0700108 protected:
109 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700110 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
111 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700112 const std::string kEchoCommand = "/system/bin/echo";
113
114 /*
115 * Copies a text file fixture to a temporary file, returning it's path.
116 *
117 * Useful in cases where the test case changes the content of the tile.
118 */
119 std::string CopyTextFileFixture(const std::string& relative_name) {
120 std::string from = kTestDataPath + relative_name;
121 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
122 // around for poking when the test fails.
123 std::string to = kTestDataPath + relative_name + ".tmp";
124 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
125 android::base::RemoveFileIfExists(to);
126 CopyTextFile(from, to);
127 return to.c_str();
128 }
129
Felipe Leme46b85da2016-11-21 17:40:45 -0800130 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700131 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800132 void ReadFileToString(const std::string& path, std::string* content) {
133 ASSERT_TRUE(android::base::ReadFileToString(path, content))
134 << "could not read contents from " << path;
135 }
136 void WriteStringToFile(const std::string& content, const std::string& path) {
137 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
138 << "could not write contents to " << path;
139 }
140
141 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700142 void CopyTextFile(const std::string& from, const std::string& to) {
143 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800144 ReadFileToString(from, &content);
145 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700146 }
147};
148
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100149class DumpOptionsTest : public Test {
150 public:
151 virtual ~DumpOptionsTest() {
152 }
153 virtual void SetUp() {
154 options_ = Dumpstate::DumpOptions();
155 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000156 void TearDown() {
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000157 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100158 Dumpstate::DumpOptions options_;
Abhijeet Kaure370d682019-10-01 16:49:30 +0100159 android::base::unique_fd fd;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100160};
161
162TEST_F(DumpOptionsTest, InitializeNone) {
163 // clang-format off
164 char* argv[] = {
165 const_cast<char*>("dumpstate")
166 };
167 // clang-format on
168
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100169 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
170
171 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000172
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100173 EXPECT_FALSE(options_.do_add_date);
174 EXPECT_FALSE(options_.do_zip_file);
mhasank3a4cfb42020-06-15 18:06:43 -0700175 EXPECT_EQ("", options_.out_dir);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100176 EXPECT_FALSE(options_.use_socket);
177 EXPECT_FALSE(options_.use_control_socket);
178 EXPECT_FALSE(options_.show_header_only);
179 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800180 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100181 EXPECT_FALSE(options_.do_progress_updates);
182 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700183 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800184 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000185}
186
187TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
188 // clang-format off
189 char* argv[] = {
190 const_cast<char*>("dumpstatez"),
191 const_cast<char*>("-S"),
192 const_cast<char*>("-d"),
193 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000194 };
195 // clang-format on
196
197 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
198
199 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
200 EXPECT_TRUE(options_.do_add_date);
201 EXPECT_TRUE(options_.do_zip_file);
202 EXPECT_TRUE(options_.use_control_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000203
204 // Other options retain default values
205 EXPECT_TRUE(options_.do_vibrate);
206 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800207 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000208 EXPECT_FALSE(options_.do_progress_updates);
209 EXPECT_FALSE(options_.is_remote_mode);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000210 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700211 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800212 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000213}
214
215TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
216 // clang-format off
217 char* argv[] = {
218 const_cast<char*>("dumpstate"),
219 const_cast<char*>("-s"),
220 };
221 // clang-format on
222
223 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
224
225 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
226 EXPECT_TRUE(options_.use_socket);
227
228 // Other options retain default values
229 EXPECT_TRUE(options_.do_vibrate);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000230 EXPECT_FALSE(options_.do_add_date);
231 EXPECT_FALSE(options_.do_zip_file);
232 EXPECT_FALSE(options_.use_control_socket);
233 EXPECT_FALSE(options_.show_header_only);
Paul Chang0d2aad72020-02-13 20:04:03 +0800234 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000235 EXPECT_FALSE(options_.do_progress_updates);
236 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700237 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800238 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000239}
240
241TEST_F(DumpOptionsTest, InitializeFullBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800242 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_FULL, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000243 EXPECT_TRUE(options_.do_add_date);
Paul Chang0d2aad72020-02-13 20:04:03 +0800244 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000245 EXPECT_TRUE(options_.do_zip_file);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800246 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::FULL);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000247
248 // Other options retain default values
249 EXPECT_TRUE(options_.do_vibrate);
250 EXPECT_FALSE(options_.use_control_socket);
251 EXPECT_FALSE(options_.show_header_only);
252 EXPECT_FALSE(options_.do_progress_updates);
253 EXPECT_FALSE(options_.is_remote_mode);
254 EXPECT_FALSE(options_.use_socket);
255 EXPECT_FALSE(options_.do_start_service);
mhasankd451a472020-05-26 18:02:39 -0700256 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000257}
258
259TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800260 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_INTERACTIVE, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000261 EXPECT_TRUE(options_.do_add_date);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000262 EXPECT_TRUE(options_.do_zip_file);
263 EXPECT_TRUE(options_.do_progress_updates);
264 EXPECT_TRUE(options_.do_start_service);
Paul Chang0d2aad72020-02-13 20:04:03 +0800265 EXPECT_TRUE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800266 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::INTERACTIVE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000267
268 // Other options retain default values
269 EXPECT_TRUE(options_.do_vibrate);
270 EXPECT_FALSE(options_.use_control_socket);
271 EXPECT_FALSE(options_.show_header_only);
272 EXPECT_FALSE(options_.is_remote_mode);
273 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700274 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000275}
276
277TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800278 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_REMOTE, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000279 EXPECT_TRUE(options_.do_add_date);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000280 EXPECT_TRUE(options_.do_zip_file);
281 EXPECT_TRUE(options_.is_remote_mode);
282 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800283 EXPECT_FALSE(options_.do_screenshot);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800284 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::REMOTE);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000285
286 // Other options retain default values
287 EXPECT_FALSE(options_.use_control_socket);
288 EXPECT_FALSE(options_.show_header_only);
289 EXPECT_FALSE(options_.do_progress_updates);
290 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700291 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000292}
293
294TEST_F(DumpOptionsTest, InitializeWearBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800295 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WEAR, fd, fd, true);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000296 EXPECT_TRUE(options_.do_add_date);
Paul Chang0d2aad72020-02-13 20:04:03 +0800297 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000298 EXPECT_TRUE(options_.do_zip_file);
299 EXPECT_TRUE(options_.do_progress_updates);
300 EXPECT_TRUE(options_.do_start_service);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800301 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WEAR);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000302
303 // Other options retain default values
304 EXPECT_TRUE(options_.do_vibrate);
305 EXPECT_FALSE(options_.use_control_socket);
306 EXPECT_FALSE(options_.show_header_only);
307 EXPECT_FALSE(options_.is_remote_mode);
308 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700309 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000310}
311
312TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800313 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_TELEPHONY, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000314 EXPECT_TRUE(options_.do_add_date);
Paul Chang0d2aad72020-02-13 20:04:03 +0800315 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000316 EXPECT_TRUE(options_.do_zip_file);
317 EXPECT_TRUE(options_.telephony_only);
Hunter Knepshield820f9bc2020-02-05 20:10:53 -0800318 EXPECT_TRUE(options_.do_progress_updates);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800319 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::CONNECTIVITY);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000320
321 // Other options retain default values
322 EXPECT_TRUE(options_.do_vibrate);
323 EXPECT_FALSE(options_.use_control_socket);
324 EXPECT_FALSE(options_.show_header_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000325 EXPECT_FALSE(options_.is_remote_mode);
326 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700327 EXPECT_FALSE(options_.limited_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000328}
329
330TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
Paul Changf59c2b72020-03-10 02:08:55 +0800331 options_.Initialize(Dumpstate::BugreportMode::BUGREPORT_WIFI, fd, fd, false);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000332 EXPECT_TRUE(options_.do_add_date);
Paul Chang0d2aad72020-02-13 20:04:03 +0800333 EXPECT_FALSE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000334 EXPECT_TRUE(options_.do_zip_file);
335 EXPECT_TRUE(options_.wifi_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800336 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::WIFI);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000337
338 // Other options retain default values
339 EXPECT_TRUE(options_.do_vibrate);
340 EXPECT_FALSE(options_.use_control_socket);
341 EXPECT_FALSE(options_.show_header_only);
342 EXPECT_FALSE(options_.do_progress_updates);
343 EXPECT_FALSE(options_.is_remote_mode);
344 EXPECT_FALSE(options_.use_socket);
mhasankd451a472020-05-26 18:02:39 -0700345 EXPECT_FALSE(options_.limited_only);
346}
347
348TEST_F(DumpOptionsTest, InitializeLimitedOnlyBugreport) {
349 // clang-format off
350 char* argv[] = {
351 const_cast<char*>("dumpstatez"),
352 const_cast<char*>("-S"),
353 const_cast<char*>("-d"),
354 const_cast<char*>("-z"),
355 const_cast<char*>("-q"),
mhasank2d75c442020-06-11 15:05:25 -0700356 const_cast<char*>("-L"),
357 const_cast<char*>("-o abc")
mhasankd451a472020-05-26 18:02:39 -0700358 };
359 // clang-format on
360
361 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
362
363 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
364 EXPECT_TRUE(options_.do_add_date);
365 EXPECT_TRUE(options_.do_zip_file);
366 EXPECT_TRUE(options_.use_control_socket);
367 EXPECT_FALSE(options_.do_vibrate);
368 EXPECT_TRUE(options_.limited_only);
mhasank3a4cfb42020-06-15 18:06:43 -0700369 EXPECT_EQ(" abc", std::string(options_.out_dir));
mhasankd451a472020-05-26 18:02:39 -0700370
371 // Other options retain default values
372 EXPECT_FALSE(options_.show_header_only);
373 EXPECT_FALSE(options_.do_screenshot);
374 EXPECT_FALSE(options_.do_progress_updates);
375 EXPECT_FALSE(options_.is_remote_mode);
376 EXPECT_FALSE(options_.use_socket);
377 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000378}
379
380TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
381 // default: commandline options are not overridden
382 // clang-format off
383 char* argv[] = {
384 const_cast<char*>("bugreport"),
385 const_cast<char*>("-d"),
386 const_cast<char*>("-p"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000387 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000388 };
389 // clang-format on
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000390 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
391
392 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
393 EXPECT_TRUE(options_.do_add_date);
Paul Chang0d2aad72020-02-13 20:04:03 +0800394 EXPECT_TRUE(options_.do_screenshot);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000395 EXPECT_TRUE(options_.do_zip_file);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800396 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000397
398 // Other options retain default values
399 EXPECT_TRUE(options_.do_vibrate);
400 EXPECT_FALSE(options_.use_control_socket);
401 EXPECT_FALSE(options_.show_header_only);
402 EXPECT_FALSE(options_.do_progress_updates);
403 EXPECT_FALSE(options_.is_remote_mode);
404 EXPECT_FALSE(options_.use_socket);
405 EXPECT_FALSE(options_.wifi_only);
mhasankd451a472020-05-26 18:02:39 -0700406 EXPECT_FALSE(options_.limited_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100407}
408
409TEST_F(DumpOptionsTest, InitializePartial1) {
410 // clang-format off
411 char* argv[] = {
412 const_cast<char*>("dumpstate"),
413 const_cast<char*>("-d"),
414 const_cast<char*>("-z"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100415 const_cast<char*>("-s"),
416 const_cast<char*>("-S"),
417
418 };
419 // clang-format on
420
421 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
422
423 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
424 EXPECT_TRUE(options_.do_add_date);
425 EXPECT_TRUE(options_.do_zip_file);
426 // TODO: Maybe we should trim the filename
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100427 EXPECT_TRUE(options_.use_socket);
428 EXPECT_TRUE(options_.use_control_socket);
429
430 // Other options retain default values
431 EXPECT_FALSE(options_.show_header_only);
432 EXPECT_TRUE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800433 EXPECT_FALSE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100434 EXPECT_FALSE(options_.do_progress_updates);
435 EXPECT_FALSE(options_.is_remote_mode);
mhasankd451a472020-05-26 18:02:39 -0700436 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800437 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100438}
439
440TEST_F(DumpOptionsTest, InitializePartial2) {
441 // clang-format off
442 char* argv[] = {
443 const_cast<char*>("dumpstate"),
444 const_cast<char*>("-v"),
445 const_cast<char*>("-q"),
446 const_cast<char*>("-p"),
447 const_cast<char*>("-P"),
448 const_cast<char*>("-R"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100449 };
450 // clang-format on
451
452 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
453
454 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
455 EXPECT_TRUE(options_.show_header_only);
456 EXPECT_FALSE(options_.do_vibrate);
Paul Chang0d2aad72020-02-13 20:04:03 +0800457 EXPECT_TRUE(options_.do_screenshot);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100458 EXPECT_TRUE(options_.do_progress_updates);
459 EXPECT_TRUE(options_.is_remote_mode);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100460
461 // Other options retain default values
462 EXPECT_FALSE(options_.do_add_date);
463 EXPECT_FALSE(options_.do_zip_file);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100464 EXPECT_FALSE(options_.use_socket);
465 EXPECT_FALSE(options_.use_control_socket);
mhasankd451a472020-05-26 18:02:39 -0700466 EXPECT_FALSE(options_.limited_only);
Hunter Knepshield8540faf2020-02-04 19:47:20 -0800467 EXPECT_EQ(options_.dumpstate_hal_mode, DumpstateMode::DEFAULT);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100468}
469
470TEST_F(DumpOptionsTest, InitializeHelp) {
471 // clang-format off
472 char* argv[] = {
473 const_cast<char*>("dumpstate"),
474 const_cast<char*>("-h")
475 };
476 // clang-format on
477
478 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
479
480 // -h is for help.
481 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
482}
483
484TEST_F(DumpOptionsTest, InitializeUnknown) {
485 // clang-format off
486 char* argv[] = {
487 const_cast<char*>("dumpstate"),
488 const_cast<char*>("-u") // unknown flag
489 };
490 // clang-format on
491
492 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
493
494 // -u is unknown.
495 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
496}
497
498TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
499 options_.do_zip_file = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000500 // Writing to socket = !writing to file.
501 options_.use_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100502 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000503
504 options_.use_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100505 EXPECT_TRUE(options_.ValidateOptions());
506}
507
508TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
Abhijeet Kaure370d682019-10-01 16:49:30 +0100509 options_.do_progress_updates = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000510 // Writing to socket = !writing to file.
511 options_.use_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100512 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000513
514 options_.use_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100515 EXPECT_TRUE(options_.ValidateOptions());
516}
517
518TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) {
519 options_.use_control_socket = true;
520 EXPECT_FALSE(options_.ValidateOptions());
521
522 options_.do_zip_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100523 EXPECT_TRUE(options_.ValidateOptions());
524}
525
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100526TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
527 options_.is_remote_mode = true;
528 EXPECT_FALSE(options_.ValidateOptions());
529
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100530 options_.do_zip_file = true;
531 options_.do_add_date = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100532 EXPECT_TRUE(options_.ValidateOptions());
533}
534
Felipe Leme7447d7c2016-11-03 18:12:22 -0700535class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700536 public:
537 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800538 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700539 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700540 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700541 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100542 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700543 }
544
545 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700546 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700547 const CommandOptions& options = CommandOptions::DEFAULT) {
548 CaptureStdout();
549 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700550 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700551 out = GetCapturedStdout();
552 err = GetCapturedStderr();
553 return status;
554 }
555
Felipe Lemecef02982016-10-03 17:22:22 -0700556 // Dumps a file and capture `stdout` and `stderr`.
557 int DumpFile(const std::string& title, const std::string& path) {
558 CaptureStdout();
559 CaptureStderr();
560 int status = ds.DumpFile(title, path);
561 out = GetCapturedStdout();
562 err = GetCapturedStderr();
563 return status;
564 }
565
Nandana Dutt402a8392019-06-14 14:25:13 +0100566 void SetProgress(long progress, long initial_max) {
567 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100568 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700569 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
570 }
571
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100572 std::string GetProgressMessage(int progress, int max,
573 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700574 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
575 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700576
Felipe Leme7447d7c2016-11-03 18:12:22 -0700577 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700578
Felipe Leme009ecbb2016-11-07 10:18:44 -0800579 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700580 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800581 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700582 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700583 }
584
Felipe Leme009ecbb2016-11-07 10:18:44 -0800585 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100586 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
587 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800588 }
589
590 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700591 }
592
Felipe Leme4c2d6632016-09-28 14:32:00 -0700593 // `stdout` and `stderr` from the last command ran.
594 std::string out, err;
595
Felipe Lemefd8affa2016-09-30 17:38:57 -0700596 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700597};
598
599TEST_F(DumpstateTest, RunCommandNoArgs) {
600 EXPECT_EQ(-1, RunCommand("", {}));
601}
602
603TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700604 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700605 EXPECT_THAT(out, StrEq("stdout\n"));
606 EXPECT_THAT(err, StrEq("stderr\n"));
607}
608
609TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700610 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700611 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700612 // The duration may not get output, depending on how long it takes,
613 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700614 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000615 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700616}
617
Felipe Lemefd8affa2016-09-30 17:38:57 -0700618TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700619 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700620 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700621 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
622 EXPECT_THAT(out, StrEq("stdout\n"));
623 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
624}
625
626TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700627 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700628 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700629 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700630 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700631}
632
633TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700634 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700635 EXPECT_THAT(err, IsEmpty());
636 EXPECT_THAT(out, StrEq("one\n"));
637}
638
Felipe Lemefd8affa2016-09-30 17:38:57 -0700639TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700640 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700641 EXPECT_THAT(err, IsEmpty());
642 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
643}
644
645TEST_F(DumpstateTest, RunCommandDryRun) {
646 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700647 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700648 // The duration may not get output, depending on how long it takes,
649 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700650 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000651 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700652 EXPECT_THAT(err, IsEmpty());
653}
654
655TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
656 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700657 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700658 EXPECT_THAT(out, IsEmpty());
659 EXPECT_THAT(err, IsEmpty());
660}
661
662TEST_F(DumpstateTest, RunCommandDryRunAlways) {
663 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700664 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700665 EXPECT_THAT(out, StrEq("stdout\n"));
666 EXPECT_THAT(err, StrEq("stderr\n"));
667}
668
Felipe Lemefd8affa2016-09-30 17:38:57 -0700669TEST_F(DumpstateTest, RunCommandNotFound) {
670 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
671 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
672 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
673}
674
675TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700676 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
677 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700678 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700679 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700680 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700681}
682
683TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700684 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700685 // We don't know the exit code, so check just the prefix.
686 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700687 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700688 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700689 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700690}
691
692TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700693 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700694 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700695 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700696 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700697 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700698 " --sleep 2' timed out after 1"));
699}
700
701TEST_F(DumpstateTest, RunCommandIsKilled) {
702 CaptureStdout();
703 CaptureStderr();
704
705 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700706 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700707 CommandOptions::WithTimeout(100).Always().Build()));
708 });
709
710 // Capture pid and pre-sleep output.
711 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
712 std::string err = GetCapturedStderr();
713 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
714
715 std::string out = GetCapturedStdout();
716 std::vector<std::string> lines = android::base::Split(out, "\n");
717 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
718
719 int pid = atoi(lines[0].c_str());
720 EXPECT_THAT(lines[1], StrEq("stdout line1"));
721 EXPECT_THAT(lines[2], IsEmpty()); // \n
722
723 // Then kill the process.
724 CaptureStdout();
725 CaptureStderr();
726 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
727 t.join();
728
729 // Finally, check output after murder.
730 out = GetCapturedStdout();
731 err = GetCapturedStderr();
732
Felipe Leme7447d7c2016-11-03 18:12:22 -0700733 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700734 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700735 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700736 " --pid --sleep 20' failed: killed by signal 15\n"));
737}
738
Felipe Leme75876a22016-10-27 16:31:27 -0700739TEST_F(DumpstateTest, RunCommandProgress) {
740 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
741 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700742 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700743
Nandana Duttbabf6c72019-01-15 14:11:12 +0000744 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700745 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100746 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700747 EXPECT_THAT(out, StrEq("stdout\n"));
748 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
749
Nandana Dutt402a8392019-06-14 14:25:13 +0100750 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
751 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100752 progress_message = GetProgressMessage(24, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700753 EXPECT_THAT(out, StrEq("stdout\n"));
754 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
755
756 // Make sure command ran while in dry_run is counted.
757 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100758 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
759 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100760 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700761 EXPECT_THAT(out, IsEmpty());
762 EXPECT_THAT(err, StrEq(progress_message));
763
Nandana Dutt402a8392019-06-14 14:25:13 +0100764 SetDryRun(false);
765 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
766 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100767 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800768 EXPECT_THAT(out, StrEq("stdout\n"));
769 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
770
Nandana Dutt402a8392019-06-14 14:25:13 +0100771 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800772 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100773 progress_message = GetProgressMessage(30, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800774 EXPECT_THAT(out, StrEq("stdout\n"));
775 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
776
777 ds.listener_.clear();
778}
779
Felipe Lemed80e6b62016-10-03 13:08:14 -0700780TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800781 if (!IsStandalone()) {
782 // TODO: temporarily disabled because it might cause other tests to fail after dropping
783 // to Shell - need to refactor tests to avoid this problem)
784 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
785 return;
786 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700787 // First check root case - only available when running with 'adb root'.
788 uid_t uid = getuid();
789 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700790 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700791 EXPECT_THAT(out, StrEq("0\nstdout\n"));
792 EXPECT_THAT(err, StrEq("stderr\n"));
793 return;
794 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700795 // Then run dropping root.
796 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700797 CommandOptions::WithTimeout(1).DropRoot().Build()));
798 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700799 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700800}
801
802TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800803 if (!IsStandalone()) {
804 // TODO: temporarily disabled because it might cause other tests to fail after dropping
805 // to Shell - need to refactor tests to avoid this problem)
806 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
807 return;
808 }
Felipe Lemef0292972016-11-22 13:57:05 -0800809 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700810 // Emulates user build if necessarily.
811 SetBuildType("user");
812 }
813
814 DropRoot();
815
Felipe Leme7447d7c2016-11-03 18:12:22 -0700816 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700817
818 // We don't know the exact path of su, so we just check for the 'root ...' commands
819 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700820 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700821 EXPECT_THAT(err, IsEmpty());
822}
823
Felipe Leme46b85da2016-11-21 17:40:45 -0800824TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
825 if (!IsStandalone()) {
826 // TODO: temporarily disabled because it might cause other tests to fail after dropping
827 // to Shell - need to refactor tests to avoid this problem)
828 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n")
829 return;
830 }
Felipe Lemef0292972016-11-22 13:57:05 -0800831 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800832 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
833 return;
834 }
835
836 DropRoot();
837
838 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
839 CommandOptions::WithTimeout(1).AsRoot().Build()));
840
841 EXPECT_THAT(out, StrEq("0\nstdout\n"));
842 EXPECT_THAT(err, StrEq("stderr\n"));
843}
844
Nandana Dutt4b392be2018-11-02 16:17:05 +0000845TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
846 if (!IsStandalone()) {
847 // TODO: temporarily disabled because it might cause other tests to fail after dropping
848 // to Shell - need to refactor tests to avoid this problem)
849 MYLOGE(
850 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
851 "on test suite\n")
852 return;
853 }
854 if (PropertiesHelper::IsUserBuild()) {
855 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
856 return;
857 }
858
859 // Same test as above, but with unroot property set, which will override su availability.
860 SetUnroot(true);
861 DropRoot();
862
863 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
864 CommandOptions::WithTimeout(1).AsRoot().Build()));
865
866 // AsRoot is ineffective.
867 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
868 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
869}
870
Yifan Hong48e83a12017-10-03 14:10:07 -0700871TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
872 if (!IsStandalone()) {
873 // TODO: temporarily disabled because it might cause other tests to fail after dropping
874 // to Shell - need to refactor tests to avoid this problem)
875 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
876 return;
877 }
878 if (!PropertiesHelper::IsUserBuild()) {
879 // Emulates user build if necessarily.
880 SetBuildType("user");
881 }
882
883 DropRoot();
884
885 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
886 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
887
888 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
889 EXPECT_THAT(err, StrEq("stderr\n"));
890}
891
892TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
893 if (!IsStandalone()) {
894 // TODO: temporarily disabled because it might cause other tests to fail after dropping
895 // to Shell - need to refactor tests to avoid this problem)
896 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
897 return;
898 }
899 if (PropertiesHelper::IsUserBuild()) {
900 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
901 return;
902 }
903
904 DropRoot();
905
906 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
907 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
908
909 EXPECT_THAT(out, StrEq("0\nstdout\n"));
910 EXPECT_THAT(err, StrEq("stderr\n"));
911}
912
Nandana Dutt4b392be2018-11-02 16:17:05 +0000913TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
914 if (!IsStandalone()) {
915 // TODO: temporarily disabled because it might cause other tests to fail after dropping
916 // to Shell - need to refactor tests to avoid this problem)
917 MYLOGE(
918 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
919 "on test suite\n")
920 return;
921 }
922 if (PropertiesHelper::IsUserBuild()) {
923 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
924 return;
925 }
926 // Same test as above, but with unroot property set, which will override su availability.
927 SetUnroot(true);
928
929 DropRoot();
930
931 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
932 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
933
934 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
935 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
936 EXPECT_THAT(err, StrEq("stderr\n"));
937}
938
Felipe Lemecef02982016-10-03 17:22:22 -0700939TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
940 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
941 EXPECT_THAT(out,
942 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
943 EXPECT_THAT(err, IsEmpty());
944}
945
946TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
947 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
948 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700949 // The duration may not get output, depending on how long it takes,
950 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700951 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
952 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700953}
954
955TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700956 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700957 EXPECT_THAT(err, IsEmpty());
958 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
959}
960
961TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700962 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700963 EXPECT_THAT(err, IsEmpty());
964 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
965}
966
967TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700968 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700969 EXPECT_THAT(err, IsEmpty());
970 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
971}
972
973TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700974 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700975 EXPECT_THAT(err, IsEmpty());
976 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
977}
978
979TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
980 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700981 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700982 EXPECT_THAT(err, IsEmpty());
983 EXPECT_THAT(out, IsEmpty());
984}
985
986TEST_F(DumpstateTest, DumpFileOnDryRun) {
987 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700988 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -0700989 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -0800990 EXPECT_THAT(
991 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +0000992 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -0700993}
994
Felipe Leme75876a22016-10-27 16:31:27 -0700995TEST_F(DumpstateTest, DumpFileUpdateProgress) {
996 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
997 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700998 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700999
Nandana Duttbabf6c72019-01-15 14:11:12 +00001000 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -07001001 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -07001002
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01001003 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -07001004 EXPECT_THAT(err, StrEq(progress_message));
1005 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1006
1007 ds.listener_.clear();
1008}
1009
Felipe Leme7447d7c2016-11-03 18:12:22 -07001010class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -07001011 public:
1012 DumpstateService dss;
1013};
1014
Felipe Leme7447d7c2016-11-03 18:12:22 -07001015class ProgressTest : public DumpstateBaseTest {
1016 public:
1017 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1018 return Progress(max, growth_factor, path);
1019 }
1020
1021 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1022 std::string expected_content =
1023 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1024 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001025 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001026 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1027 }
1028};
1029
1030TEST_F(ProgressTest, SimpleTest) {
1031 Progress progress;
1032 EXPECT_EQ(0, progress.Get());
1033 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1034 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1035
1036 bool max_increased = progress.Inc(1);
1037 EXPECT_EQ(1, progress.Get());
1038 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1039 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1040 EXPECT_FALSE(max_increased);
1041
1042 // Ignore negative increase.
1043 max_increased = progress.Inc(-1);
1044 EXPECT_EQ(1, progress.Get());
1045 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1046 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1047 EXPECT_FALSE(max_increased);
1048}
1049
1050TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1051 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1052 EXPECT_EQ(0, progress.Get());
1053 EXPECT_EQ(10, progress.GetInitialMax());
1054 EXPECT_EQ(10, progress.GetMax());
1055
1056 // No increase
1057 bool max_increased = progress.Inc(10);
1058 EXPECT_EQ(10, progress.Get());
1059 EXPECT_EQ(10, progress.GetMax());
1060 EXPECT_FALSE(max_increased);
1061
1062 // Increase, with new value < max*20%
1063 max_increased = progress.Inc(1);
1064 EXPECT_EQ(11, progress.Get());
1065 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1066 EXPECT_TRUE(max_increased);
1067}
1068
1069TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1070 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1071 EXPECT_EQ(0, progress.Get());
1072 EXPECT_EQ(10, progress.GetInitialMax());
1073 EXPECT_EQ(10, progress.GetMax());
1074
1075 // No increase
1076 bool max_increased = progress.Inc(10);
1077 EXPECT_EQ(10, progress.Get());
1078 EXPECT_EQ(10, progress.GetMax());
1079 EXPECT_FALSE(max_increased);
1080
1081 // Increase, with new value > max*20%
1082 max_increased = progress.Inc(5);
1083 EXPECT_EQ(15, progress.Get());
1084 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1085 EXPECT_TRUE(max_increased);
1086}
1087
1088TEST_F(ProgressTest, InvalidPath) {
1089 Progress progress("/devil/null");
1090 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1091}
1092
1093TEST_F(ProgressTest, EmptyFile) {
1094 Progress progress(CopyTextFileFixture("empty-file.txt"));
1095 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1096}
1097
1098TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1099 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1100 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1101}
1102
1103TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1104 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1105 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1106}
1107
1108TEST_F(ProgressTest, InvalidLineBothNAN) {
1109 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1110 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1111}
1112
1113TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1114 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1115 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1116}
1117
1118TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1119 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1120 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1121}
1122
1123TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1124 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1125 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1126}
1127
1128TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1129 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1130 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1131}
1132
1133// Tests stats are properly saved when the file does not exists.
1134TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001135 if (!IsStandalone()) {
1136 // TODO: temporarily disabled because it's failing when running as suite
1137 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1138 return;
1139 }
1140
Felipe Leme7447d7c2016-11-03 18:12:22 -07001141 std::string path = kTestDataPath + "FirstTime.txt";
1142 android::base::RemoveFileIfExists(path);
1143
1144 Progress run1(path);
1145 EXPECT_EQ(0, run1.Get());
1146 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1147 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1148
1149 bool max_increased = run1.Inc(20);
1150 EXPECT_EQ(20, run1.Get());
1151 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1152 EXPECT_FALSE(max_increased);
1153
1154 run1.Save();
1155 AssertStats(path, 1, 20);
1156}
1157
1158// Tests what happens when the persistent settings contains the average duration of 1 run.
1159// Data on file is 1 run and 109 average.
1160TEST_F(ProgressTest, SecondTime) {
1161 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1162
1163 Progress run1 = GetInstance(-42, 1.2, path);
1164 EXPECT_EQ(0, run1.Get());
1165 EXPECT_EQ(10, run1.GetInitialMax());
1166 EXPECT_EQ(10, run1.GetMax());
1167
1168 bool max_increased = run1.Inc(20);
1169 EXPECT_EQ(20, run1.Get());
1170 EXPECT_EQ(24, run1.GetMax());
1171 EXPECT_TRUE(max_increased);
1172
1173 // Average now is 2 runs and (10 + 20)/ 2 = 15
1174 run1.Save();
1175 AssertStats(path, 2, 15);
1176
1177 Progress run2 = GetInstance(-42, 1.2, path);
1178 EXPECT_EQ(0, run2.Get());
1179 EXPECT_EQ(15, run2.GetInitialMax());
1180 EXPECT_EQ(15, run2.GetMax());
1181
1182 max_increased = run2.Inc(25);
1183 EXPECT_EQ(25, run2.Get());
1184 EXPECT_EQ(30, run2.GetMax());
1185 EXPECT_TRUE(max_increased);
1186
1187 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1188 run2.Save();
1189 AssertStats(path, 3, 18);
1190
1191 Progress run3 = GetInstance(-42, 1.2, path);
1192 EXPECT_EQ(0, run3.Get());
1193 EXPECT_EQ(18, run3.GetInitialMax());
1194 EXPECT_EQ(18, run3.GetMax());
1195
1196 // Make sure average decreases as well
1197 max_increased = run3.Inc(5);
1198 EXPECT_EQ(5, run3.Get());
1199 EXPECT_EQ(18, run3.GetMax());
1200 EXPECT_FALSE(max_increased);
1201
1202 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1203 run3.Save();
1204 AssertStats(path, 4, 14);
1205}
1206
1207// Tests what happens when the persistent settings contains the average duration of 2 runs.
1208// Data on file is 2 runs and 15 average.
1209TEST_F(ProgressTest, ThirdTime) {
1210 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1211 AssertStats(path, 2, 15); // Sanity check
1212
1213 Progress run1 = GetInstance(-42, 1.2, path);
1214 EXPECT_EQ(0, run1.Get());
1215 EXPECT_EQ(15, run1.GetInitialMax());
1216 EXPECT_EQ(15, run1.GetMax());
1217
1218 bool max_increased = run1.Inc(20);
1219 EXPECT_EQ(20, run1.Get());
1220 EXPECT_EQ(24, run1.GetMax());
1221 EXPECT_TRUE(max_increased);
1222
1223 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1224 run1.Save();
1225 AssertStats(path, 3, 16);
1226}
1227
Felipe Leme46b85da2016-11-21 17:40:45 -08001228class DumpstateUtilTest : public DumpstateBaseTest {
1229 public:
1230 void SetUp() {
1231 DumpstateBaseTest::SetUp();
1232 SetDryRun(false);
1233 }
1234
Felipe Leme46b85da2016-11-21 17:40:45 -08001235 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001236 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001237 }
1238
1239 void CreateFd(const std::string& name) {
1240 path_ = kTestDataPath + name;
1241 MYLOGD("Creating fd for file %s\n", path_.c_str());
1242
1243 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1244 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1245 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1246 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1247 }
1248
1249 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001250 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001251 const CommandOptions& options = CommandOptions::DEFAULT) {
1252 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001253 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001254 close(fd);
1255
1256 CaptureFdOut();
1257 err = GetCapturedStderr();
1258 return status;
1259 }
1260
1261 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001262 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001263 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001264 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001265 close(fd);
1266
1267 CaptureFdOut();
1268 err = GetCapturedStderr();
1269 return status;
1270 }
1271
1272 int fd;
1273
1274 // 'fd` output and `stderr` from the last command ran.
1275 std::string out, err;
1276
1277 private:
1278 std::string path_;
1279};
1280
1281TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001282 CreateFd("RunCommandNoArgs.txt");
1283 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001284}
1285
Felipe Lemef0292972016-11-22 13:57:05 -08001286TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001287 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001288 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001289 EXPECT_THAT(out, StrEq("stdout\n"));
1290 EXPECT_THAT(err, StrEq("stderr\n"));
1291}
1292
Felipe Lemef0292972016-11-22 13:57:05 -08001293TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1294 CreateFd("RunCommandWithNoArgs.txt");
1295 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1296 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1297 EXPECT_THAT(err, StrEq("stderr\n"));
1298}
1299
Felipe Leme46b85da2016-11-21 17:40:45 -08001300TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1301 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001302 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001303 EXPECT_THAT(err, IsEmpty());
1304 EXPECT_THAT(out, StrEq("one\n"));
1305}
1306
1307TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1308 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001309 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001310 EXPECT_THAT(err, IsEmpty());
1311 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1312}
1313
1314TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1315 CreateFd("RunCommandWithLoggingMessage.txt");
1316 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001317 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001318 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1319 EXPECT_THAT(out, StrEq("stdout\n"));
1320 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1321}
1322
1323TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1324 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001325 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1326 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001327 EXPECT_THAT(out, IsEmpty());
1328 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1329}
1330
1331TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1332 CreateFd("RunCommandDryRun.txt");
1333 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001334 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1335 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1336 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1337 kSimpleCommand.c_str())));
1338 EXPECT_THAT(err, IsEmpty());
1339}
1340
1341TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1342 CreateFd("RunCommandDryRun.txt");
1343 SetDryRun(true);
1344 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001345 EXPECT_THAT(
1346 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1347 EXPECT_THAT(err, IsEmpty());
1348}
1349
1350TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1351 CreateFd("RunCommandDryRunAlways.txt");
1352 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001353 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001354 EXPECT_THAT(out, StrEq("stdout\n"));
1355 EXPECT_THAT(err, StrEq("stderr\n"));
1356}
1357
1358TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1359 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001360 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001361 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1362 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1363}
1364
1365TEST_F(DumpstateUtilTest, RunCommandFails) {
1366 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001367 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001368 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1369 " --exit 42' failed: exit code 42\n"));
1370 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1371 " --exit 42' failed: exit code 42\n"));
1372}
1373
1374TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1375 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001376 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001377 // We don't know the exit code, so check just the prefix.
1378 EXPECT_THAT(
1379 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1380 EXPECT_THAT(
1381 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1382}
1383
Vishnu Nair6921f802017-11-22 09:17:23 -08001384TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001385 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001386 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1387 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001388 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1389 " --sleep 2' timed out after 1"));
1390 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1391 " --sleep 2' timed out after 1"));
1392}
1393
Vishnu Nair6921f802017-11-22 09:17:23 -08001394TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1395 CreateFd("RunCommandTimesout.txt");
1396 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1397 CommandOptions::WithTimeoutInMs(1000).Build()));
1398 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1399 " --sleep 2' timed out after 1"));
1400 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1401 " --sleep 2' timed out after 1"));
1402}
1403
1404
Felipe Leme46b85da2016-11-21 17:40:45 -08001405TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1406 CreateFd("RunCommandIsKilled.txt");
1407 CaptureStderr();
1408
1409 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001410 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001411 CommandOptions::WithTimeout(100).Always().Build()));
1412 });
1413
1414 // Capture pid and pre-sleep output.
1415 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1416 std::string err = GetCapturedStderr();
1417 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1418
1419 CaptureFdOut();
1420 std::vector<std::string> lines = android::base::Split(out, "\n");
1421 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1422
1423 int pid = atoi(lines[0].c_str());
1424 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1425 EXPECT_THAT(lines[2], IsEmpty()); // \n
1426
1427 // Then kill the process.
1428 CaptureFdOut();
1429 CaptureStderr();
1430 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1431 t.join();
1432
1433 // Finally, check output after murder.
1434 CaptureFdOut();
1435 err = GetCapturedStderr();
1436
1437 // out starts with the pid, which is an unknown
1438 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1439 " --pid --sleep 20' failed: killed by signal 15\n"));
1440 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1441 " --pid --sleep 20' failed: killed by signal 15\n"));
1442}
1443
1444TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1445 if (!IsStandalone()) {
1446 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1447 // to Shell - need to refactor tests to avoid this problem)
1448 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1449 return;
1450 }
1451 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001452 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001453 // Emulates user build if necessarily.
1454 SetBuildType("user");
1455 }
1456
1457 DropRoot();
1458
Felipe Lemef0292972016-11-22 13:57:05 -08001459 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001460
1461 // We don't know the exact path of su, so we just check for the 'root ...' commands
1462 EXPECT_THAT(out, StartsWith("Skipping"));
1463 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1464 EXPECT_THAT(err, IsEmpty());
1465}
1466
1467TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1468 if (!IsStandalone()) {
1469 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1470 // to Shell - need to refactor tests to avoid this problem)
1471 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1472 return;
1473 }
1474 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001475 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001476 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1477 return;
1478 }
1479
1480 DropRoot();
1481
Felipe Lemef0292972016-11-22 13:57:05 -08001482 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1483 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001484
1485 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1486 EXPECT_THAT(err, StrEq("stderr\n"));
1487}
Felipe Leme46b85da2016-11-21 17:40:45 -08001488
Yifan Hong48e83a12017-10-03 14:10:07 -07001489
1490TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1491 if (!IsStandalone()) {
1492 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1493 // to Shell - need to refactor tests to avoid this problem)
1494 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1495 return;
1496 }
1497 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1498 if (!PropertiesHelper::IsUserBuild()) {
1499 // Emulates user build if necessarily.
1500 SetBuildType("user");
1501 }
1502
1503 DropRoot();
1504
1505 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1506 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1507
1508 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1509 EXPECT_THAT(err, StrEq("stderr\n"));
1510}
1511
1512TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1513 if (!IsStandalone()) {
1514 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1515 // to Shell - need to refactor tests to avoid this problem)
1516 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1517 return;
1518 }
1519 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1520 if (PropertiesHelper::IsUserBuild()) {
1521 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1522 return;
1523 }
1524
1525 DropRoot();
1526
1527 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1528 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1529
1530 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1531 EXPECT_THAT(err, StrEq("stderr\n"));
1532}
1533
Felipe Leme46b85da2016-11-21 17:40:45 -08001534TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1535 if (!IsStandalone()) {
1536 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1537 // to Shell - need to refactor tests to avoid this problem)
1538 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1539 return;
1540 }
1541 CreateFd("RunCommandDropRoot.txt");
1542 // First check root case - only available when running with 'adb root'.
1543 uid_t uid = getuid();
1544 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001545 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001546 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1547 EXPECT_THAT(err, StrEq("stderr\n"));
1548 return;
1549 }
1550 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001551 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001552 CommandOptions::WithTimeout(1).DropRoot().Build()));
1553 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1554 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1555}
1556
Felipe Lemef0292972016-11-22 13:57:05 -08001557TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001558 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001559 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001560 EXPECT_THAT(out,
1561 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1562 EXPECT_THAT(err, IsEmpty());
1563}
1564
Felipe Lemef0292972016-11-22 13:57:05 -08001565TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1566 CreateFd("DumpFileNotFound.txt");
1567 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1568 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1569 "file or directory\n"));
1570 EXPECT_THAT(err, IsEmpty());
1571}
1572
Felipe Leme46b85da2016-11-21 17:40:45 -08001573TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1574 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001575 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001576 EXPECT_THAT(err, IsEmpty());
1577 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1578}
1579
1580TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1581 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001582 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001583 EXPECT_THAT(err, IsEmpty());
1584 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1585}
1586
1587TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1588 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001589 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001590 EXPECT_THAT(err, IsEmpty());
1591 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1592}
1593
1594TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1595 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001596 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001597 EXPECT_THAT(err, IsEmpty());
1598 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1599}
1600
Felipe Lemef0292972016-11-22 13:57:05 -08001601TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1602 CreateFd("DumpFileOnDryRun.txt");
1603 SetDryRun(true);
1604 std::string path = kTestDataPath + "single-line.txt";
1605 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1606 EXPECT_THAT(err, IsEmpty());
1607 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1608}
1609
Felipe Leme46b85da2016-11-21 17:40:45 -08001610TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1611 CreateFd("DumpFileOnDryRun.txt");
1612 SetDryRun(true);
1613 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001614 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001615 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001616 EXPECT_THAT(
1617 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1618 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001619}
Ecco Park61ffcf72016-10-27 15:46:26 -07001620
Felipe Leme47e9be22016-12-21 15:37:07 -08001621} // namespace dumpstate
1622} // namespace os
1623} // namespace android