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.
9 #include "base/macros.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "device/core/device_client.h"
15 #include "device/devices_app/usb/device_impl.h"
16 #include "device/devices_app/usb/device_manager_impl.h"
17 #include "device/devices_app/usb/public/cpp/device_manager_delegate.h"
18 #include "device/usb/mock_usb_device.h"
19 #include "device/usb/mock_usb_device_handle.h"
20 #include "device/usb/mock_usb_service.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
24 using ::testing::Invoke
;
32 class TestDeviceManagerDelegate
: public DeviceManagerDelegate
{
34 TestDeviceManagerDelegate() {}
35 ~TestDeviceManagerDelegate() override
{}
38 // DeviceManagerDelegate implementation:
39 bool IsDeviceAllowed(const DeviceInfo
& device_info
) override
{ return true; }
42 class TestDeviceClient
: public DeviceClient
{
45 ~TestDeviceClient() override
{}
47 MockUsbService
& mock_usb_service() { return mock_usb_service_
; }
50 // DeviceClient implementation:
51 UsbService
* GetUsbService() override
{ return &mock_usb_service_
; }
53 MockUsbService mock_usb_service_
;
56 class USBDeviceManagerImplTest
: public testing::Test
{
58 USBDeviceManagerImplTest()
59 : device_client_(new TestDeviceClient
),
60 message_loop_(new base::MessageLoop
) {}
61 ~USBDeviceManagerImplTest() override
{}
64 MockUsbService
& mock_usb_service() {
65 return device_client_
->mock_usb_service();
68 DeviceManagerPtr
ConnectToDeviceManager() {
69 DeviceManagerPtr device_manager
;
70 new DeviceManagerImpl(
71 mojo::GetProxy(&device_manager
),
72 scoped_ptr
<DeviceManagerDelegate
>(new TestDeviceManagerDelegate
),
73 base::ThreadTaskRunnerHandle::Get());
74 return device_manager
.Pass();
78 scoped_ptr
<TestDeviceClient
> device_client_
;
79 scoped_ptr
<base::MessageLoop
> message_loop_
;
82 class MockOpenCallback
{
84 explicit MockOpenCallback(UsbDevice
* device
) : device_(device
) {}
86 void Open(const UsbDevice::OpenCallback
& callback
) {
87 device_handle_
= new MockUsbDeviceHandle(device_
);
88 callback
.Run(device_handle_
);
91 scoped_refptr
<MockUsbDeviceHandle
> mock_handle() { return device_handle_
; }
95 scoped_refptr
<MockUsbDeviceHandle
> device_handle_
;
98 void ExpectDevicesAndThen(const std::set
<std::string
>& expected_guids
,
99 const base::Closure
& continuation
,
100 mojo::Array
<DeviceInfoPtr
> results
) {
101 EXPECT_EQ(expected_guids
.size(), results
.size());
102 std::set
<std::string
> actual_guids
;
103 for (size_t i
= 0; i
< results
.size(); ++i
)
104 actual_guids
.insert(results
[i
]->guid
);
105 EXPECT_EQ(expected_guids
, actual_guids
);
109 void ExpectDeviceChangesAndThen(
110 const std::set
<std::string
>& expected_added_guids
,
111 const std::set
<std::string
>& expected_removed_guids
,
112 const base::Closure
& continuation
,
113 DeviceChangeNotificationPtr results
) {
114 EXPECT_EQ(expected_added_guids
.size(), results
->devices_added
.size());
115 std::set
<std::string
> actual_added_guids
;
116 for (size_t i
= 0; i
< results
->devices_added
.size(); ++i
)
117 actual_added_guids
.insert(results
->devices_added
[i
]->guid
);
118 EXPECT_EQ(expected_added_guids
, actual_added_guids
);
119 EXPECT_EQ(expected_removed_guids
.size(), results
->devices_removed
.size());
120 std::set
<std::string
> actual_removed_guids
;
121 for (size_t i
= 0; i
< results
->devices_removed
.size(); ++i
)
122 actual_removed_guids
.insert(results
->devices_removed
[i
]);
123 EXPECT_EQ(expected_removed_guids
, actual_removed_guids
);
127 void ExpectDeviceInfoAndThen(const std::string
& expected_guid
,
128 const base::Closure
& continuation
,
129 DeviceInfoPtr device_info
) {
130 EXPECT_EQ(expected_guid
, device_info
->guid
);
134 void ExpectOpenDeviceError(OpenDeviceError expected_error
,
135 OpenDeviceError actual_error
) {
136 EXPECT_EQ(expected_error
, actual_error
);
139 void FailOnGetDeviceInfoResponse(DeviceInfoPtr device_info
) {
145 // Test basic GetDevices functionality to ensure that all mock devices are
146 // returned by the service.
147 TEST_F(USBDeviceManagerImplTest
, GetDevices
) {
148 scoped_refptr
<MockUsbDevice
> device0
=
149 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
150 scoped_refptr
<MockUsbDevice
> device1
=
151 new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
152 scoped_refptr
<MockUsbDevice
> device2
=
153 new MockUsbDevice(0x1234, 0x567a, "ACME", "Frobinator Mk II", "MNOPQR");
155 mock_usb_service().AddDevice(device0
);
156 mock_usb_service().AddDevice(device1
);
157 mock_usb_service().AddDevice(device2
);
159 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
161 EnumerationOptionsPtr options
= EnumerationOptions::New();
162 options
->filters
= mojo::Array
<DeviceFilterPtr
>::New(1);
163 options
->filters
[0] = DeviceFilter::New();
164 options
->filters
[0]->has_vendor_id
= true;
165 options
->filters
[0]->vendor_id
= 0x1234;
167 std::set
<std::string
> guids
;
168 guids
.insert(device0
->guid());
169 guids
.insert(device1
->guid());
170 guids
.insert(device2
->guid());
173 device_manager
->GetDevices(
175 base::Bind(&ExpectDevicesAndThen
, guids
, loop
.QuitClosure()));
179 // Test requesting a single Device by GUID.
180 TEST_F(USBDeviceManagerImplTest
, OpenDevice
) {
181 scoped_refptr
<MockUsbDevice
> mock_device
=
182 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
184 mock_usb_service().AddDevice(mock_device
);
186 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
188 // Should be called on the mock as a result of OpenDevice() below.
189 EXPECT_CALL(*mock_device
.get(), Open(_
));
191 MockOpenCallback
open_callback(mock_device
.get());
192 ON_CALL(*mock_device
.get(), Open(_
))
193 .WillByDefault(Invoke(&open_callback
, &MockOpenCallback::Open
));
198 device_manager
->OpenDevice(
199 mock_device
->guid(), mojo::GetProxy(&device
),
200 base::Bind(&ExpectOpenDeviceError
, OPEN_DEVICE_ERROR_OK
));
201 device
->GetDeviceInfo(base::Bind(&ExpectDeviceInfoAndThen
,
202 mock_device
->guid(), loop
.QuitClosure()));
206 // The device should eventually be closed when its MessagePipe is closed.
207 DCHECK(open_callback
.mock_handle());
208 EXPECT_CALL(*open_callback
.mock_handle().get(), Close());
210 DevicePtr bad_device
;
211 device_manager
->OpenDevice(
212 "not a real guid", mojo::GetProxy(&bad_device
),
213 base::Bind(&ExpectOpenDeviceError
, OPEN_DEVICE_ERROR_NOT_FOUND
));
217 bad_device
.set_connection_error_handler(loop
.QuitClosure());
218 bad_device
->GetDeviceInfo(base::Bind(&FailOnGetDeviceInfoResponse
));
223 // Test requesting device enumeration updates with GetDeviceChanges.
224 TEST_F(USBDeviceManagerImplTest
, GetDeviceChanges
) {
225 scoped_refptr
<MockUsbDevice
> device0
=
226 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
227 scoped_refptr
<MockUsbDevice
> device1
=
228 new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
229 scoped_refptr
<MockUsbDevice
> device2
=
230 new MockUsbDevice(0x1234, 0x567a, "ACME", "Frobinator Mk II", "MNOPQR");
231 scoped_refptr
<MockUsbDevice
> device3
=
232 new MockUsbDevice(0x1234, 0x567b, "ACME", "Frobinator Xtreme", "STUVWX");
234 mock_usb_service().AddDevice(device0
);
236 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
239 std::set
<std::string
> added_guids
;
240 std::set
<std::string
> removed_guids
;
241 added_guids
.insert(device0
->guid());
243 device_manager
->GetDeviceChanges(base::Bind(&ExpectDeviceChangesAndThen
,
244 added_guids
, removed_guids
,
245 loop
.QuitClosure()));
249 mock_usb_service().AddDevice(device1
);
250 mock_usb_service().AddDevice(device2
);
251 mock_usb_service().RemoveDevice(device1
);
254 std::set
<std::string
> added_guids
;
255 std::set
<std::string
> removed_guids
;
256 added_guids
.insert(device2
->guid());
258 device_manager
->GetDeviceChanges(base::Bind(&ExpectDeviceChangesAndThen
,
259 added_guids
, removed_guids
,
260 loop
.QuitClosure()));
264 mock_usb_service().RemoveDevice(device0
);
265 mock_usb_service().RemoveDevice(device2
);
266 mock_usb_service().AddDevice(device3
);
269 std::set
<std::string
> added_guids
;
270 std::set
<std::string
> removed_guids
;
271 added_guids
.insert(device3
->guid());
272 removed_guids
.insert(device0
->guid());
273 removed_guids
.insert(device2
->guid());
275 device_manager
->GetDeviceChanges(base::Bind(&ExpectDeviceChangesAndThen
,
276 added_guids
, removed_guids
,
277 loop
.QuitClosure()));
283 } // namespace device