blob: 7010301f9a5f2d11692fde2df5ceac17a1d9abaa [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 Kaur904e0e02018-12-05 14:03:01 +000039#include <cutils/properties.h>
Felipe Leme4c2d6632016-09-28 14:32:00 -070040
Felipe Leme47e9be22016-12-21 15:37:07 -080041namespace android {
42namespace os {
43namespace dumpstate {
Felipe Lemed80e6b62016-10-03 13:08:14 -070044
Felipe Leme4c2d6632016-09-28 14:32:00 -070045using ::testing::EndsWith;
Felipe Leme46b85da2016-11-21 17:40:45 -080046using ::testing::HasSubstr;
Felipe Leme009ecbb2016-11-07 10:18:44 -080047using ::testing::IsNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070048using ::testing::IsEmpty;
Felipe Leme009ecbb2016-11-07 10:18:44 -080049using ::testing::NotNull;
Felipe Leme4c2d6632016-09-28 14:32:00 -070050using ::testing::StrEq;
51using ::testing::StartsWith;
52using ::testing::Test;
53using ::testing::internal::CaptureStderr;
54using ::testing::internal::CaptureStdout;
55using ::testing::internal::GetCapturedStderr;
56using ::testing::internal::GetCapturedStdout;
57
Nandana Dutt3f8c7172018-09-25 12:01:54 +010058#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
59
Felipe Leme75876a22016-10-27 16:31:27 -070060class DumpstateListenerMock : public IDumpstateListener {
61 public:
Nandana Dutta6a28bd2019-01-14 16:54:38 +000062 MOCK_METHOD1(onProgress, binder::Status(int32_t progress));
63 MOCK_METHOD1(onError, binder::Status(int32_t error_code));
Nandana Duttcc4ead82019-01-23 08:29:23 +000064 MOCK_METHOD0(onFinished, binder::Status());
Felipe Leme75876a22016-10-27 16:31:27 -070065
66 protected:
67 MOCK_METHOD0(onAsBinder, IBinder*());
68};
69
Felipe Leme46b85da2016-11-21 17:40:45 -080070static int calls_;
71
Felipe Leme7447d7c2016-11-03 18:12:22 -070072// Base class for all tests in this file
73class DumpstateBaseTest : public Test {
Felipe Leme46b85da2016-11-21 17:40:45 -080074 public:
75 virtual void SetUp() override {
76 calls_++;
Felipe Lemef0292972016-11-22 13:57:05 -080077 SetDryRun(false);
Felipe Leme46b85da2016-11-21 17:40:45 -080078 }
79
Felipe Lemef0292972016-11-22 13:57:05 -080080 void SetDryRun(bool dry_run) const {
81 PropertiesHelper::dry_run_ = dry_run;
82 }
83
84 void SetBuildType(const std::string& build_type) const {
85 PropertiesHelper::build_type_ = build_type;
86 }
87
Nandana Dutt4b392be2018-11-02 16:17:05 +000088 void SetUnroot(bool unroot) const {
89 PropertiesHelper::unroot_ = unroot;
90 }
91
Felipe Lemef0292972016-11-22 13:57:05 -080092 bool IsStandalone() const {
Felipe Leme46b85da2016-11-21 17:40:45 -080093 return calls_ == 1;
94 }
95
Felipe Lemef0292972016-11-22 13:57:05 -080096 void DropRoot() const {
97 DropRootUser();
Felipe Leme46b85da2016-11-21 17:40:45 -080098 uid_t uid = getuid();
99 ASSERT_EQ(2000, (int)uid);
100 }
101
Felipe Leme7447d7c2016-11-03 18:12:22 -0700102 protected:
103 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str());
Dan Shie177e8e2019-06-20 11:08:14 -0700104 const std::string kTestDataPath = kTestPath + "/tests/testdata/";
105 const std::string kSimpleCommand = kTestPath + "/dumpstate_test_fixture";
Felipe Leme7447d7c2016-11-03 18:12:22 -0700106 const std::string kEchoCommand = "/system/bin/echo";
107
108 /*
109 * Copies a text file fixture to a temporary file, returning it's path.
110 *
111 * Useful in cases where the test case changes the content of the tile.
112 */
113 std::string CopyTextFileFixture(const std::string& relative_name) {
114 std::string from = kTestDataPath + relative_name;
115 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it
116 // around for poking when the test fails.
117 std::string to = kTestDataPath + relative_name + ".tmp";
118 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str());
119 android::base::RemoveFileIfExists(to);
120 CopyTextFile(from, to);
121 return to.c_str();
122 }
123
Felipe Leme46b85da2016-11-21 17:40:45 -0800124 // Need functions that returns void to use assertions -
Felipe Leme7447d7c2016-11-03 18:12:22 -0700125 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement
Felipe Leme46b85da2016-11-21 17:40:45 -0800126 void ReadFileToString(const std::string& path, std::string* content) {
127 ASSERT_TRUE(android::base::ReadFileToString(path, content))
128 << "could not read contents from " << path;
129 }
130 void WriteStringToFile(const std::string& content, const std::string& path) {
131 ASSERT_TRUE(android::base::WriteStringToFile(content, path))
132 << "could not write contents to " << path;
133 }
134
135 private:
Felipe Leme7447d7c2016-11-03 18:12:22 -0700136 void CopyTextFile(const std::string& from, const std::string& to) {
137 std::string content;
Felipe Leme46b85da2016-11-21 17:40:45 -0800138 ReadFileToString(from, &content);
139 WriteStringToFile(content, to);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700140 }
141};
142
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100143class DumpOptionsTest : public Test {
144 public:
145 virtual ~DumpOptionsTest() {
146 }
147 virtual void SetUp() {
148 options_ = Dumpstate::DumpOptions();
149 }
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000150 void TearDown() {
151 // Reset the property
152 property_set("dumpstate.options", "");
153 }
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100154 Dumpstate::DumpOptions options_;
155};
156
157TEST_F(DumpOptionsTest, InitializeNone) {
158 // clang-format off
159 char* argv[] = {
160 const_cast<char*>("dumpstate")
161 };
162 // clang-format on
163
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100164 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
165
166 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000167
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100168 EXPECT_FALSE(options_.do_add_date);
169 EXPECT_FALSE(options_.do_zip_file);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100170 EXPECT_FALSE(options_.use_socket);
171 EXPECT_FALSE(options_.use_control_socket);
172 EXPECT_FALSE(options_.show_header_only);
173 EXPECT_TRUE(options_.do_vibrate);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000174 EXPECT_FALSE(options_.do_fb);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100175 EXPECT_FALSE(options_.do_progress_updates);
176 EXPECT_FALSE(options_.is_remote_mode);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000177 EXPECT_FALSE(options_.do_broadcast);
178}
179
180TEST_F(DumpOptionsTest, InitializeAdbBugreport) {
181 // clang-format off
182 char* argv[] = {
183 const_cast<char*>("dumpstatez"),
184 const_cast<char*>("-S"),
185 const_cast<char*>("-d"),
186 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000187 };
188 // clang-format on
189
190 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
191
192 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
193 EXPECT_TRUE(options_.do_add_date);
194 EXPECT_TRUE(options_.do_zip_file);
195 EXPECT_TRUE(options_.use_control_socket);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000196
197 // Other options retain default values
198 EXPECT_TRUE(options_.do_vibrate);
199 EXPECT_FALSE(options_.show_header_only);
200 EXPECT_FALSE(options_.do_fb);
201 EXPECT_FALSE(options_.do_progress_updates);
202 EXPECT_FALSE(options_.is_remote_mode);
203 EXPECT_FALSE(options_.do_broadcast);
204 EXPECT_FALSE(options_.use_socket);
205}
206
207TEST_F(DumpOptionsTest, InitializeAdbShellBugreport) {
208 // clang-format off
209 char* argv[] = {
210 const_cast<char*>("dumpstate"),
211 const_cast<char*>("-s"),
212 };
213 // clang-format on
214
215 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
216
217 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
218 EXPECT_TRUE(options_.use_socket);
219
220 // Other options retain default values
221 EXPECT_TRUE(options_.do_vibrate);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000222 EXPECT_FALSE(options_.do_add_date);
223 EXPECT_FALSE(options_.do_zip_file);
224 EXPECT_FALSE(options_.use_control_socket);
225 EXPECT_FALSE(options_.show_header_only);
226 EXPECT_FALSE(options_.do_fb);
227 EXPECT_FALSE(options_.do_progress_updates);
228 EXPECT_FALSE(options_.is_remote_mode);
229 EXPECT_FALSE(options_.do_broadcast);
230}
231
232TEST_F(DumpOptionsTest, InitializeFullBugReport) {
233 // clang-format off
234 char* argv[] = {
235 const_cast<char*>("bugreport"),
236 const_cast<char*>("-d"),
237 const_cast<char*>("-p"),
238 const_cast<char*>("-B"),
239 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000240 };
241 // clang-format on
242 property_set("dumpstate.options", "bugreportfull");
243
244 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
245
246 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
247 EXPECT_TRUE(options_.do_add_date);
248 EXPECT_TRUE(options_.do_fb);
249 EXPECT_TRUE(options_.do_zip_file);
Nandana Dutt58d72e22018-11-16 10:30:48 +0000250 EXPECT_TRUE(options_.do_broadcast);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000251
252 // Other options retain default values
253 EXPECT_TRUE(options_.do_vibrate);
254 EXPECT_FALSE(options_.use_control_socket);
255 EXPECT_FALSE(options_.show_header_only);
256 EXPECT_FALSE(options_.do_progress_updates);
257 EXPECT_FALSE(options_.is_remote_mode);
258 EXPECT_FALSE(options_.use_socket);
259 EXPECT_FALSE(options_.do_start_service);
260}
261
262TEST_F(DumpOptionsTest, InitializeInteractiveBugReport) {
263 // clang-format off
264 char* argv[] = {
265 const_cast<char*>("bugreport"),
266 const_cast<char*>("-d"),
267 const_cast<char*>("-p"),
268 const_cast<char*>("-B"),
269 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000270 };
271 // clang-format on
272
273 property_set("dumpstate.options", "bugreportplus");
274
275 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
276
277 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
278 EXPECT_TRUE(options_.do_add_date);
279 EXPECT_TRUE(options_.do_broadcast);
280 EXPECT_TRUE(options_.do_zip_file);
281 EXPECT_TRUE(options_.do_progress_updates);
282 EXPECT_TRUE(options_.do_start_service);
283 EXPECT_FALSE(options_.do_fb);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000284
285 // Other options retain default values
286 EXPECT_TRUE(options_.do_vibrate);
287 EXPECT_FALSE(options_.use_control_socket);
288 EXPECT_FALSE(options_.show_header_only);
289 EXPECT_FALSE(options_.is_remote_mode);
290 EXPECT_FALSE(options_.use_socket);
291}
292
293TEST_F(DumpOptionsTest, InitializeRemoteBugReport) {
294 // clang-format off
295 char* argv[] = {
296 const_cast<char*>("bugreport"),
297 const_cast<char*>("-d"),
298 const_cast<char*>("-p"),
299 const_cast<char*>("-B"),
300 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000301 };
302 // clang-format on
303
304 property_set("dumpstate.options", "bugreportremote");
305
306 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
307
308 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
309 EXPECT_TRUE(options_.do_add_date);
310 EXPECT_TRUE(options_.do_broadcast);
311 EXPECT_TRUE(options_.do_zip_file);
312 EXPECT_TRUE(options_.is_remote_mode);
313 EXPECT_FALSE(options_.do_vibrate);
314 EXPECT_FALSE(options_.do_fb);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000315
316 // Other options retain default values
317 EXPECT_FALSE(options_.use_control_socket);
318 EXPECT_FALSE(options_.show_header_only);
319 EXPECT_FALSE(options_.do_progress_updates);
320 EXPECT_FALSE(options_.use_socket);
321}
322
323TEST_F(DumpOptionsTest, InitializeWearBugReport) {
324 // clang-format off
325 char* argv[] = {
326 const_cast<char*>("bugreport"),
327 const_cast<char*>("-d"),
328 const_cast<char*>("-p"),
329 const_cast<char*>("-B"),
330 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000331 };
332 // clang-format on
333
334 property_set("dumpstate.options", "bugreportwear");
335
336 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
337
338 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
339 EXPECT_TRUE(options_.do_add_date);
340 EXPECT_TRUE(options_.do_fb);
341 EXPECT_TRUE(options_.do_broadcast);
342 EXPECT_TRUE(options_.do_zip_file);
343 EXPECT_TRUE(options_.do_progress_updates);
344 EXPECT_TRUE(options_.do_start_service);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000345
346 // Other options retain default values
347 EXPECT_TRUE(options_.do_vibrate);
348 EXPECT_FALSE(options_.use_control_socket);
349 EXPECT_FALSE(options_.show_header_only);
350 EXPECT_FALSE(options_.is_remote_mode);
351 EXPECT_FALSE(options_.use_socket);
352}
353
354TEST_F(DumpOptionsTest, InitializeTelephonyBugReport) {
355 // clang-format off
356 char* argv[] = {
357 const_cast<char*>("bugreport"),
358 const_cast<char*>("-d"),
359 const_cast<char*>("-p"),
360 const_cast<char*>("-B"),
361 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000362 };
363 // clang-format on
364
365 property_set("dumpstate.options", "bugreporttelephony");
366
367 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
368
369 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
370 EXPECT_TRUE(options_.do_add_date);
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +0000371 EXPECT_FALSE(options_.do_fb);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000372 EXPECT_TRUE(options_.do_broadcast);
373 EXPECT_TRUE(options_.do_zip_file);
374 EXPECT_TRUE(options_.telephony_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000375
376 // Other options retain default values
377 EXPECT_TRUE(options_.do_vibrate);
378 EXPECT_FALSE(options_.use_control_socket);
379 EXPECT_FALSE(options_.show_header_only);
380 EXPECT_FALSE(options_.do_progress_updates);
381 EXPECT_FALSE(options_.is_remote_mode);
382 EXPECT_FALSE(options_.use_socket);
383}
384
385TEST_F(DumpOptionsTest, InitializeWifiBugReport) {
386 // clang-format off
387 char* argv[] = {
388 const_cast<char*>("bugreport"),
389 const_cast<char*>("-d"),
390 const_cast<char*>("-p"),
391 const_cast<char*>("-B"),
392 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000393 };
394 // clang-format on
395
396 property_set("dumpstate.options", "bugreportwifi");
397
398 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
399
400 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
401 EXPECT_TRUE(options_.do_add_date);
Abhijeet Kaurd3cca0d2019-03-25 12:04:16 +0000402 EXPECT_FALSE(options_.do_fb);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000403 EXPECT_TRUE(options_.do_broadcast);
404 EXPECT_TRUE(options_.do_zip_file);
405 EXPECT_TRUE(options_.wifi_only);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000406
407 // Other options retain default values
408 EXPECT_TRUE(options_.do_vibrate);
409 EXPECT_FALSE(options_.use_control_socket);
410 EXPECT_FALSE(options_.show_header_only);
411 EXPECT_FALSE(options_.do_progress_updates);
412 EXPECT_FALSE(options_.is_remote_mode);
413 EXPECT_FALSE(options_.use_socket);
414}
415
416TEST_F(DumpOptionsTest, InitializeDefaultBugReport) {
417 // default: commandline options are not overridden
418 // clang-format off
419 char* argv[] = {
420 const_cast<char*>("bugreport"),
421 const_cast<char*>("-d"),
422 const_cast<char*>("-p"),
423 const_cast<char*>("-B"),
424 const_cast<char*>("-z"),
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000425 };
426 // clang-format on
427
428 property_set("dumpstate.options", "");
429
430 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
431
432 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
433 EXPECT_TRUE(options_.do_add_date);
434 EXPECT_TRUE(options_.do_fb);
435 EXPECT_TRUE(options_.do_zip_file);
436 EXPECT_TRUE(options_.do_broadcast);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000437
438 // Other options retain default values
439 EXPECT_TRUE(options_.do_vibrate);
440 EXPECT_FALSE(options_.use_control_socket);
441 EXPECT_FALSE(options_.show_header_only);
442 EXPECT_FALSE(options_.do_progress_updates);
443 EXPECT_FALSE(options_.is_remote_mode);
444 EXPECT_FALSE(options_.use_socket);
445 EXPECT_FALSE(options_.wifi_only);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100446}
447
448TEST_F(DumpOptionsTest, InitializePartial1) {
449 // clang-format off
450 char* argv[] = {
451 const_cast<char*>("dumpstate"),
452 const_cast<char*>("-d"),
453 const_cast<char*>("-z"),
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100454 const_cast<char*>("-s"),
455 const_cast<char*>("-S"),
456
457 };
458 // clang-format on
459
460 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
461
462 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
463 EXPECT_TRUE(options_.do_add_date);
464 EXPECT_TRUE(options_.do_zip_file);
465 // TODO: Maybe we should trim the filename
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100466 EXPECT_TRUE(options_.use_socket);
467 EXPECT_TRUE(options_.use_control_socket);
468
469 // Other options retain default values
470 EXPECT_FALSE(options_.show_header_only);
471 EXPECT_TRUE(options_.do_vibrate);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000472 EXPECT_FALSE(options_.do_fb);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100473 EXPECT_FALSE(options_.do_progress_updates);
474 EXPECT_FALSE(options_.is_remote_mode);
Abhijeet Kaur904e0e02018-12-05 14:03:01 +0000475 EXPECT_FALSE(options_.do_broadcast);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100476}
477
478TEST_F(DumpOptionsTest, InitializePartial2) {
479 // clang-format off
480 char* argv[] = {
481 const_cast<char*>("dumpstate"),
482 const_cast<char*>("-v"),
483 const_cast<char*>("-q"),
484 const_cast<char*>("-p"),
485 const_cast<char*>("-P"),
486 const_cast<char*>("-R"),
487 const_cast<char*>("-B"),
488 };
489 // clang-format on
490
491 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
492
493 EXPECT_EQ(status, Dumpstate::RunStatus::OK);
494 EXPECT_TRUE(options_.show_header_only);
495 EXPECT_FALSE(options_.do_vibrate);
496 EXPECT_TRUE(options_.do_fb);
497 EXPECT_TRUE(options_.do_progress_updates);
498 EXPECT_TRUE(options_.is_remote_mode);
499 EXPECT_TRUE(options_.do_broadcast);
500
501 // Other options retain default values
502 EXPECT_FALSE(options_.do_add_date);
503 EXPECT_FALSE(options_.do_zip_file);
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100504 EXPECT_FALSE(options_.use_socket);
505 EXPECT_FALSE(options_.use_control_socket);
506}
507
508TEST_F(DumpOptionsTest, InitializeHelp) {
509 // clang-format off
510 char* argv[] = {
511 const_cast<char*>("dumpstate"),
512 const_cast<char*>("-h")
513 };
514 // clang-format on
515
516 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
517
518 // -h is for help.
519 EXPECT_EQ(status, Dumpstate::RunStatus::HELP);
520}
521
522TEST_F(DumpOptionsTest, InitializeUnknown) {
523 // clang-format off
524 char* argv[] = {
525 const_cast<char*>("dumpstate"),
526 const_cast<char*>("-u") // unknown flag
527 };
528 // clang-format on
529
530 Dumpstate::RunStatus status = options_.Initialize(ARRAY_SIZE(argv), argv);
531
532 // -u is unknown.
533 EXPECT_EQ(status, Dumpstate::RunStatus::INVALID_INPUT);
534}
535
536TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile1) {
537 options_.do_zip_file = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000538 // Writing to socket = !writing to file.
539 options_.use_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100540 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000541
542 options_.use_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100543 EXPECT_TRUE(options_.ValidateOptions());
544}
545
546TEST_F(DumpOptionsTest, ValidateOptionsNeedOutfile2) {
547 options_.do_broadcast = true;
Nandana Dutt9a76d202019-01-21 15:56:48 +0000548 // Writing to socket = !writing to file.
549 options_.use_socket = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100550 EXPECT_FALSE(options_.ValidateOptions());
Nandana Dutt9a76d202019-01-21 15:56:48 +0000551
552 options_.use_socket = false;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100553 EXPECT_TRUE(options_.ValidateOptions());
554}
555
556TEST_F(DumpOptionsTest, ValidateOptionsNeedZipfile) {
557 options_.use_control_socket = true;
558 EXPECT_FALSE(options_.ValidateOptions());
559
560 options_.do_zip_file = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100561 EXPECT_TRUE(options_.ValidateOptions());
562}
563
564TEST_F(DumpOptionsTest, ValidateOptionsUpdateProgressNeedsBroadcast) {
565 options_.do_progress_updates = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100566 EXPECT_FALSE(options_.ValidateOptions());
567
568 options_.do_broadcast = true;
569 EXPECT_TRUE(options_.ValidateOptions());
570}
571
572TEST_F(DumpOptionsTest, ValidateOptionsRemoteMode) {
573 options_.is_remote_mode = true;
574 EXPECT_FALSE(options_.ValidateOptions());
575
576 options_.do_broadcast = true;
577 options_.do_zip_file = true;
578 options_.do_add_date = true;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100579 EXPECT_TRUE(options_.ValidateOptions());
580}
581
Felipe Leme7447d7c2016-11-03 18:12:22 -0700582class DumpstateTest : public DumpstateBaseTest {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700583 public:
584 void SetUp() {
Felipe Leme46b85da2016-11-21 17:40:45 -0800585 DumpstateBaseTest::SetUp();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700586 SetDryRun(false);
Felipe Lemed80e6b62016-10-03 13:08:14 -0700587 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700588 ds.progress_.reset(new Progress());
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100589 ds.options_.reset(new Dumpstate::DumpOptions());
Felipe Leme4c2d6632016-09-28 14:32:00 -0700590 }
591
592 // Runs a command and capture `stdout` and `stderr`.
Felipe Leme9a523ae2016-10-20 15:10:33 -0700593 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme4c2d6632016-09-28 14:32:00 -0700594 const CommandOptions& options = CommandOptions::DEFAULT) {
595 CaptureStdout();
596 CaptureStderr();
Felipe Leme9a523ae2016-10-20 15:10:33 -0700597 int status = ds.RunCommand(title, full_command, options);
Felipe Leme4c2d6632016-09-28 14:32:00 -0700598 out = GetCapturedStdout();
599 err = GetCapturedStderr();
600 return status;
601 }
602
Felipe Lemecef02982016-10-03 17:22:22 -0700603 // Dumps a file and capture `stdout` and `stderr`.
604 int DumpFile(const std::string& title, const std::string& path) {
605 CaptureStdout();
606 CaptureStderr();
607 int status = ds.DumpFile(title, path);
608 out = GetCapturedStdout();
609 err = GetCapturedStderr();
610 return status;
611 }
612
Nandana Dutt402a8392019-06-14 14:25:13 +0100613 void SetProgress(long progress, long initial_max) {
614 ds.last_reported_percent_progress_ = 0;
Nandana Dutt5fb117b2018-09-27 09:23:36 +0100615 ds.options_->do_progress_updates = true;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700616 ds.progress_.reset(new Progress(initial_max, progress, 1.2));
617 }
618
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100619 std::string GetProgressMessage(int progress, int max,
620 int old_max = 0, bool update_progress = true) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700621 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress";
622 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max";
Felipe Leme75876a22016-10-27 16:31:27 -0700623
Felipe Leme7447d7c2016-11-03 18:12:22 -0700624 bool max_increased = old_max > 0;
Felipe Leme75876a22016-10-27 16:31:27 -0700625
Felipe Leme009ecbb2016-11-07 10:18:44 -0800626 std::string message = "";
Felipe Leme75876a22016-10-27 16:31:27 -0700627 if (max_increased) {
Felipe Leme009ecbb2016-11-07 10:18:44 -0800628 message =
Felipe Leme7447d7c2016-11-03 18:12:22 -0700629 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max);
Felipe Leme75876a22016-10-27 16:31:27 -0700630 }
631
Felipe Leme009ecbb2016-11-07 10:18:44 -0800632 if (update_progress) {
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100633 message += android::base::StringPrintf("Setting progress: %d/%d (%d%%)\n",
634 progress, max, (100 * progress / max));
Felipe Leme009ecbb2016-11-07 10:18:44 -0800635 }
636
637 return message;
Felipe Lemed80e6b62016-10-03 13:08:14 -0700638 }
639
Felipe Leme4c2d6632016-09-28 14:32:00 -0700640 // `stdout` and `stderr` from the last command ran.
641 std::string out, err;
642
Felipe Lemefd8affa2016-09-30 17:38:57 -0700643 Dumpstate& ds = Dumpstate::GetInstance();
Felipe Leme4c2d6632016-09-28 14:32:00 -0700644};
645
646TEST_F(DumpstateTest, RunCommandNoArgs) {
647 EXPECT_EQ(-1, RunCommand("", {}));
648}
649
650TEST_F(DumpstateTest, RunCommandNoTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700651 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700652 EXPECT_THAT(out, StrEq("stdout\n"));
653 EXPECT_THAT(err, StrEq("stderr\n"));
654}
655
656TEST_F(DumpstateTest, RunCommandWithTitle) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700657 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700658 EXPECT_THAT(err, StrEq("stderr\n"));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700659 // The duration may not get output, depending on how long it takes,
660 // so we just check the prefix.
Felipe Lemefd8affa2016-09-30 17:38:57 -0700661 EXPECT_THAT(out,
Nandana Dutt47527b52019-03-29 15:34:36 +0000662 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700663}
664
Felipe Lemefd8affa2016-09-30 17:38:57 -0700665TEST_F(DumpstateTest, RunCommandWithLoggingMessage) {
Felipe Leme4c2d6632016-09-28 14:32:00 -0700666 EXPECT_EQ(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700667 0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700668 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
669 EXPECT_THAT(out, StrEq("stdout\n"));
670 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
671}
672
673TEST_F(DumpstateTest, RunCommandRedirectStderr) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700674 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700675 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700676 EXPECT_THAT(out, IsEmpty());
Felipe Lemefd8affa2016-09-30 17:38:57 -0700677 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700678}
679
680TEST_F(DumpstateTest, RunCommandWithOneArg) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700681 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700682 EXPECT_THAT(err, IsEmpty());
683 EXPECT_THAT(out, StrEq("one\n"));
684}
685
Felipe Lemefd8affa2016-09-30 17:38:57 -0700686TEST_F(DumpstateTest, RunCommandWithMultipleArgs) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700687 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700688 EXPECT_THAT(err, IsEmpty());
689 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
690}
691
692TEST_F(DumpstateTest, RunCommandDryRun) {
693 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700694 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
Greg Kaiser3a811c12019-05-21 12:48:59 -0700695 // The duration may not get output, depending on how long it takes,
696 // so we just check the prefix.
Felipe Leme7447d7c2016-11-03 18:12:22 -0700697 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand +
Nandana Dutt47527b52019-03-29 15:34:36 +0000698 ") ------\n\t(skipped on dry run)\n"));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700699 EXPECT_THAT(err, IsEmpty());
700}
701
702TEST_F(DumpstateTest, RunCommandDryRunNoTitle) {
703 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700704 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700705 EXPECT_THAT(out, IsEmpty());
706 EXPECT_THAT(err, IsEmpty());
707}
708
709TEST_F(DumpstateTest, RunCommandDryRunAlways) {
710 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -0700711 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme4c2d6632016-09-28 14:32:00 -0700712 EXPECT_THAT(out, StrEq("stdout\n"));
713 EXPECT_THAT(err, StrEq("stderr\n"));
714}
715
Felipe Lemefd8affa2016-09-30 17:38:57 -0700716TEST_F(DumpstateTest, RunCommandNotFound) {
717 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
718 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
719 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
720}
721
722TEST_F(DumpstateTest, RunCommandFails) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700723 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
724 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700725 " --exit 42' failed: exit code 42\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700726 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
Felipe Leme9a523ae2016-10-20 15:10:33 -0700727 " --exit 42' failed: exit code 42\n"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700728}
729
730TEST_F(DumpstateTest, RunCommandCrashes) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700731 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700732 // We don't know the exit code, so check just the prefix.
733 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700734 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700735 EXPECT_THAT(
Felipe Leme7447d7c2016-11-03 18:12:22 -0700736 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
Felipe Lemefd8affa2016-09-30 17:38:57 -0700737}
738
739TEST_F(DumpstateTest, RunCommandTimesout) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700740 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700741 CommandOptions::WithTimeout(1).Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700742 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700743 " --sleep 2' timed out after 1"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700744 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700745 " --sleep 2' timed out after 1"));
746}
747
748TEST_F(DumpstateTest, RunCommandIsKilled) {
749 CaptureStdout();
750 CaptureStderr();
751
752 std::thread t([=]() {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700753 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Lemefd8affa2016-09-30 17:38:57 -0700754 CommandOptions::WithTimeout(100).Always().Build()));
755 });
756
757 // Capture pid and pre-sleep output.
758 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
759 std::string err = GetCapturedStderr();
760 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
761
762 std::string out = GetCapturedStdout();
763 std::vector<std::string> lines = android::base::Split(out, "\n");
764 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
765
766 int pid = atoi(lines[0].c_str());
767 EXPECT_THAT(lines[1], StrEq("stdout line1"));
768 EXPECT_THAT(lines[2], IsEmpty()); // \n
769
770 // Then kill the process.
771 CaptureStdout();
772 CaptureStderr();
773 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
774 t.join();
775
776 // Finally, check output after murder.
777 out = GetCapturedStdout();
778 err = GetCapturedStderr();
779
Felipe Leme7447d7c2016-11-03 18:12:22 -0700780 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700781 " --pid --sleep 20' failed: killed by signal 15\n"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700782 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
Felipe Lemefd8affa2016-09-30 17:38:57 -0700783 " --pid --sleep 20' failed: killed by signal 15\n"));
784}
785
Felipe Leme75876a22016-10-27 16:31:27 -0700786TEST_F(DumpstateTest, RunCommandProgress) {
787 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
788 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -0700789 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700790
Nandana Duttbabf6c72019-01-15 14:11:12 +0000791 EXPECT_CALL(*listener, onProgress(66)); // 20/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -0700792 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100793 std::string progress_message = GetProgressMessage(20, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700794 EXPECT_THAT(out, StrEq("stdout\n"));
795 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
796
Nandana Dutt402a8392019-06-14 14:25:13 +0100797 EXPECT_CALL(*listener, onProgress(80)); // 24/30 %
798 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100799 progress_message = GetProgressMessage(24, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700800 EXPECT_THAT(out, StrEq("stdout\n"));
801 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
802
803 // Make sure command ran while in dry_run is counted.
804 SetDryRun(true);
Nandana Dutt402a8392019-06-14 14:25:13 +0100805 EXPECT_CALL(*listener, onProgress(90)); // 27/30 %
806 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100807 progress_message = GetProgressMessage(27, 30);
Felipe Leme75876a22016-10-27 16:31:27 -0700808 EXPECT_THAT(out, IsEmpty());
809 EXPECT_THAT(err, StrEq(progress_message));
810
Nandana Dutt402a8392019-06-14 14:25:13 +0100811 SetDryRun(false);
812 EXPECT_CALL(*listener, onProgress(96)); // 29/30 %
813 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(2).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100814 progress_message = GetProgressMessage(29, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800815 EXPECT_THAT(out, StrEq("stdout\n"));
816 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
817
Nandana Dutt402a8392019-06-14 14:25:13 +0100818 EXPECT_CALL(*listener, onProgress(100)); // 30/30 %
Felipe Leme009ecbb2016-11-07 10:18:44 -0800819 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build()));
Abhijeet Kaured5d6a62019-10-07 15:02:05 +0100820 progress_message = GetProgressMessage(30, 30);
Felipe Leme009ecbb2016-11-07 10:18:44 -0800821 EXPECT_THAT(out, StrEq("stdout\n"));
822 EXPECT_THAT(err, StrEq("stderr\n" + progress_message));
823
824 ds.listener_.clear();
825}
826
Felipe Lemed80e6b62016-10-03 13:08:14 -0700827TEST_F(DumpstateTest, RunCommandDropRoot) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800828 if (!IsStandalone()) {
829 // TODO: temporarily disabled because it might cause other tests to fail after dropping
830 // to Shell - need to refactor tests to avoid this problem)
831 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n")
832 return;
833 }
Felipe Lemed80e6b62016-10-03 13:08:14 -0700834 // First check root case - only available when running with 'adb root'.
835 uid_t uid = getuid();
836 if (uid == 0) {
Felipe Leme7447d7c2016-11-03 18:12:22 -0700837 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700838 EXPECT_THAT(out, StrEq("0\nstdout\n"));
839 EXPECT_THAT(err, StrEq("stderr\n"));
840 return;
841 }
Felipe Leme7447d7c2016-11-03 18:12:22 -0700842 // Then run dropping root.
843 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Lemed80e6b62016-10-03 13:08:14 -0700844 CommandOptions::WithTimeout(1).DropRoot().Build()));
845 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
Felipe Leme26c41572016-10-06 14:34:43 -0700846 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700847}
848
849TEST_F(DumpstateTest, RunCommandAsRootUserBuild) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800850 if (!IsStandalone()) {
851 // TODO: temporarily disabled because it might cause other tests to fail after dropping
852 // to Shell - need to refactor tests to avoid this problem)
853 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n")
854 return;
855 }
Felipe Lemef0292972016-11-22 13:57:05 -0800856 if (!PropertiesHelper::IsUserBuild()) {
Felipe Lemed80e6b62016-10-03 13:08:14 -0700857 // Emulates user build if necessarily.
858 SetBuildType("user");
859 }
860
861 DropRoot();
862
Felipe Leme7447d7c2016-11-03 18:12:22 -0700863 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700864
865 // We don't know the exact path of su, so we just check for the 'root ...' commands
866 EXPECT_THAT(out, StartsWith("Skipping"));
Felipe Leme7447d7c2016-11-03 18:12:22 -0700867 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
Felipe Lemed80e6b62016-10-03 13:08:14 -0700868 EXPECT_THAT(err, IsEmpty());
869}
870
Felipe Leme46b85da2016-11-21 17:40:45 -0800871TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) {
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.RunCommandAsRootNonUserBuild() on test suite\n")
876 return;
877 }
Felipe Lemef0292972016-11-22 13:57:05 -0800878 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -0800879 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
880 return;
881 }
882
883 DropRoot();
884
885 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
886 CommandOptions::WithTimeout(1).AsRoot().Build()));
887
888 EXPECT_THAT(out, StrEq("0\nstdout\n"));
889 EXPECT_THAT(err, StrEq("stderr\n"));
890}
891
Nandana Dutt4b392be2018-11-02 16:17:05 +0000892TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild_withUnroot) {
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(
897 "Skipping DumpstateTest.RunCommandAsRootNonUserBuild_withUnroot() "
898 "on test suite\n")
899 return;
900 }
901 if (PropertiesHelper::IsUserBuild()) {
902 ALOGI("Skipping RunCommandAsRootNonUserBuild_withUnroot on user builds\n");
903 return;
904 }
905
906 // Same test as above, but with unroot property set, which will override su availability.
907 SetUnroot(true);
908 DropRoot();
909
910 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
911 CommandOptions::WithTimeout(1).AsRoot().Build()));
912
913 // AsRoot is ineffective.
914 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
915 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
916}
917
Yifan Hong48e83a12017-10-03 14:10:07 -0700918TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnUserBuild) {
919 if (!IsStandalone()) {
920 // TODO: temporarily disabled because it might cause other tests to fail after dropping
921 // to Shell - need to refactor tests to avoid this problem)
922 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
923 return;
924 }
925 if (!PropertiesHelper::IsUserBuild()) {
926 // Emulates user build if necessarily.
927 SetBuildType("user");
928 }
929
930 DropRoot();
931
932 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
933 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
934
935 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
936 EXPECT_THAT(err, StrEq("stderr\n"));
937}
938
939TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild) {
940 if (!IsStandalone()) {
941 // TODO: temporarily disabled because it might cause other tests to fail after dropping
942 // to Shell - need to refactor tests to avoid this problem)
943 MYLOGE("Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
944 return;
945 }
946 if (PropertiesHelper::IsUserBuild()) {
947 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
948 return;
949 }
950
951 DropRoot();
952
953 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
954 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
955
956 EXPECT_THAT(out, StrEq("0\nstdout\n"));
957 EXPECT_THAT(err, StrEq("stderr\n"));
958}
959
Nandana Dutt4b392be2018-11-02 16:17:05 +0000960TEST_F(DumpstateTest, RunCommandAsRootIfAvailableOnDebugBuild_withUnroot) {
961 if (!IsStandalone()) {
962 // TODO: temporarily disabled because it might cause other tests to fail after dropping
963 // to Shell - need to refactor tests to avoid this problem)
964 MYLOGE(
965 "Skipping DumpstateTest.RunCommandAsRootIfAvailableOnDebugBuild_withUnroot() "
966 "on test suite\n")
967 return;
968 }
969 if (PropertiesHelper::IsUserBuild()) {
970 ALOGI("Skipping RunCommandAsRootIfAvailableOnDebugBuild_withUnroot on user builds\n");
971 return;
972 }
973 // Same test as above, but with unroot property set, which will override su availability.
974 SetUnroot(true);
975
976 DropRoot();
977
978 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
979 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
980
981 // It's a userdebug build, so "su root" should be available, but unroot=true overrides it.
982 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
983 EXPECT_THAT(err, StrEq("stderr\n"));
984}
985
Felipe Lemecef02982016-10-03 17:22:22 -0700986TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) {
987 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
988 EXPECT_THAT(out,
989 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
990 EXPECT_THAT(err, IsEmpty());
991}
992
993TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) {
994 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
995 EXPECT_THAT(err, IsEmpty());
Greg Kaiser3a811c12019-05-21 12:48:59 -0700996 // The duration may not get output, depending on how long it takes,
997 // so we just check the prefix.
Felipe Lemecef02982016-10-03 17:22:22 -0700998 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No "
999 "such file or directory\n"));
Felipe Lemecef02982016-10-03 17:22:22 -07001000}
1001
1002TEST_F(DumpstateTest, DumpFileSingleLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001003 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001004 EXPECT_THAT(err, IsEmpty());
1005 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1006}
1007
1008TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001009 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001010 EXPECT_THAT(err, IsEmpty());
1011 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1012}
1013
1014TEST_F(DumpstateTest, DumpFileMultipleLines) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001015 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001016 EXPECT_THAT(err, IsEmpty());
1017 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1018}
1019
1020TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001021 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001022 EXPECT_THAT(err, IsEmpty());
1023 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1024}
1025
1026TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) {
1027 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001028 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001029 EXPECT_THAT(err, IsEmpty());
1030 EXPECT_THAT(out, IsEmpty());
1031}
1032
1033TEST_F(DumpstateTest, DumpFileOnDryRun) {
1034 SetDryRun(true);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001035 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Lemecef02982016-10-03 17:22:22 -07001036 EXPECT_THAT(err, IsEmpty());
Felipe Leme46b85da2016-11-21 17:40:45 -08001037 EXPECT_THAT(
1038 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
Nandana Dutt47527b52019-03-29 15:34:36 +00001039 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n"));
Felipe Lemecef02982016-10-03 17:22:22 -07001040}
1041
Felipe Leme75876a22016-10-27 16:31:27 -07001042TEST_F(DumpstateTest, DumpFileUpdateProgress) {
1043 sp<DumpstateListenerMock> listener(new DumpstateListenerMock());
1044 ds.listener_ = listener;
Felipe Leme7447d7c2016-11-03 18:12:22 -07001045 SetProgress(0, 30);
Felipe Leme75876a22016-10-27 16:31:27 -07001046
Nandana Duttbabf6c72019-01-15 14:11:12 +00001047 EXPECT_CALL(*listener, onProgress(16)); // 5/30 %
Felipe Leme7447d7c2016-11-03 18:12:22 -07001048 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme75876a22016-10-27 16:31:27 -07001049
Abhijeet Kaured5d6a62019-10-07 15:02:05 +01001050 std::string progress_message = GetProgressMessage(5, 30); // TODO: unhardcode WEIGHT_FILE (5)?
Felipe Leme75876a22016-10-27 16:31:27 -07001051 EXPECT_THAT(err, StrEq(progress_message));
1052 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1053
1054 ds.listener_.clear();
1055}
1056
Felipe Leme7447d7c2016-11-03 18:12:22 -07001057class DumpstateServiceTest : public DumpstateBaseTest {
Felipe Leme75876a22016-10-27 16:31:27 -07001058 public:
1059 DumpstateService dss;
1060};
1061
Felipe Leme7447d7c2016-11-03 18:12:22 -07001062class ProgressTest : public DumpstateBaseTest {
1063 public:
1064 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") {
1065 return Progress(max, growth_factor, path);
1066 }
1067
1068 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) {
1069 std::string expected_content =
1070 android::base::StringPrintf("%d %d\n", expected_runs, expected_average);
1071 std::string actual_content;
Felipe Leme46b85da2016-11-21 17:40:45 -08001072 ReadFileToString(path, &actual_content);
Felipe Leme7447d7c2016-11-03 18:12:22 -07001073 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path;
1074 }
1075};
1076
1077TEST_F(ProgressTest, SimpleTest) {
1078 Progress progress;
1079 EXPECT_EQ(0, progress.Get());
1080 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1081 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1082
1083 bool max_increased = progress.Inc(1);
1084 EXPECT_EQ(1, progress.Get());
1085 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1086 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1087 EXPECT_FALSE(max_increased);
1088
1089 // Ignore negative increase.
1090 max_increased = progress.Inc(-1);
1091 EXPECT_EQ(1, progress.Get());
1092 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax());
1093 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1094 EXPECT_FALSE(max_increased);
1095}
1096
1097TEST_F(ProgressTest, MaxGrowsInsideNewRange) {
1098 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1099 EXPECT_EQ(0, progress.Get());
1100 EXPECT_EQ(10, progress.GetInitialMax());
1101 EXPECT_EQ(10, progress.GetMax());
1102
1103 // No increase
1104 bool max_increased = progress.Inc(10);
1105 EXPECT_EQ(10, progress.Get());
1106 EXPECT_EQ(10, progress.GetMax());
1107 EXPECT_FALSE(max_increased);
1108
1109 // Increase, with new value < max*20%
1110 max_increased = progress.Inc(1);
1111 EXPECT_EQ(11, progress.Get());
1112 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13
1113 EXPECT_TRUE(max_increased);
1114}
1115
1116TEST_F(ProgressTest, MaxGrowsOutsideNewRange) {
1117 Progress progress = GetInstance(10, 1.2); // 20% growth factor
1118 EXPECT_EQ(0, progress.Get());
1119 EXPECT_EQ(10, progress.GetInitialMax());
1120 EXPECT_EQ(10, progress.GetMax());
1121
1122 // No increase
1123 bool max_increased = progress.Inc(10);
1124 EXPECT_EQ(10, progress.Get());
1125 EXPECT_EQ(10, progress.GetMax());
1126 EXPECT_FALSE(max_increased);
1127
1128 // Increase, with new value > max*20%
1129 max_increased = progress.Inc(5);
1130 EXPECT_EQ(15, progress.Get());
1131 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18
1132 EXPECT_TRUE(max_increased);
1133}
1134
1135TEST_F(ProgressTest, InvalidPath) {
1136 Progress progress("/devil/null");
1137 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1138}
1139
1140TEST_F(ProgressTest, EmptyFile) {
1141 Progress progress(CopyTextFileFixture("empty-file.txt"));
1142 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1143}
1144
1145TEST_F(ProgressTest, InvalidLine1stEntryNAN) {
1146 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt"));
1147 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1148}
1149
1150TEST_F(ProgressTest, InvalidLine2ndEntryNAN) {
1151 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt"));
1152 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1153}
1154
1155TEST_F(ProgressTest, InvalidLineBothNAN) {
1156 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt"));
1157 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1158}
1159
1160TEST_F(ProgressTest, InvalidLine1stEntryNegative) {
1161 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt"));
1162 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1163}
1164
1165TEST_F(ProgressTest, InvalidLine2ndEntryNegative) {
1166 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt"));
1167 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1168}
1169
1170TEST_F(ProgressTest, InvalidLine1stEntryTooBig) {
1171 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt"));
1172 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1173}
1174
1175TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) {
1176 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt"));
1177 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax());
1178}
1179
1180// Tests stats are properly saved when the file does not exists.
1181TEST_F(ProgressTest, FirstTime) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001182 if (!IsStandalone()) {
1183 // TODO: temporarily disabled because it's failing when running as suite
1184 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n")
1185 return;
1186 }
1187
Felipe Leme7447d7c2016-11-03 18:12:22 -07001188 std::string path = kTestDataPath + "FirstTime.txt";
1189 android::base::RemoveFileIfExists(path);
1190
1191 Progress run1(path);
1192 EXPECT_EQ(0, run1.Get());
1193 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax());
1194 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1195
1196 bool max_increased = run1.Inc(20);
1197 EXPECT_EQ(20, run1.Get());
1198 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax());
1199 EXPECT_FALSE(max_increased);
1200
1201 run1.Save();
1202 AssertStats(path, 1, 20);
1203}
1204
1205// Tests what happens when the persistent settings contains the average duration of 1 run.
1206// Data on file is 1 run and 109 average.
1207TEST_F(ProgressTest, SecondTime) {
1208 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt");
1209
1210 Progress run1 = GetInstance(-42, 1.2, path);
1211 EXPECT_EQ(0, run1.Get());
1212 EXPECT_EQ(10, run1.GetInitialMax());
1213 EXPECT_EQ(10, run1.GetMax());
1214
1215 bool max_increased = run1.Inc(20);
1216 EXPECT_EQ(20, run1.Get());
1217 EXPECT_EQ(24, run1.GetMax());
1218 EXPECT_TRUE(max_increased);
1219
1220 // Average now is 2 runs and (10 + 20)/ 2 = 15
1221 run1.Save();
1222 AssertStats(path, 2, 15);
1223
1224 Progress run2 = GetInstance(-42, 1.2, path);
1225 EXPECT_EQ(0, run2.Get());
1226 EXPECT_EQ(15, run2.GetInitialMax());
1227 EXPECT_EQ(15, run2.GetMax());
1228
1229 max_increased = run2.Inc(25);
1230 EXPECT_EQ(25, run2.Get());
1231 EXPECT_EQ(30, run2.GetMax());
1232 EXPECT_TRUE(max_increased);
1233
1234 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18
1235 run2.Save();
1236 AssertStats(path, 3, 18);
1237
1238 Progress run3 = GetInstance(-42, 1.2, path);
1239 EXPECT_EQ(0, run3.Get());
1240 EXPECT_EQ(18, run3.GetInitialMax());
1241 EXPECT_EQ(18, run3.GetMax());
1242
1243 // Make sure average decreases as well
1244 max_increased = run3.Inc(5);
1245 EXPECT_EQ(5, run3.Get());
1246 EXPECT_EQ(18, run3.GetMax());
1247 EXPECT_FALSE(max_increased);
1248
1249 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14
1250 run3.Save();
1251 AssertStats(path, 4, 14);
1252}
1253
1254// Tests what happens when the persistent settings contains the average duration of 2 runs.
1255// Data on file is 2 runs and 15 average.
1256TEST_F(ProgressTest, ThirdTime) {
1257 std::string path = CopyTextFileFixture("stats-two-runs.txt");
1258 AssertStats(path, 2, 15); // Sanity check
1259
1260 Progress run1 = GetInstance(-42, 1.2, path);
1261 EXPECT_EQ(0, run1.Get());
1262 EXPECT_EQ(15, run1.GetInitialMax());
1263 EXPECT_EQ(15, run1.GetMax());
1264
1265 bool max_increased = run1.Inc(20);
1266 EXPECT_EQ(20, run1.Get());
1267 EXPECT_EQ(24, run1.GetMax());
1268 EXPECT_TRUE(max_increased);
1269
1270 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16
1271 run1.Save();
1272 AssertStats(path, 3, 16);
1273}
1274
Felipe Leme46b85da2016-11-21 17:40:45 -08001275class DumpstateUtilTest : public DumpstateBaseTest {
1276 public:
1277 void SetUp() {
1278 DumpstateBaseTest::SetUp();
1279 SetDryRun(false);
1280 }
1281
Felipe Leme46b85da2016-11-21 17:40:45 -08001282 void CaptureFdOut() {
Felipe Lemef0292972016-11-22 13:57:05 -08001283 ReadFileToString(path_, &out);
Felipe Leme46b85da2016-11-21 17:40:45 -08001284 }
1285
1286 void CreateFd(const std::string& name) {
1287 path_ = kTestDataPath + name;
1288 MYLOGD("Creating fd for file %s\n", path_.c_str());
1289
1290 fd = TEMP_FAILURE_RETRY(open(path_.c_str(),
1291 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1292 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
1293 ASSERT_GE(fd, 0) << "could not create FD for path " << path_;
1294 }
1295
1296 // Runs a command into the `fd` and capture `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001297 int RunCommand(const std::string& title, const std::vector<std::string>& full_command,
Felipe Leme46b85da2016-11-21 17:40:45 -08001298 const CommandOptions& options = CommandOptions::DEFAULT) {
1299 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001300 int status = RunCommandToFd(fd, title, full_command, options);
Felipe Leme46b85da2016-11-21 17:40:45 -08001301 close(fd);
1302
1303 CaptureFdOut();
1304 err = GetCapturedStderr();
1305 return status;
1306 }
1307
1308 // Dumps a file and into the `fd` and `stderr`.
Felipe Lemef0292972016-11-22 13:57:05 -08001309 int DumpFile(const std::string& title, const std::string& path) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001310 CaptureStderr();
Felipe Lemef0292972016-11-22 13:57:05 -08001311 int status = DumpFileToFd(fd, title, path);
Felipe Leme46b85da2016-11-21 17:40:45 -08001312 close(fd);
1313
1314 CaptureFdOut();
1315 err = GetCapturedStderr();
1316 return status;
1317 }
1318
1319 int fd;
1320
1321 // 'fd` output and `stderr` from the last command ran.
1322 std::string out, err;
1323
1324 private:
1325 std::string path_;
1326};
1327
1328TEST_F(DumpstateUtilTest, RunCommandNoArgs) {
Felipe Lemef0292972016-11-22 13:57:05 -08001329 CreateFd("RunCommandNoArgs.txt");
1330 EXPECT_EQ(-1, RunCommand("", {}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001331}
1332
Felipe Lemef0292972016-11-22 13:57:05 -08001333TEST_F(DumpstateUtilTest, RunCommandNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001334 CreateFd("RunCommandWithNoArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001335 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001336 EXPECT_THAT(out, StrEq("stdout\n"));
1337 EXPECT_THAT(err, StrEq("stderr\n"));
1338}
1339
Felipe Lemef0292972016-11-22 13:57:05 -08001340TEST_F(DumpstateUtilTest, RunCommandWithTitle) {
1341 CreateFd("RunCommandWithNoArgs.txt");
1342 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1343 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n"));
1344 EXPECT_THAT(err, StrEq("stderr\n"));
1345}
1346
Felipe Leme46b85da2016-11-21 17:40:45 -08001347TEST_F(DumpstateUtilTest, RunCommandWithOneArg) {
1348 CreateFd("RunCommandWithOneArg.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001349 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001350 EXPECT_THAT(err, IsEmpty());
1351 EXPECT_THAT(out, StrEq("one\n"));
1352}
1353
1354TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) {
1355 CreateFd("RunCommandWithMultipleArgs.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001356 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001357 EXPECT_THAT(err, IsEmpty());
1358 EXPECT_THAT(out, StrEq("one is the loniest number\n"));
1359}
1360
1361TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) {
1362 CreateFd("RunCommandWithLoggingMessage.txt");
1363 EXPECT_EQ(
Felipe Lemef0292972016-11-22 13:57:05 -08001364 0, RunCommand("", {kSimpleCommand},
Felipe Leme46b85da2016-11-21 17:40:45 -08001365 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build()));
1366 EXPECT_THAT(out, StrEq("stdout\n"));
1367 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n"));
1368}
1369
1370TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) {
1371 CreateFd("RunCommandRedirectStderr.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001372 EXPECT_EQ(0, RunCommand("", {kSimpleCommand},
1373 CommandOptions::WithTimeout(10).RedirectStderr().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001374 EXPECT_THAT(out, IsEmpty());
1375 EXPECT_THAT(err, StrEq("stdout\nstderr\n"));
1376}
1377
1378TEST_F(DumpstateUtilTest, RunCommandDryRun) {
1379 CreateFd("RunCommandDryRun.txt");
1380 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001381 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand}));
1382 EXPECT_THAT(out, StrEq(android::base::StringPrintf(
1383 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n",
1384 kSimpleCommand.c_str())));
1385 EXPECT_THAT(err, IsEmpty());
1386}
1387
1388TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) {
1389 CreateFd("RunCommandDryRun.txt");
1390 SetDryRun(true);
1391 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001392 EXPECT_THAT(
1393 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str())));
1394 EXPECT_THAT(err, IsEmpty());
1395}
1396
1397TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) {
1398 CreateFd("RunCommandDryRunAlways.txt");
1399 SetDryRun(true);
Felipe Lemef0292972016-11-22 13:57:05 -08001400 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001401 EXPECT_THAT(out, StrEq("stdout\n"));
1402 EXPECT_THAT(err, StrEq("stderr\n"));
1403}
1404
1405TEST_F(DumpstateUtilTest, RunCommandNotFound) {
1406 CreateFd("RunCommandNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001407 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001408 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code"));
1409 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed"));
1410}
1411
1412TEST_F(DumpstateUtilTest, RunCommandFails) {
1413 CreateFd("RunCommandFails.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001414 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001415 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand +
1416 " --exit 42' failed: exit code 42\n"));
1417 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand +
1418 " --exit 42' failed: exit code 42\n"));
1419}
1420
1421TEST_F(DumpstateUtilTest, RunCommandCrashes) {
1422 CreateFd("RunCommandCrashes.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001423 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001424 // We don't know the exit code, so check just the prefix.
1425 EXPECT_THAT(
1426 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1427 EXPECT_THAT(
1428 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code"));
1429}
1430
Vishnu Nair6921f802017-11-22 09:17:23 -08001431TEST_F(DumpstateUtilTest, RunCommandTimesoutWithSec) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001432 CreateFd("RunCommandTimesout.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001433 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1434 CommandOptions::WithTimeout(1).Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001435 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1436 " --sleep 2' timed out after 1"));
1437 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1438 " --sleep 2' timed out after 1"));
1439}
1440
Vishnu Nair6921f802017-11-22 09:17:23 -08001441TEST_F(DumpstateUtilTest, RunCommandTimesoutWithMsec) {
1442 CreateFd("RunCommandTimesout.txt");
1443 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"},
1444 CommandOptions::WithTimeoutInMs(1000).Build()));
1445 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand +
1446 " --sleep 2' timed out after 1"));
1447 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand +
1448 " --sleep 2' timed out after 1"));
1449}
1450
1451
Felipe Leme46b85da2016-11-21 17:40:45 -08001452TEST_F(DumpstateUtilTest, RunCommandIsKilled) {
1453 CreateFd("RunCommandIsKilled.txt");
1454 CaptureStderr();
1455
1456 std::thread t([=]() {
Felipe Lemef0292972016-11-22 13:57:05 -08001457 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001458 CommandOptions::WithTimeout(100).Always().Build()));
1459 });
1460
1461 // Capture pid and pre-sleep output.
1462 sleep(1); // Wait a little bit to make sure pid and 1st line were printed.
1463 std::string err = GetCapturedStderr();
1464 EXPECT_THAT(err, StrEq("sleeping for 20s\n"));
1465
1466 CaptureFdOut();
1467 std::vector<std::string> lines = android::base::Split(out, "\n");
1468 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out;
1469
1470 int pid = atoi(lines[0].c_str());
1471 EXPECT_THAT(lines[1], StrEq("stdout line1"));
1472 EXPECT_THAT(lines[2], IsEmpty()); // \n
1473
1474 // Then kill the process.
1475 CaptureFdOut();
1476 CaptureStderr();
1477 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid;
1478 t.join();
1479
1480 // Finally, check output after murder.
1481 CaptureFdOut();
1482 err = GetCapturedStderr();
1483
1484 // out starts with the pid, which is an unknown
1485 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand +
1486 " --pid --sleep 20' failed: killed by signal 15\n"));
1487 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand +
1488 " --pid --sleep 20' failed: killed by signal 15\n"));
1489}
1490
1491TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) {
1492 if (!IsStandalone()) {
1493 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1494 // to Shell - need to refactor tests to avoid this problem)
1495 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n")
1496 return;
1497 }
1498 CreateFd("RunCommandAsRootUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001499 if (!PropertiesHelper::IsUserBuild()) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001500 // Emulates user build if necessarily.
1501 SetBuildType("user");
1502 }
1503
1504 DropRoot();
1505
Felipe Lemef0292972016-11-22 13:57:05 -08001506 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme46b85da2016-11-21 17:40:45 -08001507
1508 // We don't know the exact path of su, so we just check for the 'root ...' commands
1509 EXPECT_THAT(out, StartsWith("Skipping"));
1510 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n"));
1511 EXPECT_THAT(err, IsEmpty());
1512}
1513
1514TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) {
1515 if (!IsStandalone()) {
1516 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1517 // to Shell - need to refactor tests to avoid this problem)
1518 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n")
1519 return;
1520 }
1521 CreateFd("RunCommandAsRootNonUserBuild.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001522 if (PropertiesHelper::IsUserBuild()) {
Felipe Leme7447d7c2016-11-03 18:12:22 -07001523 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1524 return;
1525 }
1526
1527 DropRoot();
1528
Felipe Lemef0292972016-11-22 13:57:05 -08001529 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1530 CommandOptions::WithTimeout(1).AsRoot().Build()));
Felipe Leme7447d7c2016-11-03 18:12:22 -07001531
1532 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1533 EXPECT_THAT(err, StrEq("stderr\n"));
1534}
Felipe Leme46b85da2016-11-21 17:40:45 -08001535
Yifan Hong48e83a12017-10-03 14:10:07 -07001536
1537TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnUserBuild) {
1538 if (!IsStandalone()) {
1539 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1540 // to Shell - need to refactor tests to avoid this problem)
1541 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnUserBuild() on test suite\n")
1542 return;
1543 }
1544 CreateFd("RunCommandAsRootIfAvailableOnUserBuild.txt");
1545 if (!PropertiesHelper::IsUserBuild()) {
1546 // Emulates user build if necessarily.
1547 SetBuildType("user");
1548 }
1549
1550 DropRoot();
1551
1552 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1553 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1554
1555 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1556 EXPECT_THAT(err, StrEq("stderr\n"));
1557}
1558
1559TEST_F(DumpstateUtilTest, RunCommandAsRootIfAvailableOnDebugBuild) {
1560 if (!IsStandalone()) {
1561 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1562 // to Shell - need to refactor tests to avoid this problem)
1563 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootIfAvailableOnDebugBuild() on test suite\n")
1564 return;
1565 }
1566 CreateFd("RunCommandAsRootIfAvailableOnDebugBuild.txt");
1567 if (PropertiesHelper::IsUserBuild()) {
1568 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n");
1569 return;
1570 }
1571
1572 DropRoot();
1573
1574 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
1575 CommandOptions::WithTimeout(1).AsRootIfAvailable().Build()));
1576
1577 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1578 EXPECT_THAT(err, StrEq("stderr\n"));
1579}
1580
Felipe Leme46b85da2016-11-21 17:40:45 -08001581TEST_F(DumpstateUtilTest, RunCommandDropRoot) {
1582 if (!IsStandalone()) {
1583 // TODO: temporarily disabled because it might cause other tests to fail after dropping
1584 // to Shell - need to refactor tests to avoid this problem)
1585 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n")
1586 return;
1587 }
1588 CreateFd("RunCommandDropRoot.txt");
1589 // First check root case - only available when running with 'adb root'.
1590 uid_t uid = getuid();
1591 if (uid == 0) {
Felipe Lemef0292972016-11-22 13:57:05 -08001592 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}));
Felipe Leme46b85da2016-11-21 17:40:45 -08001593 EXPECT_THAT(out, StrEq("0\nstdout\n"));
1594 EXPECT_THAT(err, StrEq("stderr\n"));
1595 return;
1596 }
1597 // Then run dropping root.
Felipe Lemef0292972016-11-22 13:57:05 -08001598 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"},
Felipe Leme46b85da2016-11-21 17:40:45 -08001599 CommandOptions::WithTimeout(1).DropRoot().Build()));
1600 EXPECT_THAT(out, StrEq("2000\nstdout\n"));
1601 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n"));
1602}
1603
Felipe Lemef0292972016-11-22 13:57:05 -08001604TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) {
Felipe Leme46b85da2016-11-21 17:40:45 -08001605 CreateFd("DumpFileNotFound.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001606 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001607 EXPECT_THAT(out,
1608 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n"));
1609 EXPECT_THAT(err, IsEmpty());
1610}
1611
Felipe Lemef0292972016-11-22 13:57:05 -08001612TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) {
1613 CreateFd("DumpFileNotFound.txt");
1614 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist"));
1615 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such "
1616 "file or directory\n"));
1617 EXPECT_THAT(err, IsEmpty());
1618}
1619
Felipe Leme46b85da2016-11-21 17:40:45 -08001620TEST_F(DumpstateUtilTest, DumpFileSingleLine) {
1621 CreateFd("DumpFileSingleLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001622 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001623 EXPECT_THAT(err, IsEmpty());
1624 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline
1625}
1626
1627TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) {
1628 CreateFd("DumpFileSingleLineWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001629 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001630 EXPECT_THAT(err, IsEmpty());
1631 EXPECT_THAT(out, StrEq("I AM LINE1\n"));
1632}
1633
1634TEST_F(DumpstateUtilTest, DumpFileMultipleLines) {
1635 CreateFd("DumpFileMultipleLines.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001636 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001637 EXPECT_THAT(err, IsEmpty());
1638 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1639}
1640
1641TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) {
1642 CreateFd("DumpFileMultipleLinesWithNewLine.txt");
Felipe Lemef0292972016-11-22 13:57:05 -08001643 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001644 EXPECT_THAT(err, IsEmpty());
1645 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n"));
1646}
1647
Felipe Lemef0292972016-11-22 13:57:05 -08001648TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) {
1649 CreateFd("DumpFileOnDryRun.txt");
1650 SetDryRun(true);
1651 std::string path = kTestDataPath + "single-line.txt";
1652 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt"));
1653 EXPECT_THAT(err, IsEmpty());
1654 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n"));
1655}
1656
Felipe Leme46b85da2016-11-21 17:40:45 -08001657TEST_F(DumpstateUtilTest, DumpFileOnDryRun) {
1658 CreateFd("DumpFileOnDryRun.txt");
1659 SetDryRun(true);
1660 std::string path = kTestDataPath + "single-line.txt";
Felipe Lemef0292972016-11-22 13:57:05 -08001661 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001662 EXPECT_THAT(err, IsEmpty());
Felipe Lemef0292972016-11-22 13:57:05 -08001663 EXPECT_THAT(
1664 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:"));
1665 EXPECT_THAT(out, EndsWith("skipped on dry run\n"));
Felipe Leme46b85da2016-11-21 17:40:45 -08001666}
Ecco Park61ffcf72016-10-27 15:46:26 -07001667
Felipe Leme47e9be22016-12-21 15:37:07 -08001668} // namespace dumpstate
1669} // namespace os
1670} // namespace android