OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "chrome/browser/extensions/api/usb/usb_api.h" | |
6 #include "chrome/browser/extensions/extension_apitest.h" | |
7 #include "chrome/browser/ui/browser.h" | |
8 #include "components/usb_service/usb_service.h" | |
9 #include "content/public/browser/browser_thread.h" | |
10 #include "content/public/test/test_utils.h" | |
11 #include "net/base/io_buffer.h" | |
12 #include "testing/gmock/include/gmock/gmock.h" | |
13 | |
14 using testing::AnyNumber; | |
15 using testing::_; | |
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::UsbService; | |
23 using usb_service::UsbTransferCallback; | |
24 | |
25 namespace { | |
26 | |
27 ACTION_TEMPLATE(InvokeUsbTransferCallback, | |
28 HAS_1_TEMPLATE_PARAMS(int, k), | |
29 AND_1_VALUE_PARAMS(p1)) { | |
30 ::std::tr1::get<k>(args).Run(p1, new net::IOBuffer(1), 1); | |
31 } | |
32 | |
33 // MSVC erroneously thinks that at least one of the arguments for the transfer | |
34 // methods differ by const or volatility and emits a warning about the old | |
35 // standards-noncompliant behaviour of their compiler. | |
36 #if defined(OS_WIN) | |
37 #pragma warning(push) | |
38 #pragma warning(disable:4373) | |
39 #endif | |
40 | |
41 class MockUsbDeviceHandle : public UsbDeviceHandle { | |
42 public: | |
43 MockUsbDeviceHandle() : UsbDeviceHandle() {} | |
44 | |
45 MOCK_METHOD0(Close, void()); | |
46 | |
47 MOCK_METHOD10(ControlTransfer, void(const UsbEndpointDirection direction, | |
48 const TransferRequestType request_type, const TransferRecipient recipient, | |
49 const uint8 request, const uint16 value, const uint16 index, | |
50 net::IOBuffer* buffer, const size_t length, const unsigned int timeout, | |
51 const UsbTransferCallback& callback)); | |
52 | |
53 MOCK_METHOD6(BulkTransfer, void(const UsbEndpointDirection direction, | |
54 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | |
55 const unsigned int timeout, const UsbTransferCallback& callback)); | |
56 | |
57 MOCK_METHOD6(InterruptTransfer, void(const UsbEndpointDirection direction, | |
58 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | |
59 const unsigned int timeout, const UsbTransferCallback& callback)); | |
60 | |
61 MOCK_METHOD8(IsochronousTransfer, void(const UsbEndpointDirection direction, | |
62 const uint8 endpoint, net::IOBuffer* buffer, const size_t length, | |
63 const unsigned int packets, const unsigned int packet_length, | |
64 const unsigned int timeout, const UsbTransferCallback& callback)); | |
65 | |
66 MOCK_METHOD0(ResetDevice, bool()); | |
67 | |
68 void set_device(UsbDevice* device) { device_ = device; } | |
69 | |
70 protected: | |
71 virtual ~MockUsbDeviceHandle() {} | |
72 }; | |
73 | |
74 class MockUsbConfigDescriptor : public UsbConfigDescriptor { | |
75 public: | |
76 MOCK_CONST_METHOD0(GetNumInterfaces, size_t()); | |
77 | |
78 protected: | |
79 virtual ~MockUsbConfigDescriptor() {} | |
80 }; | |
81 | |
82 class MockUsbDevice : public UsbDevice { | |
83 public: | |
84 explicit MockUsbDevice(MockUsbDeviceHandle* mock_handle) | |
85 : UsbDevice(), | |
86 mock_handle_(mock_handle) { | |
87 mock_handle->set_device(this); | |
88 } | |
89 | |
90 virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE { | |
91 return mock_handle_; | |
92 } | |
93 | |
94 virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE { | |
95 EXPECT_TRUE(false) << "Should not be reached"; | |
96 return false; | |
97 } | |
98 | |
99 #if defined(OS_CHROMEOS) | |
100 virtual void RequestUsbAcess( | |
101 int interface_id, | |
102 const base::Callback<void(bool success)>& callback) OVERRIDE { | |
103 BrowserThread::PostTask( | |
104 BrowserThread::FILE, FROM_HERE, base::Bind(callback, true)); | |
105 } | |
106 #endif // OS_CHROMEOS | |
107 | |
108 MOCK_METHOD0(ListInterfaces, scoped_refptr<UsbConfigDescriptor>()); | |
109 | |
110 private: | |
111 MockUsbDeviceHandle* mock_handle_; | |
112 virtual ~MockUsbDevice() {} | |
113 }; | |
114 | |
115 class MockUsbService : public UsbService { | |
116 public: | |
117 explicit MockUsbService(scoped_refptr<UsbDevice> device) : device_(device) {} | |
118 | |
119 protected: | |
120 virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE { | |
121 EXPECT_EQ(unique_id, 0U); | |
122 return device_; | |
123 } | |
124 | |
125 virtual void GetDevices( | |
126 std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE { | |
127 STLClearObject(devices); | |
128 devices->push_back(device_); | |
129 } | |
130 | |
131 scoped_refptr<UsbDevice> device_; | |
132 }; | |
133 | |
134 #if defined(OS_WIN) | |
135 #pragma warning(pop) | |
136 #endif | |
137 | |
138 class UsbApiTest : public ExtensionApiTest { | |
139 public: | |
140 virtual void SetUpOnMainThread() OVERRIDE { | |
141 mock_device_handle_ = new MockUsbDeviceHandle(); | |
142 mock_device_ = new MockUsbDevice(mock_device_handle_.get()); | |
143 scoped_refptr<content::MessageLoopRunner> runner = | |
144 new content::MessageLoopRunner; | |
145 BrowserThread::PostTaskAndReply(BrowserThread::FILE, | |
146 FROM_HERE, | |
147 base::Bind(&UsbApiTest::SetUpService, this), | |
148 runner->QuitClosure()); | |
149 runner->Run(); | |
150 } | |
151 | |
152 void SetUpService() { | |
153 UsbService::SetInstanceForTest(new MockUsbService(mock_device_)); | |
154 } | |
155 | |
156 virtual void CleanUpOnMainThread() OVERRIDE { | |
157 scoped_refptr<content::MessageLoopRunner> runner = | |
158 new content::MessageLoopRunner; | |
159 UsbService* service = NULL; | |
160 BrowserThread::PostTaskAndReply( | |
161 BrowserThread::FILE, | |
162 FROM_HERE, | |
163 base::Bind(&UsbService::SetInstanceForTest, service), | |
164 runner->QuitClosure()); | |
165 runner->Run(); | |
166 } | |
167 | |
168 protected: | |
169 scoped_refptr<MockUsbDeviceHandle> mock_device_handle_; | |
170 scoped_refptr<MockUsbDevice> mock_device_; | |
171 }; | |
172 | |
173 } // namespace | |
174 | |
175 IN_PROC_BROWSER_TEST_F(UsbApiTest, DeviceHandling) { | |
176 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(4); | |
177 ASSERT_TRUE(RunExtensionTest("usb/device_handling")); | |
178 } | |
179 | |
180 IN_PROC_BROWSER_TEST_F(UsbApiTest, ResetDevice) { | |
181 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(2); | |
182 EXPECT_CALL(*mock_device_handle_.get(), ResetDevice()) | |
183 .WillOnce(Return(true)) | |
184 .WillOnce(Return(false)); | |
185 EXPECT_CALL( | |
186 *mock_device_handle_.get(), | |
187 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) | |
188 .WillOnce( | |
189 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_COMPLETED)); | |
190 ASSERT_TRUE(RunExtensionTest("usb/reset_device")); | |
191 } | |
192 | |
193 IN_PROC_BROWSER_TEST_F(UsbApiTest, ListInterfaces) { | |
194 scoped_refptr<MockUsbConfigDescriptor> mock_descriptor = | |
195 new MockUsbConfigDescriptor(); | |
196 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); | |
197 EXPECT_CALL(*mock_descriptor.get(), GetNumInterfaces()).WillOnce(Return(0)); | |
198 EXPECT_CALL(*mock_device_.get(), ListInterfaces()) | |
199 .WillOnce(Return(mock_descriptor)); | |
200 ASSERT_TRUE(RunExtensionTest("usb/list_interfaces")); | |
201 } | |
202 | |
203 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferEvent) { | |
204 EXPECT_CALL(*mock_device_handle_.get(), | |
205 ControlTransfer(usb_service::USB_DIRECTION_OUTBOUND, | |
206 UsbDeviceHandle::STANDARD, | |
207 UsbDeviceHandle::DEVICE, | |
208 1, 2, 3, _, 1, _, _)) | |
209 .WillOnce( | |
210 InvokeUsbTransferCallback<9>(usb_service::USB_TRANSFER_COMPLETED)); | |
211 EXPECT_CALL(*mock_device_handle_.get(), | |
212 BulkTransfer(usb_service::USB_DIRECTION_OUTBOUND, 1, _, 1, _, _)) | |
213 .WillOnce( | |
214 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_COMPLETED)); | |
215 EXPECT_CALL( | |
216 *mock_device_handle_.get(), | |
217 InterruptTransfer(usb_service::USB_DIRECTION_OUTBOUND, 2, _, 1, _, _)) | |
218 .WillOnce( | |
219 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_COMPLETED)); | |
220 EXPECT_CALL(*mock_device_handle_.get(), | |
221 IsochronousTransfer( | |
222 usb_service::USB_DIRECTION_OUTBOUND, 3, _, 1, 1, 1, _, _)) | |
223 .WillOnce( | |
224 InvokeUsbTransferCallback<7>(usb_service::USB_TRANSFER_COMPLETED)); | |
225 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); | |
226 ASSERT_TRUE(RunExtensionTest("usb/transfer_event")); | |
227 } | |
228 | |
229 IN_PROC_BROWSER_TEST_F(UsbApiTest, ZeroLengthTransfer) { | |
230 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, 0, _, _)) | |
231 .WillOnce( | |
232 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_COMPLETED)); | |
233 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); | |
234 ASSERT_TRUE(RunExtensionTest("usb/zero_length_transfer")); | |
235 } | |
236 | |
237 IN_PROC_BROWSER_TEST_F(UsbApiTest, TransferFailure) { | |
238 EXPECT_CALL(*mock_device_handle_.get(), BulkTransfer(_, _, _, _, _, _)) | |
239 .WillOnce( | |
240 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_COMPLETED)) | |
241 .WillOnce(InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_ERROR)) | |
242 .WillOnce( | |
243 InvokeUsbTransferCallback<5>(usb_service::USB_TRANSFER_TIMEOUT)); | |
244 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); | |
245 ASSERT_TRUE(RunExtensionTest("usb/transfer_failure")); | |
246 } | |
247 | |
248 IN_PROC_BROWSER_TEST_F(UsbApiTest, InvalidLengthTransfer) { | |
249 EXPECT_CALL(*mock_device_handle_.get(), Close()).Times(AnyNumber()); | |
250 ASSERT_TRUE(RunExtensionTest("usb/invalid_length_transfer")); | |
251 } | |
OLD | NEW |