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 "base/format_macros.h"
8 #include "base/strings/stringprintf.h"
9 #include "device/bluetooth/bluetooth_adapter.h"
10 #include "device/bluetooth/bluetooth_device.h"
11 #include "device/bluetooth/bluetooth_discovery_session.h"
12 #include "device/bluetooth/bluetooth_uuid.h"
13 #include "device/bluetooth/test/mock_bluetooth_adapter.h"
14 #include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
15 #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
16 #include "testing/gmock/include/gmock/gmock.h"
18 using device::BluetoothAdapter
;
19 using device::BluetoothDevice
;
20 using device::BluetoothGattService
;
21 using device::BluetoothUUID
;
22 using device::MockBluetoothAdapter
;
23 using device::MockBluetoothDevice
;
24 using device::MockBluetoothDiscoverySession
;
25 using device::MockBluetoothGattCharacteristic
;
26 using device::MockBluetoothGattConnection
;
27 using device::MockBluetoothGattService
;
28 using testing::ElementsAre
;
29 using testing::Invoke
;
30 using testing::ResultOf
;
31 using testing::Return
;
34 typedef testing::NiceMock
<MockBluetoothAdapter
> NiceMockBluetoothAdapter
;
35 typedef testing::NiceMock
<MockBluetoothDevice
> NiceMockBluetoothDevice
;
36 typedef testing::NiceMock
<MockBluetoothDiscoverySession
>
37 NiceMockBluetoothDiscoverySession
;
38 typedef testing::NiceMock
<MockBluetoothGattCharacteristic
>
39 NiceMockBluetoothGattCharacteristic
;
40 typedef testing::NiceMock
<MockBluetoothGattConnection
>
41 NiceMockBluetoothGattConnection
;
42 typedef testing::NiceMock
<MockBluetoothGattService
>
43 NiceMockBluetoothGattService
;
46 // Bluetooth UUIDs suitable to pass to BluetoothUUID().
47 const char kBatteryServiceUUID
[] = "180f";
48 const char kGenericAccessServiceUUID
[] = "1800";
49 const char kGlucoseServiceUUID
[] = "1808";
50 const char kHeartRateServiceUUID
[] = "180d";
51 const char kDeviceNameUUID
[] = "2a00";
53 // Invokes Run() on the k-th argument of the function with no arguments.
54 ACTION_TEMPLATE(RunCallback
,
55 HAS_1_TEMPLATE_PARAMS(int, k
),
56 AND_0_VALUE_PARAMS()) {
57 return ::testing::get
<k
>(args
).Run();
60 // Invokes Run() on the k-th argument of the function with 1 argument.
61 ACTION_TEMPLATE(RunCallback
,
62 HAS_1_TEMPLATE_PARAMS(int, k
),
63 AND_1_VALUE_PARAMS(p0
)) {
64 return ::testing::get
<k
>(args
).Run(p0
);
67 // Invokes Run() on the k-th argument of the function with the result
68 // of |func| as an argument.
69 ACTION_TEMPLATE(RunCallbackWithResult
,
70 HAS_1_TEMPLATE_PARAMS(int, k
),
71 AND_1_VALUE_PARAMS(func
)) {
72 return ::testing::get
<k
>(args
).Run(func());
75 // Function to iterate over the adapter's devices and return the one
76 // that matches the address.
77 ACTION_P(GetMockDevice
, adapter
) {
78 std::string address
= arg0
;
79 for (BluetoothDevice
* device
: adapter
->GetMockDevices()) {
80 if (device
->GetAddress() == address
)
86 std::set
<BluetoothUUID
> GetUUIDs(
87 const device::BluetoothDiscoveryFilter
* filter
) {
88 std::set
<BluetoothUUID
> result
;
89 filter
->GetUUIDs(result
);
98 scoped_refptr
<BluetoothAdapter
>
99 LayoutTestBluetoothAdapterProvider::GetBluetoothAdapter(
100 const std::string
& fake_adapter_name
) {
101 if (fake_adapter_name
== "BaseAdapter")
102 return GetBaseAdapter();
103 else if (fake_adapter_name
== "ScanFilterCheckingAdapter")
104 return GetScanFilterCheckingAdapter();
105 else if (fake_adapter_name
== "EmptyAdapter")
106 return GetEmptyAdapter();
107 else if (fake_adapter_name
== "FailStartDiscoveryAdapter")
108 return GetFailStartDiscoveryAdapter();
109 else if (fake_adapter_name
== "GlucoseHeartRateAdapter")
110 return GetGlucoseHeartRateAdapter();
111 else if (fake_adapter_name
== "MissingServiceGenericAccessAdapter")
112 return GetMissingServiceGenericAccessAdapter();
113 else if (fake_adapter_name
== "MissingCharacteristicGenericAccessAdapter")
114 return GetMissingCharacteristicGenericAccessAdapter();
115 else if (fake_adapter_name
== "GenericAccessAdapter")
116 return GetGenericAccessAdapter();
117 else if (fake_adapter_name
== "FailingConnectionsAdapter")
118 return GetFailingConnectionsAdapter();
119 else if (fake_adapter_name
== "FailingGATTOperationsAdapter")
120 return GetFailingGATTOperationsAdapter();
121 else if (fake_adapter_name
== "")
124 NOTREACHED() << fake_adapter_name
;
131 scoped_refptr
<NiceMockBluetoothAdapter
>
132 LayoutTestBluetoothAdapterProvider::GetBaseAdapter() {
133 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(
134 new NiceMockBluetoothAdapter());
136 // Using Invoke allows the adapter returned from this method to be futher
137 // modified and have devices added to it. The call to ::GetDevices will
138 // invoke ::GetConstMockDevices, returning all devices added up to that time.
139 ON_CALL(*adapter
, GetDevices())
141 Invoke(adapter
.get(), &MockBluetoothAdapter::GetConstMockDevices
));
143 // The call to ::GetDevice will invoke GetMockDevice which returns a device
144 // matching the address provided if the device was added to the mock.
145 ON_CALL(*adapter
, GetDevice(_
)).WillByDefault(GetMockDevice(adapter
.get()));
147 return adapter
.Pass();
151 scoped_refptr
<NiceMockBluetoothAdapter
>
152 LayoutTestBluetoothAdapterProvider::GetScanFilterCheckingAdapter() {
153 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetBaseAdapter());
155 // This fails the test with an error message listing actual and expected UUIDs
156 // if StartDiscoverySessionWithFilter() is called with the wrong argument.
159 StartDiscoverySessionWithFilterRaw(
160 ResultOf(&GetUUIDs
, ElementsAre(BluetoothUUID(kGlucoseServiceUUID
),
161 BluetoothUUID(kHeartRateServiceUUID
),
162 BluetoothUUID(kBatteryServiceUUID
))),
164 .WillRepeatedly(RunCallbackWithResult
<1 /* success_callback */>(
165 []() { return GetDiscoverySession(); }));
167 // Any unexpected call results in the failure callback.
168 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
169 .WillByDefault(RunCallback
<2 /* error_callback */>());
171 // We need to add a device otherwise requestDevice would reject.
172 adapter
->AddMockDevice(GetBatteryDevice(adapter
.get()));
174 return adapter
.Pass();
178 scoped_refptr
<NiceMockBluetoothAdapter
>
179 LayoutTestBluetoothAdapterProvider::GetFailStartDiscoveryAdapter() {
180 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetBaseAdapter());
182 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
183 .WillByDefault(RunCallback
<2 /* error_callback */>());
185 return adapter
.Pass();
189 scoped_refptr
<NiceMockBluetoothAdapter
>
190 LayoutTestBluetoothAdapterProvider::GetEmptyAdapter() {
191 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetBaseAdapter());
193 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
194 .WillByDefault(RunCallbackWithResult
<1 /* success_callback */>(
195 []() { return GetDiscoverySession(); }));
197 return adapter
.Pass();
201 scoped_refptr
<NiceMockBluetoothAdapter
>
202 LayoutTestBluetoothAdapterProvider::GetGlucoseHeartRateAdapter() {
203 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
205 adapter
->AddMockDevice(GetHeartRateDevice(adapter
.get()));
206 adapter
->AddMockDevice(GetGlucoseDevice(adapter
.get()));
208 return adapter
.Pass();
212 scoped_refptr
<NiceMockBluetoothAdapter
>
213 LayoutTestBluetoothAdapterProvider::GetMissingServiceGenericAccessAdapter() {
214 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
216 adapter
->AddMockDevice(GetGenericAccessDevice(adapter
.get()));
218 return adapter
.Pass();
222 scoped_refptr
<NiceMockBluetoothAdapter
> LayoutTestBluetoothAdapterProvider::
223 GetMissingCharacteristicGenericAccessAdapter() {
224 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
226 scoped_ptr
<NiceMockBluetoothDevice
> device(
227 GetGenericAccessDevice(adapter
.get()));
229 scoped_ptr
<NiceMockBluetoothGattService
> generic_access(
230 GetBaseGATTService(device
.get(), kGenericAccessServiceUUID
));
232 // Intentionally NOT adding a characteristic to generic_access service.
234 device
->AddMockService(generic_access
.Pass());
236 adapter
->AddMockDevice(device
.Pass());
238 return adapter
.Pass();
242 scoped_refptr
<NiceMockBluetoothAdapter
>
243 LayoutTestBluetoothAdapterProvider::GetGenericAccessAdapter() {
244 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
246 scoped_ptr
<NiceMockBluetoothDevice
> device(
247 GetGenericAccessDevice(adapter
.get()));
249 scoped_ptr
<NiceMockBluetoothGattService
> generic_access(
250 GetBaseGATTService(device
.get(), kGenericAccessServiceUUID
));
252 scoped_ptr
<NiceMockBluetoothGattCharacteristic
> device_name(
253 GetBaseGATTCharacteristic(generic_access
.get(), kDeviceNameUUID
));
256 std::string device_name_str
= device
->GetDeviceName();
257 std::vector
<uint8_t> device_name_value(device_name_str
.begin(),
258 device_name_str
.end());
260 ON_CALL(*device_name
, ReadRemoteCharacteristic(_
, _
))
261 .WillByDefault(RunCallback
<0>(device_name_value
));
264 ON_CALL(*device_name
, WriteRemoteCharacteristic(_
, _
, _
))
265 .WillByDefault(RunCallback
<1 /* sucess callback */>());
267 generic_access
->AddMockCharacteristic(device_name
.Pass());
268 device
->AddMockService(generic_access
.Pass());
269 adapter
->AddMockDevice(device
.Pass());
271 return adapter
.Pass();
275 scoped_refptr
<NiceMockBluetoothAdapter
>
276 LayoutTestBluetoothAdapterProvider::GetFailingConnectionsAdapter() {
277 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
279 for (int error
= BluetoothDevice::ERROR_UNKNOWN
;
280 error
<= BluetoothDevice::ERROR_UNSUPPORTED_DEVICE
; error
++) {
281 adapter
->AddMockDevice(GetUnconnectableDevice(
282 adapter
.get(), static_cast<BluetoothDevice::ConnectErrorCode
>(error
)));
284 return adapter
.Pass();
288 scoped_refptr
<NiceMockBluetoothAdapter
>
289 LayoutTestBluetoothAdapterProvider::GetFailingGATTOperationsAdapter() {
290 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
292 const std::string errorsServiceUUID
= errorUUID(0xA0);
294 BluetoothDevice::UUIDList uuids
;
295 uuids
.push_back(BluetoothUUID(errorsServiceUUID
));
297 scoped_ptr
<NiceMockBluetoothDevice
> device(
298 GetConnectableDevice(adapter
.get(), "Errors Device", uuids
));
300 scoped_ptr
<NiceMockBluetoothGattService
> service(
301 GetBaseGATTService(device
.get(), errorsServiceUUID
));
303 for (int error
= BluetoothGattService::GATT_ERROR_UNKNOWN
;
304 error
<= BluetoothGattService::GATT_ERROR_NOT_SUPPORTED
; error
++) {
305 service
->AddMockCharacteristic(GetErrorCharacteristic(
307 static_cast<BluetoothGattService::GattErrorCode
>(error
)));
310 device
->AddMockService(service
.Pass());
311 adapter
->AddMockDevice(device
.Pass());
313 return adapter
.Pass();
316 // Discovery Sessions
319 scoped_ptr
<NiceMockBluetoothDiscoverySession
>
320 LayoutTestBluetoothAdapterProvider::GetDiscoverySession() {
321 scoped_ptr
<NiceMockBluetoothDiscoverySession
> discovery_session(
322 new NiceMockBluetoothDiscoverySession());
324 ON_CALL(*discovery_session
, Stop(_
, _
))
325 .WillByDefault(RunCallback
<0 /* success_callback */>());
327 return discovery_session
.Pass();
333 scoped_ptr
<NiceMockBluetoothDevice
>
334 LayoutTestBluetoothAdapterProvider::GetBaseDevice(
335 MockBluetoothAdapter
* adapter
,
336 const std::string
& device_name
,
337 device::BluetoothDevice::UUIDList uuids
,
338 const std::string
& address
) {
339 scoped_ptr
<NiceMockBluetoothDevice
> device(new NiceMockBluetoothDevice(
340 adapter
, 0x1F00 /* Bluetooth class */, device_name
, address
,
341 true /* paired */, true /* connected */));
343 ON_CALL(*device
, GetUUIDs()).WillByDefault(Return(uuids
));
345 // Using Invoke allows the device returned from this method to be futher
346 // modified and have more services added to it. The call to ::GetGattServices
347 // will invoke ::GetMockServices, returning all services added up to that
349 ON_CALL(*device
, GetGattServices())
351 Invoke(device
.get(), &MockBluetoothDevice::GetMockServices
));
352 // The call to BluetoothDevice::GetGattService will invoke ::GetMockService
353 // which returns a service matching the identifier provided if the service
354 // was added to the mock.
355 ON_CALL(*device
, GetGattService(_
))
357 Invoke(device
.get(), &MockBluetoothDevice::GetMockService
));
359 ON_CALL(*device
, GetVendorIDSource())
360 .WillByDefault(Return(BluetoothDevice::VENDOR_ID_BLUETOOTH
));
361 ON_CALL(*device
, GetVendorID()).WillByDefault(Return(0xFFFF));
362 ON_CALL(*device
, GetProductID()).WillByDefault(Return(1));
363 ON_CALL(*device
, GetDeviceID()).WillByDefault(Return(2));
365 return device
.Pass();
369 scoped_ptr
<NiceMockBluetoothDevice
>
370 LayoutTestBluetoothAdapterProvider::GetBatteryDevice(
371 MockBluetoothAdapter
* adapter
) {
372 BluetoothDevice::UUIDList uuids
;
373 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
374 uuids
.push_back(BluetoothUUID(kBatteryServiceUUID
));
376 return GetBaseDevice(adapter
, "Battery Device", uuids
, makeMACAddress(0x1));
380 scoped_ptr
<NiceMockBluetoothDevice
>
381 LayoutTestBluetoothAdapterProvider::GetGlucoseDevice(
382 MockBluetoothAdapter
* adapter
) {
383 BluetoothDevice::UUIDList uuids
;
384 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
385 uuids
.push_back(BluetoothUUID(kGlucoseServiceUUID
));
387 return GetBaseDevice(adapter
, "Glucose Device", uuids
, makeMACAddress(0x2));
391 scoped_ptr
<NiceMockBluetoothDevice
>
392 LayoutTestBluetoothAdapterProvider::GetHeartRateDevice(
393 MockBluetoothAdapter
* adapter
) {
394 BluetoothDevice::UUIDList uuids
;
395 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
396 uuids
.push_back(BluetoothUUID(kHeartRateServiceUUID
));
398 return GetBaseDevice(adapter
, "Heart Rate Device", uuids
,
399 makeMACAddress(0x3));
403 scoped_ptr
<NiceMockBluetoothDevice
>
404 LayoutTestBluetoothAdapterProvider::GetConnectableDevice(
405 device::MockBluetoothAdapter
* adapter
,
406 const std::string
& device_name
,
407 BluetoothDevice::UUIDList uuids
) {
408 scoped_ptr
<NiceMockBluetoothDevice
> device(
409 GetBaseDevice(adapter
, device_name
, uuids
));
411 BluetoothDevice
* device_ptr
= device
.get();
413 ON_CALL(*device
, CreateGattConnection(_
, _
))
415 RunCallbackWithResult
<0 /* success_callback */>([device_ptr
]() {
416 return make_scoped_ptr(
417 new NiceMockBluetoothGattConnection(device_ptr
->GetAddress()));
420 return device
.Pass();
424 scoped_ptr
<NiceMockBluetoothDevice
>
425 LayoutTestBluetoothAdapterProvider::GetUnconnectableDevice(
426 MockBluetoothAdapter
* adapter
,
427 BluetoothDevice::ConnectErrorCode error_code
,
428 const std::string
& device_name
) {
429 BluetoothDevice::UUIDList uuids
;
430 uuids
.push_back(BluetoothUUID(errorUUID(error_code
)));
432 scoped_ptr
<NiceMockBluetoothDevice
> device(
433 GetBaseDevice(adapter
, device_name
, uuids
, makeMACAddress(error_code
)));
435 ON_CALL(*device
, CreateGattConnection(_
, _
))
436 .WillByDefault(RunCallback
<1 /* error_callback */>(error_code
));
438 return device
.Pass();
442 scoped_ptr
<NiceMockBluetoothDevice
>
443 LayoutTestBluetoothAdapterProvider::GetGenericAccessDevice(
444 MockBluetoothAdapter
* adapter
,
445 const std::string
& device_name
) {
446 BluetoothDevice::UUIDList uuids
;
447 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
449 return GetConnectableDevice(adapter
, device_name
, uuids
);
455 scoped_ptr
<NiceMockBluetoothGattService
>
456 LayoutTestBluetoothAdapterProvider::GetBaseGATTService(
457 MockBluetoothDevice
* device
,
458 const std::string
& uuid
) {
459 scoped_ptr
<NiceMockBluetoothGattService
> service(
460 new NiceMockBluetoothGattService(
461 device
, uuid
/* identifier */, BluetoothUUID(uuid
),
462 true /* is_primary */, false /* is_local */));
464 ON_CALL(*service
, GetCharacteristics())
465 .WillByDefault(Invoke(service
.get(),
466 &MockBluetoothGattService::GetMockCharacteristics
));
468 ON_CALL(*service
, GetCharacteristic(_
))
469 .WillByDefault(Invoke(service
.get(),
470 &MockBluetoothGattService::GetMockCharacteristic
));
472 return service
.Pass();
478 scoped_ptr
<NiceMockBluetoothGattCharacteristic
>
479 LayoutTestBluetoothAdapterProvider::GetBaseGATTCharacteristic(
480 MockBluetoothGattService
* service
,
481 const std::string
& uuid
) {
482 return make_scoped_ptr(new NiceMockBluetoothGattCharacteristic(
483 service
, uuid
+ " Identifier", BluetoothUUID(uuid
), false /* is_local */,
484 NULL
/* properties */, NULL
/* permissions */));
488 scoped_ptr
<NiceMockBluetoothGattCharacteristic
>
489 LayoutTestBluetoothAdapterProvider::GetErrorCharacteristic(
490 MockBluetoothGattService
* service
,
491 BluetoothGattService::GattErrorCode error_code
) {
492 uint32_t error_alias
= error_code
+ 0xA1; // Error UUIDs start at 0xA1.
493 scoped_ptr
<NiceMockBluetoothGattCharacteristic
> characteristic(
494 GetBaseGATTCharacteristic(service
, errorUUID(error_alias
)));
497 ON_CALL(*characteristic
, ReadRemoteCharacteristic(_
, _
))
498 .WillByDefault(RunCallback
<1 /* error_callback */>(error_code
));
501 ON_CALL(*characteristic
, WriteRemoteCharacteristic(_
, _
, _
))
502 .WillByDefault(RunCallback
<2 /* error_callback */>(error_code
));
504 return characteristic
.Pass();
510 std::string
LayoutTestBluetoothAdapterProvider::errorUUID(uint32_t alias
) {
511 return base::StringPrintf("%08x-97e5-4cd7-b9f1-f5a427670c59", alias
);
515 std::string
LayoutTestBluetoothAdapterProvider::makeMACAddress(uint64_t addr
) {
516 return BluetoothDevice::CanonicalizeAddress(
517 base::StringPrintf("%012" PRIx64
, addr
));
520 } // namespace content