system/corennnnn
Revision | 307951e124afc0ab385dc679a57562d339049e2b (tree) |
---|---|
Time | 2016-08-02 07:28:12 |
Author | Felipe Leme <felipeal@goog...> |
Commiter | Felipe Leme |
Deprecated 'adb bugreport' with flat files.
Starting on Android N, zipped bugreports contain more information than
flat-file, text bugreports. On N, calls to 'adb bugreport' would still
generate a flat-file bugreport, but with a warning.
With this change, 'adb bugreport' will generate a zipped bugreport in
the current directory, using the bugreport name provided by the
device. Similarly, calling 'adb bugreport dir' will generate a bugreport
with a device-provided name, but in such directory.
BUG: 30451114
BUG: 29448020
Change-Id: Ibc8920dd44a5f62feb15bf3fefdcb0bdbf389a90
@@ -14,31 +14,38 @@ | ||
14 | 14 | * limitations under the License. |
15 | 15 | */ |
16 | 16 | |
17 | +#include "bugreport.h" | |
18 | + | |
17 | 19 | #include <string> |
18 | 20 | #include <vector> |
19 | 21 | |
20 | 22 | #include <android-base/strings.h> |
21 | 23 | |
22 | -#include "bugreport.h" | |
24 | +#include "sysdeps.h" | |
25 | +#include "adb_utils.h" | |
23 | 26 | #include "file_sync_service.h" |
24 | 27 | |
25 | -static constexpr char BUGZ_OK_PREFIX[] = "OK:"; | |
26 | -static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:"; | |
28 | +static constexpr char BUGZ_BEGIN_PREFIX[] = "BEGIN:"; | |
27 | 29 | static constexpr char BUGZ_PROGRESS_PREFIX[] = "PROGRESS:"; |
28 | 30 | static constexpr char BUGZ_PROGRESS_SEPARATOR[] = "/"; |
31 | +static constexpr char BUGZ_OK_PREFIX[] = "OK:"; | |
32 | +static constexpr char BUGZ_FAIL_PREFIX[] = "FAIL:"; | |
29 | 33 | |
30 | 34 | // Custom callback used to handle the output of zipped bugreports. |
31 | 35 | class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface { |
32 | 36 | public: |
33 | - 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) | |
34 | 39 | : br_(br), |
35 | 40 | src_file_(), |
41 | + dest_dir_(dest_dir), | |
36 | 42 | dest_file_(dest_file), |
37 | - line_message_(android::base::StringPrintf("generating %s", dest_file_.c_str())), | |
43 | + line_message_(), | |
38 | 44 | invalid_lines_(), |
39 | 45 | show_progress_(show_progress), |
40 | 46 | status_(0), |
41 | 47 | line_() { |
48 | + SetLineMessage(); | |
42 | 49 | } |
43 | 50 | |
44 | 51 | void OnStdout(const char* buffer, int length) { |
@@ -80,25 +87,49 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface | ||
80 | 87 | BUGZ_FAIL_PREFIX); |
81 | 88 | return -1; |
82 | 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 | + } | |
83 | 97 | std::vector<const char*> srcs{src_file_.c_str()}; |
84 | - status_ = br_->DoSyncPull(srcs, dest_file_.c_str(), true, line_message_.c_str()) ? 0 : 1; | |
98 | + status_ = | |
99 | + br_->DoSyncPull(srcs, destination.c_str(), true, line_message_.c_str()) ? 0 : 1; | |
85 | 100 | if (status_ != 0) { |
86 | 101 | fprintf(stderr, |
87 | 102 | "Bug report finished but could not be copied to '%s'.\n" |
88 | 103 | "Try to run 'adb pull %s <directory>'\n" |
89 | 104 | "to copy it to a directory that can be written.\n", |
90 | - dest_file_.c_str(), src_file_.c_str()); | |
105 | + destination.c_str(), src_file_.c_str()); | |
91 | 106 | } |
92 | 107 | } |
93 | 108 | return status_; |
94 | 109 | } |
95 | 110 | |
96 | 111 | 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 | + | |
97 | 126 | void ProcessLine(const std::string& line) { |
98 | 127 | if (line.empty()) return; |
99 | 128 | |
100 | - if (android::base::StartsWith(line, BUGZ_OK_PREFIX)) { | |
101 | - src_file_ = &line[strlen(BUGZ_OK_PREFIX)]; | |
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)]); | |
102 | 133 | } else if (android::base::StartsWith(line, BUGZ_FAIL_PREFIX)) { |
103 | 134 | const char* error_message = &line[strlen(BUGZ_FAIL_PREFIX)]; |
104 | 135 | fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message); |
@@ -112,22 +143,38 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface | ||
112 | 143 | size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR); |
113 | 144 | int progress = std::stoi(line.substr(idx1, (idx2 - idx1))); |
114 | 145 | int total = std::stoi(line.substr(idx2 + 1)); |
115 | - br_->UpdateProgress(dest_file_, progress, total); | |
146 | + br_->UpdateProgress(line_message_, progress, total); | |
116 | 147 | } else { |
117 | 148 | invalid_lines_.push_back(line); |
118 | 149 | } |
119 | 150 | } |
120 | 151 | |
121 | 152 | Bugreport* br_; |
153 | + | |
154 | + // Path of bugreport on device. | |
122 | 155 | std::string src_file_; |
123 | - const std::string dest_file_; | |
124 | - const std::string line_message_; | |
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. | |
125 | 169 | std::vector<std::string> invalid_lines_; |
170 | + | |
171 | + // Whether PROGRESS_LINES should be interpreted as progress. | |
126 | 172 | bool show_progress_; |
173 | + | |
174 | + // Overall process of the operation, as returned by Done(). | |
127 | 175 | int status_; |
128 | 176 | |
129 | - // Temporary buffer containing the characters read since the last newline | |
130 | - // (\n). | |
177 | + // Temporary buffer containing the characters read since the last newline (\n). | |
131 | 178 | std::string line_; |
132 | 179 | |
133 | 180 | DISALLOW_COPY_AND_ASSIGN(BugreportStandardStreamsCallback); |
@@ -137,17 +184,7 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface | ||
137 | 184 | int usage(); |
138 | 185 | |
139 | 186 | int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) { |
140 | - if (argc == 1) return SendShellCommand(transport_type, serial, "bugreport", false); | |
141 | - if (argc != 2) return usage(); | |
142 | - | |
143 | - // Zipped bugreport option - will call 'bugreportz', which prints the location | |
144 | - // of the generated | |
145 | - // file, then pull it to the destination file provided by the user. | |
146 | - std::string dest_file = argv[1]; | |
147 | - if (!android::base::EndsWith(argv[1], ".zip")) { | |
148 | - // TODO: use a case-insensitive comparison (like EndsWithIgnoreCase | |
149 | - dest_file += ".zip"; | |
150 | - } | |
187 | + if (argc > 2) return usage(); | |
151 | 188 | |
152 | 189 | // Gets bugreportz version. |
153 | 190 | std::string bugz_stderr; |
@@ -156,6 +193,12 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, | ||
156 | 193 | std::string bugz_version = android::base::Trim(bugz_stderr); |
157 | 194 | |
158 | 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); | |
199 | + | |
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) | |
159 | 202 | fprintf(stderr, |
160 | 203 | "Failed to get bugreportz version: 'bugreportz -v' returned '%s' (code %d).\n" |
161 | 204 | "If the device runs Android M or below, try 'adb bugreport' instead.\n", |
@@ -163,6 +206,33 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, | ||
163 | 206 | return status != 0 ? status : -1; |
164 | 207 | } |
165 | 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 | + } | |
234 | + } | |
235 | + | |
166 | 236 | bool show_progress = true; |
167 | 237 | std::string bugz_command = "bugreportz -p"; |
168 | 238 | if (bugz_version == "1.0") { |
@@ -175,7 +245,7 @@ int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, | ||
175 | 245 | show_progress = false; |
176 | 246 | bugz_command = "bugreportz"; |
177 | 247 | } |
178 | - BugreportStandardStreamsCallback bugz_callback(dest_file, show_progress, this); | |
248 | + BugreportStandardStreamsCallback bugz_callback(dest_dir, dest_file, show_progress, this); | |
179 | 249 | return SendShellCommand(transport_type, serial, bugz_command, false, &bugz_callback); |
180 | 250 | } |
181 | 251 |
@@ -19,6 +19,12 @@ | ||
19 | 19 | #include <gmock/gmock.h> |
20 | 20 | #include <gtest/gtest.h> |
21 | 21 | |
22 | +#include <android-base/strings.h> | |
23 | +#include <android-base/test_utils.h> | |
24 | + | |
25 | +#include "sysdeps.h" | |
26 | +#include "adb_utils.h" | |
27 | + | |
22 | 28 | using ::testing::_; |
23 | 29 | using ::testing::Action; |
24 | 30 | using ::testing::ActionInterface; |
@@ -122,28 +128,38 @@ class BugreportMock : public Bugreport { | ||
122 | 128 | |
123 | 129 | class BugreportTest : public ::testing::Test { |
124 | 130 | 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) { | |
126 | 139 | EXPECT_CALL(br_, |
127 | 140 | SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _)) |
128 | 141 | .WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())), |
129 | 142 | WithArg<4>(ReturnCallbackDone(0)))); |
130 | 143 | } |
131 | 144 | |
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)); | |
134 | 147 | } |
135 | 148 | |
136 | 149 | BugreportMock br_; |
150 | + std::string cwd_; // TODO: make it static | |
137 | 151 | }; |
138 | 152 | |
139 | -// Tests when called with invalid number of argumnts | |
153 | +// Tests when called with invalid number of arguments | |
140 | 154 | TEST_F(BugreportTest, InvalidNumberArgs) { |
141 | 155 | const char* args[1024] = {"bugreport", "to", "principal"}; |
142 | 156 | ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args)); |
143 | 157 | } |
144 | 158 | |
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(""); | |
147 | 163 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _)) |
148 | 164 | .WillOnce(Return(0)); |
149 | 165 |
@@ -151,15 +167,52 @@ TEST_F(BugreportTest, FlatFileFormat) { | ||
151 | 167 | ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args)); |
152 | 168 | } |
153 | 169 | |
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"); | |
158 | 211 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _)) |
159 | 212 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")), |
160 | 213 | WithArg<4>(ReturnCallbackDone()))); |
161 | 214 | EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"), |
162 | - true, HasSubstr("file.zip"))) | |
215 | + true, StrEq("generating file.zip"))) | |
163 | 216 | .WillOnce(Return(true)); |
164 | 217 | |
165 | 218 | const char* args[1024] = {"bugreport", "file.zip"}; |
@@ -168,14 +221,14 @@ TEST_F(BugreportTest, OkLegacy) { | ||
168 | 221 | |
169 | 222 | // Tests 'adb bugreport file.zip' when it succeeds but response was sent in |
170 | 223 | // 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"); | |
173 | 226 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _)) |
174 | 227 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")), |
175 | 228 | WithArg<4>(WriteOnStdout("/bugreport.zip")), |
176 | 229 | WithArg<4>(ReturnCallbackDone()))); |
177 | 230 | EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"), |
178 | - true, HasSubstr("file.zip"))) | |
231 | + true, StrEq("generating file.zip"))) | |
179 | 232 | .WillOnce(Return(true)); |
180 | 233 | |
181 | 234 | const char* args[1024] = {"bugreport", "file.zip"}; |
@@ -183,16 +236,18 @@ TEST_F(BugreportTest, OkLegacySplitBuffer) { | ||
183 | 236 | } |
184 | 237 | |
185 | 238 | // 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"); | |
188 | 241 | ExpectProgress(1, 100); |
189 | 242 | ExpectProgress(10, 100); |
190 | 243 | ExpectProgress(50, 100); |
191 | 244 | ExpectProgress(99, 100); |
192 | 245 | // clang-format off |
193 | 246 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
194 | - // NOTE: DoAll accepts at most 10 arguments, and we have reached that limit... | |
247 | + // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit... | |
195 | 248 | .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")), | |
196 | 251 | // Progress line in one write |
197 | 252 | WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), |
198 | 253 | // Add some bogus lines |
@@ -209,30 +264,68 @@ TEST_F(BugreportTest, Ok) { | ||
209 | 264 | WithArg<4>(ReturnCallbackDone()))); |
210 | 265 | // clang-format on |
211 | 266 | EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"), |
212 | - true, HasSubstr("file.zip"))) | |
267 | + true, StrEq("generating file.zip"))) | |
213 | 268 | .WillOnce(Return(true)); |
214 | 269 | |
215 | 270 | const char* args[1024] = {"bugreport", "file.zip"}; |
216 | 271 | ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args)); |
217 | 272 | } |
218 | 273 | |
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 | + | |
219 | 293 | // Tests 'adb bugreport file' when it succeeds |
220 | 294 | TEST_F(BugreportTest, OkNoExtension) { |
221 | - SetBugreportzVersion("1.1"); | |
295 | + ExpectBugreportzVersion("1.1"); | |
222 | 296 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
223 | 297 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")), |
224 | 298 | WithArg<4>(ReturnCallbackDone()))); |
225 | 299 | EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"), |
226 | - true, HasSubstr("file.zip"))) | |
300 | + true, StrEq("generating file.zip"))) | |
227 | 301 | .WillOnce(Return(true)); |
228 | 302 | |
229 | 303 | const char* args[1024] = {"bugreport", "file"}; |
230 | 304 | ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args)); |
231 | 305 | } |
232 | 306 | |
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 | + | |
233 | 326 | // Tests 'adb bugreport file.zip' when the bugreport itself failed |
234 | 327 | TEST_F(BugreportTest, BugreportzReturnedFail) { |
235 | - SetBugreportzVersion("1.1"); | |
328 | + ExpectBugreportzVersion("1.1"); | |
236 | 329 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
237 | 330 | .WillOnce( |
238 | 331 | DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<4>(ReturnCallbackDone()))); |
@@ -247,7 +340,7 @@ TEST_F(BugreportTest, BugreportzReturnedFail) { | ||
247 | 340 | // was sent in |
248 | 341 | // multiple buffer writes |
249 | 342 | TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) { |
250 | - SetBugreportzVersion("1.1"); | |
343 | + ExpectBugreportzVersion("1.1"); | |
251 | 344 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
252 | 345 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")), |
253 | 346 | WithArg<4>(ReturnCallbackDone()))); |
@@ -261,7 +354,7 @@ TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) { | ||
261 | 354 | // Tests 'adb bugreport file.zip' when the bugreportz returned an unsupported |
262 | 355 | // response. |
263 | 356 | TEST_F(BugreportTest, BugreportzReturnedUnsupported) { |
264 | - SetBugreportzVersion("1.1"); | |
357 | + ExpectBugreportzVersion("1.1"); | |
265 | 358 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
266 | 359 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")), |
267 | 360 | WithArg<4>(ReturnCallbackDone()))); |
@@ -283,7 +376,7 @@ TEST_F(BugreportTest, BugreportzVersionFailed) { | ||
283 | 376 | |
284 | 377 | // Tests 'adb bugreport file.zip' when the bugreportz -v returns status 0 but with no output. |
285 | 378 | TEST_F(BugreportTest, BugreportzVersionEmpty) { |
286 | - SetBugreportzVersion(""); | |
379 | + ExpectBugreportzVersion(""); | |
287 | 380 | |
288 | 381 | const char* args[1024] = {"bugreport", "file.zip"}; |
289 | 382 | ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args)); |
@@ -291,7 +384,7 @@ TEST_F(BugreportTest, BugreportzVersionEmpty) { | ||
291 | 384 | |
292 | 385 | // Tests 'adb bugreport file.zip' when the main bugreportz command failed |
293 | 386 | TEST_F(BugreportTest, BugreportzFailed) { |
294 | - SetBugreportzVersion("1.1"); | |
387 | + ExpectBugreportzVersion("1.1"); | |
295 | 388 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
296 | 389 | .WillOnce(Return(666)); |
297 | 390 |
@@ -301,7 +394,7 @@ TEST_F(BugreportTest, BugreportzFailed) { | ||
301 | 394 | |
302 | 395 | // Tests 'adb bugreport file.zip' when the bugreport could not be pulled |
303 | 396 | TEST_F(BugreportTest, PullFails) { |
304 | - SetBugreportzVersion("1.1"); | |
397 | + ExpectBugreportzVersion("1.1"); | |
305 | 398 | EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _)) |
306 | 399 | .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")), |
307 | 400 | WithArg<4>(ReturnCallbackDone()))); |
@@ -81,6 +81,7 @@ static std::string product_file(const char *extra) { | ||
81 | 81 | |
82 | 82 | static void help() { |
83 | 83 | fprintf(stderr, "%s\n", adb_version().c_str()); |
84 | + // clang-format off | |
84 | 85 | fprintf(stderr, |
85 | 86 | " -a - directs adb to listen on all interfaces for a connection\n" |
86 | 87 | " -d - directs command to the only connected USB device\n" |
@@ -173,9 +174,11 @@ static void help() { | ||
173 | 174 | " (-g: grant all runtime permissions)\n" |
174 | 175 | " adb uninstall [-k] <package> - remove this app package from the device\n" |
175 | 176 | " ('-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" | |
179 | 182 | " adb backup [-f <file>] [-apk|-noapk] [-obb|-noobb] [-shared|-noshared] [-all] [-system|-nosystem] [<packages...>]\n" |
180 | 183 | " - write an archive of the device's data to <file>.\n" |
181 | 184 | " If no -f option is supplied then the data is written\n" |
@@ -249,8 +252,8 @@ static void help() { | ||
249 | 252 | " ADB_TRACE - Print debug information. A comma separated list of the following values\n" |
250 | 253 | " 1 or all, adb, sockets, packets, rwx, usb, sync, sysdeps, transport, jdwp\n" |
251 | 254 | " 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 | |
254 | 257 | } |
255 | 258 | |
256 | 259 | int usage() { |
@@ -1327,7 +1330,7 @@ static std::string find_product_out_path(const std::string& hint) { | ||
1327 | 1330 | if (hint.find_first_of(OS_PATH_SEPARATORS) != std::string::npos) { |
1328 | 1331 | std::string cwd; |
1329 | 1332 | if (!getcwd(&cwd)) { |
1330 | - fprintf(stderr, "adb: getcwd failed: %s\n", strerror(errno)); | |
1333 | + perror("adb: getcwd failed"); | |
1331 | 1334 | return ""; |
1332 | 1335 | } |
1333 | 1336 | return android::base::StringPrintf("%s%c%s", cwd.c_str(), OS_PATH_SEPARATOR, hint.c_str()); |