1/* 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 17#define LOG_TAG "dumpstate" 18#include <cutils/log.h> 19 20#include "DumpstateInternal.h" 21#include "DumpstateService.h" 22#include "android/os/BnDumpstate.h" 23#include "dumpstate.h" 24 25#include <gmock/gmock.h> 26#include <gtest/gtest.h> 27 28#include <fcntl.h> 29#include <libgen.h> 30#include <signal.h> 31#include <sys/types.h> 32#include <unistd.h> 33#include <thread> 34 35#include <android-base/file.h> 36#include <android-base/properties.h> 37#include <android-base/stringprintf.h> 38#include <android-base/strings.h> 39 40namespace android { 41namespace os { 42namespace dumpstate { 43 44using ::testing::EndsWith; 45using ::testing::HasSubstr; 46using ::testing::IsNull; 47using ::testing::IsEmpty; 48using ::testing::NotNull; 49using ::testing::StrEq; 50using ::testing::StartsWith; 51using ::testing::Test; 52using ::testing::internal::CaptureStderr; 53using ::testing::internal::CaptureStdout; 54using ::testing::internal::GetCapturedStderr; 55using ::testing::internal::GetCapturedStdout; 56 57class DumpstateListenerMock : public IDumpstateListener { 58 public: 59 MOCK_METHOD1(onProgressUpdated, binder::Status(int32_t progress)); 60 MOCK_METHOD1(onMaxProgressUpdated, binder::Status(int32_t max_progress)); 61 62 protected: 63 MOCK_METHOD0(onAsBinder, IBinder*()); 64}; 65 66static int calls_; 67 68// Base class for all tests in this file 69class DumpstateBaseTest : public Test { 70 public: 71 virtual void SetUp() override { 72 calls_++; 73 SetDryRun(false); 74 } 75 76 void SetDryRun(bool dry_run) const { 77 PropertiesHelper::dry_run_ = dry_run; 78 } 79 80 void SetBuildType(const std::string& build_type) const { 81 PropertiesHelper::build_type_ = build_type; 82 } 83 84 bool IsStandalone() const { 85 return calls_ == 1; 86 } 87 88 void DropRoot() const { 89 DropRootUser(); 90 uid_t uid = getuid(); 91 ASSERT_EQ(2000, (int)uid); 92 } 93 94 protected: 95 const std::string kTestPath = dirname(android::base::GetExecutablePath().c_str()); 96 const std::string kFixturesPath = kTestPath + "/../dumpstate_test_fixture/"; 97 const std::string kTestDataPath = kFixturesPath + "/testdata/"; 98 const std::string kSimpleCommand = kFixturesPath + "dumpstate_test_fixture"; 99 const std::string kEchoCommand = "/system/bin/echo"; 100 101 /* 102 * Copies a text file fixture to a temporary file, returning it's path. 103 * 104 * Useful in cases where the test case changes the content of the tile. 105 */ 106 std::string CopyTextFileFixture(const std::string& relative_name) { 107 std::string from = kTestDataPath + relative_name; 108 // Not using TemporaryFile because it's deleted at the end, and it's useful to keep it 109 // around for poking when the test fails. 110 std::string to = kTestDataPath + relative_name + ".tmp"; 111 ALOGD("CopyTextFileFixture: from %s to %s\n", from.c_str(), to.c_str()); 112 android::base::RemoveFileIfExists(to); 113 CopyTextFile(from, to); 114 return to.c_str(); 115 } 116 117 // Need functions that returns void to use assertions - 118 // https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md#assertion-placement 119 void ReadFileToString(const std::string& path, std::string* content) { 120 ASSERT_TRUE(android::base::ReadFileToString(path, content)) 121 << "could not read contents from " << path; 122 } 123 void WriteStringToFile(const std::string& content, const std::string& path) { 124 ASSERT_TRUE(android::base::WriteStringToFile(content, path)) 125 << "could not write contents to " << path; 126 } 127 128 private: 129 void CopyTextFile(const std::string& from, const std::string& to) { 130 std::string content; 131 ReadFileToString(from, &content); 132 WriteStringToFile(content, to); 133 } 134}; 135 136class DumpstateTest : public DumpstateBaseTest { 137 public: 138 void SetUp() { 139 DumpstateBaseTest::SetUp(); 140 SetDryRun(false); 141 SetBuildType(android::base::GetProperty("ro.build.type", "(unknown)")); 142 ds.progress_.reset(new Progress()); 143 ds.update_progress_ = false; 144 ds.update_progress_threshold_ = 0; 145 } 146 147 // Runs a command and capture `stdout` and `stderr`. 148 int RunCommand(const std::string& title, const std::vector<std::string>& full_command, 149 const CommandOptions& options = CommandOptions::DEFAULT) { 150 CaptureStdout(); 151 CaptureStderr(); 152 int status = ds.RunCommand(title, full_command, options); 153 out = GetCapturedStdout(); 154 err = GetCapturedStderr(); 155 return status; 156 } 157 158 // Dumps a file and capture `stdout` and `stderr`. 159 int DumpFile(const std::string& title, const std::string& path) { 160 CaptureStdout(); 161 CaptureStderr(); 162 int status = ds.DumpFile(title, path); 163 out = GetCapturedStdout(); 164 err = GetCapturedStderr(); 165 return status; 166 } 167 168 void SetProgress(long progress, long initial_max, long threshold = 0) { 169 ds.update_progress_ = true; 170 ds.update_progress_threshold_ = threshold; 171 ds.last_updated_progress_ = 0; 172 ds.progress_.reset(new Progress(initial_max, progress, 1.2)); 173 } 174 175 std::string GetProgressMessage(const std::string& listener_name, int progress, int max, 176 int old_max = 0, bool update_progress = true) { 177 EXPECT_EQ(progress, ds.progress_->Get()) << "invalid progress"; 178 EXPECT_EQ(max, ds.progress_->GetMax()) << "invalid max"; 179 180 bool max_increased = old_max > 0; 181 182 std::string message = ""; 183 if (max_increased) { 184 message = 185 android::base::StringPrintf("Adjusting max progress from %d to %d\n", old_max, max); 186 } 187 188 if (update_progress) { 189 message += android::base::StringPrintf("Setting progress (%s): %d/%d\n", 190 listener_name.c_str(), progress, max); 191 } 192 193 return message; 194 } 195 196 // `stdout` and `stderr` from the last command ran. 197 std::string out, err; 198 199 Dumpstate& ds = Dumpstate::GetInstance(); 200}; 201 202TEST_F(DumpstateTest, RunCommandNoArgs) { 203 EXPECT_EQ(-1, RunCommand("", {})); 204} 205 206TEST_F(DumpstateTest, RunCommandNoTitle) { 207 EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 208 EXPECT_THAT(out, StrEq("stdout\n")); 209 EXPECT_THAT(err, StrEq("stderr\n")); 210} 211 212TEST_F(DumpstateTest, RunCommandWithTitle) { 213 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 214 EXPECT_THAT(err, StrEq("stderr\n")); 215 // We don't know the exact duration, so we check the prefix and suffix 216 EXPECT_THAT(out, 217 StartsWith("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n------")); 218 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); 219} 220 221TEST_F(DumpstateTest, RunCommandWithLoggingMessage) { 222 EXPECT_EQ( 223 0, RunCommand("", {kSimpleCommand}, 224 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build())); 225 EXPECT_THAT(out, StrEq("stdout\n")); 226 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n")); 227} 228 229TEST_F(DumpstateTest, RunCommandRedirectStderr) { 230 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, 231 CommandOptions::WithTimeout(10).RedirectStderr().Build())); 232 EXPECT_THAT(out, IsEmpty()); 233 EXPECT_THAT(err, StrEq("stdout\nstderr\n")); 234} 235 236TEST_F(DumpstateTest, RunCommandWithOneArg) { 237 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"})); 238 EXPECT_THAT(err, IsEmpty()); 239 EXPECT_THAT(out, StrEq("one\n")); 240} 241 242TEST_F(DumpstateTest, RunCommandWithMultipleArgs) { 243 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"})); 244 EXPECT_THAT(err, IsEmpty()); 245 EXPECT_THAT(out, StrEq("one is the loniest number\n")); 246} 247 248TEST_F(DumpstateTest, RunCommandDryRun) { 249 SetDryRun(true); 250 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 251 // We don't know the exact duration, so we check the prefix and suffix 252 EXPECT_THAT(out, StartsWith("------ I AM GROOT (" + kSimpleCommand + 253 ") ------\n\t(skipped on dry run)\n------")); 254 EXPECT_THAT(out, EndsWith("s was the duration of 'I AM GROOT' ------\n")); 255 EXPECT_THAT(err, IsEmpty()); 256} 257 258TEST_F(DumpstateTest, RunCommandDryRunNoTitle) { 259 SetDryRun(true); 260 EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 261 EXPECT_THAT(out, IsEmpty()); 262 EXPECT_THAT(err, IsEmpty()); 263} 264 265TEST_F(DumpstateTest, RunCommandDryRunAlways) { 266 SetDryRun(true); 267 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build())); 268 EXPECT_THAT(out, StrEq("stdout\n")); 269 EXPECT_THAT(err, StrEq("stderr\n")); 270} 271 272TEST_F(DumpstateTest, RunCommandNotFound) { 273 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"})); 274 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code")); 275 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed")); 276} 277 278TEST_F(DumpstateTest, RunCommandFails) { 279 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"})); 280 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand + 281 " --exit 42' failed: exit code 42\n")); 282 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand + 283 " --exit 42' failed: exit code 42\n")); 284} 285 286TEST_F(DumpstateTest, RunCommandCrashes) { 287 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"})); 288 // We don't know the exit code, so check just the prefix. 289 EXPECT_THAT( 290 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 291 EXPECT_THAT( 292 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 293} 294 295TEST_F(DumpstateTest, RunCommandTimesout) { 296 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"}, 297 CommandOptions::WithTimeout(1).Build())); 298 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand + 299 " --sleep 2' timed out after 1")); 300 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand + 301 " --sleep 2' timed out after 1")); 302} 303 304TEST_F(DumpstateTest, RunCommandIsKilled) { 305 CaptureStdout(); 306 CaptureStderr(); 307 308 std::thread t([=]() { 309 EXPECT_EQ(SIGTERM, ds.RunCommand("", {kSimpleCommand, "--pid", "--sleep", "20"}, 310 CommandOptions::WithTimeout(100).Always().Build())); 311 }); 312 313 // Capture pid and pre-sleep output. 314 sleep(1); // Wait a little bit to make sure pid and 1st line were printed. 315 std::string err = GetCapturedStderr(); 316 EXPECT_THAT(err, StrEq("sleeping for 20s\n")); 317 318 std::string out = GetCapturedStdout(); 319 std::vector<std::string> lines = android::base::Split(out, "\n"); 320 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out; 321 322 int pid = atoi(lines[0].c_str()); 323 EXPECT_THAT(lines[1], StrEq("stdout line1")); 324 EXPECT_THAT(lines[2], IsEmpty()); // \n 325 326 // Then kill the process. 327 CaptureStdout(); 328 CaptureStderr(); 329 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid; 330 t.join(); 331 332 // Finally, check output after murder. 333 out = GetCapturedStdout(); 334 err = GetCapturedStderr(); 335 336 EXPECT_THAT(out, StrEq("*** command '" + kSimpleCommand + 337 " --pid --sleep 20' failed: killed by signal 15\n")); 338 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand + 339 " --pid --sleep 20' failed: killed by signal 15\n")); 340} 341 342TEST_F(DumpstateTest, RunCommandProgress) { 343 sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 344 ds.listener_ = listener; 345 ds.listener_name_ = "FoxMulder"; 346 SetProgress(0, 30); 347 348 EXPECT_CALL(*listener, onProgressUpdated(20)); 349 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(20).Build())); 350 std::string progress_message = GetProgressMessage(ds.listener_name_, 20, 30); 351 EXPECT_THAT(out, StrEq("stdout\n")); 352 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 353 354 EXPECT_CALL(*listener, onProgressUpdated(30)); 355 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Build())); 356 progress_message = GetProgressMessage(ds.listener_name_, 30, 30); 357 EXPECT_THAT(out, StrEq("stdout\n")); 358 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 359 360 // Run a command that will increase maximum timeout. 361 EXPECT_CALL(*listener, onProgressUpdated(31)); 362 EXPECT_CALL(*listener, onMaxProgressUpdated(37)); 363 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); 364 progress_message = GetProgressMessage(ds.listener_name_, 31, 37, 30); // 20% increase 365 EXPECT_THAT(out, StrEq("stdout\n")); 366 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 367 368 // Make sure command ran while in dry_run is counted. 369 SetDryRun(true); 370 EXPECT_CALL(*listener, onProgressUpdated(35)); 371 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); 372 progress_message = GetProgressMessage(ds.listener_name_, 35, 37); 373 EXPECT_THAT(out, IsEmpty()); 374 EXPECT_THAT(err, StrEq(progress_message)); 375 376 ds.listener_.clear(); 377} 378 379TEST_F(DumpstateTest, RunCommandProgressIgnoreThreshold) { 380 sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 381 ds.listener_ = listener; 382 ds.listener_name_ = "FoxMulder"; 383 SetProgress(0, 8, 5); // 8 max, 5 threshold 384 385 // First update should always be sent. 386 EXPECT_CALL(*listener, onProgressUpdated(1)); 387 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); 388 std::string progress_message = GetProgressMessage(ds.listener_name_, 1, 8); 389 EXPECT_THAT(out, StrEq("stdout\n")); 390 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 391 392 // Fourth update should be ignored because it's between the threshold (5 -1 = 4 < 5). 393 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(4).Build())); 394 EXPECT_THAT(out, StrEq("stdout\n")); 395 EXPECT_THAT(err, StrEq("stderr\n")); 396 397 // Third update should be sent because it reaches threshold (6 - 1 = 5). 398 EXPECT_CALL(*listener, onProgressUpdated(6)); 399 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).Build())); 400 progress_message = GetProgressMessage(ds.listener_name_, 6, 8); 401 EXPECT_THAT(out, StrEq("stdout\n")); 402 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 403 404 // Fourth update should be ignored because it's between the threshold (9 - 6 = 3 < 5). 405 // But max update should be sent. 406 EXPECT_CALL(*listener, onMaxProgressUpdated(10)); // 9 * 120% = 10.8 = 10 407 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(3).Build())); 408 progress_message = GetProgressMessage(ds.listener_name_, 9, 10, 8, false); 409 EXPECT_THAT(out, StrEq("stdout\n")); 410 EXPECT_THAT(err, StrEq("stderr\n" + progress_message)); 411 412 ds.listener_.clear(); 413} 414 415TEST_F(DumpstateTest, RunCommandDropRoot) { 416 if (!IsStandalone()) { 417 // TODO: temporarily disabled because it might cause other tests to fail after dropping 418 // to Shell - need to refactor tests to avoid this problem) 419 MYLOGE("Skipping DumpstateTest.RunCommandDropRoot() on test suite\n") 420 return; 421 } 422 // First check root case - only available when running with 'adb root'. 423 uid_t uid = getuid(); 424 if (uid == 0) { 425 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"})); 426 EXPECT_THAT(out, StrEq("0\nstdout\n")); 427 EXPECT_THAT(err, StrEq("stderr\n")); 428 return; 429 } 430 // Then run dropping root. 431 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 432 CommandOptions::WithTimeout(1).DropRoot().Build())); 433 EXPECT_THAT(out, StrEq("2000\nstdout\n")); 434 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n")); 435} 436 437TEST_F(DumpstateTest, RunCommandAsRootUserBuild) { 438 if (!IsStandalone()) { 439 // TODO: temporarily disabled because it might cause other tests to fail after dropping 440 // to Shell - need to refactor tests to avoid this problem) 441 MYLOGE("Skipping DumpstateTest.RunCommandAsRootUserBuild() on test suite\n") 442 return; 443 } 444 if (!PropertiesHelper::IsUserBuild()) { 445 // Emulates user build if necessarily. 446 SetBuildType("user"); 447 } 448 449 DropRoot(); 450 451 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build())); 452 453 // We don't know the exact path of su, so we just check for the 'root ...' commands 454 EXPECT_THAT(out, StartsWith("Skipping")); 455 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n")); 456 EXPECT_THAT(err, IsEmpty()); 457} 458 459TEST_F(DumpstateTest, RunCommandAsRootNonUserBuild) { 460 if (!IsStandalone()) { 461 // TODO: temporarily disabled because it might cause other tests to fail after dropping 462 // to Shell - need to refactor tests to avoid this problem) 463 MYLOGE("Skipping DumpstateTest.RunCommandAsRootNonUserBuild() on test suite\n") 464 return; 465 } 466 if (PropertiesHelper::IsUserBuild()) { 467 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n"); 468 return; 469 } 470 471 DropRoot(); 472 473 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 474 CommandOptions::WithTimeout(1).AsRoot().Build())); 475 476 EXPECT_THAT(out, StrEq("0\nstdout\n")); 477 EXPECT_THAT(err, StrEq("stderr\n")); 478} 479 480TEST_F(DumpstateTest, DumpFileNotFoundNoTitle) { 481 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist")); 482 EXPECT_THAT(out, 483 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n")); 484 EXPECT_THAT(err, IsEmpty()); 485} 486 487TEST_F(DumpstateTest, DumpFileNotFoundWithTitle) { 488 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); 489 EXPECT_THAT(err, IsEmpty()); 490 // We don't know the exact duration, so we check the prefix and suffix 491 EXPECT_THAT(out, StartsWith("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No " 492 "such file or directory\n")); 493 EXPECT_THAT(out, EndsWith("s was the duration of 'Y U NO EXIST?' ------\n")); 494} 495 496TEST_F(DumpstateTest, DumpFileSingleLine) { 497 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 498 EXPECT_THAT(err, IsEmpty()); 499 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 500} 501 502TEST_F(DumpstateTest, DumpFileSingleLineWithNewLine) { 503 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt")); 504 EXPECT_THAT(err, IsEmpty()); 505 EXPECT_THAT(out, StrEq("I AM LINE1\n")); 506} 507 508TEST_F(DumpstateTest, DumpFileMultipleLines) { 509 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt")); 510 EXPECT_THAT(err, IsEmpty()); 511 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 512} 513 514TEST_F(DumpstateTest, DumpFileMultipleLinesWithNewLine) { 515 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt")); 516 EXPECT_THAT(err, IsEmpty()); 517 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 518} 519 520TEST_F(DumpstateTest, DumpFileOnDryRunNoTitle) { 521 SetDryRun(true); 522 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 523 EXPECT_THAT(err, IsEmpty()); 524 EXPECT_THAT(out, IsEmpty()); 525} 526 527TEST_F(DumpstateTest, DumpFileOnDryRun) { 528 SetDryRun(true); 529 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt")); 530 EXPECT_THAT(err, IsEmpty()); 531 EXPECT_THAT( 532 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:")); 533 EXPECT_THAT(out, HasSubstr("\n\t(skipped on dry run)\n------")); 534 EXPECT_THAT(out, EndsWith("s was the duration of 'Might as well dump. Dump!' ------\n")); 535} 536 537TEST_F(DumpstateTest, DumpFileUpdateProgress) { 538 sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 539 ds.listener_ = listener; 540 ds.listener_name_ = "FoxMulder"; 541 SetProgress(0, 30); 542 543 EXPECT_CALL(*listener, onProgressUpdated(5)); 544 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 545 546 std::string progress_message = 547 GetProgressMessage(ds.listener_name_, 5, 30); // TODO: unhardcode WEIGHT_FILE (5)? 548 EXPECT_THAT(err, StrEq(progress_message)); 549 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 550 551 ds.listener_.clear(); 552} 553 554class DumpstateServiceTest : public DumpstateBaseTest { 555 public: 556 DumpstateService dss; 557}; 558 559TEST_F(DumpstateServiceTest, SetListenerNoName) { 560 sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 561 sp<IDumpstateToken> token; 562 EXPECT_TRUE(dss.setListener("", listener, &token).isOk()); 563 ASSERT_THAT(token, IsNull()); 564} 565 566TEST_F(DumpstateServiceTest, SetListenerNoPointer) { 567 sp<IDumpstateToken> token; 568 EXPECT_TRUE(dss.setListener("whatever", nullptr, &token).isOk()); 569 ASSERT_THAT(token, IsNull()); 570} 571 572TEST_F(DumpstateServiceTest, SetListenerTwice) { 573 sp<DumpstateListenerMock> listener(new DumpstateListenerMock()); 574 sp<IDumpstateToken> token; 575 EXPECT_TRUE(dss.setListener("whatever", listener, &token).isOk()); 576 ASSERT_THAT(token, NotNull()); 577 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); 578 579 token.clear(); 580 EXPECT_TRUE(dss.setListener("whatsoever", listener, &token).isOk()); 581 ASSERT_THAT(token, IsNull()); 582 EXPECT_THAT(Dumpstate::GetInstance().listener_name_, StrEq("whatever")); 583} 584 585class ProgressTest : public DumpstateBaseTest { 586 public: 587 Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { 588 return Progress(max, growth_factor, path); 589 } 590 591 void AssertStats(const std::string& path, int32_t expected_runs, int32_t expected_average) { 592 std::string expected_content = 593 android::base::StringPrintf("%d %d\n", expected_runs, expected_average); 594 std::string actual_content; 595 ReadFileToString(path, &actual_content); 596 ASSERT_THAT(actual_content, StrEq(expected_content)) << "invalid stats on " << path; 597 } 598}; 599 600TEST_F(ProgressTest, SimpleTest) { 601 Progress progress; 602 EXPECT_EQ(0, progress.Get()); 603 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 604 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 605 606 bool max_increased = progress.Inc(1); 607 EXPECT_EQ(1, progress.Get()); 608 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 609 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 610 EXPECT_FALSE(max_increased); 611 612 // Ignore negative increase. 613 max_increased = progress.Inc(-1); 614 EXPECT_EQ(1, progress.Get()); 615 EXPECT_EQ(Progress::kDefaultMax, progress.GetInitialMax()); 616 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 617 EXPECT_FALSE(max_increased); 618} 619 620TEST_F(ProgressTest, MaxGrowsInsideNewRange) { 621 Progress progress = GetInstance(10, 1.2); // 20% growth factor 622 EXPECT_EQ(0, progress.Get()); 623 EXPECT_EQ(10, progress.GetInitialMax()); 624 EXPECT_EQ(10, progress.GetMax()); 625 626 // No increase 627 bool max_increased = progress.Inc(10); 628 EXPECT_EQ(10, progress.Get()); 629 EXPECT_EQ(10, progress.GetMax()); 630 EXPECT_FALSE(max_increased); 631 632 // Increase, with new value < max*20% 633 max_increased = progress.Inc(1); 634 EXPECT_EQ(11, progress.Get()); 635 EXPECT_EQ(13, progress.GetMax()); // 11 average * 20% growth = 13.2 = 13 636 EXPECT_TRUE(max_increased); 637} 638 639TEST_F(ProgressTest, MaxGrowsOutsideNewRange) { 640 Progress progress = GetInstance(10, 1.2); // 20% growth factor 641 EXPECT_EQ(0, progress.Get()); 642 EXPECT_EQ(10, progress.GetInitialMax()); 643 EXPECT_EQ(10, progress.GetMax()); 644 645 // No increase 646 bool max_increased = progress.Inc(10); 647 EXPECT_EQ(10, progress.Get()); 648 EXPECT_EQ(10, progress.GetMax()); 649 EXPECT_FALSE(max_increased); 650 651 // Increase, with new value > max*20% 652 max_increased = progress.Inc(5); 653 EXPECT_EQ(15, progress.Get()); 654 EXPECT_EQ(18, progress.GetMax()); // 15 average * 20% growth = 18 655 EXPECT_TRUE(max_increased); 656} 657 658TEST_F(ProgressTest, InvalidPath) { 659 Progress progress("/devil/null"); 660 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 661} 662 663TEST_F(ProgressTest, EmptyFile) { 664 Progress progress(CopyTextFileFixture("empty-file.txt")); 665 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 666} 667 668TEST_F(ProgressTest, InvalidLine1stEntryNAN) { 669 Progress progress(CopyTextFileFixture("stats-invalid-1st-NAN.txt")); 670 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 671} 672 673TEST_F(ProgressTest, InvalidLine2ndEntryNAN) { 674 Progress progress(CopyTextFileFixture("stats-invalid-2nd-NAN.txt")); 675 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 676} 677 678TEST_F(ProgressTest, InvalidLineBothNAN) { 679 Progress progress(CopyTextFileFixture("stats-invalid-both-NAN.txt")); 680 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 681} 682 683TEST_F(ProgressTest, InvalidLine1stEntryNegative) { 684 Progress progress(CopyTextFileFixture("stats-invalid-1st-negative.txt")); 685 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 686} 687 688TEST_F(ProgressTest, InvalidLine2ndEntryNegative) { 689 Progress progress(CopyTextFileFixture("stats-invalid-2nd-negative.txt")); 690 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 691} 692 693TEST_F(ProgressTest, InvalidLine1stEntryTooBig) { 694 Progress progress(CopyTextFileFixture("stats-invalid-1st-too-big.txt")); 695 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 696} 697 698TEST_F(ProgressTest, InvalidLine2ndEntryTooBig) { 699 Progress progress(CopyTextFileFixture("stats-invalid-2nd-too-big.txt")); 700 EXPECT_EQ(Progress::kDefaultMax, progress.GetMax()); 701} 702 703// Tests stats are properly saved when the file does not exists. 704TEST_F(ProgressTest, FirstTime) { 705 if (!IsStandalone()) { 706 // TODO: temporarily disabled because it's failing when running as suite 707 MYLOGE("Skipping ProgressTest.FirstTime() on test suite\n") 708 return; 709 } 710 711 std::string path = kTestDataPath + "FirstTime.txt"; 712 android::base::RemoveFileIfExists(path); 713 714 Progress run1(path); 715 EXPECT_EQ(0, run1.Get()); 716 EXPECT_EQ(Progress::kDefaultMax, run1.GetInitialMax()); 717 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); 718 719 bool max_increased = run1.Inc(20); 720 EXPECT_EQ(20, run1.Get()); 721 EXPECT_EQ(Progress::kDefaultMax, run1.GetMax()); 722 EXPECT_FALSE(max_increased); 723 724 run1.Save(); 725 AssertStats(path, 1, 20); 726} 727 728// Tests what happens when the persistent settings contains the average duration of 1 run. 729// Data on file is 1 run and 109 average. 730TEST_F(ProgressTest, SecondTime) { 731 std::string path = CopyTextFileFixture("stats-one-run-no-newline.txt"); 732 733 Progress run1 = GetInstance(-42, 1.2, path); 734 EXPECT_EQ(0, run1.Get()); 735 EXPECT_EQ(10, run1.GetInitialMax()); 736 EXPECT_EQ(10, run1.GetMax()); 737 738 bool max_increased = run1.Inc(20); 739 EXPECT_EQ(20, run1.Get()); 740 EXPECT_EQ(24, run1.GetMax()); 741 EXPECT_TRUE(max_increased); 742 743 // Average now is 2 runs and (10 + 20)/ 2 = 15 744 run1.Save(); 745 AssertStats(path, 2, 15); 746 747 Progress run2 = GetInstance(-42, 1.2, path); 748 EXPECT_EQ(0, run2.Get()); 749 EXPECT_EQ(15, run2.GetInitialMax()); 750 EXPECT_EQ(15, run2.GetMax()); 751 752 max_increased = run2.Inc(25); 753 EXPECT_EQ(25, run2.Get()); 754 EXPECT_EQ(30, run2.GetMax()); 755 EXPECT_TRUE(max_increased); 756 757 // Average now is 3 runs and (15 * 2 + 25)/ 3 = 18.33 = 18 758 run2.Save(); 759 AssertStats(path, 3, 18); 760 761 Progress run3 = GetInstance(-42, 1.2, path); 762 EXPECT_EQ(0, run3.Get()); 763 EXPECT_EQ(18, run3.GetInitialMax()); 764 EXPECT_EQ(18, run3.GetMax()); 765 766 // Make sure average decreases as well 767 max_increased = run3.Inc(5); 768 EXPECT_EQ(5, run3.Get()); 769 EXPECT_EQ(18, run3.GetMax()); 770 EXPECT_FALSE(max_increased); 771 772 // Average now is 4 runs and (18 * 3 + 5)/ 4 = 14.75 = 14 773 run3.Save(); 774 AssertStats(path, 4, 14); 775} 776 777// Tests what happens when the persistent settings contains the average duration of 2 runs. 778// Data on file is 2 runs and 15 average. 779TEST_F(ProgressTest, ThirdTime) { 780 std::string path = CopyTextFileFixture("stats-two-runs.txt"); 781 AssertStats(path, 2, 15); // Sanity check 782 783 Progress run1 = GetInstance(-42, 1.2, path); 784 EXPECT_EQ(0, run1.Get()); 785 EXPECT_EQ(15, run1.GetInitialMax()); 786 EXPECT_EQ(15, run1.GetMax()); 787 788 bool max_increased = run1.Inc(20); 789 EXPECT_EQ(20, run1.Get()); 790 EXPECT_EQ(24, run1.GetMax()); 791 EXPECT_TRUE(max_increased); 792 793 // Average now is 3 runs and (15 * 2 + 20)/ 3 = 16.66 = 16 794 run1.Save(); 795 AssertStats(path, 3, 16); 796} 797 798class DumpstateUtilTest : public DumpstateBaseTest { 799 public: 800 void SetUp() { 801 DumpstateBaseTest::SetUp(); 802 SetDryRun(false); 803 } 804 805 void CaptureFdOut() { 806 ReadFileToString(path_, &out); 807 } 808 809 void CreateFd(const std::string& name) { 810 path_ = kTestDataPath + name; 811 MYLOGD("Creating fd for file %s\n", path_.c_str()); 812 813 fd = TEMP_FAILURE_RETRY(open(path_.c_str(), 814 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 815 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); 816 ASSERT_GE(fd, 0) << "could not create FD for path " << path_; 817 } 818 819 // Runs a command into the `fd` and capture `stderr`. 820 int RunCommand(const std::string& title, const std::vector<std::string>& full_command, 821 const CommandOptions& options = CommandOptions::DEFAULT) { 822 CaptureStderr(); 823 int status = RunCommandToFd(fd, title, full_command, options); 824 close(fd); 825 826 CaptureFdOut(); 827 err = GetCapturedStderr(); 828 return status; 829 } 830 831 // Dumps a file and into the `fd` and `stderr`. 832 int DumpFile(const std::string& title, const std::string& path) { 833 CaptureStderr(); 834 int status = DumpFileToFd(fd, title, path); 835 close(fd); 836 837 CaptureFdOut(); 838 err = GetCapturedStderr(); 839 return status; 840 } 841 842 // Find out the pid of the process_name 843 int FindPidOfProcess(const std::string& process_name) { 844 CaptureStderr(); 845 int status = GetPidByName(process_name); 846 err = GetCapturedStderr(); 847 return status; 848 } 849 850 int fd; 851 852 // 'fd` output and `stderr` from the last command ran. 853 std::string out, err; 854 855 private: 856 std::string path_; 857}; 858 859TEST_F(DumpstateUtilTest, RunCommandNoArgs) { 860 CreateFd("RunCommandNoArgs.txt"); 861 EXPECT_EQ(-1, RunCommand("", {})); 862} 863 864TEST_F(DumpstateUtilTest, RunCommandNoTitle) { 865 CreateFd("RunCommandWithNoArgs.txt"); 866 EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 867 EXPECT_THAT(out, StrEq("stdout\n")); 868 EXPECT_THAT(err, StrEq("stderr\n")); 869} 870 871TEST_F(DumpstateUtilTest, RunCommandWithTitle) { 872 CreateFd("RunCommandWithNoArgs.txt"); 873 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 874 EXPECT_THAT(out, StrEq("------ I AM GROOT (" + kSimpleCommand + ") ------\nstdout\n")); 875 EXPECT_THAT(err, StrEq("stderr\n")); 876} 877 878TEST_F(DumpstateUtilTest, RunCommandWithOneArg) { 879 CreateFd("RunCommandWithOneArg.txt"); 880 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one"})); 881 EXPECT_THAT(err, IsEmpty()); 882 EXPECT_THAT(out, StrEq("one\n")); 883} 884 885TEST_F(DumpstateUtilTest, RunCommandWithMultipleArgs) { 886 CreateFd("RunCommandWithMultipleArgs.txt"); 887 EXPECT_EQ(0, RunCommand("", {kEchoCommand, "one", "is", "the", "loniest", "number"})); 888 EXPECT_THAT(err, IsEmpty()); 889 EXPECT_THAT(out, StrEq("one is the loniest number\n")); 890} 891 892TEST_F(DumpstateUtilTest, RunCommandWithLoggingMessage) { 893 CreateFd("RunCommandWithLoggingMessage.txt"); 894 EXPECT_EQ( 895 0, RunCommand("", {kSimpleCommand}, 896 CommandOptions::WithTimeout(10).Log("COMMAND, Y U NO LOG FIRST?").Build())); 897 EXPECT_THAT(out, StrEq("stdout\n")); 898 EXPECT_THAT(err, StrEq("COMMAND, Y U NO LOG FIRST?stderr\n")); 899} 900 901TEST_F(DumpstateUtilTest, RunCommandRedirectStderr) { 902 CreateFd("RunCommandRedirectStderr.txt"); 903 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, 904 CommandOptions::WithTimeout(10).RedirectStderr().Build())); 905 EXPECT_THAT(out, IsEmpty()); 906 EXPECT_THAT(err, StrEq("stdout\nstderr\n")); 907} 908 909TEST_F(DumpstateUtilTest, RunCommandDryRun) { 910 CreateFd("RunCommandDryRun.txt"); 911 SetDryRun(true); 912 EXPECT_EQ(0, RunCommand("I AM GROOT", {kSimpleCommand})); 913 EXPECT_THAT(out, StrEq(android::base::StringPrintf( 914 "------ I AM GROOT (%s) ------\n\t(skipped on dry run)\n", 915 kSimpleCommand.c_str()))); 916 EXPECT_THAT(err, IsEmpty()); 917} 918 919TEST_F(DumpstateUtilTest, RunCommandDryRunNoTitle) { 920 CreateFd("RunCommandDryRun.txt"); 921 SetDryRun(true); 922 EXPECT_EQ(0, RunCommand("", {kSimpleCommand})); 923 EXPECT_THAT( 924 out, StrEq(android::base::StringPrintf("%s: skipped on dry run\n", kSimpleCommand.c_str()))); 925 EXPECT_THAT(err, IsEmpty()); 926} 927 928TEST_F(DumpstateUtilTest, RunCommandDryRunAlways) { 929 CreateFd("RunCommandDryRunAlways.txt"); 930 SetDryRun(true); 931 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(10).Always().Build())); 932 EXPECT_THAT(out, StrEq("stdout\n")); 933 EXPECT_THAT(err, StrEq("stderr\n")); 934} 935 936TEST_F(DumpstateUtilTest, RunCommandNotFound) { 937 CreateFd("RunCommandNotFound.txt"); 938 EXPECT_NE(0, RunCommand("", {"/there/cannot/be/such/command"})); 939 EXPECT_THAT(out, StartsWith("*** command '/there/cannot/be/such/command' failed: exit code")); 940 EXPECT_THAT(err, StartsWith("execvp on command '/there/cannot/be/such/command' failed")); 941} 942 943TEST_F(DumpstateUtilTest, RunCommandFails) { 944 CreateFd("RunCommandFails.txt"); 945 EXPECT_EQ(42, RunCommand("", {kSimpleCommand, "--exit", "42"})); 946 EXPECT_THAT(out, StrEq("stdout\n*** command '" + kSimpleCommand + 947 " --exit 42' failed: exit code 42\n")); 948 EXPECT_THAT(err, StrEq("stderr\n*** command '" + kSimpleCommand + 949 " --exit 42' failed: exit code 42\n")); 950} 951 952TEST_F(DumpstateUtilTest, RunCommandCrashes) { 953 CreateFd("RunCommandCrashes.txt"); 954 EXPECT_NE(0, RunCommand("", {kSimpleCommand, "--crash"})); 955 // We don't know the exit code, so check just the prefix. 956 EXPECT_THAT( 957 out, StartsWith("stdout\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 958 EXPECT_THAT( 959 err, StartsWith("stderr\n*** command '" + kSimpleCommand + " --crash' failed: exit code")); 960} 961 962TEST_F(DumpstateUtilTest, RunCommandTimesout) { 963 CreateFd("RunCommandTimesout.txt"); 964 EXPECT_EQ(-1, RunCommand("", {kSimpleCommand, "--sleep", "2"}, 965 CommandOptions::WithTimeout(1).Build())); 966 EXPECT_THAT(out, StartsWith("stdout line1\n*** command '" + kSimpleCommand + 967 " --sleep 2' timed out after 1")); 968 EXPECT_THAT(err, StartsWith("sleeping for 2s\n*** command '" + kSimpleCommand + 969 " --sleep 2' timed out after 1")); 970} 971 972TEST_F(DumpstateUtilTest, RunCommandIsKilled) { 973 CreateFd("RunCommandIsKilled.txt"); 974 CaptureStderr(); 975 976 std::thread t([=]() { 977 EXPECT_EQ(SIGTERM, RunCommandToFd(fd, "", {kSimpleCommand, "--pid", "--sleep", "20"}, 978 CommandOptions::WithTimeout(100).Always().Build())); 979 }); 980 981 // Capture pid and pre-sleep output. 982 sleep(1); // Wait a little bit to make sure pid and 1st line were printed. 983 std::string err = GetCapturedStderr(); 984 EXPECT_THAT(err, StrEq("sleeping for 20s\n")); 985 986 CaptureFdOut(); 987 std::vector<std::string> lines = android::base::Split(out, "\n"); 988 ASSERT_EQ(3, (int)lines.size()) << "Invalid lines before sleep: " << out; 989 990 int pid = atoi(lines[0].c_str()); 991 EXPECT_THAT(lines[1], StrEq("stdout line1")); 992 EXPECT_THAT(lines[2], IsEmpty()); // \n 993 994 // Then kill the process. 995 CaptureFdOut(); 996 CaptureStderr(); 997 ASSERT_EQ(0, kill(pid, SIGTERM)) << "failed to kill pid " << pid; 998 t.join(); 999 1000 // Finally, check output after murder. 1001 CaptureFdOut(); 1002 err = GetCapturedStderr(); 1003 1004 // out starts with the pid, which is an unknown 1005 EXPECT_THAT(out, EndsWith("stdout line1\n*** command '" + kSimpleCommand + 1006 " --pid --sleep 20' failed: killed by signal 15\n")); 1007 EXPECT_THAT(err, StrEq("*** command '" + kSimpleCommand + 1008 " --pid --sleep 20' failed: killed by signal 15\n")); 1009} 1010 1011TEST_F(DumpstateUtilTest, RunCommandAsRootUserBuild) { 1012 if (!IsStandalone()) { 1013 // TODO: temporarily disabled because it might cause other tests to fail after dropping 1014 // to Shell - need to refactor tests to avoid this problem) 1015 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootUserBuild() on test suite\n") 1016 return; 1017 } 1018 CreateFd("RunCommandAsRootUserBuild.txt"); 1019 if (!PropertiesHelper::IsUserBuild()) { 1020 // Emulates user build if necessarily. 1021 SetBuildType("user"); 1022 } 1023 1024 DropRoot(); 1025 1026 EXPECT_EQ(0, RunCommand("", {kSimpleCommand}, CommandOptions::WithTimeout(1).AsRoot().Build())); 1027 1028 // We don't know the exact path of su, so we just check for the 'root ...' commands 1029 EXPECT_THAT(out, StartsWith("Skipping")); 1030 EXPECT_THAT(out, EndsWith("root " + kSimpleCommand + "' on user build.\n")); 1031 EXPECT_THAT(err, IsEmpty()); 1032} 1033 1034TEST_F(DumpstateUtilTest, RunCommandAsRootNonUserBuild) { 1035 if (!IsStandalone()) { 1036 // TODO: temporarily disabled because it might cause other tests to fail after dropping 1037 // to Shell - need to refactor tests to avoid this problem) 1038 MYLOGE("Skipping DumpstateUtilTest.RunCommandAsRootNonUserBuild() on test suite\n") 1039 return; 1040 } 1041 CreateFd("RunCommandAsRootNonUserBuild.txt"); 1042 if (PropertiesHelper::IsUserBuild()) { 1043 ALOGI("Skipping RunCommandAsRootNonUserBuild on user builds\n"); 1044 return; 1045 } 1046 1047 DropRoot(); 1048 1049 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 1050 CommandOptions::WithTimeout(1).AsRoot().Build())); 1051 1052 EXPECT_THAT(out, StrEq("0\nstdout\n")); 1053 EXPECT_THAT(err, StrEq("stderr\n")); 1054} 1055 1056TEST_F(DumpstateUtilTest, RunCommandDropRoot) { 1057 if (!IsStandalone()) { 1058 // TODO: temporarily disabled because it might cause other tests to fail after dropping 1059 // to Shell - need to refactor tests to avoid this problem) 1060 MYLOGE("Skipping DumpstateUtilTest.RunCommandDropRoot() on test suite\n") 1061 return; 1062 } 1063 CreateFd("RunCommandDropRoot.txt"); 1064 // First check root case - only available when running with 'adb root'. 1065 uid_t uid = getuid(); 1066 if (uid == 0) { 1067 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"})); 1068 EXPECT_THAT(out, StrEq("0\nstdout\n")); 1069 EXPECT_THAT(err, StrEq("stderr\n")); 1070 return; 1071 } 1072 // Then run dropping root. 1073 EXPECT_EQ(0, RunCommand("", {kSimpleCommand, "--uid"}, 1074 CommandOptions::WithTimeout(1).DropRoot().Build())); 1075 EXPECT_THAT(out, StrEq("2000\nstdout\n")); 1076 EXPECT_THAT(err, StrEq("drop_root_user(): already running as Shell\nstderr\n")); 1077} 1078 1079TEST_F(DumpstateUtilTest, DumpFileNotFoundNoTitle) { 1080 CreateFd("DumpFileNotFound.txt"); 1081 EXPECT_EQ(-1, DumpFile("", "/I/cant/believe/I/exist")); 1082 EXPECT_THAT(out, 1083 StrEq("*** Error dumping /I/cant/believe/I/exist: No such file or directory\n")); 1084 EXPECT_THAT(err, IsEmpty()); 1085} 1086 1087TEST_F(DumpstateUtilTest, DumpFileNotFoundWithTitle) { 1088 CreateFd("DumpFileNotFound.txt"); 1089 EXPECT_EQ(-1, DumpFile("Y U NO EXIST?", "/I/cant/believe/I/exist")); 1090 EXPECT_THAT(out, StrEq("*** Error dumping /I/cant/believe/I/exist (Y U NO EXIST?): No such " 1091 "file or directory\n")); 1092 EXPECT_THAT(err, IsEmpty()); 1093} 1094 1095TEST_F(DumpstateUtilTest, DumpFileSingleLine) { 1096 CreateFd("DumpFileSingleLine.txt"); 1097 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 1098 EXPECT_THAT(err, IsEmpty()); 1099 EXPECT_THAT(out, StrEq("I AM LINE1\n")); // dumpstate adds missing newline 1100} 1101 1102TEST_F(DumpstateUtilTest, DumpFileSingleLineWithNewLine) { 1103 CreateFd("DumpFileSingleLineWithNewLine.txt"); 1104 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line-with-newline.txt")); 1105 EXPECT_THAT(err, IsEmpty()); 1106 EXPECT_THAT(out, StrEq("I AM LINE1\n")); 1107} 1108 1109TEST_F(DumpstateUtilTest, DumpFileMultipleLines) { 1110 CreateFd("DumpFileMultipleLines.txt"); 1111 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines.txt")); 1112 EXPECT_THAT(err, IsEmpty()); 1113 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 1114} 1115 1116TEST_F(DumpstateUtilTest, DumpFileMultipleLinesWithNewLine) { 1117 CreateFd("DumpFileMultipleLinesWithNewLine.txt"); 1118 EXPECT_EQ(0, DumpFile("", kTestDataPath + "multiple-lines-with-newline.txt")); 1119 EXPECT_THAT(err, IsEmpty()); 1120 EXPECT_THAT(out, StrEq("I AM LINE1\nI AM LINE2\nI AM LINE3\n")); 1121} 1122 1123TEST_F(DumpstateUtilTest, DumpFileOnDryRunNoTitle) { 1124 CreateFd("DumpFileOnDryRun.txt"); 1125 SetDryRun(true); 1126 std::string path = kTestDataPath + "single-line.txt"; 1127 EXPECT_EQ(0, DumpFile("", kTestDataPath + "single-line.txt")); 1128 EXPECT_THAT(err, IsEmpty()); 1129 EXPECT_THAT(out, StrEq(path + ": skipped on dry run\n")); 1130} 1131 1132TEST_F(DumpstateUtilTest, DumpFileOnDryRun) { 1133 CreateFd("DumpFileOnDryRun.txt"); 1134 SetDryRun(true); 1135 std::string path = kTestDataPath + "single-line.txt"; 1136 EXPECT_EQ(0, DumpFile("Might as well dump. Dump!", kTestDataPath + "single-line.txt")); 1137 EXPECT_THAT(err, IsEmpty()); 1138 EXPECT_THAT( 1139 out, StartsWith("------ Might as well dump. Dump! (" + kTestDataPath + "single-line.txt:")); 1140 EXPECT_THAT(out, EndsWith("skipped on dry run\n")); 1141} 1142 1143TEST_F(DumpstateUtilTest, FindingPidWithExistingProcess) { 1144 // init process always has pid 1. 1145 EXPECT_EQ(1, FindPidOfProcess("init")); 1146 EXPECT_THAT(err, IsEmpty()); 1147} 1148 1149TEST_F(DumpstateUtilTest, FindingPidWithNotExistingProcess) { 1150 // find the process with abnormal name. 1151 EXPECT_EQ(-1, FindPidOfProcess("abcdef12345-543")); 1152 EXPECT_THAT(err, StrEq("can't find the pid\n")); 1153} 1154 1155} // namespace dumpstate 1156} // namespace os 1157} // namespace android 1158