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 #include "../dumpsys.h" 18 19 #include <vector> 20 21 #include <gmock/gmock.h> 22 #include <gtest/gtest.h> 23 24 #include <android-base/file.h> 25 #include <serviceutils/PriorityDumper.h> 26 #include <utils/String16.h> 27 #include <utils/String8.h> 28 #include <utils/Vector.h> 29 30 using namespace android; 31 32 using ::testing::_; 33 using ::testing::Action; 34 using ::testing::ActionInterface; 35 using ::testing::DoAll; 36 using ::testing::Eq; 37 using ::testing::HasSubstr; 38 using ::testing::MakeAction; 39 using ::testing::Mock; 40 using ::testing::Not; 41 using ::testing::Return; 42 using ::testing::StrEq; 43 using ::testing::Test; 44 using ::testing::WithArg; 45 using ::testing::internal::CaptureStderr; 46 using ::testing::internal::CaptureStdout; 47 using ::testing::internal::GetCapturedStderr; 48 using ::testing::internal::GetCapturedStdout; 49 50 class ServiceManagerMock : public IServiceManager { 51 public: 52 MOCK_CONST_METHOD1(getService, sp<IBinder>(const String16&)); 53 MOCK_CONST_METHOD1(checkService, sp<IBinder>(const String16&)); 54 MOCK_METHOD4(addService, status_t(const String16&, const sp<IBinder>&, bool, int)); 55 MOCK_METHOD1(listServices, Vector<String16>(int)); 56 57 protected: 58 MOCK_METHOD0(onAsBinder, IBinder*()); 59 }; 60 61 class BinderMock : public BBinder { 62 public: 63 BinderMock() { 64 } 65 66 MOCK_METHOD2(dump, status_t(int, const Vector<String16>&)); 67 }; 68 69 // gmock black magic to provide a WithArg<0>(WriteOnFd(output)) matcher 70 typedef void WriteOnFdFunction(int); 71 72 class WriteOnFdAction : public ActionInterface<WriteOnFdFunction> { 73 public: 74 explicit WriteOnFdAction(const std::string& output) : output_(output) { 75 } 76 virtual Result Perform(const ArgumentTuple& args) { 77 int fd = ::std::tr1::get<0>(args); 78 android::base::WriteStringToFd(output_, fd); 79 } 80 81 private: 82 std::string output_; 83 }; 84 85 // Matcher used to emulate dump() by writing on its file descriptor. 86 Action<WriteOnFdFunction> WriteOnFd(const std::string& output) { 87 return MakeAction(new WriteOnFdAction(output)); 88 } 89 90 // Matcher for args using Android's Vector<String16> format 91 // TODO: move it to some common testing library 92 MATCHER_P(AndroidElementsAre, expected, "") { 93 std::ostringstream errors; 94 if (arg.size() != expected.size()) { 95 errors << " sizes do not match (expected " << expected.size() << ", got " << arg.size() 96 << ")\n"; 97 } 98 int i = 0; 99 std::ostringstream actual_stream, expected_stream; 100 for (const String16& actual : arg) { 101 std::string actual_str = String8(actual).c_str(); 102 std::string expected_str = expected[i]; 103 actual_stream << "'" << actual_str << "' "; 104 expected_stream << "'" << expected_str << "' "; 105 if (actual_str != expected_str) { 106 errors << " element mismatch at index " << i << "\n"; 107 } 108 i++; 109 } 110 111 if (!errors.str().empty()) { 112 errors << "\nExpected args: " << expected_stream.str() 113 << "\nActual args: " << actual_stream.str(); 114 *result_listener << errors.str(); 115 return false; 116 } 117 return true; 118 } 119 120 // Custom action to sleep for timeout seconds 121 ACTION_P(Sleep, timeout) { 122 sleep(timeout); 123 } 124 125 class DumpsysTest : public Test { 126 public: 127 DumpsysTest() : sm_(), dump_(&sm_), stdout_(), stderr_() { 128 } 129 130 void ExpectListServices(std::vector<std::string> services) { 131 Vector<String16> services16; 132 for (auto& service : services) { 133 services16.add(String16(service.c_str())); 134 } 135 EXPECT_CALL(sm_, listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL)) 136 .WillRepeatedly(Return(services16)); 137 } 138 139 void ExpectListServicesWithPriority(std::vector<std::string> services, int dumpFlags) { 140 Vector<String16> services16; 141 for (auto& service : services) { 142 services16.add(String16(service.c_str())); 143 } 144 EXPECT_CALL(sm_, listServices(dumpFlags)).WillRepeatedly(Return(services16)); 145 } 146 147 sp<BinderMock> ExpectCheckService(const char* name, bool running = true) { 148 sp<BinderMock> binder_mock; 149 if (running) { 150 binder_mock = new BinderMock; 151 } 152 EXPECT_CALL(sm_, checkService(String16(name))).WillRepeatedly(Return(binder_mock)); 153 return binder_mock; 154 } 155 156 void ExpectDump(const char* name, const std::string& output) { 157 sp<BinderMock> binder_mock = ExpectCheckService(name); 158 EXPECT_CALL(*binder_mock, dump(_, _)) 159 .WillRepeatedly(DoAll(WithArg<0>(WriteOnFd(output)), Return(0))); 160 } 161 162 void ExpectDumpWithArgs(const char* name, std::vector<std::string> args, 163 const std::string& output) { 164 sp<BinderMock> binder_mock = ExpectCheckService(name); 165 EXPECT_CALL(*binder_mock, dump(_, AndroidElementsAre(args))) 166 .WillRepeatedly(DoAll(WithArg<0>(WriteOnFd(output)), Return(0))); 167 } 168 169 sp<BinderMock> ExpectDumpAndHang(const char* name, int timeout_s, const std::string& output) { 170 sp<BinderMock> binder_mock = ExpectCheckService(name); 171 EXPECT_CALL(*binder_mock, dump(_, _)) 172 .WillRepeatedly(DoAll(Sleep(timeout_s), WithArg<0>(WriteOnFd(output)), Return(0))); 173 return binder_mock; 174 } 175 176 void CallMain(const std::vector<std::string>& args) { 177 const char* argv[1024] = {"/some/virtual/dir/dumpsys"}; 178 int argc = (int)args.size() + 1; 179 int i = 1; 180 for (const std::string& arg : args) { 181 argv[i++] = arg.c_str(); 182 } 183 CaptureStdout(); 184 CaptureStderr(); 185 int status = dump_.main(argc, const_cast<char**>(argv)); 186 stdout_ = GetCapturedStdout(); 187 stderr_ = GetCapturedStderr(); 188 EXPECT_THAT(status, Eq(0)); 189 } 190 191 void CallSingleService(const String16& serviceName, Vector<String16>& args, int priorityFlags, 192 bool supportsProto, std::chrono::duration<double>& elapsedDuration, 193 size_t& bytesWritten) { 194 CaptureStdout(); 195 CaptureStderr(); 196 dump_.setServiceArgs(args, supportsProto, priorityFlags); 197 status_t status = dump_.startDumpThread(serviceName, args); 198 EXPECT_THAT(status, Eq(0)); 199 status = dump_.writeDump(STDOUT_FILENO, serviceName, std::chrono::milliseconds(500), false, 200 elapsedDuration, bytesWritten); 201 EXPECT_THAT(status, Eq(0)); 202 dump_.stopDumpThread(/* dumpCompleted = */ true); 203 stdout_ = GetCapturedStdout(); 204 stderr_ = GetCapturedStderr(); 205 } 206 207 void AssertRunningServices(const std::vector<std::string>& services) { 208 std::string expected; 209 if (services.size() > 1) { 210 expected.append("Currently running services:\n"); 211 } 212 for (const std::string& service : services) { 213 expected.append(" ").append(service).append("\n"); 214 } 215 EXPECT_THAT(stdout_, HasSubstr(expected)); 216 } 217 218 void AssertOutput(const std::string& expected) { 219 EXPECT_THAT(stdout_, StrEq(expected)); 220 } 221 222 void AssertOutputContains(const std::string& expected) { 223 EXPECT_THAT(stdout_, HasSubstr(expected)); 224 } 225 226 void AssertDumped(const std::string& service, const std::string& dump) { 227 EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump)); 228 EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: ")); 229 } 230 231 void AssertDumpedWithPriority(const std::string& service, const std::string& dump, 232 const char16_t* priorityType) { 233 std::string priority = String8(priorityType).c_str(); 234 EXPECT_THAT(stdout_, 235 HasSubstr("DUMP OF SERVICE " + priority + " " + service + ":\n" + dump)); 236 EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: ")); 237 } 238 239 void AssertNotDumped(const std::string& dump) { 240 EXPECT_THAT(stdout_, Not(HasSubstr(dump))); 241 } 242 243 void AssertStopped(const std::string& service) { 244 EXPECT_THAT(stderr_, HasSubstr("Can't find service: " + service + "\n")); 245 } 246 247 ServiceManagerMock sm_; 248 Dumpsys dump_; 249 250 private: 251 std::string stdout_, stderr_; 252 }; 253 254 // Tests 'dumpsys -l' when all services are running 255 TEST_F(DumpsysTest, ListAllServices) { 256 ExpectListServices({"Locksmith", "Valet"}); 257 ExpectCheckService("Locksmith"); 258 ExpectCheckService("Valet"); 259 260 CallMain({"-l"}); 261 262 AssertRunningServices({"Locksmith", "Valet"}); 263 } 264 265 // Tests 'dumpsys -l' when a service is not running 266 TEST_F(DumpsysTest, ListRunningServices) { 267 ExpectListServices({"Locksmith", "Valet"}); 268 ExpectCheckService("Locksmith"); 269 ExpectCheckService("Valet", false); 270 271 CallMain({"-l"}); 272 273 AssertRunningServices({"Locksmith"}); 274 AssertNotDumped({"Valet"}); 275 } 276 277 // Tests 'dumpsys -l --priority HIGH' 278 TEST_F(DumpsysTest, ListAllServicesWithPriority) { 279 ExpectListServicesWithPriority({"Locksmith", "Valet"}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH); 280 ExpectCheckService("Locksmith"); 281 ExpectCheckService("Valet"); 282 283 CallMain({"-l", "--priority", "HIGH"}); 284 285 AssertRunningServices({"Locksmith", "Valet"}); 286 } 287 288 // Tests 'dumpsys -l --priority HIGH' with and empty list 289 TEST_F(DumpsysTest, ListEmptyServicesWithPriority) { 290 ExpectListServicesWithPriority({}, IServiceManager::DUMP_FLAG_PRIORITY_HIGH); 291 292 CallMain({"-l", "--priority", "HIGH"}); 293 294 AssertRunningServices({}); 295 } 296 297 // Tests 'dumpsys -l --proto' 298 TEST_F(DumpsysTest, ListAllServicesWithProto) { 299 ExpectListServicesWithPriority({"Locksmith", "Valet", "Car"}, 300 IServiceManager::DUMP_FLAG_PRIORITY_ALL); 301 ExpectListServicesWithPriority({"Valet", "Car"}, IServiceManager::DUMP_FLAG_PROTO); 302 ExpectCheckService("Car"); 303 ExpectCheckService("Valet"); 304 305 CallMain({"-l", "--proto"}); 306 307 AssertRunningServices({"Car", "Valet"}); 308 } 309 310 // Tests 'dumpsys service_name' on a service is running 311 TEST_F(DumpsysTest, DumpRunningService) { 312 ExpectDump("Valet", "Here's your car"); 313 314 CallMain({"Valet"}); 315 316 AssertOutput("Here's your car"); 317 } 318 319 // Tests 'dumpsys -t 1 service_name' on a service that times out after 2s 320 TEST_F(DumpsysTest, DumpRunningServiceTimeoutInSec) { 321 sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car"); 322 323 CallMain({"-t", "1", "Valet"}); 324 325 AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (1000ms) EXPIRED"); 326 AssertNotDumped("Here's your car"); 327 328 // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp 329 Mock::AllowLeak(binder_mock.get()); 330 } 331 332 // Tests 'dumpsys -T 500 service_name' on a service that times out after 2s 333 TEST_F(DumpsysTest, DumpRunningServiceTimeoutInMs) { 334 sp<BinderMock> binder_mock = ExpectDumpAndHang("Valet", 2, "Here's your car"); 335 336 CallMain({"-T", "500", "Valet"}); 337 338 AssertOutputContains("SERVICE 'Valet' DUMP TIMEOUT (500ms) EXPIRED"); 339 AssertNotDumped("Here's your car"); 340 341 // TODO(b/65056227): BinderMock is not destructed because thread is detached on dumpsys.cpp 342 Mock::AllowLeak(binder_mock.get()); 343 } 344 345 // Tests 'dumpsys service_name Y U NO HAVE ARGS' on a service that is running 346 TEST_F(DumpsysTest, DumpWithArgsRunningService) { 347 ExpectDumpWithArgs("SERVICE", {"Y", "U", "NO", "HANDLE", "ARGS"}, "I DO!"); 348 349 CallMain({"SERVICE", "Y", "U", "NO", "HANDLE", "ARGS"}); 350 351 AssertOutput("I DO!"); 352 } 353 354 // Tests dumpsys passes the -a flag when called on all services 355 TEST_F(DumpsysTest, PassAllFlagsToServices) { 356 ExpectListServices({"Locksmith", "Valet"}); 357 ExpectCheckService("Locksmith"); 358 ExpectCheckService("Valet"); 359 ExpectDumpWithArgs("Locksmith", {"-a"}, "dumped1"); 360 ExpectDumpWithArgs("Valet", {"-a"}, "dumped2"); 361 362 CallMain({"-T", "500"}); 363 364 AssertDumped("Locksmith", "dumped1"); 365 AssertDumped("Valet", "dumped2"); 366 } 367 368 // Tests dumpsys passes the -a flag when called on NORMAL priority services 369 TEST_F(DumpsysTest, PassAllFlagsToNormalServices) { 370 ExpectListServicesWithPriority({"Locksmith", "Valet"}, 371 IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); 372 ExpectCheckService("Locksmith"); 373 ExpectCheckService("Valet"); 374 ExpectDumpWithArgs("Locksmith", {"-a", "--dump-priority", "NORMAL"}, "dump1"); 375 ExpectDumpWithArgs("Valet", {"-a", "--dump-priority", "NORMAL"}, "dump2"); 376 377 CallMain({"--priority", "NORMAL"}); 378 379 AssertDumped("Locksmith", "dump1"); 380 AssertDumped("Valet", "dump2"); 381 } 382 383 // Tests dumpsys passes only priority flags when called on CRITICAL priority services 384 TEST_F(DumpsysTest, PassPriorityFlagsToCriticalServices) { 385 ExpectListServicesWithPriority({"Locksmith", "Valet"}, 386 IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); 387 ExpectCheckService("Locksmith"); 388 ExpectCheckService("Valet"); 389 ExpectDumpWithArgs("Locksmith", {"--dump-priority", "CRITICAL"}, "dump1"); 390 ExpectDumpWithArgs("Valet", {"--dump-priority", "CRITICAL"}, "dump2"); 391 392 CallMain({"--priority", "CRITICAL"}); 393 394 AssertDumpedWithPriority("Locksmith", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL); 395 AssertDumpedWithPriority("Valet", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL); 396 } 397 398 // Tests dumpsys passes only priority flags when called on HIGH priority services 399 TEST_F(DumpsysTest, PassPriorityFlagsToHighServices) { 400 ExpectListServicesWithPriority({"Locksmith", "Valet"}, 401 IServiceManager::DUMP_FLAG_PRIORITY_HIGH); 402 ExpectCheckService("Locksmith"); 403 ExpectCheckService("Valet"); 404 ExpectDumpWithArgs("Locksmith", {"--dump-priority", "HIGH"}, "dump1"); 405 ExpectDumpWithArgs("Valet", {"--dump-priority", "HIGH"}, "dump2"); 406 407 CallMain({"--priority", "HIGH"}); 408 409 AssertDumpedWithPriority("Locksmith", "dump1", PriorityDumper::PRIORITY_ARG_HIGH); 410 AssertDumpedWithPriority("Valet", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); 411 } 412 413 // Tests 'dumpsys' with no arguments 414 TEST_F(DumpsysTest, DumpMultipleServices) { 415 ExpectListServices({"running1", "stopped2", "running3"}); 416 ExpectDump("running1", "dump1"); 417 ExpectCheckService("stopped2", false); 418 ExpectDump("running3", "dump3"); 419 420 CallMain({}); 421 422 AssertRunningServices({"running1", "running3"}); 423 AssertDumped("running1", "dump1"); 424 AssertStopped("stopped2"); 425 AssertDumped("running3", "dump3"); 426 } 427 428 // Tests 'dumpsys --skip skipped3 skipped5', which should skip these services 429 TEST_F(DumpsysTest, DumpWithSkip) { 430 ExpectListServices({"running1", "stopped2", "skipped3", "running4", "skipped5"}); 431 ExpectDump("running1", "dump1"); 432 ExpectCheckService("stopped2", false); 433 ExpectDump("skipped3", "dump3"); 434 ExpectDump("running4", "dump4"); 435 ExpectDump("skipped5", "dump5"); 436 437 CallMain({"--skip", "skipped3", "skipped5"}); 438 439 AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"}); 440 AssertDumped("running1", "dump1"); 441 AssertDumped("running4", "dump4"); 442 AssertStopped("stopped2"); 443 AssertNotDumped("dump3"); 444 AssertNotDumped("dump5"); 445 } 446 447 // Tests 'dumpsys --skip skipped3 skipped5 --priority CRITICAL', which should skip these services 448 TEST_F(DumpsysTest, DumpWithSkipAndPriority) { 449 ExpectListServicesWithPriority({"running1", "stopped2", "skipped3", "running4", "skipped5"}, 450 IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); 451 ExpectDump("running1", "dump1"); 452 ExpectCheckService("stopped2", false); 453 ExpectDump("skipped3", "dump3"); 454 ExpectDump("running4", "dump4"); 455 ExpectDump("skipped5", "dump5"); 456 457 CallMain({"--priority", "CRITICAL", "--skip", "skipped3", "skipped5"}); 458 459 AssertRunningServices({"running1", "running4", "skipped3 (skipped)", "skipped5 (skipped)"}); 460 AssertDumpedWithPriority("running1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL); 461 AssertDumpedWithPriority("running4", "dump4", PriorityDumper::PRIORITY_ARG_CRITICAL); 462 AssertStopped("stopped2"); 463 AssertNotDumped("dump3"); 464 AssertNotDumped("dump5"); 465 } 466 467 // Tests 'dumpsys --priority CRITICAL' 468 TEST_F(DumpsysTest, DumpWithPriorityCritical) { 469 ExpectListServicesWithPriority({"runningcritical1", "runningcritical2"}, 470 IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL); 471 ExpectDump("runningcritical1", "dump1"); 472 ExpectDump("runningcritical2", "dump2"); 473 474 CallMain({"--priority", "CRITICAL"}); 475 476 AssertRunningServices({"runningcritical1", "runningcritical2"}); 477 AssertDumpedWithPriority("runningcritical1", "dump1", PriorityDumper::PRIORITY_ARG_CRITICAL); 478 AssertDumpedWithPriority("runningcritical2", "dump2", PriorityDumper::PRIORITY_ARG_CRITICAL); 479 } 480 481 // Tests 'dumpsys --priority HIGH' 482 TEST_F(DumpsysTest, DumpWithPriorityHigh) { 483 ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"}, 484 IServiceManager::DUMP_FLAG_PRIORITY_HIGH); 485 ExpectDump("runninghigh1", "dump1"); 486 ExpectDump("runninghigh2", "dump2"); 487 488 CallMain({"--priority", "HIGH"}); 489 490 AssertRunningServices({"runninghigh1", "runninghigh2"}); 491 AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH); 492 AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); 493 } 494 495 // Tests 'dumpsys --priority NORMAL' 496 TEST_F(DumpsysTest, DumpWithPriorityNormal) { 497 ExpectListServicesWithPriority({"runningnormal1", "runningnormal2"}, 498 IServiceManager::DUMP_FLAG_PRIORITY_NORMAL); 499 ExpectDump("runningnormal1", "dump1"); 500 ExpectDump("runningnormal2", "dump2"); 501 502 CallMain({"--priority", "NORMAL"}); 503 504 AssertRunningServices({"runningnormal1", "runningnormal2"}); 505 AssertDumped("runningnormal1", "dump1"); 506 AssertDumped("runningnormal2", "dump2"); 507 } 508 509 // Tests 'dumpsys --proto' 510 TEST_F(DumpsysTest, DumpWithProto) { 511 ExpectListServicesWithPriority({"run8", "run1", "run2", "run5"}, 512 IServiceManager::DUMP_FLAG_PRIORITY_ALL); 513 ExpectListServicesWithPriority({"run3", "run2", "run4", "run8"}, 514 IServiceManager::DUMP_FLAG_PROTO); 515 ExpectDump("run2", "dump1"); 516 ExpectDump("run8", "dump2"); 517 518 CallMain({"--proto"}); 519 520 AssertRunningServices({"run2", "run8"}); 521 AssertDumped("run2", "dump1"); 522 AssertDumped("run8", "dump2"); 523 } 524 525 // Tests 'dumpsys --priority HIGH --proto' 526 TEST_F(DumpsysTest, DumpWithPriorityHighAndProto) { 527 ExpectListServicesWithPriority({"runninghigh1", "runninghigh2"}, 528 IServiceManager::DUMP_FLAG_PRIORITY_HIGH); 529 ExpectListServicesWithPriority({"runninghigh1", "runninghigh2", "runninghigh3"}, 530 IServiceManager::DUMP_FLAG_PROTO); 531 532 ExpectDump("runninghigh1", "dump1"); 533 ExpectDump("runninghigh2", "dump2"); 534 535 CallMain({"--priority", "HIGH", "--proto"}); 536 537 AssertRunningServices({"runninghigh1", "runninghigh2"}); 538 AssertDumpedWithPriority("runninghigh1", "dump1", PriorityDumper::PRIORITY_ARG_HIGH); 539 AssertDumpedWithPriority("runninghigh2", "dump2", PriorityDumper::PRIORITY_ARG_HIGH); 540 } 541 542 TEST_F(DumpsysTest, GetBytesWritten) { 543 const char* serviceName = "service2"; 544 const char* dumpContents = "dump1"; 545 ExpectDump(serviceName, dumpContents); 546 547 String16 service(serviceName); 548 Vector<String16> args; 549 std::chrono::duration<double> elapsedDuration; 550 size_t bytesWritten; 551 552 CallSingleService(service, args, IServiceManager::DUMP_FLAG_PRIORITY_ALL, 553 /* as_proto = */ false, elapsedDuration, bytesWritten); 554 555 AssertOutput(dumpContents); 556 EXPECT_THAT(bytesWritten, Eq(strlen(dumpContents))); 557 } 558 559 TEST_F(DumpsysTest, WriteDumpWithoutThreadStart) { 560 std::chrono::duration<double> elapsedDuration; 561 size_t bytesWritten; 562 status_t status = 563 dump_.writeDump(STDOUT_FILENO, String16("service"), std::chrono::milliseconds(500), 564 /* as_proto = */ false, elapsedDuration, bytesWritten); 565 EXPECT_THAT(status, Eq(INVALID_OPERATION)); 566 }