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.
5 #include "content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h"
7 #include "device/bluetooth/bluetooth_adapter.h"
8 #include "device/bluetooth/bluetooth_device.h"
9 #include "device/bluetooth/bluetooth_discovery_session.h"
10 #include "device/bluetooth/bluetooth_uuid.h"
11 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
12 #include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
13 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
14 #include "testing/gmock/include/gmock/gmock.h"
16 using device::BluetoothAdapter
;
17 using device::BluetoothAdapterFactory
;
18 using device::BluetoothDevice
;
19 using device::BluetoothDiscoverySession
;
20 using device::BluetoothGattConnection
;
21 using device::BluetoothGattService
;
22 using device::BluetoothUUID
;
23 using device::MockBluetoothAdapter
;
24 using device::MockBluetoothDevice
;
25 using device::MockBluetoothDiscoverySession
;
26 using device::MockBluetoothGattCharacteristic
;
27 using device::MockBluetoothGattConnection
;
28 using device::MockBluetoothGattService
;
29 using testing::Between
;
30 using testing::ElementsAre
;
31 using testing::Invoke
;
32 using testing::NiceMock
;
33 using testing::ResultOf
;
34 using testing::Return
;
35 using testing::WithArgs
;
39 // Bluetooth UUIDs suitable to pass to BluetoothUUID().
40 const char kBatteryServiceUUID
[] = "180f";
41 const char kGenericAccessServiceUUID
[] = "1800";
42 const char kGenericAttributeServiceUUID
[] = "1801";
43 const char kGlucoseServiceUUID
[] = "1808";
44 const char kHeartRateServiceUUID
[] = "180d";
46 // Invokes Run() on the k-th argument of the function with no arguments.
47 ACTION_TEMPLATE(RunCallback
,
48 HAS_1_TEMPLATE_PARAMS(int, k
),
49 AND_0_VALUE_PARAMS()) {
50 return ::testing::get
<k
>(args
).Run();
53 // Invokes Run() on the k-th argument of the function with 1 argument.
54 ACTION_TEMPLATE(RunCallback
,
55 HAS_1_TEMPLATE_PARAMS(int, k
),
56 AND_1_VALUE_PARAMS(p0
)) {
57 return ::testing::get
<k
>(args
).Run(p0
);
60 // Invokes Run() on the k-th argument of the function with the result
61 // of |func| as an argument.
62 ACTION_TEMPLATE(RunCallbackWithResult
,
63 HAS_1_TEMPLATE_PARAMS(int, k
),
64 AND_1_VALUE_PARAMS(func
)) {
65 return ::testing::get
<k
>(args
).Run(func());
68 // Function to iterate over the adapter's devices and return the one
69 // that matches the address.
70 ACTION_P(GetMockDevice
, adapter
) {
71 std::string address
= arg0
;
72 for (BluetoothDevice
* device
: adapter
->GetMockDevices()) {
73 if (device
->GetAddress() == address
)
79 std::set
<BluetoothUUID
> GetUUIDs(
80 const device::BluetoothDiscoveryFilter
* filter
) {
81 std::set
<BluetoothUUID
> result
;
82 filter
->GetUUIDs(result
);
91 scoped_refptr
<BluetoothAdapter
>
92 LayoutTestBluetoothAdapterProvider::GetBluetoothAdapter(
93 const std::string
& fake_adapter_name
) {
94 if (fake_adapter_name
== "EmptyAdapter")
95 return GetEmptyAdapter();
96 else if (fake_adapter_name
== "SingleEmptyDeviceAdapter")
97 return GetSingleEmptyDeviceAdapter();
98 else if (fake_adapter_name
== "ConnectableDeviceAdapter")
99 return GetConnectableDeviceAdapter();
100 else if (fake_adapter_name
== "UnconnectableDeviceAdapter")
101 return GetUnconnectableDeviceAdapter();
102 else if (fake_adapter_name
== "ScanFilterCheckingAdapter")
103 return GetScanFilterCheckingAdapter();
104 else if (fake_adapter_name
== "MultiDeviceAdapter")
105 return GetMultiDeviceAdapter();
106 else if (fake_adapter_name
== "")
109 NOTREACHED() << fake_adapter_name
;
114 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
115 LayoutTestBluetoothAdapterProvider::GetEmptyAdapter() {
116 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(
117 new NiceMock
<MockBluetoothAdapter
>());
119 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
120 .WillByDefault(RunCallbackWithResult
<1 /* success_callback */>(
121 []() { return GetDiscoverySession(); }));
123 // Using Invoke allows the adapter returned from this method to be futher
124 // modified and have devices added to it. The call to ::GetDevices will
125 // invoke ::GetConstMockDevices, returning all devices added up to that time.
126 ON_CALL(*adapter
, GetDevices())
128 Invoke(adapter
.get(), &MockBluetoothAdapter::GetConstMockDevices
));
130 // The call to ::GetDevice will invoke GetMockDevice which returns a device
131 // matching the address provided if the device was added to the mock.
132 ON_CALL(*adapter
, GetDevice(_
)).WillByDefault(GetMockDevice(adapter
.get()));
134 return adapter
.Pass();
138 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
139 LayoutTestBluetoothAdapterProvider::GetScanFilterCheckingAdapter() {
140 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(
141 new NiceMock
<MockBluetoothAdapter
>());
143 // This fails the test with an error message listing actual and expected UUIDs
144 // if StartDiscoverySessionWithFilter() is called with the wrong argument.
147 StartDiscoverySessionWithFilterRaw(
148 ResultOf(&GetUUIDs
, ElementsAre(BluetoothUUID(kGlucoseServiceUUID
),
149 BluetoothUUID(kHeartRateServiceUUID
),
150 BluetoothUUID(kBatteryServiceUUID
))),
152 .WillRepeatedly(RunCallbackWithResult
<1 /* success_callback */>(
153 []() { return GetDiscoverySession(); }));
155 // Any unexpected call results in the failure callback.
156 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
157 .WillByDefault(RunCallback
<2 /* failure_callback */>());
159 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> battery_device
=
160 GetEmptyDevice(adapter
.get(), "Battery Device");
161 BluetoothDevice::UUIDList battery_uuid_list
;
162 battery_uuid_list
.push_back(BluetoothUUID(kBatteryServiceUUID
));
163 ON_CALL(*battery_device
, GetUUIDs()).WillByDefault(Return(battery_uuid_list
));
164 adapter
->AddMockDevice(battery_device
.Pass());
166 // This adapter isn't modified further, so we just return a hard-coded list.
167 ON_CALL(*adapter
, GetDevices())
168 .WillByDefault(Return(adapter
->GetConstMockDevices()));
170 return adapter
.Pass();
174 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
175 LayoutTestBluetoothAdapterProvider::GetSingleEmptyDeviceAdapter() {
176 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(GetEmptyAdapter());
178 adapter
->AddMockDevice(GetEmptyDevice(adapter
.get()));
180 return adapter
.Pass();
184 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
185 LayoutTestBluetoothAdapterProvider::GetMultiDeviceAdapter() {
186 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(GetEmptyAdapter());
188 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> heart_rate_device
=
189 GetEmptyDevice(adapter
.get(), "Heart Rate Device");
190 BluetoothDevice::UUIDList heart_rate_uuid_list
;
191 heart_rate_uuid_list
.push_back(BluetoothUUID(kHeartRateServiceUUID
));
192 heart_rate_uuid_list
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
193 heart_rate_uuid_list
.push_back(BluetoothUUID(kGenericAttributeServiceUUID
));
194 ON_CALL(*heart_rate_device
, GetUUIDs())
195 .WillByDefault(Return(heart_rate_uuid_list
));
196 adapter
->AddMockDevice(heart_rate_device
.Pass());
198 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> glucose_device
=
199 GetEmptyDevice(adapter
.get(), "Glucose Device");
200 BluetoothDevice::UUIDList glucose_uuid_list
;
201 glucose_uuid_list
.push_back(BluetoothUUID(kGlucoseServiceUUID
));
202 glucose_uuid_list
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
203 glucose_uuid_list
.push_back(BluetoothUUID(kGenericAttributeServiceUUID
));
204 ON_CALL(*glucose_device
, GetUUIDs()).WillByDefault(Return(glucose_uuid_list
));
205 adapter
->AddMockDevice(glucose_device
.Pass());
207 return adapter
.Pass();
211 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
212 LayoutTestBluetoothAdapterProvider::GetConnectableDeviceAdapter() {
213 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(GetEmptyAdapter());
215 adapter
->AddMockDevice(GetConnectableDevice(adapter
.get()));
217 return adapter
.Pass();
221 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>>
222 LayoutTestBluetoothAdapterProvider::GetUnconnectableDeviceAdapter() {
223 scoped_refptr
<NiceMock
<MockBluetoothAdapter
>> adapter(GetEmptyAdapter());
225 adapter
->AddMockDevice(GetUnconnectableDevice(adapter
.get()));
227 return adapter
.Pass();
231 scoped_ptr
<NiceMock
<MockBluetoothDiscoverySession
>>
232 LayoutTestBluetoothAdapterProvider::GetDiscoverySession() {
233 scoped_ptr
<NiceMock
<MockBluetoothDiscoverySession
>> discovery_session(
234 new NiceMock
<MockBluetoothDiscoverySession
>());
236 ON_CALL(*discovery_session
, Stop(_
, _
))
237 .WillByDefault(RunCallback
<0 /* success_callback */>());
239 return discovery_session
.Pass();
243 scoped_ptr
<NiceMock
<MockBluetoothDevice
>>
244 LayoutTestBluetoothAdapterProvider::GetEmptyDevice(
245 MockBluetoothAdapter
* adapter
,
246 const std::string
& device_name
) {
247 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> empty_device(
248 new NiceMock
<MockBluetoothDevice
>(
249 adapter
, 0x1F00 /* Bluetooth Class */, device_name
,
250 device_name
+ " instanceID", true /* Paired */,
251 true /* Connected */));
253 ON_CALL(*empty_device
, GetVendorIDSource())
254 .WillByDefault(Return(BluetoothDevice::VENDOR_ID_BLUETOOTH
));
255 ON_CALL(*empty_device
, GetVendorID()).WillByDefault(Return(0xFFFF));
256 ON_CALL(*empty_device
, GetProductID()).WillByDefault(Return(1));
257 ON_CALL(*empty_device
, GetDeviceID()).WillByDefault(Return(2));
259 BluetoothDevice::UUIDList list
;
260 list
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
261 list
.push_back(BluetoothUUID(kGenericAttributeServiceUUID
));
262 ON_CALL(*empty_device
, GetUUIDs()).WillByDefault(Return(list
));
264 scoped_ptr
<NiceMock
<MockBluetoothGattService
>> generic_access(
265 GetGattService(empty_device
.get(), kGenericAccessServiceUUID
));
266 scoped_ptr
<NiceMock
<MockBluetoothGattCharacteristic
>>
267 device_name_characteristic(GetGattCharacteristic(
268 generic_access
.get(), "2A00" /* Device Name */));
270 std::vector
<uint8_t> device_name_value(device_name
.begin(),
272 ON_CALL(*device_name_characteristic
, ReadRemoteCharacteristic(_
, _
))
273 .WillByDefault(RunCallback
<0>(device_name_value
));
275 ON_CALL(*device_name_characteristic
, WriteRemoteCharacteristic(_
, _
, _
))
276 .WillByDefault(RunCallback
<2 /* error callback */>(
277 BluetoothGattService::GATT_ERROR_NOT_PERMITTED
));
279 generic_access
->AddMockCharacteristic(device_name_characteristic
.Pass());
281 scoped_ptr
<NiceMock
<MockBluetoothGattCharacteristic
>> reconnection_address(
282 GetGattCharacteristic(generic_access
.get(),
283 "2A03" /* Reconnection Address */));
285 ON_CALL(*reconnection_address
, ReadRemoteCharacteristic(_
, _
))
287 RunCallback
<1>(BluetoothGattService::GATT_ERROR_NOT_PERMITTED
));
289 ON_CALL(*reconnection_address
, WriteRemoteCharacteristic(_
, _
, _
))
290 .WillByDefault(RunCallback
<1 /* success callback */>());
292 generic_access
->AddMockCharacteristic(reconnection_address
.Pass());
294 empty_device
->AddMockService(generic_access
.Pass());
296 // Using Invoke allows the device returned from this method to be futher
297 // modified and have more services added to it. The call to ::GetGattServices
298 // will invoke ::GetMockServices, returning all services added up to that
300 ON_CALL(*empty_device
, GetGattServices())
302 Invoke(empty_device
.get(), &MockBluetoothDevice::GetMockServices
));
304 // The call to BluetoothDevice::GetGattService will invoke ::GetMockService
305 // which returns a service matching the identifier provided if the service
306 // was added to the mock.
307 ON_CALL(*empty_device
, GetGattService(_
))
309 Invoke(empty_device
.get(), &MockBluetoothDevice::GetMockService
));
311 return empty_device
.Pass();
315 scoped_ptr
<NiceMock
<MockBluetoothDevice
>>
316 LayoutTestBluetoothAdapterProvider::GetConnectableDevice(
317 MockBluetoothAdapter
* adapter
) {
318 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> device(GetEmptyDevice(adapter
));
320 BluetoothDevice
* device_ptr
= device
.get();
322 ON_CALL(*device
, CreateGattConnection(_
, _
))
324 RunCallbackWithResult
<0 /* success_callback */>([device_ptr
]() {
325 return make_scoped_ptr(new NiceMock
<MockBluetoothGattConnection
>(
326 device_ptr
->GetAddress()));
329 return device
.Pass();
333 scoped_ptr
<NiceMock
<MockBluetoothDevice
>>
334 LayoutTestBluetoothAdapterProvider::GetUnconnectableDevice(
335 MockBluetoothAdapter
* adapter
) {
336 scoped_ptr
<NiceMock
<MockBluetoothDevice
>> device(GetEmptyDevice(adapter
));
338 ON_CALL(*device
, CreateGattConnection(_
, _
))
340 RunCallback
<1 /* error_callback */>(BluetoothDevice::ERROR_FAILED
));
342 return device
.Pass();
346 scoped_ptr
<NiceMock
<MockBluetoothGattService
>>
347 LayoutTestBluetoothAdapterProvider::GetGattService(MockBluetoothDevice
* device
,
348 const std::string
& uuid
) {
349 scoped_ptr
<NiceMock
<MockBluetoothGattService
>> service(
350 new NiceMock
<MockBluetoothGattService
>(
351 device
, uuid
/* identifier */, BluetoothUUID(uuid
),
352 true /* is_primary */, false /* is_local */));
354 ON_CALL(*service
, GetCharacteristics())
355 .WillByDefault(Invoke(service
.get(),
356 &MockBluetoothGattService::GetMockCharacteristics
));
358 ON_CALL(*service
, GetCharacteristic(_
))
359 .WillByDefault(Invoke(service
.get(),
360 &MockBluetoothGattService::GetMockCharacteristic
));
362 return service
.Pass();
366 scoped_ptr
<NiceMock
<MockBluetoothGattCharacteristic
>>
367 LayoutTestBluetoothAdapterProvider::GetGattCharacteristic(
368 MockBluetoothGattService
* service
,
369 const std::string
& uuid
) {
370 return make_scoped_ptr(new NiceMock
<MockBluetoothGattCharacteristic
>(
371 service
, uuid
/* identifier */, BluetoothUUID(uuid
), false /* is_local */,
372 NULL
/* properties */, NULL
/* permissions */));
375 } // namespace content