1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/extension_apitest.h"
6 #include "chrome/browser/ui/browser.h"
7 #include "components/usb_service/usb_service.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/test/test_utils.h"
10 #include "extensions/browser/api/usb/usb_api.h"
11 #include "net/base/io_buffer.h"
12 #include "testing/gmock/include/gmock/gmock.h"
14 using testing::AnyNumber
;
16 using testing::Return
;
17 using content::BrowserThread
;
18 using usb_service::UsbConfigDescriptor
;
19 using usb_service::UsbDevice
;
20 using usb_service::UsbDeviceHandle
;
21 using usb_service::UsbEndpointDirection
;
22 using usb_service::UsbInterfaceDescriptor
;
23 using usb_service::UsbService
;
24 using usb_service::UsbTransferCallback
;
28 ACTION_TEMPLATE(InvokeUsbTransferCallback
,
29 HAS_1_TEMPLATE_PARAMS(int, k
),
30 AND_1_VALUE_PARAMS(p1
)) {
31 net::IOBuffer
* io_buffer
= new net::IOBuffer(1);
32 memset(io_buffer
->data(), 0, 1); // Avoid uninitialized reads.
33 ::std::tr1::get
<k
>(args
).Run(p1
, io_buffer
, 1);
36 // MSVC erroneously thinks that at least one of the arguments for the transfer
37 // methods differ by const or volatility and emits a warning about the old
38 // standards-noncompliant behaviour of their compiler.
41 #pragma warning(disable : 4373)
44 class MockUsbDeviceHandle
: public UsbDeviceHandle
{
46 MockUsbDeviceHandle() : UsbDeviceHandle() {}
48 MOCK_METHOD0(Close
, void());
50 MOCK_METHOD10(ControlTransfer
,
51 void(const UsbEndpointDirection direction
,
52 const TransferRequestType request_type
,
53 const TransferRecipient recipient
,
57 net::IOBuffer
* buffer
,
59 const unsigned int timeout
,
60 const UsbTransferCallback
& callback
));
62 MOCK_METHOD6(BulkTransfer
,
63 void(const UsbEndpointDirection direction
,
65 net::IOBuffer
* buffer
,
67 const unsigned int timeout
,
68 const UsbTransferCallback
& callback
));
70 MOCK_METHOD6(InterruptTransfer
,
71 void(const UsbEndpointDirection direction
,
73 net::IOBuffer
* buffer
,
75 const unsigned int timeout
,
76 const UsbTransferCallback
& callback
));
78 MOCK_METHOD8(IsochronousTransfer
,
79 void(const UsbEndpointDirection direction
,
81 net::IOBuffer
* buffer
,
83 const unsigned int packets
,
84 const unsigned int packet_length
,
85 const unsigned int timeout
,
86 const UsbTransferCallback
& callback
));
88 MOCK_METHOD0(ResetDevice
, bool());
89 MOCK_METHOD1(ClaimInterface
, bool(const int interface_number
));
90 MOCK_METHOD1(ReleaseInterface
, bool(const int interface_number
));
91 MOCK_METHOD2(SetInterfaceAlternateSetting
,
92 bool(const int interface_number
, const int alternate_setting
));
93 MOCK_METHOD1(GetSerial
, bool(base::string16
* serial
));
95 virtual scoped_refptr
<UsbDevice
> GetDevice() const OVERRIDE
{
99 void set_device(UsbDevice
* device
) { device_
= device
; }
104 virtual ~MockUsbDeviceHandle() {}
107 class MockUsbConfigDescriptor
: public UsbConfigDescriptor
{
109 MOCK_CONST_METHOD0(GetNumInterfaces
, size_t());
110 MOCK_CONST_METHOD1(GetInterface
,
111 scoped_refptr
<const UsbInterfaceDescriptor
>(size_t index
));
114 virtual ~MockUsbConfigDescriptor() {}
117 class MockUsbDevice
: public UsbDevice
{
119 explicit MockUsbDevice(MockUsbDeviceHandle
* mock_handle
)
120 : UsbDevice(0, 0, 0), mock_handle_(mock_handle
) {
121 mock_handle
->set_device(this);
124 virtual scoped_refptr
<UsbDeviceHandle
> Open() OVERRIDE
{
128 virtual bool Close(scoped_refptr
<UsbDeviceHandle
> handle
) OVERRIDE
{
129 EXPECT_TRUE(false) << "Should not be reached";
133 #if defined(OS_CHROMEOS)
134 virtual void RequestUsbAcess(
136 const base::Callback
<void(bool success
)>& callback
) OVERRIDE
{
137 BrowserThread::PostTask(
138 BrowserThread::FILE, FROM_HERE
, base::Bind(callback
, true));
140 #endif // OS_CHROMEOS
142 MOCK_METHOD0(ListInterfaces
, scoped_refptr
<UsbConfigDescriptor
>());
145 MockUsbDeviceHandle
* mock_handle_
;
146 virtual ~MockUsbDevice() {}
149 class MockUsbService
: public UsbService
{
151 explicit MockUsbService(scoped_refptr
<UsbDevice
> device
) : device_(device
) {}
154 virtual scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) OVERRIDE
{
155 EXPECT_EQ(unique_id
, 0U);
159 virtual void GetDevices(
160 std::vector
<scoped_refptr
<UsbDevice
> >* devices
) OVERRIDE
{
161 STLClearObject(devices
);
162 devices
->push_back(device_
);
165 scoped_refptr
<UsbDevice
> device_
;
172 class UsbApiTest
: public ExtensionApiTest
{
174 virtual void SetUpOnMainThread() OVERRIDE
{
175 mock_device_handle_
= new MockUsbDeviceHandle();
176 mock_device_
= new MockUsbDevice(mock_device_handle_
.get());
177 scoped_refptr
<content::MessageLoopRunner
> runner
=
178 new content::MessageLoopRunner
;
179 BrowserThread::PostTaskAndReply(BrowserThread::FILE,
181 base::Bind(&UsbApiTest::SetUpService
, this),
182 runner
->QuitClosure());
186 void SetUpService() {
187 UsbService::SetInstanceForTest(new MockUsbService(mock_device_
));
190 virtual void CleanUpOnMainThread() OVERRIDE
{
191 scoped_refptr
<content::MessageLoopRunner
> runner
=
192 new content::MessageLoopRunner
;
193 UsbService
* service
= NULL
;
194 BrowserThread::PostTaskAndReply(
197 base::Bind(&UsbService::SetInstanceForTest
, service
),
198 runner
->QuitClosure());
203 scoped_refptr
<MockUsbDeviceHandle
> mock_device_handle_
;
204 scoped_refptr
<MockUsbDevice
> mock_device_
;
209 IN_PROC_BROWSER_TEST_F(UsbApiTest
, DeviceHandling
) {
210 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(4);
211 ASSERT_TRUE(RunExtensionTest("usb/device_handling"));
214 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ResetDevice
) {
215 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(2);
216 EXPECT_CALL(*mock_device_handle_
.get(), ResetDevice())
217 .WillOnce(Return(true))
218 .WillOnce(Return(false));
220 *mock_device_handle_
.get(),
221 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
223 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
224 ASSERT_TRUE(RunExtensionTest("usb/reset_device"));
227 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ListInterfaces
) {
228 scoped_refptr
<MockUsbConfigDescriptor
> mock_descriptor
=
229 new MockUsbConfigDescriptor();
230 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
231 EXPECT_CALL(*mock_descriptor
.get(), GetNumInterfaces()).WillOnce(Return(0));
232 EXPECT_CALL(*mock_device_
.get(), ListInterfaces())
233 .WillOnce(Return(mock_descriptor
));
234 ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
237 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferEvent
) {
238 EXPECT_CALL(*mock_device_handle_
.get(),
239 ControlTransfer(usb_service::USB_DIRECTION_OUTBOUND
,
240 UsbDeviceHandle::STANDARD
,
241 UsbDeviceHandle::DEVICE
,
250 InvokeUsbTransferCallback
<9>(usb_service::USB_TRANSFER_COMPLETED
));
251 EXPECT_CALL(*mock_device_handle_
.get(),
252 BulkTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 1, _
, 1, _
, _
))
254 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
256 *mock_device_handle_
.get(),
257 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
259 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
260 EXPECT_CALL(*mock_device_handle_
.get(),
262 usb_service::USB_DIRECTION_OUTBOUND
, 3, _
, 1, 1, 1, _
, _
))
264 InvokeUsbTransferCallback
<7>(usb_service::USB_TRANSFER_COMPLETED
));
265 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
266 ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
269 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ZeroLengthTransfer
) {
270 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, 0, _
, _
))
272 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
273 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
274 ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
277 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferFailure
) {
278 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, _
, _
, _
))
280 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
))
281 .WillOnce(InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_ERROR
))
283 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_TIMEOUT
));
284 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
285 ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
288 IN_PROC_BROWSER_TEST_F(UsbApiTest
, InvalidLengthTransfer
) {
289 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
290 ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));