• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/corennnnn


Commit MetaInfo

Révisionaed7048ce0c8ff20a2ed7ce46a848d8af1d3142d (tree)
l'heure2016-08-04 23:44:35
AuteurTreeHugger Robot <treehugger-gerrit@goog...>
CommiterAndroid (Google) Code Review

Message de Log

Merge changes from topic 'bug_30451114' into nyc-mr1-dev

* changes:

Deprecated 'adb bugreport' with flat files.
Minor improvements on bugreport generation.

Change Summary

Modification

--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -14,28 +14,38 @@
1414 * limitations under the License.
1515 */
1616
17+#include "bugreport.h"
18+
1719 #include <string>
20+#include <vector>
1821
1922 #include <android-base/strings.h>
2023
21-#include "bugreport.h"
24+#include "sysdeps.h"
25+#include "adb_utils.h"
2226 #include "file_sync_service.h"
2327
24-static constexpr char BUGZ_OK_PREFIX[] = "OK:";
25-static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
28+static constexpr char BUGZ_BEGIN_PREFIX[] = "BEGIN:";
2629 static constexpr char BUGZ_PROGRESS_PREFIX[] = "PROGRESS:";
2730 static constexpr char BUGZ_PROGRESS_SEPARATOR[] = "/";
31+static constexpr char BUGZ_OK_PREFIX[] = "OK:";
32+static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:";
2833
2934 // Custom callback used to handle the output of zipped bugreports.
3035 class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface {
3136 public:
32- BugreportStandardStreamsCallback(const std::string& dest_file, bool show_progress, Bugreport* br)
37+ BugreportStandardStreamsCallback(const std::string& dest_dir, const std::string& dest_file,
38+ bool show_progress, Bugreport* br)
3339 : br_(br),
40+ src_file_(),
41+ dest_dir_(dest_dir),
3442 dest_file_(dest_file),
35- line_message_(android::base::StringPrintf("generating %s", dest_file_.c_str())),
43+ line_message_(),
44+ invalid_lines_(),
3645 show_progress_(show_progress),
37- status_(-1),
46+ status_(0),
3847 line_() {
48+ SetLineMessage();
3949 }
4050
4151 void OnStdout(const char* buffer, int length) {
@@ -54,28 +64,72 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface
5464 OnStream(nullptr, stderr, buffer, length);
5565 }
5666 int Done(int unused_) {
57- // Process remaining line, if any...
67+ // Process remaining line, if any.
5868 ProcessLine(line_);
59- // ..then return.
69+
70+ // Warn about invalid lines, if any.
71+ if (!invalid_lines_.empty()) {
72+ fprintf(stderr,
73+ "WARNING: bugreportz generated %zu line(s) with unknown commands, "
74+ "device might not support zipped bugreports:\n",
75+ invalid_lines_.size());
76+ for (const auto& line : invalid_lines_) {
77+ fprintf(stderr, "\t%s\n", line.c_str());
78+ }
79+ fprintf(stderr,
80+ "If the zipped bugreport was not generated, try 'adb bugreport' instead.\n");
81+ }
82+
83+ // Pull the generated bug report.
84+ if (status_ == 0) {
85+ if (src_file_.empty()) {
86+ fprintf(stderr, "bugreportz did not return a '%s' or '%s' line\n", BUGZ_OK_PREFIX,
87+ BUGZ_FAIL_PREFIX);
88+ return -1;
89+ }
90+ std::string destination;
91+ if (dest_dir_.empty()) {
92+ destination = dest_file_;
93+ } else {
94+ destination = android::base::StringPrintf("%s%c%s", dest_dir_.c_str(),
95+ OS_PATH_SEPARATOR, dest_file_.c_str());
96+ }
97+ std::vector<const char*> srcs{src_file_.c_str()};
98+ status_ =
99+ br_->DoSyncPull(srcs, destination.c_str(), true, line_message_.c_str()) ? 0 : 1;
100+ if (status_ != 0) {
101+ fprintf(stderr,
102+ "Bug report finished but could not be copied to '%s'.\n"
103+ "Try to run 'adb pull %s <directory>'\n"
104+ "to copy it to a directory that can be written.\n",
105+ destination.c_str(), src_file_.c_str());
106+ }
107+ }
60108 return status_;
61109 }
62110
63111 private:
112+ void SetLineMessage() {
113+ line_message_ =
114+ android::base::StringPrintf("generating %s", adb_basename(dest_file_).c_str());
115+ }
116+
117+ void SetSrcFile(const std::string path) {
118+ src_file_ = path;
119+ if (!dest_dir_.empty()) {
120+ // Only uses device-provided name when user passed a directory.
121+ dest_file_ = adb_basename(path);
122+ SetLineMessage();
123+ }
124+ }
125+
64126 void ProcessLine(const std::string& line) {
65127 if (line.empty()) return;
66128
67- if (android::base::StartsWith(line, BUGZ_OK_PREFIX)) {
68- if (show_progress_) {
69- // Make sure pull message doesn't conflict with generation message.
70- br_->UpdateProgress(line_message_, 100, 100);
71- }
72-
73- const char* zip_file = &line[strlen(BUGZ_OK_PREFIX)];
74- std::vector<const char*> srcs{zip_file};
75- status_ = br_->DoSyncPull(srcs, dest_file_.c_str(), true, line_message_.c_str()) ? 0 : 1;
76- if (status_ != 0) {
77- fprintf(stderr, "Could not copy file '%s' to '%s'\n", zip_file, dest_file_.c_str());
78- }
129+ if (android::base::StartsWith(line, BUGZ_BEGIN_PREFIX)) {
130+ SetSrcFile(&line[strlen(BUGZ_BEGIN_PREFIX)]);
131+ } else if (android::base::StartsWith(line, BUGZ_OK_PREFIX)) {
132+ SetSrcFile(&line[strlen(BUGZ_OK_PREFIX)]);
79133 } else if (android::base::StartsWith(line, BUGZ_FAIL_PREFIX)) {
80134 const char* error_message = &line[strlen(BUGZ_FAIL_PREFIX)];
81135 fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message);
@@ -89,24 +143,38 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface
89143 size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
90144 int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
91145 int total = std::stoi(line.substr(idx2 + 1));
92- br_->UpdateProgress(dest_file_, progress, total);
146+ br_->UpdateProgress(line_message_, progress, total);
93147 } else {
94- fprintf(stderr,
95- "WARNING: unexpected line (%s) returned by bugreportz, "
96- "device probably does not support zipped bugreports.\n"
97- "Try 'adb bugreport' instead.",
98- line.c_str());
148+ invalid_lines_.push_back(line);
99149 }
100150 }
101151
102152 Bugreport* br_;
103- const std::string dest_file_;
104- const std::string line_message_;
153+
154+ // Path of bugreport on device.
155+ std::string src_file_;
156+
157+ // Bugreport destination on host, depending on argument passed on constructor:
158+ // - if argument is a directory, dest_dir_ is set with it and dest_file_ will be the name
159+ // of the bugreport reported by the device.
160+ // - if argument is empty, dest_dir is set as the current directory and dest_file_ will be the
161+ // name of the bugreport reported by the device.
162+ // - otherwise, dest_dir_ is not set and dest_file_ is set with the value passed on constructor.
163+ std::string dest_dir_, dest_file_;
164+
165+ // Message displayed on LinePrinter, it's updated every time the destination above change.
166+ std::string line_message_;
167+
168+ // Lines sent by bugreportz that contain invalid commands; will be displayed at the end.
169+ std::vector<std::string> invalid_lines_;
170+
171+ // Whether PROGRESS_LINES should be interpreted as progress.
105172 bool show_progress_;
173+
174+ // Overall process of the operation, as returned by Done().
106175 int status_;
107176
108- // Temporary buffer containing the characters read since the last newline
109- // (\n).
177+ // Temporary buffer containing the characters read since the last newline (\n).
110178 std::string line_;
111179
112180 DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback);
@@ -116,34 +184,54 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface
116184 int usage();
117185
118186 int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) {
119- if (argc == 1) return SendShellCommand(transport_type, serial, "bugreport", false);
120- if (argc != 2) return usage();
121-
122- // Zipped bugreport option - will call 'bugreportz', which prints the location
123- // of the generated
124- // file, then pull it to the destination file provided by the user.
125- std::string dest_file = argv[1];
126- if (!android::base::EndsWith(argv[1], ".zip")) {
127- // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase
128- dest_file += ".zip";
129- }
187+ if (argc > 2) return usage();
130188
131189 // Gets bugreportz version.
132190 std::string bugz_stderr;
133191 DefaultStandardStreamsCallback version_callback(nullptr, &bugz_stderr);
134192 int status = SendShellCommand(transport_type, serial, "bugreportz -v", false, &version_callback);
193+ std::string bugz_version = android::base::Trim(bugz_stderr);
194+
195+ if (status != 0 || bugz_version.empty()) {
196+ // Device does not support bugreportz: if called as 'adb bugreport', just falls out to the
197+ // flat-file version
198+ if (argc == 1) return SendShellCommand(transport_type, serial, "bugreport", false);
135199
136- if (status != 0) {
200+ // But if user explicitly asked for a zipped bug report, fails instead (otherwise calling
201+ // 'bugreport' would generate a lot of output the user might not be prepared to handle)
137202 fprintf(stderr,
138- "Failed to get bugreportz version: 'bugreport -v' returned '%s' "
139- "(code %d)."
140- "\nIf the device does not support it, try running 'adb bugreport' "
141- "to get a "
142- "flat-file bugreport.",
203+ "Failed to get bugreportz version: 'bugreportz -v' returned '%s' (code %d).\n"
204+ "If the device runs Android M or below, try 'adb bugreport' instead.\n",
143205 bugz_stderr.c_str(), status);
144- return status;
206+ return status != 0 ? status : -1;
207+ }
208+
209+ std::string dest_file, dest_dir;
210+
211+ if (argc == 1) {
212+ // No args - use current directory
213+ if (!getcwd(&dest_dir)) {
214+ perror("adb: getcwd failed");
215+ return 1;
216+ }
217+ } else {
218+ // Check whether argument is a directory or file
219+ if (directory_exists(argv[1])) {
220+ dest_dir = argv[1];
221+ } else {
222+ dest_file = argv[1];
223+ }
224+ }
225+
226+ if (dest_file.empty()) {
227+ // Uses a default value until device provides the proper name
228+ dest_file = "bugreport.zip";
229+ } else {
230+ if (!android::base::EndsWith(dest_file, ".zip")) {
231+ // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase
232+ dest_file += ".zip";
233+ }
145234 }
146- std::string bugz_version = android::base::Trim(bugz_stderr);
147235
148236 bool show_progress = true;
149237 std::string bugz_command = "bugreportz -p";
@@ -153,12 +241,11 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc,
153241 fprintf(stderr,
154242 "Bugreport is in progress and it could take minutes to complete.\n"
155243 "Please be patient and do not cancel or disconnect your device "
156- "until it completes."
157- "\n");
244+ "until it completes.\n");
158245 show_progress = false;
159246 bugz_command = "bugreportz";
160247 }
161- BugreportStandardStreamsCallback bugz_callback(dest_file, show_progress, this);
248+ BugreportStandardStreamsCallback bugz_callback(dest_dir, dest_file, show_progress, this);
162249 return SendShellCommand(transport_type, serial, bugz_command, false, &bugz_callback);
163250 }
164251
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -19,6 +19,12 @@
1919 #include <gmock/gmock.h>
2020 #include <gtest/gtest.h>
2121
22+#include <android-base/strings.h>
23+#include <android-base/test_utils.h>
24+
25+#include "sysdeps.h"
26+#include "adb_utils.h"
27+
2228 using ::testing::_;
2329 using ::testing::Action;
2430 using ::testing::ActionInterface;
@@ -122,28 +128,38 @@ class BugreportMock : public Bugreport {
122128
123129 class BugreportTest : public ::testing::Test {
124130 public:
125- void SetBugreportzVersion(const std::string& version) {
131+ void SetUp() {
132+ if (!getcwd(&cwd_)) {
133+ ADD_FAILURE() << "getcwd failed: " << strerror(errno);
134+ return;
135+ }
136+ }
137+
138+ void ExpectBugreportzVersion(const std::string& version) {
126139 EXPECT_CALL(br_,
127140 SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
128141 .WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())),
129142 WithArg<4>(ReturnCallbackDone(0))));
130143 }
131144
132- void ExpectProgress(int progress, int total) {
133- EXPECT_CALL(br_, UpdateProgress(HasSubstr("file.zip"), progress, total));
145+ void ExpectProgress(int progress, int total, const std::string& file = "file.zip") {
146+ EXPECT_CALL(br_, UpdateProgress(StrEq("generating " + file), progress, total));
134147 }
135148
136149 BugreportMock br_;
150+ std::string cwd_; // TODO: make it static
137151 };
138152
139-// Tests when called with invalid number of argumnts
153+// Tests when called with invalid number of arguments
140154 TEST_F(BugreportTest, InvalidNumberArgs) {
141155 const char* args[1024] = {"bugreport", "to", "principal"};
142156 ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
143157 }
144158
145-// Tests the legacy 'adb bugreport' option
146-TEST_F(BugreportTest, FlatFileFormat) {
159+// Tests the 'adb bugreport' option when the device does not support 'bugreportz' - it falls back
160+// to the flat-file format ('bugreport' binary on device)
161+TEST_F(BugreportTest, NoArgumentsPreNDevice) {
162+ ExpectBugreportzVersion("");
147163 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
148164 .WillOnce(Return(0));
149165
@@ -151,15 +167,52 @@ TEST_F(BugreportTest, FlatFileFormat) {
151167 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
152168 }
153169
154-// Tests 'adb bugreport file.zip' when it succeeds and device does not support
155-// progress.
156-TEST_F(BugreportTest, OkLegacy) {
157- SetBugreportzVersion("1.0");
170+// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.0 - it will
171+// save the bugreport in the current directory with the name provided by the device.
172+TEST_F(BugreportTest, NoArgumentsNDevice) {
173+ ExpectBugreportzVersion("1.0");
174+
175+ std::string dest_file =
176+ android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
177+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
178+ .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
179+ WithArg<4>(ReturnCallbackDone())));
180+ EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
181+ true, StrEq("generating da_bugreport.zip")))
182+ .WillOnce(Return(true));
183+
184+ const char* args[1024] = {"bugreport"};
185+ ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
186+}
187+
188+// Tests the 'adb bugreport' option when the device supports 'bugreportz' version 1.1 - it will
189+// save the bugreport in the current directory with the name provided by the device.
190+TEST_F(BugreportTest, NoArgumentsPostNDevice) {
191+ ExpectBugreportzVersion("1.1");
192+ std::string dest_file =
193+ android::base::StringPrintf("%s%cda_bugreport.zip", cwd_.c_str(), OS_PATH_SEPARATOR);
194+ ExpectProgress(50, 100, "da_bugreport.zip");
195+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
196+ .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
197+ WithArg<4>(WriteOnStdout("PROGRESS:50/100\n")),
198+ WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip\n")),
199+ WithArg<4>(ReturnCallbackDone())));
200+ EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
201+ true, StrEq("generating da_bugreport.zip")))
202+ .WillOnce(Return(true));
203+
204+ const char* args[1024] = {"bugreport"};
205+ ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
206+}
207+
208+// Tests 'adb bugreport file.zip' when it succeeds and device does not support progress.
209+TEST_F(BugreportTest, OkNDevice) {
210+ ExpectBugreportzVersion("1.0");
158211 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
159212 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
160213 WithArg<4>(ReturnCallbackDone())));
161214 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
162- true, HasSubstr("file.zip")))
215+ true, StrEq("generating file.zip")))
163216 .WillOnce(Return(true));
164217
165218 const char* args[1024] = {"bugreport", "file.zip"};
@@ -168,14 +221,14 @@ TEST_F(BugreportTest, OkLegacy) {
168221
169222 // Tests 'adb bugreport file.zip' when it succeeds but response was sent in
170223 // multiple buffer writers and without progress updates.
171-TEST_F(BugreportTest, OkLegacySplitBuffer) {
172- SetBugreportzVersion("1.0");
224+TEST_F(BugreportTest, OkNDeviceSplitBuffer) {
225+ ExpectBugreportzVersion("1.0");
173226 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
174227 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")),
175228 WithArg<4>(WriteOnStdout("/bugreport.zip")),
176229 WithArg<4>(ReturnCallbackDone())));
177230 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
178- true, HasSubstr("file.zip")))
231+ true, StrEq("generating file.zip")))
179232 .WillOnce(Return(true));
180233
181234 const char* args[1024] = {"bugreport", "file.zip"};
@@ -183,20 +236,22 @@ TEST_F(BugreportTest, OkLegacySplitBuffer) {
183236 }
184237
185238 // Tests 'adb bugreport file.zip' when it succeeds and displays progress.
186-TEST_F(BugreportTest, Ok) {
187- SetBugreportzVersion("1.1");
239+TEST_F(BugreportTest, OkProgress) {
240+ ExpectBugreportzVersion("1.1");
188241 ExpectProgress(1, 100);
189242 ExpectProgress(10, 100);
190243 ExpectProgress(50, 100);
191244 ExpectProgress(99, 100);
192- ExpectProgress(100, 100);
193245 // clang-format off
194246 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
247+ // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
195248 .WillOnce(DoAll(
249+ // Name might change on OK, so make sure the right one is picked.
250+ WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport___NOT.zip\n")),
196251 // Progress line in one write
197252 WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
198253 // Add some bogus lines
199- WithArg<4>(WriteOnStdout("\nDUDE:SWEET\n\n")),
254+ WithArg<4>(WriteOnStdout("\nDUDE:SWEET\n\nBLA\n\nBLA\nBLA\n\n")),
200255 // Multiple progress lines in one write
201256 WithArg<4>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
202257 // Progress line in multiple writes
@@ -207,32 +262,70 @@ TEST_F(BugreportTest, Ok) {
207262 WithArg<4>(WriteOnStdout("OK:/device/bugreport")),
208263 WithArg<4>(WriteOnStdout(".zip")),
209264 WithArg<4>(ReturnCallbackDone())));
265+ // clang-format on
210266 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
211- true, HasSubstr("file.zip")))
267+ true, StrEq("generating file.zip")))
212268 .WillOnce(Return(true));
213269
214270 const char* args[1024] = {"bugreport", "file.zip"};
215271 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
216272 }
217273
274+// Tests 'adb bugreport dir' when it succeeds and destination is a directory.
275+TEST_F(BugreportTest, OkDirectory) {
276+ ExpectBugreportzVersion("1.1");
277+ TemporaryDir td;
278+ std::string dest_file =
279+ android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
280+
281+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
282+ .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
283+ WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
284+ WithArg<4>(ReturnCallbackDone())));
285+ EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
286+ true, StrEq("generating da_bugreport.zip")))
287+ .WillOnce(Return(true));
288+
289+ const char* args[1024] = {"bugreport", td.path};
290+ ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
291+}
292+
218293 // Tests 'adb bugreport file' when it succeeds
219294 TEST_F(BugreportTest, OkNoExtension) {
220- SetBugreportzVersion("1.1");
221- ExpectProgress(100, 100);
295+ ExpectBugreportzVersion("1.1");
222296 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
223297 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
224298 WithArg<4>(ReturnCallbackDone())));
225299 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
226- true, HasSubstr("file.zip")))
300+ true, StrEq("generating file.zip")))
227301 .WillOnce(Return(true));
228302
229303 const char* args[1024] = {"bugreport", "file"};
230304 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
231305 }
232306
307+// Tests 'adb bugreport dir' when it succeeds and destination is a directory and device runs N.
308+TEST_F(BugreportTest, OkNDeviceDirectory) {
309+ ExpectBugreportzVersion("1.0");
310+ TemporaryDir td;
311+ std::string dest_file =
312+ android::base::StringPrintf("%s%cda_bugreport.zip", td.path, OS_PATH_SEPARATOR);
313+
314+ EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
315+ .WillOnce(DoAll(WithArg<4>(WriteOnStdout("BEGIN:/device/da_bugreport.zip\n")),
316+ WithArg<4>(WriteOnStdout("OK:/device/da_bugreport.zip")),
317+ WithArg<4>(ReturnCallbackDone())));
318+ EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/da_bugreport.zip")), StrEq(dest_file),
319+ true, StrEq("generating da_bugreport.zip")))
320+ .WillOnce(Return(true));
321+
322+ const char* args[1024] = {"bugreport", td.path};
323+ ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
324+}
325+
233326 // Tests 'adb bugreport file.zip' when the bugreport itself failed
234327 TEST_F(BugreportTest, BugreportzReturnedFail) {
235- SetBugreportzVersion("1.1");
328+ ExpectBugreportzVersion("1.1");
236329 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
237330 .WillOnce(
238331 DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<4>(ReturnCallbackDone())));
@@ -247,7 +340,7 @@ TEST_F(BugreportTest, BugreportzReturnedFail) {
247340 // was sent in
248341 // multiple buffer writes
249342 TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
250- SetBugreportzVersion("1.1");
343+ ExpectBugreportzVersion("1.1");
251344 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
252345 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")),
253346 WithArg<4>(ReturnCallbackDone())));
@@ -261,7 +354,7 @@ TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
261354 // Tests 'adb bugreport file.zip' when the bugreportz returned an unsupported
262355 // response.
263356 TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
264- SetBugreportzVersion("1.1");
357+ ExpectBugreportzVersion("1.1");
265358 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
266359 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
267360 WithArg<4>(ReturnCallbackDone())));
@@ -281,9 +374,17 @@ TEST_F(BugreportTest, BugreportzVersionFailed) {
281374 ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
282375 }
283376
377+// Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output.
378+TEST_F(BugreportTest, BugreportzVersionEmpty) {
379+ ExpectBugreportzVersion("");
380+
381+ const char* args[1024] = {"bugreport", "file.zip"};
382+ ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
383+}
384+
284385 // Tests 'adb bugreport file.zip' when the main bugreportz command failed
285386 TEST_F(BugreportTest, BugreportzFailed) {
286- SetBugreportzVersion("1.1");
387+ ExpectBugreportzVersion("1.1");
287388 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
288389 .WillOnce(Return(666));
289390
@@ -293,8 +394,7 @@ TEST_F(BugreportTest, BugreportzFailed) {
293394
294395 // Tests 'adb bugreport file.zip' when the bugreport could not be pulled
295396 TEST_F(BugreportTest, PullFails) {
296- SetBugreportzVersion("1.1");
297- ExpectProgress(100, 100);
397+ ExpectBugreportzVersion("1.1");
298398 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
299399 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
300400 WithArg<4>(ReturnCallbackDone())));
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -81,6 +81,7 @@ static std::string product_file(const char *extra) {
8181
8282 static void help() {
8383 fprintf(stderr, "%s\n", adb_version().c_str());
84+ // clang-format off
8485 fprintf(stderr,
8586 " -a - directs adb to listen on all interfaces for a connection\n"
8687 " -d - directs command to the only connected USB device\n"
@@ -173,9 +174,11 @@ static void help() {
173174 " (-g: grant all runtime permissions)\n"
174175 " adb uninstall [-k] <package> - remove this app package from the device\n"
175176 " ('-k' means keep the data and cache directories)\n"
176- " adb bugreport [<zip_file>] - return all information from the device\n"
177- " that should be included in a bug report.\n"
178- "\n"
177+ " adb bugreport [<path>] - return all information from the device that should be included in a zipped bug report.\n"
178+ " If <path> is a file, the bug report will be saved as that file.\n"
179+ " If <path> is a directory, the bug report will be saved in that directory with the name provided by the device.\n"
180+ " If <path> is omitted, the bug report will be saved in the current directory with the name provided by the device.\n"
181+ " NOTE: if the device does not support zipped bug reports, the bug report will be output on stdout.\n"
179182 " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n"
180183 " - write an archive of the device's data to <file>.\n"
181184 " If no -f option is supplied then the data is written\n"
@@ -249,8 +252,8 @@ static void help() {
249252 " ADB_TRACE - Print debug information. A comma separated list of the following values\n"
250253 " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n"
251254 " ANDROID_SERIAL - The serial number to connect to. -s takes priority over this if given.\n"
252- " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n"
253- );
255+ " ANDROID_LOG_TAGS - When used with the logcat option, only these debug tags are printed.\n");
256+ // clang-format on
254257 }
255258
256259 int usage() {
@@ -1327,7 +1330,7 @@ static std::string find_product_out_path(const std::string& hint) {
13271330 if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) {
13281331 std::string cwd;
13291332 if (!getcwd(&cwd)) {
1330- fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno));
1333+ perror("adb: getcwd failed");
13311334 return "";
13321335 }
13331336 return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str());