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.
6 #include "base/message_loop/message_loop.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/test/test_io_thread.h"
10 #include "device/test/test_device_client.h"
11 #include "device/test/usb_test_gadget.h"
12 #include "device/usb/usb_device.h"
13 #include "device/usb/usb_device_handle.h"
14 #include "testing/gtest/include/gtest/gtest.h"
20 class UsbDeviceHandleTest
: public ::testing::Test
{
22 void SetUp() override
{
23 message_loop_
.reset(new base::MessageLoopForUI
);
24 io_thread_
.reset(new base::TestIOThread(base::TestIOThread::kAutoStart
));
25 device_client_
.reset(new TestDeviceClient(io_thread_
->task_runner()));
29 scoped_ptr
<base::TestIOThread
> io_thread_
;
32 scoped_ptr
<base::MessageLoop
> message_loop_
;
33 scoped_ptr
<TestDeviceClient
> device_client_
;
36 class TestOpenCallback
{
40 base::Bind(&TestOpenCallback::SetResult
, base::Unretained(this))) {}
42 scoped_refptr
<UsbDeviceHandle
> WaitForResult() {
44 return device_handle_
;
47 const UsbDevice::OpenCallback
& callback() const { return callback_
; }
50 void SetResult(scoped_refptr
<UsbDeviceHandle
> device_handle
) {
51 device_handle_
= device_handle
;
55 const UsbDevice::OpenCallback callback_
;
56 base::RunLoop run_loop_
;
57 scoped_refptr
<UsbDeviceHandle
> device_handle_
;
60 class TestResultCallback
{
63 : callback_(base::Bind(&TestResultCallback::SetResult
,
64 base::Unretained(this))) {}
66 bool WaitForResult() {
71 const UsbDeviceHandle::ResultCallback
& callback() const { return callback_
; }
74 void SetResult(bool success
) {
79 const UsbDeviceHandle::ResultCallback callback_
;
80 base::RunLoop run_loop_
;
84 class TestCompletionCallback
{
86 TestCompletionCallback()
87 : callback_(base::Bind(&TestCompletionCallback::SetResult
,
88 base::Unretained(this))) {}
90 void WaitForResult() { run_loop_
.Run(); }
92 const UsbDeviceHandle::TransferCallback
& callback() const {
95 UsbTransferStatus
status() const { return status_
; }
96 size_t transferred() const { return transferred_
; }
99 void SetResult(UsbTransferStatus status
,
100 scoped_refptr
<net::IOBuffer
> buffer
,
101 size_t transferred
) {
103 transferred_
= transferred
;
107 const UsbDeviceHandle::TransferCallback callback_
;
108 base::RunLoop run_loop_
;
109 UsbTransferStatus status_
;
113 TEST_F(UsbDeviceHandleTest
, InterruptTransfer
) {
114 if (!UsbTestGadget::IsTestEnabled()) {
118 scoped_ptr
<UsbTestGadget
> gadget
=
119 UsbTestGadget::Claim(io_thread_
->task_runner());
120 ASSERT_TRUE(gadget
.get());
121 ASSERT_TRUE(gadget
->SetType(UsbTestGadget::ECHO
));
123 TestOpenCallback open_device
;
124 gadget
->GetDevice()->Open(open_device
.callback());
125 scoped_refptr
<UsbDeviceHandle
> handle
= open_device
.WaitForResult();
126 ASSERT_TRUE(handle
.get());
128 TestResultCallback claim_interface
;
129 handle
->ClaimInterface(0, claim_interface
.callback());
130 ASSERT_TRUE(claim_interface
.WaitForResult());
132 scoped_refptr
<net::IOBufferWithSize
> in_buffer(new net::IOBufferWithSize(64));
133 TestCompletionCallback in_completion
;
134 handle
->GenericTransfer(USB_DIRECTION_INBOUND
, 0x81, in_buffer
.get(),
136 5000, // 5 second timeout
137 in_completion
.callback());
139 scoped_refptr
<net::IOBufferWithSize
> out_buffer(
140 new net::IOBufferWithSize(in_buffer
->size()));
141 TestCompletionCallback out_completion
;
142 for (int i
= 0; i
< out_buffer
->size(); ++i
) {
143 out_buffer
->data()[i
] = i
;
146 handle
->GenericTransfer(USB_DIRECTION_OUTBOUND
, 0x01, out_buffer
.get(),
148 5000, // 5 second timeout
149 out_completion
.callback());
150 out_completion
.WaitForResult();
151 ASSERT_EQ(USB_TRANSFER_COMPLETED
, out_completion
.status());
152 EXPECT_EQ(static_cast<size_t>(out_buffer
->size()),
153 out_completion
.transferred());
155 in_completion
.WaitForResult();
156 ASSERT_EQ(USB_TRANSFER_COMPLETED
, in_completion
.status());
157 EXPECT_EQ(static_cast<size_t>(in_buffer
->size()),
158 in_completion
.transferred());
159 for (size_t i
= 0; i
< in_completion
.transferred(); ++i
) {
160 EXPECT_EQ(out_buffer
->data()[i
], in_buffer
->data()[i
])
161 << "Mismatch at index " << i
<< ".";
167 TEST_F(UsbDeviceHandleTest
, BulkTransfer
) {
168 if (!UsbTestGadget::IsTestEnabled()) {
172 scoped_ptr
<UsbTestGadget
> gadget
=
173 UsbTestGadget::Claim(io_thread_
->task_runner());
174 ASSERT_TRUE(gadget
.get());
175 ASSERT_TRUE(gadget
->SetType(UsbTestGadget::ECHO
));
177 TestOpenCallback open_device
;
178 gadget
->GetDevice()->Open(open_device
.callback());
179 scoped_refptr
<UsbDeviceHandle
> handle
= open_device
.WaitForResult();
180 ASSERT_TRUE(handle
.get());
182 TestResultCallback claim_interface
;
183 handle
->ClaimInterface(1, claim_interface
.callback());
184 ASSERT_TRUE(claim_interface
.WaitForResult());
186 scoped_refptr
<net::IOBufferWithSize
> in_buffer(
187 new net::IOBufferWithSize(512));
188 TestCompletionCallback in_completion
;
189 handle
->GenericTransfer(USB_DIRECTION_INBOUND
, 0x82, in_buffer
.get(),
191 5000, // 5 second timeout
192 in_completion
.callback());
194 scoped_refptr
<net::IOBufferWithSize
> out_buffer(
195 new net::IOBufferWithSize(in_buffer
->size()));
196 TestCompletionCallback out_completion
;
197 for (int i
= 0; i
< out_buffer
->size(); ++i
) {
198 out_buffer
->data()[i
] = i
;
201 handle
->GenericTransfer(USB_DIRECTION_OUTBOUND
, 0x02, out_buffer
.get(),
203 5000, // 5 second timeout
204 out_completion
.callback());
205 out_completion
.WaitForResult();
206 ASSERT_EQ(USB_TRANSFER_COMPLETED
, out_completion
.status());
207 EXPECT_EQ(static_cast<size_t>(out_buffer
->size()),
208 out_completion
.transferred());
210 in_completion
.WaitForResult();
211 ASSERT_EQ(USB_TRANSFER_COMPLETED
, in_completion
.status());
212 EXPECT_EQ(static_cast<size_t>(in_buffer
->size()),
213 in_completion
.transferred());
214 for (size_t i
= 0; i
< in_completion
.transferred(); ++i
) {
215 EXPECT_EQ(out_buffer
->data()[i
], in_buffer
->data()[i
])
216 << "Mismatch at index " << i
<< ".";
222 TEST_F(UsbDeviceHandleTest
, SetInterfaceAlternateSetting
) {
223 if (!UsbTestGadget::IsTestEnabled()) {
227 scoped_ptr
<UsbTestGadget
> gadget
=
228 UsbTestGadget::Claim(io_thread_
->task_runner());
229 ASSERT_TRUE(gadget
.get());
230 ASSERT_TRUE(gadget
->SetType(UsbTestGadget::ECHO
));
232 TestOpenCallback open_device
;
233 gadget
->GetDevice()->Open(open_device
.callback());
234 scoped_refptr
<UsbDeviceHandle
> handle
= open_device
.WaitForResult();
235 ASSERT_TRUE(handle
.get());
237 TestResultCallback claim_interface
;
238 handle
->ClaimInterface(2, claim_interface
.callback());
239 ASSERT_TRUE(claim_interface
.WaitForResult());
241 TestResultCallback set_interface
;
242 handle
->SetInterfaceAlternateSetting(2, 1, set_interface
.callback());
243 ASSERT_TRUE(set_interface
.WaitForResult());
250 } // namespace device