OLD | NEW |
| (Empty) |
1 // Copyright 2015 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 <map> | |
6 #include <queue> | |
7 #include <set> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/macros.h" | |
12 #include "base/message_loop/message_loop.h" | |
13 #include "base/run_loop.h" | |
14 #include "base/stl_util.h" | |
15 #include "device/usb/device_impl.h" | |
16 #include "device/usb/mock_usb_device.h" | |
17 #include "device/usb/mock_usb_device_handle.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" | |
20 | |
21 using ::testing::Invoke; | |
22 using ::testing::_; | |
23 | |
24 namespace device { | |
25 namespace usb { | |
26 | |
27 namespace { | |
28 | |
29 class ConfigBuilder { | |
30 public: | |
31 ConfigBuilder(uint8_t value) { config_.configuration_value = value; } | |
32 | |
33 ConfigBuilder& AddInterface(uint8_t interface_number, | |
34 uint8_t alternate_setting, | |
35 uint8_t class_code, | |
36 uint8_t subclass_code, | |
37 uint8_t protocol_code) { | |
38 UsbInterfaceDescriptor interface; | |
39 interface.interface_number = interface_number; | |
40 interface.alternate_setting = alternate_setting; | |
41 interface.interface_class = class_code; | |
42 interface.interface_subclass = subclass_code; | |
43 interface.interface_protocol = protocol_code; | |
44 config_.interfaces.push_back(interface); | |
45 return *this; | |
46 } | |
47 | |
48 const UsbConfigDescriptor& config() const { return config_; } | |
49 | |
50 private: | |
51 UsbConfigDescriptor config_; | |
52 }; | |
53 | |
54 void ExpectDeviceInfoAndThen(const std::string& guid, | |
55 uint16_t vendor_id, | |
56 uint16_t product_id, | |
57 const std::string& manufacturer, | |
58 const std::string& product, | |
59 const std::string& serial_number, | |
60 const base::Closure& continuation, | |
61 DeviceInfoPtr device_info) { | |
62 EXPECT_EQ(guid, device_info->guid); | |
63 EXPECT_EQ(vendor_id, device_info->vendor_id); | |
64 EXPECT_EQ(product_id, device_info->product_id); | |
65 EXPECT_EQ(manufacturer, device_info->manufacturer); | |
66 EXPECT_EQ(product, device_info->product); | |
67 EXPECT_EQ(serial_number, device_info->serial_number); | |
68 continuation.Run(); | |
69 } | |
70 | |
71 void ExpectResultAndThen(bool expected_result, | |
72 const base::Closure& continuation, | |
73 bool actual_result) { | |
74 EXPECT_EQ(expected_result, actual_result); | |
75 continuation.Run(); | |
76 } | |
77 | |
78 void ExpectTransferInAndThen(TransferStatus expected_status, | |
79 const std::vector<uint8_t>& expected_bytes, | |
80 const base::Closure& continuation, | |
81 TransferStatus actual_status, | |
82 mojo::Array<uint8_t> actual_bytes) { | |
83 EXPECT_EQ(expected_status, actual_status); | |
84 ASSERT_EQ(expected_bytes.size(), actual_bytes.size()); | |
85 for (size_t i = 0; i < actual_bytes.size(); ++i) { | |
86 EXPECT_EQ(expected_bytes[i], actual_bytes[i]) | |
87 << "Contents differ at index: " << i; | |
88 } | |
89 continuation.Run(); | |
90 } | |
91 | |
92 void ExpectPacketsAndThen( | |
93 TransferStatus expected_status, | |
94 const std::vector<std::vector<uint8_t>>& expected_packets, | |
95 const base::Closure& continuation, | |
96 TransferStatus actual_status, | |
97 mojo::Array<mojo::Array<uint8_t>> actual_packets) { | |
98 EXPECT_EQ(expected_status, actual_status); | |
99 ASSERT_EQ(expected_packets.size(), actual_packets.size()); | |
100 for (size_t i = 0; i < expected_packets.size(); ++i) { | |
101 EXPECT_EQ(expected_packets[i].size(), actual_packets[i].size()) | |
102 << "Packet sizes differ at index: " << i; | |
103 for (size_t j = 0; j < expected_packets[i].size(); ++j) { | |
104 EXPECT_EQ(expected_packets[i][j], actual_packets[i][j]) | |
105 << "Contents of packet " << i << " differ at index " << j; | |
106 } | |
107 } | |
108 continuation.Run(); | |
109 } | |
110 | |
111 void ExpectTransferStatusAndThen(TransferStatus expected_status, | |
112 const base::Closure& continuation, | |
113 TransferStatus actual_status) { | |
114 EXPECT_EQ(expected_status, actual_status); | |
115 continuation.Run(); | |
116 } | |
117 | |
118 class USBDeviceImplTest : public testing::Test { | |
119 public: | |
120 USBDeviceImplTest() | |
121 : message_loop_(new base::MessageLoop), | |
122 is_device_open_(false), | |
123 allow_reset_(false), | |
124 current_config_(0) {} | |
125 | |
126 ~USBDeviceImplTest() override {} | |
127 | |
128 protected: | |
129 MockUsbDevice& mock_device() { return *mock_device_.get(); } | |
130 bool is_device_open() const { return is_device_open_; } | |
131 MockUsbDeviceHandle& mock_handle() { return *mock_handle_.get(); } | |
132 | |
133 void set_allow_reset(bool allow_reset) { allow_reset_ = allow_reset; } | |
134 | |
135 // Creates a mock device and binds a Device proxy to a Device service impl | |
136 // wrapping the mock device. | |
137 DevicePtr GetMockDeviceProxy(uint16_t vendor_id, | |
138 uint16_t product_id, | |
139 const std::string& manufacturer, | |
140 const std::string& product, | |
141 const std::string& serial) { | |
142 is_device_open_ = true; | |
143 | |
144 mock_device_ = | |
145 new MockUsbDevice(vendor_id, product_id, manufacturer, product, serial); | |
146 mock_handle_ = new MockUsbDeviceHandle(mock_device_.get()); | |
147 | |
148 DevicePtr proxy; | |
149 new DeviceImpl(mock_handle_, mojo::GetProxy(&proxy)); | |
150 | |
151 // Set up mock handle calls to respond based on mock device configs | |
152 // established by the test. | |
153 ON_CALL(mock_handle(), Close()) | |
154 .WillByDefault(Invoke(this, &USBDeviceImplTest::CloseMockHandle)); | |
155 ON_CALL(mock_handle(), SetConfiguration(_, _)) | |
156 .WillByDefault(Invoke(this, &USBDeviceImplTest::SetConfiguration)); | |
157 ON_CALL(mock_handle(), ClaimInterface(_, _)) | |
158 .WillByDefault(Invoke(this, &USBDeviceImplTest::ClaimInterface)); | |
159 ON_CALL(mock_handle(), ReleaseInterface(_)) | |
160 .WillByDefault(Invoke(this, &USBDeviceImplTest::ReleaseInterface)); | |
161 ON_CALL(mock_handle(), SetInterfaceAlternateSetting(_, _, _)) | |
162 .WillByDefault( | |
163 Invoke(this, &USBDeviceImplTest::SetInterfaceAlternateSetting)); | |
164 ON_CALL(mock_handle(), ResetDevice(_)) | |
165 .WillByDefault(Invoke(this, &USBDeviceImplTest::ResetDevice)); | |
166 ON_CALL(mock_handle(), ControlTransfer(_, _, _, _, _, _, _, _, _, _)) | |
167 .WillByDefault(Invoke(this, &USBDeviceImplTest::ControlTransfer)); | |
168 ON_CALL(mock_handle(), BulkTransfer(_, _, _, _, _, _)) | |
169 .WillByDefault( | |
170 Invoke(this, &USBDeviceImplTest::BulkOrInterruptTransfer)); | |
171 ON_CALL(mock_handle(), InterruptTransfer(_, _, _, _, _, _)) | |
172 .WillByDefault( | |
173 Invoke(this, &USBDeviceImplTest::BulkOrInterruptTransfer)); | |
174 ON_CALL(mock_handle(), IsochronousTransfer(_, _, _, _, _, _, _, _)) | |
175 .WillByDefault(Invoke(this, &USBDeviceImplTest::IsochronousTransfer)); | |
176 | |
177 return proxy.Pass(); | |
178 } | |
179 | |
180 DevicePtr GetMockDeviceProxy() { | |
181 return GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF"); | |
182 } | |
183 | |
184 void AddMockConfig(const ConfigBuilder& builder) { | |
185 const UsbConfigDescriptor& config = builder.config(); | |
186 DCHECK(!ContainsKey(mock_configs_, config.configuration_value)); | |
187 mock_configs_[config.configuration_value] = config; | |
188 } | |
189 | |
190 void AddMockInboundData(const std::vector<uint8_t>& data) { | |
191 mock_inbound_data_.push(data); | |
192 } | |
193 | |
194 void AddMockOutboundData(const std::vector<uint8_t>& data) { | |
195 mock_outbound_data_.push(data); | |
196 } | |
197 | |
198 private: | |
199 void CloseMockHandle() { | |
200 EXPECT_TRUE(is_device_open_); | |
201 is_device_open_ = false; | |
202 } | |
203 | |
204 void SetConfiguration(uint8_t value, | |
205 const UsbDeviceHandle::ResultCallback& callback) { | |
206 if (mock_configs_.find(value) != mock_configs_.end()) { | |
207 current_config_ = value; | |
208 callback.Run(true); | |
209 } else { | |
210 callback.Run(false); | |
211 } | |
212 } | |
213 | |
214 void ClaimInterface(uint8_t interface_number, | |
215 const UsbDeviceHandle::ResultCallback& callback) { | |
216 for (const auto& config : mock_configs_) { | |
217 for (const auto& interface : config.second.interfaces) { | |
218 if (interface.interface_number == interface_number) { | |
219 claimed_interfaces_.insert(interface_number); | |
220 callback.Run(true); | |
221 return; | |
222 } | |
223 } | |
224 } | |
225 callback.Run(false); | |
226 } | |
227 | |
228 bool ReleaseInterface(uint8_t interface_number) { | |
229 if (ContainsKey(claimed_interfaces_, interface_number)) { | |
230 claimed_interfaces_.erase(interface_number); | |
231 return true; | |
232 } | |
233 return false; | |
234 } | |
235 | |
236 void SetInterfaceAlternateSetting( | |
237 uint8_t interface_number, | |
238 uint8_t alternate_setting, | |
239 const UsbDeviceHandle::ResultCallback& callback) { | |
240 for (const auto& config : mock_configs_) { | |
241 for (const auto& interface : config.second.interfaces) { | |
242 if (interface.interface_number == interface_number && | |
243 interface.alternate_setting == alternate_setting) { | |
244 callback.Run(true); | |
245 return; | |
246 } | |
247 } | |
248 } | |
249 callback.Run(false); | |
250 } | |
251 | |
252 void ResetDevice(const UsbDeviceHandle::ResultCallback& callback) { | |
253 callback.Run(allow_reset_); | |
254 } | |
255 | |
256 void InboundTransfer(const UsbDeviceHandle::TransferCallback& callback) { | |
257 ASSERT_GE(mock_inbound_data_.size(), 1u); | |
258 const std::vector<uint8_t>& bytes = mock_inbound_data_.front(); | |
259 size_t length = bytes.size(); | |
260 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(length); | |
261 std::copy(bytes.begin(), bytes.end(), buffer->data()); | |
262 mock_inbound_data_.pop(); | |
263 callback.Run(USB_TRANSFER_COMPLETED, buffer, length); | |
264 } | |
265 | |
266 void OutboundTransfer(scoped_refptr<net::IOBuffer> buffer, | |
267 size_t length, | |
268 const UsbDeviceHandle::TransferCallback& callback) { | |
269 ASSERT_GE(mock_outbound_data_.size(), 1u); | |
270 const std::vector<uint8_t>& bytes = mock_outbound_data_.front(); | |
271 ASSERT_EQ(bytes.size(), length); | |
272 for (size_t i = 0; i < length; ++i) { | |
273 EXPECT_EQ(bytes[i], buffer->data()[i]) | |
274 << "Contents differ at index: " << i; | |
275 } | |
276 mock_outbound_data_.pop(); | |
277 callback.Run(USB_TRANSFER_COMPLETED, buffer, length); | |
278 } | |
279 | |
280 void ControlTransfer(UsbEndpointDirection direction, | |
281 UsbDeviceHandle::TransferRequestType request_type, | |
282 UsbDeviceHandle::TransferRecipient recipient, | |
283 uint8_t request, | |
284 uint16_t value, | |
285 uint16_t index, | |
286 scoped_refptr<net::IOBuffer> buffer, | |
287 size_t length, | |
288 unsigned int timeout, | |
289 const UsbDeviceHandle::TransferCallback& callback) { | |
290 if (direction == USB_DIRECTION_INBOUND) | |
291 InboundTransfer(callback); | |
292 else | |
293 OutboundTransfer(buffer, length, callback); | |
294 } | |
295 | |
296 void BulkOrInterruptTransfer( | |
297 UsbEndpointDirection direction, | |
298 uint8_t endpoint, | |
299 scoped_refptr<net::IOBuffer> buffer, | |
300 size_t length, | |
301 unsigned int timeout, | |
302 const UsbDeviceHandle::TransferCallback& callback) { | |
303 if (direction == USB_DIRECTION_INBOUND) | |
304 InboundTransfer(callback); | |
305 else | |
306 OutboundTransfer(buffer, length, callback); | |
307 } | |
308 | |
309 void IsochronousTransfer(UsbEndpointDirection direction, | |
310 uint8_t endpoint, | |
311 scoped_refptr<net::IOBuffer> buffer, | |
312 size_t length, | |
313 unsigned int packets, | |
314 unsigned int packet_length, | |
315 unsigned int timeout, | |
316 const UsbDeviceHandle::TransferCallback& callback) { | |
317 if (direction == USB_DIRECTION_INBOUND) | |
318 InboundTransfer(callback); | |
319 else | |
320 OutboundTransfer(buffer, length, callback); | |
321 } | |
322 | |
323 scoped_ptr<base::MessageLoop> message_loop_; | |
324 scoped_refptr<MockUsbDevice> mock_device_; | |
325 scoped_refptr<MockUsbDeviceHandle> mock_handle_; | |
326 bool is_device_open_; | |
327 bool allow_reset_; | |
328 | |
329 std::map<uint8_t, UsbConfigDescriptor> mock_configs_; | |
330 uint8_t current_config_; | |
331 | |
332 std::queue<std::vector<uint8_t>> mock_inbound_data_; | |
333 std::queue<std::vector<uint8_t>> mock_outbound_data_; | |
334 | |
335 std::set<uint8_t> claimed_interfaces_; | |
336 | |
337 DISALLOW_COPY_AND_ASSIGN(USBDeviceImplTest); | |
338 }; | |
339 | |
340 } // namespace | |
341 | |
342 TEST_F(USBDeviceImplTest, Close) { | |
343 DevicePtr device = GetMockDeviceProxy(); | |
344 | |
345 EXPECT_TRUE(is_device_open()); | |
346 | |
347 EXPECT_CALL(mock_handle(), Close()); | |
348 | |
349 base::RunLoop loop; | |
350 device->Close(loop.QuitClosure()); | |
351 loop.Run(); | |
352 | |
353 EXPECT_FALSE(is_device_open()); | |
354 } | |
355 | |
356 // Test that the information returned via the Device::GetDeviceInfo matches that | |
357 // of the underlying device. | |
358 TEST_F(USBDeviceImplTest, GetDeviceInfo) { | |
359 DevicePtr device = | |
360 GetMockDeviceProxy(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF"); | |
361 | |
362 EXPECT_CALL(mock_device(), GetConfiguration()); | |
363 | |
364 base::RunLoop loop; | |
365 device->GetDeviceInfo(base::Bind(&ExpectDeviceInfoAndThen, | |
366 mock_device().guid(), 0x1234, 0x5678, "ACME", | |
367 "Frobinator", "ABCDEF", loop.QuitClosure())); | |
368 loop.Run(); | |
369 | |
370 EXPECT_CALL(mock_handle(), Close()); | |
371 } | |
372 | |
373 TEST_F(USBDeviceImplTest, SetInvalidConfiguration) { | |
374 DevicePtr device = GetMockDeviceProxy(); | |
375 | |
376 EXPECT_CALL(mock_handle(), SetConfiguration(42, _)); | |
377 | |
378 // SetConfiguration should fail because 42 is not a valid mock configuration. | |
379 base::RunLoop loop; | |
380 device->SetConfiguration( | |
381 42, base::Bind(&ExpectResultAndThen, false, loop.QuitClosure())); | |
382 loop.Run(); | |
383 | |
384 EXPECT_CALL(mock_handle(), Close()); | |
385 } | |
386 | |
387 TEST_F(USBDeviceImplTest, SetValidConfiguration) { | |
388 DevicePtr device = GetMockDeviceProxy(); | |
389 | |
390 EXPECT_CALL(mock_handle(), SetConfiguration(42, _)); | |
391 | |
392 AddMockConfig(ConfigBuilder(42)); | |
393 | |
394 // SetConfiguration should succeed because 42 is a valid mock configuration. | |
395 base::RunLoop loop; | |
396 device->SetConfiguration( | |
397 42, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure())); | |
398 loop.Run(); | |
399 | |
400 EXPECT_CALL(mock_handle(), Close()); | |
401 } | |
402 | |
403 // Verify that the result of Reset() reflects the underlying UsbDeviceHandle's | |
404 // ResetDevice() result. | |
405 TEST_F(USBDeviceImplTest, Reset) { | |
406 DevicePtr device = GetMockDeviceProxy(); | |
407 | |
408 EXPECT_CALL(mock_handle(), ResetDevice(_)); | |
409 | |
410 set_allow_reset(true); | |
411 | |
412 { | |
413 base::RunLoop loop; | |
414 device->Reset(base::Bind(&ExpectResultAndThen, true, loop.QuitClosure())); | |
415 loop.Run(); | |
416 } | |
417 | |
418 EXPECT_CALL(mock_handle(), ResetDevice(_)); | |
419 | |
420 set_allow_reset(false); | |
421 | |
422 { | |
423 base::RunLoop loop; | |
424 device->Reset(base::Bind(&ExpectResultAndThen, false, loop.QuitClosure())); | |
425 loop.Run(); | |
426 } | |
427 | |
428 EXPECT_CALL(mock_handle(), Close()); | |
429 } | |
430 | |
431 TEST_F(USBDeviceImplTest, ClaimAndReleaseInterface) { | |
432 DevicePtr device = GetMockDeviceProxy(); | |
433 | |
434 // Now add a mock interface #1. | |
435 AddMockConfig(ConfigBuilder(0).AddInterface(1, 0, 1, 2, 3)); | |
436 | |
437 EXPECT_CALL(mock_handle(), ClaimInterface(2, _)); | |
438 | |
439 { | |
440 // Try to claim an invalid interface and expect failure. | |
441 base::RunLoop loop; | |
442 device->ClaimInterface( | |
443 2, base::Bind(&ExpectResultAndThen, false, loop.QuitClosure())); | |
444 loop.Run(); | |
445 } | |
446 | |
447 EXPECT_CALL(mock_handle(), ClaimInterface(1, _)); | |
448 | |
449 { | |
450 base::RunLoop loop; | |
451 device->ClaimInterface( | |
452 1, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure())); | |
453 loop.Run(); | |
454 } | |
455 | |
456 EXPECT_CALL(mock_handle(), ReleaseInterface(2)); | |
457 | |
458 { | |
459 // Releasing a non-existent interface should fail. | |
460 base::RunLoop loop; | |
461 device->ReleaseInterface( | |
462 2, base::Bind(&ExpectResultAndThen, false, loop.QuitClosure())); | |
463 loop.Run(); | |
464 } | |
465 | |
466 EXPECT_CALL(mock_handle(), ReleaseInterface(1)); | |
467 | |
468 { | |
469 // Now this should release the claimed interface and close the handle. | |
470 base::RunLoop loop; | |
471 device->ReleaseInterface( | |
472 1, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure())); | |
473 loop.Run(); | |
474 } | |
475 | |
476 EXPECT_CALL(mock_handle(), Close()); | |
477 } | |
478 | |
479 TEST_F(USBDeviceImplTest, SetInterfaceAlternateSetting) { | |
480 DevicePtr device = GetMockDeviceProxy(); | |
481 | |
482 AddMockConfig(ConfigBuilder(0) | |
483 .AddInterface(1, 0, 1, 2, 3) | |
484 .AddInterface(1, 42, 1, 2, 3) | |
485 .AddInterface(2, 0, 1, 2, 3)); | |
486 | |
487 EXPECT_CALL(mock_handle(), SetInterfaceAlternateSetting(1, 42, _)); | |
488 | |
489 { | |
490 base::RunLoop loop; | |
491 device->SetInterfaceAlternateSetting( | |
492 1, 42, base::Bind(&ExpectResultAndThen, true, loop.QuitClosure())); | |
493 loop.Run(); | |
494 } | |
495 | |
496 EXPECT_CALL(mock_handle(), SetInterfaceAlternateSetting(1, 100, _)); | |
497 | |
498 { | |
499 base::RunLoop loop; | |
500 device->SetInterfaceAlternateSetting( | |
501 1, 100, base::Bind(&ExpectResultAndThen, false, loop.QuitClosure())); | |
502 loop.Run(); | |
503 } | |
504 | |
505 EXPECT_CALL(mock_handle(), Close()); | |
506 } | |
507 | |
508 TEST_F(USBDeviceImplTest, ControlTransfer) { | |
509 DevicePtr device = GetMockDeviceProxy(); | |
510 | |
511 std::vector<uint8_t> fake_data; | |
512 fake_data.push_back(41); | |
513 fake_data.push_back(42); | |
514 fake_data.push_back(43); | |
515 | |
516 AddMockInboundData(fake_data); | |
517 | |
518 EXPECT_CALL(mock_handle(), | |
519 ControlTransfer(USB_DIRECTION_INBOUND, UsbDeviceHandle::STANDARD, | |
520 UsbDeviceHandle::DEVICE, 5, 6, 7, _, _, 0, _)); | |
521 | |
522 { | |
523 auto params = ControlTransferParams::New(); | |
524 params->type = CONTROL_TRANSFER_TYPE_STANDARD; | |
525 params->recipient = CONTROL_TRANSFER_RECIPIENT_DEVICE; | |
526 params->request = 5; | |
527 params->value = 6; | |
528 params->index = 7; | |
529 base::RunLoop loop; | |
530 device->ControlTransferIn( | |
531 params.Pass(), static_cast<uint32_t>(fake_data.size()), 0, | |
532 base::Bind(&ExpectTransferInAndThen, TRANSFER_STATUS_COMPLETED, | |
533 fake_data, loop.QuitClosure())); | |
534 loop.Run(); | |
535 } | |
536 | |
537 AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3)); | |
538 AddMockOutboundData(fake_data); | |
539 | |
540 EXPECT_CALL(mock_handle(), | |
541 ControlTransfer(USB_DIRECTION_OUTBOUND, UsbDeviceHandle::STANDARD, | |
542 UsbDeviceHandle::INTERFACE, 5, 6, 7, _, _, 0, _)); | |
543 | |
544 { | |
545 auto params = ControlTransferParams::New(); | |
546 params->type = CONTROL_TRANSFER_TYPE_STANDARD; | |
547 params->recipient = CONTROL_TRANSFER_RECIPIENT_INTERFACE; | |
548 params->request = 5; | |
549 params->value = 6; | |
550 params->index = 7; | |
551 base::RunLoop loop; | |
552 device->ControlTransferOut( | |
553 params.Pass(), mojo::Array<uint8_t>::From(fake_data), 0, | |
554 base::Bind(&ExpectTransferStatusAndThen, TRANSFER_STATUS_COMPLETED, | |
555 loop.QuitClosure())); | |
556 loop.Run(); | |
557 } | |
558 | |
559 EXPECT_CALL(mock_handle(), Close()); | |
560 } | |
561 | |
562 TEST_F(USBDeviceImplTest, BulkTransfer) { | |
563 DevicePtr device = GetMockDeviceProxy(); | |
564 | |
565 std::string message1 = "say hello please"; | |
566 std::vector<uint8_t> fake_outbound_data(message1.size()); | |
567 std::copy(message1.begin(), message1.end(), fake_outbound_data.begin()); | |
568 | |
569 std::string message2 = "hello world!"; | |
570 std::vector<uint8_t> fake_inbound_data(message2.size()); | |
571 std::copy(message2.begin(), message2.end(), fake_inbound_data.begin()); | |
572 | |
573 AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3)); | |
574 AddMockOutboundData(fake_outbound_data); | |
575 AddMockInboundData(fake_inbound_data); | |
576 | |
577 EXPECT_CALL(mock_handle(), BulkTransfer(USB_DIRECTION_OUTBOUND, 0, _, | |
578 fake_outbound_data.size(), 0, _)); | |
579 | |
580 { | |
581 base::RunLoop loop; | |
582 device->BulkTransferOut( | |
583 0, mojo::Array<uint8_t>::From(fake_outbound_data), 0, | |
584 base::Bind(&ExpectTransferStatusAndThen, TRANSFER_STATUS_COMPLETED, | |
585 loop.QuitClosure())); | |
586 loop.Run(); | |
587 } | |
588 | |
589 EXPECT_CALL(mock_handle(), BulkTransfer(USB_DIRECTION_INBOUND, 0, _, | |
590 fake_inbound_data.size(), 0, _)); | |
591 | |
592 { | |
593 base::RunLoop loop; | |
594 device->BulkTransferIn( | |
595 0, static_cast<uint32_t>(fake_inbound_data.size()), 0, | |
596 base::Bind(&ExpectTransferInAndThen, TRANSFER_STATUS_COMPLETED, | |
597 fake_inbound_data, loop.QuitClosure())); | |
598 loop.Run(); | |
599 } | |
600 | |
601 EXPECT_CALL(mock_handle(), Close()); | |
602 } | |
603 | |
604 TEST_F(USBDeviceImplTest, InterruptTransfer) { | |
605 DevicePtr device = GetMockDeviceProxy(); | |
606 | |
607 std::string message1 = "say hello please"; | |
608 std::vector<uint8_t> fake_outbound_data(message1.size()); | |
609 std::copy(message1.begin(), message1.end(), fake_outbound_data.begin()); | |
610 | |
611 std::string message2 = "hello world!"; | |
612 std::vector<uint8_t> fake_inbound_data(message2.size()); | |
613 std::copy(message2.begin(), message2.end(), fake_inbound_data.begin()); | |
614 | |
615 AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3)); | |
616 AddMockOutboundData(fake_outbound_data); | |
617 AddMockInboundData(fake_inbound_data); | |
618 | |
619 EXPECT_CALL(mock_handle(), | |
620 InterruptTransfer(USB_DIRECTION_OUTBOUND, 0, _, | |
621 fake_outbound_data.size(), 0, _)); | |
622 | |
623 { | |
624 base::RunLoop loop; | |
625 device->InterruptTransferOut( | |
626 0, mojo::Array<uint8_t>::From(fake_outbound_data), 0, | |
627 base::Bind(&ExpectTransferStatusAndThen, TRANSFER_STATUS_COMPLETED, | |
628 loop.QuitClosure())); | |
629 loop.Run(); | |
630 } | |
631 | |
632 EXPECT_CALL(mock_handle(), InterruptTransfer(USB_DIRECTION_INBOUND, 0, _, | |
633 fake_inbound_data.size(), 0, _)); | |
634 | |
635 { | |
636 base::RunLoop loop; | |
637 device->InterruptTransferIn( | |
638 0, static_cast<uint32_t>(fake_inbound_data.size()), 0, | |
639 base::Bind(&ExpectTransferInAndThen, TRANSFER_STATUS_COMPLETED, | |
640 fake_inbound_data, loop.QuitClosure())); | |
641 loop.Run(); | |
642 } | |
643 | |
644 EXPECT_CALL(mock_handle(), Close()); | |
645 } | |
646 | |
647 TEST_F(USBDeviceImplTest, IsochronousTransfer) { | |
648 DevicePtr device = GetMockDeviceProxy(); | |
649 | |
650 std::string outbound_packet_data = "aaaaaaaabbbbbbbbccccccccdddddddd"; | |
651 std::vector<uint8_t> fake_outbound_packets(outbound_packet_data.size()); | |
652 std::copy(outbound_packet_data.begin(), outbound_packet_data.end(), | |
653 fake_outbound_packets.begin()); | |
654 | |
655 std::string inbound_packet_data = "ddddddddccccccccbbbbbbbbaaaaaaaa"; | |
656 std::vector<uint8_t> fake_inbound_packets(inbound_packet_data.size()); | |
657 std::copy(inbound_packet_data.begin(), inbound_packet_data.end(), | |
658 fake_inbound_packets.begin()); | |
659 | |
660 AddMockConfig(ConfigBuilder(0).AddInterface(7, 0, 1, 2, 3)); | |
661 AddMockOutboundData(fake_outbound_packets); | |
662 AddMockInboundData(fake_inbound_packets); | |
663 | |
664 EXPECT_CALL(mock_handle(), | |
665 IsochronousTransfer(USB_DIRECTION_OUTBOUND, 0, _, | |
666 fake_outbound_packets.size(), 4, 8, 0, _)); | |
667 | |
668 { | |
669 base::RunLoop loop; | |
670 mojo::Array<mojo::Array<uint8_t>> packets = | |
671 mojo::Array<mojo::Array<uint8_t>>::New(4); | |
672 for (size_t i = 0; i < 4; ++i) { | |
673 std::vector<uint8_t> bytes(8); | |
674 std::copy(outbound_packet_data.begin() + i * 8, | |
675 outbound_packet_data.begin() + i * 8 + 8, bytes.begin()); | |
676 packets[i].Swap(&bytes); | |
677 } | |
678 device->IsochronousTransferOut( | |
679 0, packets.Pass(), 0, | |
680 base::Bind(&ExpectTransferStatusAndThen, TRANSFER_STATUS_COMPLETED, | |
681 loop.QuitClosure())); | |
682 loop.Run(); | |
683 } | |
684 | |
685 EXPECT_CALL(mock_handle(), | |
686 IsochronousTransfer(USB_DIRECTION_INBOUND, 0, _, | |
687 fake_inbound_packets.size(), 4, 8, 0, _)); | |
688 | |
689 { | |
690 base::RunLoop loop; | |
691 std::vector<std::vector<uint8_t>> packets(4); | |
692 for (size_t i = 0; i < 4; ++i) { | |
693 packets[i].resize(8); | |
694 std::copy(inbound_packet_data.begin() + i * 8, | |
695 inbound_packet_data.begin() + i * 8 + 8, packets[i].begin()); | |
696 } | |
697 device->IsochronousTransferIn( | |
698 0, 4, 8, 0, base::Bind(&ExpectPacketsAndThen, TRANSFER_STATUS_COMPLETED, | |
699 packets, loop.QuitClosure())); | |
700 loop.Run(); | |
701 } | |
702 | |
703 EXPECT_CALL(mock_handle(), Close()); | |
704 } | |
705 | |
706 } // namespace usb | |
707 } // namespace device | |
OLD | NEW |