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(GetManufacturer
, bool(base::string16
* manufacturer
));
94 MOCK_METHOD1(GetProduct
, bool(base::string16
* product
));
95 MOCK_METHOD1(GetSerial
, bool(base::string16
* serial
));
97 virtual scoped_refptr
<UsbDevice
> GetDevice() const OVERRIDE
{
101 void set_device(UsbDevice
* device
) { device_
= device
; }
106 virtual ~MockUsbDeviceHandle() {}
109 class MockUsbConfigDescriptor
: public UsbConfigDescriptor
{
111 MOCK_CONST_METHOD0(GetNumInterfaces
, size_t());
112 MOCK_CONST_METHOD1(GetInterface
,
113 scoped_refptr
<const UsbInterfaceDescriptor
>(size_t index
));
116 virtual ~MockUsbConfigDescriptor() {}
119 class MockUsbDevice
: public UsbDevice
{
121 explicit MockUsbDevice(MockUsbDeviceHandle
* mock_handle
)
122 : UsbDevice(0, 0, 0), mock_handle_(mock_handle
) {
123 mock_handle
->set_device(this);
126 virtual scoped_refptr
<UsbDeviceHandle
> Open() OVERRIDE
{
130 virtual bool Close(scoped_refptr
<UsbDeviceHandle
> handle
) OVERRIDE
{
131 EXPECT_TRUE(false) << "Should not be reached";
135 #if defined(OS_CHROMEOS)
136 virtual void RequestUsbAccess(
138 const base::Callback
<void(bool success
)>& callback
) OVERRIDE
{
139 BrowserThread::PostTask(
140 BrowserThread::FILE, FROM_HERE
, base::Bind(callback
, true));
142 #endif // OS_CHROMEOS
144 MOCK_METHOD0(ListInterfaces
, scoped_refptr
<UsbConfigDescriptor
>());
147 MockUsbDeviceHandle
* mock_handle_
;
148 virtual ~MockUsbDevice() {}
151 class MockUsbService
: public UsbService
{
153 explicit MockUsbService(scoped_refptr
<UsbDevice
> device
) : device_(device
) {}
156 virtual scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) OVERRIDE
{
157 EXPECT_EQ(unique_id
, 0U);
161 virtual void GetDevices(
162 std::vector
<scoped_refptr
<UsbDevice
> >* devices
) OVERRIDE
{
163 STLClearObject(devices
);
164 devices
->push_back(device_
);
167 scoped_refptr
<UsbDevice
> device_
;
174 class UsbApiTest
: public ExtensionApiTest
{
176 virtual void SetUpOnMainThread() OVERRIDE
{
177 mock_device_handle_
= new MockUsbDeviceHandle();
178 mock_device_
= new MockUsbDevice(mock_device_handle_
.get());
179 scoped_refptr
<content::MessageLoopRunner
> runner
=
180 new content::MessageLoopRunner
;
181 BrowserThread::PostTaskAndReply(BrowserThread::FILE,
183 base::Bind(&UsbApiTest::SetUpService
, this),
184 runner
->QuitClosure());
188 void SetUpService() {
189 UsbService::SetInstanceForTest(new MockUsbService(mock_device_
));
192 virtual void TearDownOnMainThread() OVERRIDE
{
193 scoped_refptr
<content::MessageLoopRunner
> runner
=
194 new content::MessageLoopRunner
;
195 UsbService
* service
= NULL
;
196 BrowserThread::PostTaskAndReply(
199 base::Bind(&UsbService::SetInstanceForTest
, service
),
200 runner
->QuitClosure());
205 scoped_refptr
<MockUsbDeviceHandle
> mock_device_handle_
;
206 scoped_refptr
<MockUsbDevice
> mock_device_
;
211 IN_PROC_BROWSER_TEST_F(UsbApiTest
, DeviceHandling
) {
212 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(4);
213 ASSERT_TRUE(RunExtensionTest("usb/device_handling"));
216 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ResetDevice
) {
217 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(2);
218 EXPECT_CALL(*mock_device_handle_
.get(), ResetDevice())
219 .WillOnce(Return(true))
220 .WillOnce(Return(false));
222 *mock_device_handle_
.get(),
223 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
225 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
226 ASSERT_TRUE(RunExtensionTest("usb/reset_device"));
229 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ListInterfaces
) {
230 scoped_refptr
<MockUsbConfigDescriptor
> mock_descriptor
=
231 new MockUsbConfigDescriptor();
232 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
233 EXPECT_CALL(*mock_descriptor
.get(), GetNumInterfaces()).WillOnce(Return(0));
234 EXPECT_CALL(*mock_device_
.get(), ListInterfaces())
235 .WillOnce(Return(mock_descriptor
));
236 ASSERT_TRUE(RunExtensionTest("usb/list_interfaces"));
239 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferEvent
) {
240 EXPECT_CALL(*mock_device_handle_
.get(),
241 ControlTransfer(usb_service::USB_DIRECTION_OUTBOUND
,
242 UsbDeviceHandle::STANDARD
,
243 UsbDeviceHandle::DEVICE
,
252 InvokeUsbTransferCallback
<9>(usb_service::USB_TRANSFER_COMPLETED
));
253 EXPECT_CALL(*mock_device_handle_
.get(),
254 BulkTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 1, _
, 1, _
, _
))
256 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
258 *mock_device_handle_
.get(),
259 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND
, 2, _
, 1, _
, _
))
261 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
262 EXPECT_CALL(*mock_device_handle_
.get(),
264 usb_service::USB_DIRECTION_OUTBOUND
, 3, _
, 1, 1, 1, _
, _
))
266 InvokeUsbTransferCallback
<7>(usb_service::USB_TRANSFER_COMPLETED
));
267 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
268 ASSERT_TRUE(RunExtensionTest("usb/transfer_event"));
271 IN_PROC_BROWSER_TEST_F(UsbApiTest
, ZeroLengthTransfer
) {
272 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, 0, _
, _
))
274 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
));
275 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
276 ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer"));
279 IN_PROC_BROWSER_TEST_F(UsbApiTest
, TransferFailure
) {
280 EXPECT_CALL(*mock_device_handle_
.get(), BulkTransfer(_
, _
, _
, _
, _
, _
))
282 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_COMPLETED
))
283 .WillOnce(InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_ERROR
))
285 InvokeUsbTransferCallback
<5>(usb_service::USB_TRANSFER_TIMEOUT
));
286 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
287 ASSERT_TRUE(RunExtensionTest("usb/transfer_failure"));
290 IN_PROC_BROWSER_TEST_F(UsbApiTest
, InvalidLengthTransfer
) {
291 EXPECT_CALL(*mock_device_handle_
.get(), Close()).Times(AnyNumber());
292 ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer"));