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
== "NotPresentAdapter")
104 return GetNotPresentAdapter();
105 else if (fake_adapter_name
== "NotPoweredAdapter")
106 return GetNotPoweredAdapter();
107 else if (fake_adapter_name
== "ScanFilterCheckingAdapter")
108 return GetScanFilterCheckingAdapter();
109 else if (fake_adapter_name
== "EmptyAdapter")
110 return GetEmptyAdapter();
111 else if (fake_adapter_name
== "FailStartDiscoveryAdapter")
112 return GetFailStartDiscoveryAdapter();
113 else if (fake_adapter_name
== "GlucoseHeartRateAdapter")
114 return GetGlucoseHeartRateAdapter();
115 else if (fake_adapter_name
== "MissingServiceGenericAccessAdapter")
116 return GetMissingServiceGenericAccessAdapter();
117 else if (fake_adapter_name
== "MissingCharacteristicGenericAccessAdapter")
118 return GetMissingCharacteristicGenericAccessAdapter();
119 else if (fake_adapter_name
== "GenericAccessAdapter")
120 return GetGenericAccessAdapter();
121 else if (fake_adapter_name
== "FailingConnectionsAdapter")
122 return GetFailingConnectionsAdapter();
123 else if (fake_adapter_name
== "FailingGATTOperationsAdapter")
124 return GetFailingGATTOperationsAdapter();
125 else if (fake_adapter_name
== "")
128 NOTREACHED() << fake_adapter_name
;
135 scoped_refptr
<NiceMockBluetoothAdapter
>
136 LayoutTestBluetoothAdapterProvider::GetBaseAdapter() {
137 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(
138 new NiceMockBluetoothAdapter());
140 // Using Invoke allows the adapter returned from this method to be futher
141 // modified and have devices added to it. The call to ::GetDevices will
142 // invoke ::GetConstMockDevices, returning all devices added up to that time.
143 ON_CALL(*adapter
, GetDevices())
145 Invoke(adapter
.get(), &MockBluetoothAdapter::GetConstMockDevices
));
147 // The call to ::GetDevice will invoke GetMockDevice which returns a device
148 // matching the address provided if the device was added to the mock.
149 ON_CALL(*adapter
, GetDevice(_
)).WillByDefault(GetMockDevice(adapter
.get()));
151 return adapter
.Pass();
155 scoped_refptr
<NiceMockBluetoothAdapter
>
156 LayoutTestBluetoothAdapterProvider::GetPresentAdapter() {
157 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetBaseAdapter());
158 ON_CALL(*adapter
, IsPresent()).WillByDefault(Return(true));
160 return adapter
.Pass();
164 scoped_refptr
<NiceMockBluetoothAdapter
>
165 LayoutTestBluetoothAdapterProvider::GetNotPresentAdapter() {
166 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetBaseAdapter());
167 ON_CALL(*adapter
, IsPresent()).WillByDefault(Return(false));
169 return adapter
.Pass();
173 scoped_refptr
<NiceMockBluetoothAdapter
>
174 LayoutTestBluetoothAdapterProvider::GetPoweredAdapter() {
175 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetPresentAdapter());
176 ON_CALL(*adapter
, IsPowered()).WillByDefault(Return(true));
178 return adapter
.Pass();
182 scoped_refptr
<NiceMockBluetoothAdapter
>
183 LayoutTestBluetoothAdapterProvider::GetNotPoweredAdapter() {
184 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetPresentAdapter());
185 ON_CALL(*adapter
, IsPowered()).WillByDefault(Return(false));
187 return adapter
.Pass();
191 scoped_refptr
<NiceMockBluetoothAdapter
>
192 LayoutTestBluetoothAdapterProvider::GetScanFilterCheckingAdapter() {
193 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetPoweredAdapter());
195 // This fails the test with an error message listing actual and expected UUIDs
196 // if StartDiscoverySessionWithFilter() is called with the wrong argument.
199 StartDiscoverySessionWithFilterRaw(
200 ResultOf(&GetUUIDs
, ElementsAre(BluetoothUUID(kGlucoseServiceUUID
),
201 BluetoothUUID(kHeartRateServiceUUID
),
202 BluetoothUUID(kBatteryServiceUUID
))),
204 .WillRepeatedly(RunCallbackWithResult
<1 /* success_callback */>(
205 []() { return GetDiscoverySession(); }));
207 // Any unexpected call results in the failure callback.
208 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
209 .WillByDefault(RunCallback
<2 /* error_callback */>());
211 // We need to add a device otherwise requestDevice would reject.
212 adapter
->AddMockDevice(GetBatteryDevice(adapter
.get()));
214 return adapter
.Pass();
218 scoped_refptr
<NiceMockBluetoothAdapter
>
219 LayoutTestBluetoothAdapterProvider::GetFailStartDiscoveryAdapter() {
220 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetPoweredAdapter());
222 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
223 .WillByDefault(RunCallback
<2 /* error_callback */>());
225 return adapter
.Pass();
229 scoped_refptr
<NiceMockBluetoothAdapter
>
230 LayoutTestBluetoothAdapterProvider::GetEmptyAdapter() {
231 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetPoweredAdapter());
233 ON_CALL(*adapter
, StartDiscoverySessionWithFilterRaw(_
, _
, _
))
234 .WillByDefault(RunCallbackWithResult
<1 /* success_callback */>(
235 []() { return GetDiscoverySession(); }));
237 return adapter
.Pass();
241 scoped_refptr
<NiceMockBluetoothAdapter
>
242 LayoutTestBluetoothAdapterProvider::GetGlucoseHeartRateAdapter() {
243 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
245 adapter
->AddMockDevice(GetHeartRateDevice(adapter
.get()));
246 adapter
->AddMockDevice(GetGlucoseDevice(adapter
.get()));
248 return adapter
.Pass();
252 scoped_refptr
<NiceMockBluetoothAdapter
>
253 LayoutTestBluetoothAdapterProvider::GetMissingServiceGenericAccessAdapter() {
254 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
256 adapter
->AddMockDevice(GetGenericAccessDevice(adapter
.get()));
258 return adapter
.Pass();
262 scoped_refptr
<NiceMockBluetoothAdapter
> LayoutTestBluetoothAdapterProvider::
263 GetMissingCharacteristicGenericAccessAdapter() {
264 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
266 scoped_ptr
<NiceMockBluetoothDevice
> device(
267 GetGenericAccessDevice(adapter
.get()));
269 scoped_ptr
<NiceMockBluetoothGattService
> generic_access(
270 GetBaseGATTService(device
.get(), kGenericAccessServiceUUID
));
272 // Intentionally NOT adding a characteristic to generic_access service.
274 device
->AddMockService(generic_access
.Pass());
276 adapter
->AddMockDevice(device
.Pass());
278 return adapter
.Pass();
282 scoped_refptr
<NiceMockBluetoothAdapter
>
283 LayoutTestBluetoothAdapterProvider::GetGenericAccessAdapter() {
284 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
286 scoped_ptr
<NiceMockBluetoothDevice
> device(
287 GetGenericAccessDevice(adapter
.get()));
289 scoped_ptr
<NiceMockBluetoothGattService
> generic_access(
290 GetBaseGATTService(device
.get(), kGenericAccessServiceUUID
));
292 scoped_ptr
<NiceMockBluetoothGattCharacteristic
> device_name(
293 GetBaseGATTCharacteristic(generic_access
.get(), kDeviceNameUUID
));
296 std::string device_name_str
= device
->GetDeviceName();
297 std::vector
<uint8_t> device_name_value(device_name_str
.begin(),
298 device_name_str
.end());
300 ON_CALL(*device_name
, ReadRemoteCharacteristic(_
, _
))
301 .WillByDefault(RunCallback
<0>(device_name_value
));
304 ON_CALL(*device_name
, WriteRemoteCharacteristic(_
, _
, _
))
305 .WillByDefault(RunCallback
<1 /* sucess callback */>());
307 generic_access
->AddMockCharacteristic(device_name
.Pass());
308 device
->AddMockService(generic_access
.Pass());
309 adapter
->AddMockDevice(device
.Pass());
311 return adapter
.Pass();
315 scoped_refptr
<NiceMockBluetoothAdapter
>
316 LayoutTestBluetoothAdapterProvider::GetFailingConnectionsAdapter() {
317 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
319 for (int error
= BluetoothDevice::ERROR_UNKNOWN
;
320 error
<= BluetoothDevice::ERROR_UNSUPPORTED_DEVICE
; error
++) {
321 adapter
->AddMockDevice(GetUnconnectableDevice(
322 adapter
.get(), static_cast<BluetoothDevice::ConnectErrorCode
>(error
)));
324 return adapter
.Pass();
328 scoped_refptr
<NiceMockBluetoothAdapter
>
329 LayoutTestBluetoothAdapterProvider::GetFailingGATTOperationsAdapter() {
330 scoped_refptr
<NiceMockBluetoothAdapter
> adapter(GetEmptyAdapter());
332 const std::string errorsServiceUUID
= errorUUID(0xA0);
334 BluetoothDevice::UUIDList uuids
;
335 uuids
.push_back(BluetoothUUID(errorsServiceUUID
));
337 scoped_ptr
<NiceMockBluetoothDevice
> device(
338 GetConnectableDevice(adapter
.get(), "Errors Device", uuids
));
340 scoped_ptr
<NiceMockBluetoothGattService
> service(
341 GetBaseGATTService(device
.get(), errorsServiceUUID
));
343 for (int error
= BluetoothGattService::GATT_ERROR_UNKNOWN
;
344 error
<= BluetoothGattService::GATT_ERROR_NOT_SUPPORTED
; error
++) {
345 service
->AddMockCharacteristic(GetErrorCharacteristic(
347 static_cast<BluetoothGattService::GattErrorCode
>(error
)));
350 device
->AddMockService(service
.Pass());
351 adapter
->AddMockDevice(device
.Pass());
353 return adapter
.Pass();
356 // Discovery Sessions
359 scoped_ptr
<NiceMockBluetoothDiscoverySession
>
360 LayoutTestBluetoothAdapterProvider::GetDiscoverySession() {
361 scoped_ptr
<NiceMockBluetoothDiscoverySession
> discovery_session(
362 new NiceMockBluetoothDiscoverySession());
364 ON_CALL(*discovery_session
, Stop(_
, _
))
365 .WillByDefault(RunCallback
<0 /* success_callback */>());
367 return discovery_session
.Pass();
373 scoped_ptr
<NiceMockBluetoothDevice
>
374 LayoutTestBluetoothAdapterProvider::GetBaseDevice(
375 MockBluetoothAdapter
* adapter
,
376 const std::string
& device_name
,
377 device::BluetoothDevice::UUIDList uuids
,
378 const std::string
& address
) {
379 scoped_ptr
<NiceMockBluetoothDevice
> device(new NiceMockBluetoothDevice(
380 adapter
, 0x1F00 /* Bluetooth class */, device_name
, address
,
381 true /* paired */, true /* connected */));
383 ON_CALL(*device
, GetUUIDs()).WillByDefault(Return(uuids
));
385 // Using Invoke allows the device returned from this method to be futher
386 // modified and have more services added to it. The call to ::GetGattServices
387 // will invoke ::GetMockServices, returning all services added up to that
389 ON_CALL(*device
, GetGattServices())
391 Invoke(device
.get(), &MockBluetoothDevice::GetMockServices
));
392 // The call to BluetoothDevice::GetGattService will invoke ::GetMockService
393 // which returns a service matching the identifier provided if the service
394 // was added to the mock.
395 ON_CALL(*device
, GetGattService(_
))
397 Invoke(device
.get(), &MockBluetoothDevice::GetMockService
));
399 ON_CALL(*device
, GetVendorIDSource())
400 .WillByDefault(Return(BluetoothDevice::VENDOR_ID_BLUETOOTH
));
401 ON_CALL(*device
, GetVendorID()).WillByDefault(Return(0xFFFF));
402 ON_CALL(*device
, GetProductID()).WillByDefault(Return(1));
403 ON_CALL(*device
, GetDeviceID()).WillByDefault(Return(2));
405 return device
.Pass();
409 scoped_ptr
<NiceMockBluetoothDevice
>
410 LayoutTestBluetoothAdapterProvider::GetBatteryDevice(
411 MockBluetoothAdapter
* adapter
) {
412 BluetoothDevice::UUIDList uuids
;
413 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
414 uuids
.push_back(BluetoothUUID(kBatteryServiceUUID
));
416 return GetBaseDevice(adapter
, "Battery Device", uuids
, makeMACAddress(0x1));
420 scoped_ptr
<NiceMockBluetoothDevice
>
421 LayoutTestBluetoothAdapterProvider::GetGlucoseDevice(
422 MockBluetoothAdapter
* adapter
) {
423 BluetoothDevice::UUIDList uuids
;
424 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
425 uuids
.push_back(BluetoothUUID(kGlucoseServiceUUID
));
427 return GetBaseDevice(adapter
, "Glucose Device", uuids
, makeMACAddress(0x2));
431 scoped_ptr
<NiceMockBluetoothDevice
>
432 LayoutTestBluetoothAdapterProvider::GetHeartRateDevice(
433 MockBluetoothAdapter
* adapter
) {
434 BluetoothDevice::UUIDList uuids
;
435 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
436 uuids
.push_back(BluetoothUUID(kHeartRateServiceUUID
));
438 return GetBaseDevice(adapter
, "Heart Rate Device", uuids
,
439 makeMACAddress(0x3));
443 scoped_ptr
<NiceMockBluetoothDevice
>
444 LayoutTestBluetoothAdapterProvider::GetConnectableDevice(
445 device::MockBluetoothAdapter
* adapter
,
446 const std::string
& device_name
,
447 BluetoothDevice::UUIDList uuids
) {
448 scoped_ptr
<NiceMockBluetoothDevice
> device(
449 GetBaseDevice(adapter
, device_name
, uuids
));
451 BluetoothDevice
* device_ptr
= device
.get();
453 ON_CALL(*device
, CreateGattConnection(_
, _
))
455 RunCallbackWithResult
<0 /* success_callback */>([device_ptr
]() {
456 return make_scoped_ptr(
457 new NiceMockBluetoothGattConnection(device_ptr
->GetAddress()));
460 return device
.Pass();
464 scoped_ptr
<NiceMockBluetoothDevice
>
465 LayoutTestBluetoothAdapterProvider::GetUnconnectableDevice(
466 MockBluetoothAdapter
* adapter
,
467 BluetoothDevice::ConnectErrorCode error_code
,
468 const std::string
& device_name
) {
469 BluetoothDevice::UUIDList uuids
;
470 uuids
.push_back(BluetoothUUID(errorUUID(error_code
)));
472 scoped_ptr
<NiceMockBluetoothDevice
> device(
473 GetBaseDevice(adapter
, device_name
, uuids
, makeMACAddress(error_code
)));
475 ON_CALL(*device
, CreateGattConnection(_
, _
))
476 .WillByDefault(RunCallback
<1 /* error_callback */>(error_code
));
478 return device
.Pass();
482 scoped_ptr
<NiceMockBluetoothDevice
>
483 LayoutTestBluetoothAdapterProvider::GetGenericAccessDevice(
484 MockBluetoothAdapter
* adapter
,
485 const std::string
& device_name
) {
486 BluetoothDevice::UUIDList uuids
;
487 uuids
.push_back(BluetoothUUID(kGenericAccessServiceUUID
));
489 return GetConnectableDevice(adapter
, device_name
, uuids
);
495 scoped_ptr
<NiceMockBluetoothGattService
>
496 LayoutTestBluetoothAdapterProvider::GetBaseGATTService(
497 MockBluetoothDevice
* device
,
498 const std::string
& uuid
) {
499 scoped_ptr
<NiceMockBluetoothGattService
> service(
500 new NiceMockBluetoothGattService(
501 device
, uuid
/* identifier */, BluetoothUUID(uuid
),
502 true /* is_primary */, false /* is_local */));
504 ON_CALL(*service
, GetCharacteristics())
505 .WillByDefault(Invoke(service
.get(),
506 &MockBluetoothGattService::GetMockCharacteristics
));
508 ON_CALL(*service
, GetCharacteristic(_
))
509 .WillByDefault(Invoke(service
.get(),
510 &MockBluetoothGattService::GetMockCharacteristic
));
512 return service
.Pass();
518 scoped_ptr
<NiceMockBluetoothGattCharacteristic
>
519 LayoutTestBluetoothAdapterProvider::GetBaseGATTCharacteristic(
520 MockBluetoothGattService
* service
,
521 const std::string
& uuid
) {
522 return make_scoped_ptr(new NiceMockBluetoothGattCharacteristic(
523 service
, uuid
+ " Identifier", BluetoothUUID(uuid
), false /* is_local */,
524 NULL
/* properties */, NULL
/* permissions */));
528 scoped_ptr
<NiceMockBluetoothGattCharacteristic
>
529 LayoutTestBluetoothAdapterProvider::GetErrorCharacteristic(
530 MockBluetoothGattService
* service
,
531 BluetoothGattService::GattErrorCode error_code
) {
532 uint32_t error_alias
= error_code
+ 0xA1; // Error UUIDs start at 0xA1.
533 scoped_ptr
<NiceMockBluetoothGattCharacteristic
> characteristic(
534 GetBaseGATTCharacteristic(service
, errorUUID(error_alias
)));
537 ON_CALL(*characteristic
, ReadRemoteCharacteristic(_
, _
))
538 .WillByDefault(RunCallback
<1 /* error_callback */>(error_code
));
541 ON_CALL(*characteristic
, WriteRemoteCharacteristic(_
, _
, _
))
542 .WillByDefault(RunCallback
<2 /* error_callback */>(error_code
));
544 return characteristic
.Pass();
550 std::string
LayoutTestBluetoothAdapterProvider::errorUUID(uint32_t alias
) {
551 return base::StringPrintf("%08x-97e5-4cd7-b9f1-f5a427670c59", alias
);
555 std::string
LayoutTestBluetoothAdapterProvider::makeMACAddress(uint64_t addr
) {
556 return BluetoothDevice::CanonicalizeAddress(
557 base::StringPrintf("%012" PRIx64
, addr
));
560 } // namespace content