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/usb/mock_usb_device.h"
18 #include "device/usb/mock_usb_device_handle.h"
19 #include "device/usb/mock_usb_service.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h"
23 using ::testing::Invoke
;
31 class TestPermissionProvider
: public PermissionProvider
{
33 TestPermissionProvider(mojo::InterfaceRequest
<PermissionProvider
> request
)
34 : binding_(this, request
.Pass()) {}
35 ~TestPermissionProvider() override
{}
37 void HasDevicePermission(
38 mojo::Array
<DeviceInfoPtr
> requested_devices
,
39 const HasDevicePermissionCallback
& callback
) override
{
40 // Permission to access all devices granted.
41 mojo::Array
<mojo::String
> allowed_guids(requested_devices
.size());
42 for (size_t i
= 0; i
< requested_devices
.size(); ++i
)
43 allowed_guids
[i
] = requested_devices
[i
]->guid
;
44 callback
.Run(allowed_guids
.Pass());
48 mojo::StrongBinding
<PermissionProvider
> binding_
;
51 class TestDeviceClient
: public DeviceClient
{
54 ~TestDeviceClient() override
{}
56 MockUsbService
& mock_usb_service() { return mock_usb_service_
; }
59 // DeviceClient implementation:
60 UsbService
* GetUsbService() override
{ return &mock_usb_service_
; }
62 MockUsbService mock_usb_service_
;
65 class USBDeviceManagerImplTest
: public testing::Test
{
67 USBDeviceManagerImplTest()
68 : device_client_(new TestDeviceClient
),
69 message_loop_(new base::MessageLoop
) {}
70 ~USBDeviceManagerImplTest() override
{}
73 MockUsbService
& mock_usb_service() {
74 return device_client_
->mock_usb_service();
77 DeviceManagerPtr
ConnectToDeviceManager() {
78 PermissionProviderPtr permission_provider
;
79 new TestPermissionProvider(mojo::GetProxy(&permission_provider
));
80 DeviceManagerPtr device_manager
;
81 new DeviceManagerImpl(mojo::GetProxy(&device_manager
),
82 permission_provider
.Pass(),
83 base::ThreadTaskRunnerHandle::Get());
84 return device_manager
.Pass();
88 scoped_ptr
<TestDeviceClient
> device_client_
;
89 scoped_ptr
<base::MessageLoop
> message_loop_
;
92 void ExpectDevicesAndThen(const std::set
<std::string
>& expected_guids
,
93 const base::Closure
& continuation
,
94 mojo::Array
<DeviceInfoPtr
> results
) {
95 EXPECT_EQ(expected_guids
.size(), results
.size());
96 std::set
<std::string
> actual_guids
;
97 for (size_t i
= 0; i
< results
.size(); ++i
)
98 actual_guids
.insert(results
[i
]->guid
);
99 EXPECT_EQ(expected_guids
, actual_guids
);
103 void ExpectDeviceChangesAndThen(
104 const std::set
<std::string
>& expected_added_guids
,
105 const std::set
<std::string
>& expected_removed_guids
,
106 const base::Closure
& continuation
,
107 DeviceChangeNotificationPtr results
) {
108 EXPECT_EQ(expected_added_guids
.size(), results
->devices_added
.size());
109 std::set
<std::string
> actual_added_guids
;
110 for (size_t i
= 0; i
< results
->devices_added
.size(); ++i
)
111 actual_added_guids
.insert(results
->devices_added
[i
]->guid
);
112 EXPECT_EQ(expected_added_guids
, actual_added_guids
);
113 EXPECT_EQ(expected_removed_guids
.size(), results
->devices_removed
.size());
114 std::set
<std::string
> actual_removed_guids
;
115 for (size_t i
= 0; i
< results
->devices_removed
.size(); ++i
)
116 actual_removed_guids
.insert(results
->devices_removed
[i
]->guid
);
117 EXPECT_EQ(expected_removed_guids
, actual_removed_guids
);
121 void ExpectDeviceInfoAndThen(const std::string
& expected_guid
,
122 const base::Closure
& continuation
,
123 DeviceInfoPtr device_info
) {
124 ASSERT_TRUE(device_info
);
125 EXPECT_EQ(expected_guid
, device_info
->guid
);
131 // Test basic GetDevices functionality to ensure that all mock devices are
132 // returned by the service.
133 TEST_F(USBDeviceManagerImplTest
, GetDevices
) {
134 scoped_refptr
<MockUsbDevice
> device0
=
135 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
136 scoped_refptr
<MockUsbDevice
> device1
=
137 new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
138 scoped_refptr
<MockUsbDevice
> device2
=
139 new MockUsbDevice(0x1234, 0x567a, "ACME", "Frobinator Mk II", "MNOPQR");
141 mock_usb_service().AddDevice(device0
);
142 mock_usb_service().AddDevice(device1
);
143 mock_usb_service().AddDevice(device2
);
145 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
147 EnumerationOptionsPtr options
= EnumerationOptions::New();
148 options
->filters
= mojo::Array
<DeviceFilterPtr
>::New(1);
149 options
->filters
[0] = DeviceFilter::New();
150 options
->filters
[0]->has_vendor_id
= true;
151 options
->filters
[0]->vendor_id
= 0x1234;
153 std::set
<std::string
> guids
;
154 guids
.insert(device0
->guid());
155 guids
.insert(device1
->guid());
156 guids
.insert(device2
->guid());
159 device_manager
->GetDevices(
161 base::Bind(&ExpectDevicesAndThen
, guids
, loop
.QuitClosure()));
165 // Test requesting a single Device by GUID.
166 TEST_F(USBDeviceManagerImplTest
, GetDevice
) {
167 scoped_refptr
<MockUsbDevice
> mock_device
=
168 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
170 mock_usb_service().AddDevice(mock_device
);
172 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
177 device_manager
->GetDevice(mock_device
->guid(), mojo::GetProxy(&device
));
178 device
->GetDeviceInfo(base::Bind(&ExpectDeviceInfoAndThen
,
179 mock_device
->guid(), loop
.QuitClosure()));
183 DevicePtr bad_device
;
184 device_manager
->GetDevice("not a real guid", mojo::GetProxy(&bad_device
));
188 bad_device
.set_connection_error_handler(loop
.QuitClosure());
193 // Test requesting device enumeration updates with GetDeviceChanges.
194 TEST_F(USBDeviceManagerImplTest
, GetDeviceChanges
) {
195 scoped_refptr
<MockUsbDevice
> device0
=
196 new MockUsbDevice(0x1234, 0x5678, "ACME", "Frobinator", "ABCDEF");
197 scoped_refptr
<MockUsbDevice
> device1
=
198 new MockUsbDevice(0x1234, 0x5679, "ACME", "Frobinator+", "GHIJKL");
199 scoped_refptr
<MockUsbDevice
> device2
=
200 new MockUsbDevice(0x1234, 0x567a, "ACME", "Frobinator Mk II", "MNOPQR");
201 scoped_refptr
<MockUsbDevice
> device3
=
202 new MockUsbDevice(0x1234, 0x567b, "ACME", "Frobinator Xtreme", "STUVWX");
204 mock_usb_service().AddDevice(device0
);
206 DeviceManagerPtr device_manager
= ConnectToDeviceManager();
209 // Call GetDevices once to make sure the device manager is up and running
210 // or else we could end up waiting forever for device changes as the next
211 // block races with the ServiceThreadHelper startup.
212 std::set
<std::string
> guids
;
213 guids
.insert(device0
->guid());
215 device_manager
->GetDevices(
216 nullptr, base::Bind(&ExpectDevicesAndThen
, guids
, loop
.QuitClosure()));
220 mock_usb_service().AddDevice(device1
);
221 mock_usb_service().AddDevice(device2
);
222 mock_usb_service().RemoveDevice(device1
);
225 std::set
<std::string
> added_guids
;
226 std::set
<std::string
> removed_guids
;
227 added_guids
.insert(device2
->guid());
229 device_manager
->GetDeviceChanges(base::Bind(&ExpectDeviceChangesAndThen
,
230 added_guids
, removed_guids
,
231 loop
.QuitClosure()));
235 mock_usb_service().RemoveDevice(device0
);
236 mock_usb_service().RemoveDevice(device2
);
237 mock_usb_service().AddDevice(device3
);
240 std::set
<std::string
> added_guids
;
241 std::set
<std::string
> removed_guids
;
242 added_guids
.insert(device3
->guid());
243 removed_guids
.insert(device0
->guid());
244 removed_guids
.insert(device2
->guid());
246 device_manager
->GetDeviceChanges(base::Bind(&ExpectDeviceChangesAndThen
,
247 added_guids
, removed_guids
,
248 loop
.QuitClosure()));
254 } // namespace device