| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/api/usb/usb_api.h" |
| #include "chrome/browser/extensions/extension_apitest.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "net/base/io_buffer.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| |
| using testing::AnyNumber; |
| using testing::_; |
| using testing::Return; |
| using content::BrowserThread; |
| |
| namespace { |
| |
| ACTION_TEMPLATE(InvokeUsbTransferCallback, |
| HAS_1_TEMPLATE_PARAMS(int, k), |
| AND_1_VALUE_PARAMS(p1)) { |
| ::std::tr1::get<k>(args).Run(p1, new net::IOBuffer(1), 1); |
| } |
| |
| // MSVC erroneously thinks that at least one of the arguments for the transfer |
| // methods differ by const or volatility and emits a warning about the old |
| // standards-noncompliant behaviour of their compiler. |
| #if defined(OS_WIN) |
| #pragma warning(push) |
| #pragma warning(disable:4373) |
| #endif |
| |
| class MockUsbDeviceHandle : public UsbDeviceHandle { |
| public: |
| MockUsbDeviceHandle() : UsbDeviceHandle() {} |
| |
| MOCK_METHOD0(Close, void()); |
| |
| MOCK_METHOD10(ControlTransfer, void(const UsbEndpointDirection direction, |
| const TransferRequestType request_type, const TransferRecipient recipient, |
| const uint8 request, const uint16 value, const uint16 index, |
| net::IOBuffer* buffer, const size_t length, const unsigned int timeout, |
| const UsbTransferCallback& callback)); |
| |
| MOCK_METHOD6(BulkTransfer, void(const UsbEndpointDirection direction, |
| const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| const unsigned int timeout, const UsbTransferCallback& callback)); |
| |
| MOCK_METHOD6(InterruptTransfer, void(const UsbEndpointDirection direction, |
| const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| const unsigned int timeout, const UsbTransferCallback& callback)); |
| |
| MOCK_METHOD8(IsochronousTransfer, void(const UsbEndpointDirection direction, |
| const uint8 endpoint, net::IOBuffer* buffer, const size_t length, |
| const unsigned int packets, const unsigned int packet_length, |
| const unsigned int timeout, const UsbTransferCallback& callback)); |
| |
| MOCK_METHOD0(ResetDevice, bool()); |
| |
| void set_device(UsbDevice* device) { device_ = device; } |
| |
| protected: |
| virtual ~MockUsbDeviceHandle() {} |
| }; |
| |
| class MockUsbDevice : public UsbDevice { |
| public: |
| explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle) |
| : UsbDevice(), |
| mock_handle_(mock_handle) { |
| mock_handle->set_device(this); |
| } |
| |
| virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE { |
| return mock_handle_; |
| } |
| |
| virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE { |
| EXPECT_TRUE(false) << "Should not be reached"; |
| return false; |
| } |
| |
| MOCK_METHOD1(ListInterfaces, bool(UsbConfigDescriptor* config)); |
| |
| private: |
| MockUsbDeviceHandle* mock_handle_; |
| virtual ~MockUsbDevice() {} |
| }; |
| |
| #if defined(OS_WIN) |
| #pragma warning(pop) |
| #endif |
| |
| class UsbApiTest : public ExtensionApiTest { |
| public: |
| virtual void SetUpOnMainThread() OVERRIDE { |
| mock_device_handle_ = new MockUsbDeviceHandle(); |
| mock_device_ = new MockUsbDevice(mock_device_handle_.get()); |
| extensions::UsbFindDevicesFunction::SetDeviceForTest(mock_device_.get()); |
| } |
| |
| protected: |
| scoped_refptr<MockUsbDeviceHandle> mock_device_handle_; |
| scoped_refptr<MockUsbDevice> mock_device_; |
| }; |
| |
| } // namespace |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) { |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| EXPECT_CALL(*mock_device_handle_.get(), ResetDevice()) |
| .WillOnce(Return(true)) |
| .WillOnce(Return(false)); |
| EXPECT_CALL(*mock_device_handle_.get(), |
| InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED)); |
| ASSERT_TRUE(RunExtensionTest("usb/device_handling")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) { |
| EXPECT_CALL(*mock_device_.get(), ListInterfaces(_)) |
| .WillOnce(Return(false)); |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| ASSERT_TRUE(RunExtensionTest("usb/list_interfaces")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) { |
| EXPECT_CALL(*mock_device_handle_.get(), |
| ControlTransfer(USB_DIRECTION_OUTBOUND, |
| UsbDeviceHandle::STANDARD, |
| UsbDeviceHandle::DEVICE, |
| 1, |
| 2, |
| 3, |
| _, |
| 1, |
| _, |
| _)) |
| .WillOnce(InvokeUsbTransferCallback<9>(USB_TRANSFER_COMPLETED)); |
| EXPECT_CALL(*mock_device_handle_.get(), |
| BulkTransfer(USB_DIRECTION_OUTBOUND, 1, _, 1, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED)); |
| EXPECT_CALL(*mock_device_handle_.get(), |
| InterruptTransfer(USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED)); |
| EXPECT_CALL(*mock_device_handle_.get(), |
| IsochronousTransfer(USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<7>(USB_TRANSFER_COMPLETED)); |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| ASSERT_TRUE(RunExtensionTest("usb/transfer_event")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) { |
| EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED)); |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) { |
| EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_COMPLETED)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_ERROR)) |
| .WillOnce(InvokeUsbTransferCallback<5>(USB_TRANSFER_TIMEOUT)); |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| ASSERT_TRUE(RunExtensionTest("usb/transfer_failure")); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) { |
| EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); |
| ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer")); |
| } |