blob: a89d8dc7be3c8ae4b423fc026c112c047a66aeba [file] [log] [blame]
Felipe Leme042c3512016-07-19 17:07:22 -07001/*
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 "bugreport.h"
18
19#include <gmock/gmock.h>
20#include <gtest/gtest.h>
21
22using ::testing::_;
Felipe Leme60192aa2016-07-26 12:14:39 -070023using ::testing::Action;
24using ::testing::ActionInterface;
Felipe Leme042c3512016-07-19 17:07:22 -070025using ::testing::DoAll;
26using ::testing::ElementsAre;
27using ::testing::HasSubstr;
Felipe Leme60192aa2016-07-26 12:14:39 -070028using ::testing::MakeAction;
Felipe Leme042c3512016-07-19 17:07:22 -070029using ::testing::Return;
Felipe Leme042c3512016-07-19 17:07:22 -070030using ::testing::StrEq;
Felipe Leme60192aa2016-07-26 12:14:39 -070031using ::testing::WithArg;
Felipe Leme042c3512016-07-19 17:07:22 -070032using ::testing::internal::CaptureStderr;
33using ::testing::internal::GetCapturedStderr;
34
Felipe Leme60192aa2016-07-26 12:14:39 -070035// Empty function so tests don't need to be linked against file_sync_service.cpp, which requires
Felipe Leme042c3512016-07-19 17:07:22 -070036// SELinux and its transitive dependencies...
37bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
38 const char* name) {
39 ADD_FAILURE() << "do_sync_pull() should have been mocked";
40 return false;
41}
42
Felipe Leme60192aa2016-07-26 12:14:39 -070043// Empty functions so tests don't need to be linked against commandline.cpp
44DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK(nullptr, nullptr);
Felipe Leme042c3512016-07-19 17:07:22 -070045int usage() {
46 return -42;
47}
Felipe Leme042c3512016-07-19 17:07:22 -070048int send_shell_command(TransportType transport_type, const char* serial, const std::string& command,
Felipe Leme60192aa2016-07-26 12:14:39 -070049 bool disable_shell_protocol, StandardStreamsCallbackInterface* callback) {
Felipe Leme042c3512016-07-19 17:07:22 -070050 ADD_FAILURE() << "send_shell_command() should have been mocked";
51 return -42;
52}
53
Felipe Lemee53b12b2016-07-26 12:23:40 -070054enum StreamType {
55 kStreamStdout,
56 kStreamStderr,
57};
58
Felipe Leme60192aa2016-07-26 12:14:39 -070059// gmock black magic to provide a WithArg<4>(WriteOnStdout(output)) matcher
60typedef void OnStandardStreamsCallbackFunction(StandardStreamsCallbackInterface*);
61
62class OnStandardStreamsCallbackAction : public ActionInterface<OnStandardStreamsCallbackFunction> {
63 public:
Felipe Lemee53b12b2016-07-26 12:23:40 -070064 explicit OnStandardStreamsCallbackAction(StreamType type, const std::string& output)
65 : type_(type), output_(output) {
Felipe Leme60192aa2016-07-26 12:14:39 -070066 }
67 virtual Result Perform(const ArgumentTuple& args) {
Felipe Lemee53b12b2016-07-26 12:23:40 -070068 if (type_ == kStreamStdout) {
69 ::std::tr1::get<0>(args)->OnStdout(output_.c_str(), output_.size());
70 }
71 if (type_ == kStreamStderr) {
72 ::std::tr1::get<0>(args)->OnStderr(output_.c_str(), output_.size());
73 }
Felipe Leme60192aa2016-07-26 12:14:39 -070074 }
75
76 private:
Felipe Lemee53b12b2016-07-26 12:23:40 -070077 StreamType type_;
Felipe Leme60192aa2016-07-26 12:14:39 -070078 std::string output_;
79};
80
Felipe Lemee53b12b2016-07-26 12:23:40 -070081// Matcher used to emulated StandardStreamsCallbackInterface.OnStdout(buffer,
82// length)
Felipe Leme60192aa2016-07-26 12:14:39 -070083Action<OnStandardStreamsCallbackFunction> WriteOnStdout(const std::string& output) {
Felipe Lemee53b12b2016-07-26 12:23:40 -070084 return MakeAction(new OnStandardStreamsCallbackAction(kStreamStdout, output));
85}
86
87// Matcher used to emulated StandardStreamsCallbackInterface.OnStderr(buffer,
88// length)
89Action<OnStandardStreamsCallbackFunction> WriteOnStderr(const std::string& output) {
90 return MakeAction(new OnStandardStreamsCallbackAction(kStreamStderr, output));
Felipe Leme60192aa2016-07-26 12:14:39 -070091}
92
93typedef int CallbackDoneFunction(StandardStreamsCallbackInterface*);
94
95class CallbackDoneAction : public ActionInterface<CallbackDoneFunction> {
96 public:
Felipe Lemee53b12b2016-07-26 12:23:40 -070097 explicit CallbackDoneAction(int status) : status_(status) {
98 }
Felipe Leme60192aa2016-07-26 12:14:39 -070099 virtual Result Perform(const ArgumentTuple& args) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700100 int status = ::std::tr1::get<0>(args)->Done(status_);
Felipe Leme60192aa2016-07-26 12:14:39 -0700101 return status;
102 }
Felipe Lemee53b12b2016-07-26 12:23:40 -0700103
104 private:
105 int status_;
Felipe Leme60192aa2016-07-26 12:14:39 -0700106};
107
Felipe Lemee53b12b2016-07-26 12:23:40 -0700108// Matcher used to emulated StandardStreamsCallbackInterface.Done(status)
109Action<CallbackDoneFunction> ReturnCallbackDone(int status = -1337) {
110 return MakeAction(new CallbackDoneAction(status));
Felipe Leme60192aa2016-07-26 12:14:39 -0700111}
112
Felipe Leme042c3512016-07-19 17:07:22 -0700113class BugreportMock : public Bugreport {
114 public:
Felipe Leme60192aa2016-07-26 12:14:39 -0700115 MOCK_METHOD5(SendShellCommand,
Felipe Leme042c3512016-07-19 17:07:22 -0700116 int(TransportType transport_type, const char* serial, const std::string& command,
Felipe Leme60192aa2016-07-26 12:14:39 -0700117 bool disable_shell_protocol, StandardStreamsCallbackInterface* callback));
Felipe Leme042c3512016-07-19 17:07:22 -0700118 MOCK_METHOD4(DoSyncPull, bool(const std::vector<const char*>& srcs, const char* dst,
119 bool copy_attrs, const char* name));
Felipe Leme954af842016-07-27 19:23:09 -0700120 MOCK_METHOD3(UpdateProgress, void(const std::string&, int, int));
Felipe Leme042c3512016-07-19 17:07:22 -0700121};
122
123class BugreportTest : public ::testing::Test {
124 public:
Felipe Lemee53b12b2016-07-26 12:23:40 -0700125 void SetBugreportzVersion(const std::string& version) {
126 EXPECT_CALL(br_,
127 SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
128 .WillOnce(DoAll(WithArg<4>(WriteOnStderr(version.c_str())),
129 WithArg<4>(ReturnCallbackDone(0))));
130 }
131
Felipe Leme954af842016-07-27 19:23:09 -0700132 void ExpectProgress(int progress, int total) {
133 EXPECT_CALL(br_, UpdateProgress(HasSubstr("file.zip"), progress, total));
Felipe Lemee53b12b2016-07-26 12:23:40 -0700134 }
135
Felipe Leme042c3512016-07-19 17:07:22 -0700136 BugreportMock br_;
137};
138
139// Tests when called with invalid number of argumnts
140TEST_F(BugreportTest, InvalidNumberArgs) {
141 const char* args[1024] = {"bugreport", "to", "principal"};
142 ASSERT_EQ(-42, br_.DoIt(kTransportLocal, "HannibalLecter", 3, args));
143}
144
145// Tests the legacy 'adb bugreport' option
146TEST_F(BugreportTest, FlatFileFormat) {
Felipe Leme60192aa2016-07-26 12:14:39 -0700147 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreport", false, _))
Felipe Leme042c3512016-07-19 17:07:22 -0700148 .WillOnce(Return(0));
149
150 const char* args[1024] = {"bugreport"};
151 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 1, args));
152}
153
Felipe Lemee53b12b2016-07-26 12:23:40 -0700154// Tests 'adb bugreport file.zip' when it succeeds and device does not support
155// progress.
156TEST_F(BugreportTest, OkLegacy) {
157 SetBugreportzVersion("1.0");
Felipe Leme60192aa2016-07-26 12:14:39 -0700158 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
159 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
160 WithArg<4>(ReturnCallbackDone())));
Felipe Leme042c3512016-07-19 17:07:22 -0700161 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
Felipe Leme954af842016-07-27 19:23:09 -0700162 true, HasSubstr("file.zip")))
Felipe Leme042c3512016-07-19 17:07:22 -0700163 .WillOnce(Return(true));
164
165 const char* args[1024] = {"bugreport", "file.zip"};
166 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
167}
168
Felipe Leme60192aa2016-07-26 12:14:39 -0700169// Tests 'adb bugreport file.zip' when it succeeds but response was sent in
Felipe Lemee53b12b2016-07-26 12:23:40 -0700170// multiple buffer writers and without progress updates.
171TEST_F(BugreportTest, OkLegacySplitBuffer) {
172 SetBugreportzVersion("1.0");
Felipe Leme60192aa2016-07-26 12:14:39 -0700173 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz", false, _))
174 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device")),
175 WithArg<4>(WriteOnStdout("/bugreport.zip")),
176 WithArg<4>(ReturnCallbackDone())));
177 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
Felipe Leme954af842016-07-27 19:23:09 -0700178 true, HasSubstr("file.zip")))
Felipe Leme60192aa2016-07-26 12:14:39 -0700179 .WillOnce(Return(true));
180
181 const char* args[1024] = {"bugreport", "file.zip"};
182 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
183}
184
Felipe Lemee53b12b2016-07-26 12:23:40 -0700185// Tests 'adb bugreport file.zip' when it succeeds and displays progress.
186TEST_F(BugreportTest, Ok) {
187 SetBugreportzVersion("1.1");
188 ExpectProgress(1, 100);
189 ExpectProgress(10, 100);
190 ExpectProgress(50, 100);
191 ExpectProgress(99, 100);
Felipe Leme954af842016-07-27 19:23:09 -0700192 ExpectProgress(100, 100);
Felipe Lemee53b12b2016-07-26 12:23:40 -0700193 // clang-format off
194 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
195 .WillOnce(DoAll(
196 // Progress line in one write
197 WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")),
198 // Add some bogus lines
199 WithArg<4>(WriteOnStdout("\nDUDE:SWEET\n\n")),
200 // Multiple progress lines in one write
201 WithArg<4>(WriteOnStdout("PROGRESS:10/100\nPROGRESS:50/100\n")),
202 // Progress line in multiple writes
203 WithArg<4>(WriteOnStdout("PROG")),
204 WithArg<4>(WriteOnStdout("RESS:99")),
205 WithArg<4>(WriteOnStdout("/100\n")),
206 // Split last message as well, just in case
207 WithArg<4>(WriteOnStdout("OK:/device/bugreport")),
208 WithArg<4>(WriteOnStdout(".zip")),
209 WithArg<4>(ReturnCallbackDone())));
210 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
Felipe Leme954af842016-07-27 19:23:09 -0700211 true, HasSubstr("file.zip")))
Felipe Lemee53b12b2016-07-26 12:23:40 -0700212 .WillOnce(Return(true));
213
214 const char* args[1024] = {"bugreport", "file.zip"};
215 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
216}
217
218// Tests 'adb bugreport file' when it succeeds
219TEST_F(BugreportTest, OkNoExtension) {
220 SetBugreportzVersion("1.1");
Felipe Leme954af842016-07-27 19:23:09 -0700221 ExpectProgress(100, 100);
Felipe Lemee53b12b2016-07-26 12:23:40 -0700222 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
223 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip\n")),
224 WithArg<4>(ReturnCallbackDone())));
225 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
Felipe Leme954af842016-07-27 19:23:09 -0700226 true, HasSubstr("file.zip")))
Felipe Lemee53b12b2016-07-26 12:23:40 -0700227 .WillOnce(Return(true));
228
229 const char* args[1024] = {"bugreport", "file"};
230 ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
231}
232
Felipe Leme042c3512016-07-19 17:07:22 -0700233// Tests 'adb bugreport file.zip' when the bugreport itself failed
234TEST_F(BugreportTest, BugreportzReturnedFail) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700235 SetBugreportzVersion("1.1");
236 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
237 .WillOnce(
238 DoAll(WithArg<4>(WriteOnStdout("FAIL:D'OH!\n")), WithArg<4>(ReturnCallbackDone())));
Felipe Leme60192aa2016-07-26 12:14:39 -0700239
240 CaptureStderr();
241 const char* args[1024] = {"bugreport", "file.zip"};
242 ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
Felipe Lemee53b12b2016-07-26 12:23:40 -0700243 ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
Felipe Leme60192aa2016-07-26 12:14:39 -0700244}
245
246// Tests 'adb bugreport file.zip' when the bugreport itself failed but response
247// was sent in
248// multiple buffer writes
249TEST_F(BugreportTest, BugreportzReturnedFailSplitBuffer) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700250 SetBugreportzVersion("1.1");
251 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
252 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("FAIL")), WithArg<4>(WriteOnStdout(":D'OH!\n")),
Felipe Leme60192aa2016-07-26 12:14:39 -0700253 WithArg<4>(ReturnCallbackDone())));
Felipe Leme042c3512016-07-19 17:07:22 -0700254
255 CaptureStderr();
256 const char* args[1024] = {"bugreport", "file.zip"};
257 ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
Felipe Lemee53b12b2016-07-26 12:23:40 -0700258 ASSERT_THAT(GetCapturedStderr(), HasSubstr("D'OH!"));
Felipe Leme042c3512016-07-19 17:07:22 -0700259}
260
261// Tests 'adb bugreport file.zip' when the bugreportz returned an unsupported
262// response.
263TEST_F(BugreportTest, BugreportzReturnedUnsupported) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700264 SetBugreportzVersion("1.1");
265 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
Felipe Leme60192aa2016-07-26 12:14:39 -0700266 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("bugreportz? What am I, a zombie?")),
267 WithArg<4>(ReturnCallbackDone())));
Felipe Leme042c3512016-07-19 17:07:22 -0700268
269 CaptureStderr();
270 const char* args[1024] = {"bugreport", "file.zip"};
271 ASSERT_EQ(-1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
272 ASSERT_THAT(GetCapturedStderr(), HasSubstr("bugreportz? What am I, a zombie?"));
273}
274
Felipe Lemee53b12b2016-07-26 12:23:40 -0700275// Tests 'adb bugreport file.zip' when the bugreportz -v command failed
276TEST_F(BugreportTest, BugreportzVersionFailed) {
277 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -v", false, _))
278 .WillOnce(Return(666));
279
280 const char* args[1024] = {"bugreport", "file.zip"};
281 ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
282}
283
284// Tests 'adb bugreport file.zip' when the main bugreportz command failed
Felipe Leme042c3512016-07-19 17:07:22 -0700285TEST_F(BugreportTest, BugreportzFailed) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700286 SetBugreportzVersion("1.1");
287 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
Felipe Leme042c3512016-07-19 17:07:22 -0700288 .WillOnce(Return(666));
289
290 const char* args[1024] = {"bugreport", "file.zip"};
291 ASSERT_EQ(666, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
292}
293
294// Tests 'adb bugreport file.zip' when the bugreport could not be pulled
295TEST_F(BugreportTest, PullFails) {
Felipe Lemee53b12b2016-07-26 12:23:40 -0700296 SetBugreportzVersion("1.1");
Felipe Leme954af842016-07-27 19:23:09 -0700297 ExpectProgress(100, 100);
Felipe Lemee53b12b2016-07-26 12:23:40 -0700298 EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
Felipe Leme60192aa2016-07-26 12:14:39 -0700299 .WillOnce(DoAll(WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
300 WithArg<4>(ReturnCallbackDone())));
Felipe Leme042c3512016-07-19 17:07:22 -0700301 EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
Felipe Leme954af842016-07-27 19:23:09 -0700302 true, HasSubstr("file.zip")))
Felipe Leme042c3512016-07-19 17:07:22 -0700303 .WillOnce(Return(false));
304
305 const char* args[1024] = {"bugreport", "file.zip"};
306 ASSERT_EQ(1, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
307}