bugreport_test.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  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. #include "bugreport.h"
  17. #include <gmock/gmock.h>
  18. #include <gtest/gtest.h>
  19. #include <android-base/strings.h>
  20. #include <android-base/test_utils.h>
  21. #include "sysdeps.h"
  22. #include "adb_utils.h"
  23. using ::testing::_;
  24. using ::testing::Action;
  25. using ::testing::ActionInterface;
  26. using ::testing::DoAll;
  27. using ::testing::ElementsAre;
  28. using ::testing::HasSubstr;
  29. using ::testing::MakeAction;
  30. using ::testing::Return;
  31. using ::testing::StrEq;
  32. using ::testing::WithArg;
  33. using ::testing::internal::CaptureStderr;
  34. using ::testing::internal::CaptureStdout;
  35. using ::testing::internal::GetCapturedStderr;
  36. using ::testing::internal::GetCapturedStdout;
  37. // Empty function so tests don't need to be linked against file_sync_service.cpp, which requires
  38. // SELinux and its transitive dependencies...
  39. bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
  40. const char* name) {
  41. ADD_FAILURE() << "do_sync_pull() should have been mocked";
  42. return false;
  43. }
  44. // Empty functions so tests don't need to be linked against commandline.cpp
  45. DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
  46. int send_shell_command(const std::string& command, bool disable_shell_protocol,
  47. StandardStreamsCallbackInterface* callback) {
  48. ADD_FAILURE() << "send_shell_command() should have been mocked";
  49. return -42;
  50. }
  51. enum StreamType {
  52. kStreamStdout,
  53. kStreamStderr,
  54. };
  55. // gmock black magic to provide a WithArg<2>(WriteOnStdout(output)) matcher
  56. typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
  57. class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
  58. public:
  59. explicit OnStandardStreamsCallbackAction(StreamType type, const std::string& output)
  60. : type_(type), output_(output) {
  61. }
  62. virtual Result Perform(const ArgumentTuple& args) {
  63. if (type_ == kStreamStdout) {
  64. ::std::tr1::get<0>(args)->OnStdout(output_.c_str(), output_.size());
  65. }
  66. if (type_ == kStreamStderr) {
  67. ::std::tr1::get<0>(args)->OnStderr(output_.c_str(), output_.size());
  68. }
  69. }
  70. private:
  71. StreamType type_;
  72. std::string output_;
  73. };
  74. // Matcher used to emulated StandardStreamsCallbackInterface.OnStdout(buffer,
  75. // length)
  76. Action<OnStandardStreamsCallbackFunction> WriteOnStdout(const std::string& output) {
  77. return MakeAction(new OnStandardStreamsCallbackAction(kStreamStdout, output));
  78. }
  79. // Matcher used to emulated StandardStreamsCallbackInterface.OnStderr(buffer,
  80. // length)
  81. Action<OnStandardStreamsCallbackFunction> WriteOnStderr(const std::string& output) {
  82. return MakeAction(new OnStandardStreamsCallbackAction(kStreamStderr, output));
  83. }
  84. typedef int CallbackDoneFunction(StandardStreamsCallbackInterface*);
  85. class CallbackDoneAction : public ActionInterface<CallbackDoneFunction> {
  86. public:
  87. explicit CallbackDoneAction(int status) : status_(status) {
  88. }
  89. virtual Result Perform(const ArgumentTuple& args) {
  90. int status = ::std::tr1::get<0>(args)->Done(status_);
  91. return status;
  92. }
  93. private:
  94. int status_;
  95. };
  96. // Matcher used to emulated StandardStreamsCallbackInterface.Done(status)
  97. Action<CallbackDoneFunction> ReturnCallbackDone(int status = -1337) {
  98. return MakeAction(new CallbackDoneAction(status));
  99. }
  100. class BugreportMock : public Bugreport {
  101. public:
  102. MOCK_METHOD3(SendShellCommand, int(const std::string& command, bool disable_shell_protocol,
  103. StandardStreamsCallbackInterface* callback));
  104. MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
  105. bool copy_attrs, const char* name));
  106. MOCK_METHOD2(UpdateProgress, void(const std::string&, int));
  107. };
  108. class BugreportTest : public ::testing::Test {
  109. public:
  110. void SetUp() {
  111. if (!getcwd(&cwd_)) {
  112. ADD_FAILURE() << "getcwd failed: " << strerror(errno);
  113. return;
  114. }
  115. }
  116. void ExpectBugreportzVersion(const std::string& version) {
  117. EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
  118. .WillOnce(DoAll(WithArg<2>(WriteOnStderr(version)),
  119. WithArg<2>(ReturnCallbackDone(0))));
  120. }
  121. void ExpectProgress(int progress_percentage, const std::string& file = "file.zip") {
  122. EXPECT_CALL(br_, UpdateProgress(StrEq("generating " + file), progress_percentage));
  123. }
  124. BugreportMock br_;
  125. std::string cwd_; // TODO: make it static
  126. };
  127. // Tests when called with invalid number of arguments
  128. TEST_F(BugreportTest, InvalidNumberArgs) {
  129. const char* args[] = {"bugreport", "to", "principal"};
  130. ASSERT_EQ(1, br_.DoIt(3, args));
  131. }
  132. // Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
  133. // to the flat-file format ('bugreport' binary on device)
  134. TEST_F(BugreportTest, NoArgumentsPreNDevice) {
  135. // clang-format off
  136. EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _))
  137. .WillOnce(DoAll(WithArg<2>(WriteOnStderr("")),
  138. // Write some bogus output on stdout to make sure it's ignored
  139. WithArg<2>(WriteOnStdout("Dude, where is my bugreportz?")),
  140. WithArg<2>(ReturnCallbackDone(0))));
  141. // clang-format on
  142. std::string bugreport = "Reported the bug was.";
  143. CaptureStdout();
  144. EXPECT_CALL(br_, SendShellCommand("bugreport", false, _))
  145. .WillOnce(DoAll(WithArg<2>(WriteOnStdout(bugreport)), Return(0)));
  146. const char* args[] = {"bugreport"};
  147. ASSERT_EQ(0, br_.DoIt(1, args));
  148. ASSERT_THAT(GetCapturedStdout(), StrEq(bugreport));
  149. }
  150. // Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.0 - it will
  151. // save the bugreport in the current directory with the name provided by the device.
  152. TEST_F(BugreportTest, NoArgumentsNDevice) {
  153. ExpectBugreportzVersion("1.0");
  154. std::string dest_file =
  155. android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
  156. EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
  157. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
  158. WithArg<2>(ReturnCallbackDone())));
  159. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
  160. false, StrEq("pulling da_bugreport.zip")))
  161. .WillOnce(Return(true));
  162. const char* args[] = {"bugreport"};
  163. ASSERT_EQ(0, br_.DoIt(1, args));
  164. }
  165. // Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.1 - it will
  166. // save the bugreport in the current directory with the name provided by the device.
  167. TEST_F(BugreportTest, NoArgumentsPostNDevice) {
  168. ExpectBugreportzVersion("1.1");
  169. std::string dest_file =
  170. android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
  171. ExpectProgress(50, "da_bugreport.zip");
  172. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  173. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
  174. WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")),
  175. WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
  176. WithArg<2>(ReturnCallbackDone())));
  177. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
  178. false, StrEq("pulling da_bugreport.zip")))
  179. .WillOnce(Return(true));
  180. const char* args[] = {"bugreport"};
  181. ASSERT_EQ(0, br_.DoIt(1, args));
  182. }
  183. // Tests 'adb bugreport file.zip' when it succeeds and device does not support progress.
  184. TEST_F(BugreportTest, OkNDevice) {
  185. ExpectBugreportzVersion("1.0");
  186. EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
  187. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
  188. WithArg<2>(ReturnCallbackDone())));
  189. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  190. false, StrEq("pulling file.zip")))
  191. .WillOnce(Return(true));
  192. const char* args[] = {"bugreport", "file.zip"};
  193. ASSERT_EQ(0, br_.DoIt(2, args));
  194. }
  195. // Tests 'adb bugreport file.zip' when it succeeds but response was sent in
  196. // multiple buffer writers and without progress updates.
  197. TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
  198. ExpectBugreportzVersion("1.0");
  199. EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
  200. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device")),
  201. WithArg<2>(WriteOnStdout("/bugreport.zip")),
  202. WithArg<2>(ReturnCallbackDone())));
  203. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  204. false, StrEq("pulling file.zip")))
  205. .WillOnce(Return(true));
  206. const char* args[] = {"bugreport", "file.zip"};
  207. ASSERT_EQ(0, br_.DoIt(2, args));
  208. }
  209. // Tests 'adb bugreport file.zip' when it succeeds and displays progress.
  210. TEST_F(BugreportTest, OkProgress) {
  211. ExpectBugreportzVersion("1.1");
  212. ExpectProgress(1);
  213. ExpectProgress(10);
  214. ExpectProgress(50);
  215. ExpectProgress(99);
  216. // clang-format off
  217. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  218. // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
  219. .WillOnce(DoAll(
  220. // Name might change on OK, so make sure the right one is picked.
  221. WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport___NOT.zip\n")),
  222. // Progress line in one write
  223. WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")),
  224. // Add some bogus lines
  225. WithArg<2>(WriteOnStdout("\nDUDE:SWEET\n\nBLA\n\nBLA\nBLA\n\n")),
  226. // Multiple progress lines in one write
  227. WithArg<2>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
  228. // Progress line in multiple writes
  229. WithArg<2>(WriteOnStdout("PROG")),
  230. WithArg<2>(WriteOnStdout("RESS:99")),
  231. WithArg<2>(WriteOnStdout("/100\n")),
  232. // Split last message as well, just in case
  233. WithArg<2>(WriteOnStdout("OK:/device/bugreport")),
  234. WithArg<2>(WriteOnStdout(".zip")),
  235. WithArg<2>(ReturnCallbackDone())));
  236. // clang-format on
  237. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  238. false, StrEq("pulling file.zip")))
  239. .WillOnce(Return(true));
  240. const char* args[] = {"bugreport", "file.zip"};
  241. ASSERT_EQ(0, br_.DoIt(2, args));
  242. }
  243. // Tests 'adb bugreport file.zip' when it succeeds and displays progress, even if progress recedes.
  244. TEST_F(BugreportTest, OkProgressAlwaysForward) {
  245. ExpectBugreportzVersion("1.1");
  246. ExpectProgress(1);
  247. ExpectProgress(50);
  248. ExpectProgress(75);
  249. // clang-format off
  250. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  251. // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
  252. .WillOnce(DoAll(
  253. WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
  254. WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
  255. WithArg<2>(WriteOnStdout("PROGRESS:50/100\n")), // 50%
  256. // 25% should be ignored becaused it receded.
  257. WithArg<2>(WriteOnStdout("PROGRESS:25/100\n")), // 25%
  258. WithArg<2>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
  259. // 75% should be ignored becaused it didn't change.
  260. WithArg<2>(WriteOnStdout("PROGRESS:75/100\n")), // 75%
  261. // Try a receeding percentage with a different max progress
  262. WithArg<2>(WriteOnStdout("PROGRESS:700/1000\n")), // 70%
  263. WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
  264. WithArg<2>(ReturnCallbackDone())));
  265. // clang-format on
  266. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  267. false, StrEq("pulling file.zip")))
  268. .WillOnce(Return(true));
  269. const char* args[] = {"bugreport", "file.zip"};
  270. ASSERT_EQ(0, br_.DoIt(2, args));
  271. }
  272. // Tests 'adb bugreport file.zip' when it succeeds and displays the initial progress of 0%
  273. TEST_F(BugreportTest, OkProgressZeroPercentIsNotIgnored) {
  274. ExpectBugreportzVersion("1.1");
  275. ExpectProgress(0);
  276. ExpectProgress(1);
  277. // clang-format off
  278. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  279. // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
  280. .WillOnce(DoAll(
  281. WithArg<2>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
  282. WithArg<2>(WriteOnStdout("PROGRESS:1/100000\n")),
  283. WithArg<2>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
  284. WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
  285. WithArg<2>(ReturnCallbackDone())));
  286. // clang-format on
  287. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  288. false, StrEq("pulling file.zip")))
  289. .WillOnce(Return(true));
  290. const char* args[] = {"bugreport", "file.zip"};
  291. ASSERT_EQ(0, br_.DoIt(2, args));
  292. }
  293. // Tests 'adb bugreport dir' when it succeeds and destination is a directory.
  294. TEST_F(BugreportTest, OkDirectory) {
  295. ExpectBugreportzVersion("1.1");
  296. TemporaryDir td;
  297. std::string dest_file =
  298. android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
  299. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  300. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
  301. WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
  302. WithArg<2>(ReturnCallbackDone())));
  303. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
  304. false, StrEq("pulling da_bugreport.zip")))
  305. .WillOnce(Return(true));
  306. const char* args[] = {"bugreport", td.path};
  307. ASSERT_EQ(0, br_.DoIt(2, args));
  308. }
  309. // Tests 'adb bugreport file' when it succeeds
  310. TEST_F(BugreportTest, OkNoExtension) {
  311. ExpectBugreportzVersion("1.1");
  312. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  313. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip\n")),
  314. WithArg<2>(ReturnCallbackDone())));
  315. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  316. false, StrEq("pulling file.zip")))
  317. .WillOnce(Return(true));
  318. const char* args[] = {"bugreport", "file"};
  319. ASSERT_EQ(0, br_.DoIt(2, args));
  320. }
  321. // Tests 'adb bugreport dir' when it succeeds and destination is a directory and device runs N.
  322. TEST_F(BugreportTest, OkNDeviceDirectory) {
  323. ExpectBugreportzVersion("1.0");
  324. TemporaryDir td;
  325. std::string dest_file =
  326. android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
  327. EXPECT_CALL(br_, SendShellCommand("bugreportz", false, _))
  328. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
  329. WithArg<2>(WriteOnStdout("OK:/device/da_bugreport.zip")),
  330. WithArg<2>(ReturnCallbackDone())));
  331. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
  332. false, StrEq("pulling da_bugreport.zip")))
  333. .WillOnce(Return(true));
  334. const char* args[] = {"bugreport", td.path};
  335. ASSERT_EQ(0, br_.DoIt(2, args));
  336. }
  337. // Tests 'adb bugreport file.zip' when the bugreport itself failed
  338. TEST_F(BugreportTest, BugreportzReturnedFail) {
  339. ExpectBugreportzVersion("1.1");
  340. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  341. .WillOnce(
  342. DoAll(WithArg<2>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<2>(ReturnCallbackDone())));
  343. CaptureStderr();
  344. const char* args[] = {"bugreport", "file.zip"};
  345. ASSERT_EQ(-1, br_.DoIt(2, args));
  346. ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
  347. }
  348. // Tests 'adb bugreport file.zip' when the bugreport itself failed but response
  349. // was sent in
  350. // multiple buffer writes
  351. TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
  352. ExpectBugreportzVersion("1.1");
  353. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  354. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("FAIL")), WithArg<2>(WriteOnStdout(":D'OH!\n")),
  355. WithArg<2>(ReturnCallbackDone())));
  356. CaptureStderr();
  357. const char* args[] = {"bugreport", "file.zip"};
  358. ASSERT_EQ(-1, br_.DoIt(2, args));
  359. ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
  360. }
  361. // Tests 'adb bugreport file.zip' when the bugreportz returned an unsupported
  362. // response.
  363. TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
  364. ExpectBugreportzVersion("1.1");
  365. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  366. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("bugreportz? What am I, a zombie?")),
  367. WithArg<2>(ReturnCallbackDone())));
  368. CaptureStderr();
  369. const char* args[] = {"bugreport", "file.zip"};
  370. ASSERT_EQ(-1, br_.DoIt(2, args));
  371. ASSERT_THAT(GetCapturedStderr(), HasSubstr("bugreportz? What am I, a zombie?"));
  372. }
  373. // Tests 'adb bugreport file.zip' when the bugreportz -v command failed
  374. TEST_F(BugreportTest, BugreportzVersionFailed) {
  375. EXPECT_CALL(br_, SendShellCommand("bugreportz -v", false, _)).WillOnce(Return(666));
  376. const char* args[] = {"bugreport", "file.zip"};
  377. ASSERT_EQ(666, br_.DoIt(2, args));
  378. }
  379. // Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output.
  380. TEST_F(BugreportTest, BugreportzVersionEmpty) {
  381. ExpectBugreportzVersion("");
  382. const char* args[] = {"bugreport", "file.zip"};
  383. ASSERT_EQ(-1, br_.DoIt(2, args));
  384. }
  385. // Tests 'adb bugreport file.zip' when the main bugreportz command failed
  386. TEST_F(BugreportTest, BugreportzFailed) {
  387. ExpectBugreportzVersion("1.1");
  388. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _)).WillOnce(Return(666));
  389. const char* args[] = {"bugreport", "file.zip"};
  390. ASSERT_EQ(666, br_.DoIt(2, args));
  391. }
  392. // Tests 'adb bugreport file.zip' when the bugreport could not be pulled
  393. TEST_F(BugreportTest, PullFails) {
  394. ExpectBugreportzVersion("1.1");
  395. EXPECT_CALL(br_, SendShellCommand("bugreportz -p", false, _))
  396. .WillOnce(DoAll(WithArg<2>(WriteOnStdout("OK:/device/bugreport.zip")),
  397. WithArg<2>(ReturnCallbackDone())));
  398. EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
  399. false, HasSubstr("file.zip")))
  400. .WillOnce(Return(false));
  401. const char* args[] = {"bugreport", "file.zip"};
  402. ASSERT_EQ(1, br_.DoIt(2, args));
  403. }