Skip to content

Commit a334747

Browse files
author
bors-servo
authored
Auto merge of #13612 - szeged:test-api-impl, r=jdm
WebBluetooth Test API and tests <!-- Please describe your changes on the following line: --> This patch depends on the [devices mock device support PR](servo/devices#17). After it lands, the Cargo files can be updated. 1. Adjust to the changes in [devices mock device support PR](servo/devices#17). 2. WebBluetooth Test API implementation. Based on : https://webbluetoothcg.github.io/web-bluetooth/tests.html 3. Wpt tests for the already landed WebBluetooth functions. <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors <!-- Either: --> - [x] There are tests for these changes <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/13612) <!-- Reviewable:end -->
2 parents 4c5d84d + b468990 commit a334747

File tree

253 files changed

+5455
-24
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

253 files changed

+5455
-24
lines changed

components/bluetooth/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ path = "lib.rs"
1212
[dependencies]
1313
bitflags = "0.7"
1414
bluetooth_traits = {path = "../bluetooth_traits"}
15-
device = {git = "https://github.com/servo/devices"}
15+
device = {git = "https://github.com/servo/devices", features = ["bluetooth-test"]}
1616
ipc-channel = "0.5"
1717
rand = "0.3"
1818
util = {path = "../util"}
19+
uuid = {version = "0.3.1", features = ["v4"]}
1920

2021
[target.'cfg(target_os = "linux")'.dependencies]
2122
tinyfiledialogs = {git = "https://github.com/jdm/tinyfiledialogs"}

components/bluetooth/lib.rs

Lines changed: 99 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,17 @@ extern crate rand;
1111
#[cfg(target_os = "linux")]
1212
extern crate tinyfiledialogs;
1313
extern crate util;
14+
extern crate uuid;
15+
16+
pub mod test;
1417

1518
use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothCharacteristicsMsg};
1619
use bluetooth_traits::{BluetoothDescriptorMsg, BluetoothDescriptorsMsg};
1720
use bluetooth_traits::{BluetoothDeviceMsg, BluetoothError, BluetoothMethodMsg};
1821
use bluetooth_traits::{BluetoothResult, BluetoothServiceMsg, BluetoothServicesMsg};
1922
use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence, RequestDeviceoptions};
20-
use device::bluetooth::BluetoothAdapter;
21-
use device::bluetooth::BluetoothDevice;
22-
use device::bluetooth::BluetoothGATTCharacteristic;
23-
use device::bluetooth::BluetoothGATTDescriptor;
24-
use device::bluetooth::BluetoothGATTService;
23+
use device::bluetooth::{BluetoothAdapter, BluetoothDevice, BluetoothGATTCharacteristic};
24+
use device::bluetooth::{BluetoothGATTDescriptor, BluetoothGATTService};
2525
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
2626
use rand::Rng;
2727
use std::borrow::ToOwned;
@@ -33,6 +33,8 @@ use util::thread::spawn_named;
3333

3434
const ADAPTER_ERROR: &'static str = "No adapter found";
3535

36+
const ADAPTER_NOT_POWERED_ERROR: &'static str = "Bluetooth adapter not powered";
37+
3638
// A transaction not completed within 30 seconds shall time out. Such a transaction shall be considered to have failed.
3739
// https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=286439 (Vol. 3, page 480)
3840
const MAXIMUM_TRANSACTION_TIME: u8 = 30;
@@ -71,7 +73,12 @@ macro_rules! return_if_cached(
7173
macro_rules! get_adapter_or_return_error(
7274
($bl_manager:expr, $sender:expr) => (
7375
match $bl_manager.get_or_create_adapter() {
74-
Some(adapter) => adapter,
76+
Some(adapter) => {
77+
if !adapter.is_powered().unwrap_or(false) {
78+
return drop($sender.send(Err(BluetoothError::Type(ADAPTER_NOT_POWERED_ERROR.to_string()))))
79+
}
80+
adapter
81+
},
7582
None => return drop($sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
7683
}
7784
);
@@ -155,6 +162,13 @@ fn matches_filters(device: &BluetoothDevice, filters: &BluetoothScanfilterSequen
155162
return filters.iter().any(|f| matches_filter(device, f))
156163
}
157164

165+
fn is_mock_adapter(adapter: &BluetoothAdapter) -> bool {
166+
match adapter {
167+
&BluetoothAdapter::Mock(_) => true,
168+
_ => false,
169+
}
170+
}
171+
158172
pub struct BluetoothManager {
159173
receiver: IpcReceiver<BluetoothMethodMsg>,
160174
adapter: Option<BluetoothAdapter>,
@@ -228,20 +242,56 @@ impl BluetoothManager {
228242
BluetoothMethodMsg::WriteValue(id, value, sender) => {
229243
self.write_value(id, value, sender)
230244
},
245+
BluetoothMethodMsg::Test(data_set_name, sender) => {
246+
self.test(data_set_name, sender)
247+
}
231248
BluetoothMethodMsg::Exit => {
232249
break
233250
},
234251
}
235252
}
236253
}
237254

255+
// Test
256+
257+
fn test(&mut self, data_set_name: String, sender: IpcSender<BluetoothResult<()>>) {
258+
self.address_to_id.clear();
259+
self.service_to_device.clear();
260+
self.characteristic_to_service.clear();
261+
self.descriptor_to_characteristic.clear();
262+
self.cached_devices.clear();
263+
self.cached_services.clear();
264+
self.cached_characteristics.clear();
265+
self.cached_descriptors.clear();
266+
self.allowed_services.clear();
267+
self.adapter = BluetoothAdapter::init_mock().ok();
268+
match test::test(self, data_set_name) {
269+
Ok(_) => {
270+
let _ = sender.send(Ok(()));
271+
},
272+
Err(error) => {
273+
let _ = sender.send(Err(BluetoothError::Type(error.description().to_owned())));
274+
},
275+
}
276+
}
277+
238278
// Adapter
239279

240-
fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
280+
pub fn get_or_create_adapter(&mut self) -> Option<BluetoothAdapter> {
241281
let adapter_valid = self.adapter.as_ref().map_or(false, |a| a.get_address().is_ok());
242282
if !adapter_valid {
243283
self.adapter = BluetoothAdapter::init().ok();
244284
}
285+
286+
let adapter = match self.adapter.as_ref() {
287+
Some(adapter) => adapter,
288+
None => return None,
289+
};
290+
291+
if is_mock_adapter(adapter) && !adapter.is_present().unwrap_or(false) {
292+
return None;
293+
}
294+
245295
self.adapter.clone()
246296
}
247297

@@ -270,7 +320,16 @@ impl BluetoothManager {
270320
}
271321

272322
#[cfg(target_os = "linux")]
273-
fn select_device(&mut self, devices: Vec<BluetoothDevice>) -> Option<String> {
323+
fn select_device(&mut self, devices: Vec<BluetoothDevice>, adapter: &BluetoothAdapter) -> Option<String> {
324+
if is_mock_adapter(adapter) {
325+
for device in devices {
326+
if let Ok(address) = device.get_address() {
327+
return Some(address);
328+
}
329+
}
330+
return None;
331+
}
332+
274333
let mut dialog_rows: Vec<String> = vec!();
275334
for device in devices {
276335
dialog_rows.extend_from_slice(&[device.get_address().unwrap_or("".to_string()),
@@ -291,7 +350,7 @@ impl BluetoothManager {
291350
}
292351

293352
#[cfg(not(target_os = "linux"))]
294-
fn select_device(&mut self, devices: Vec<BluetoothDevice>) -> Option<String> {
353+
fn select_device(&mut self, devices: Vec<BluetoothDevice>, _adapter: &BluetoothAdapter) -> Option<String> {
295354
for device in devices {
296355
if let Ok(address) = device.get_address() {
297356
return Some(address);
@@ -312,6 +371,17 @@ impl BluetoothManager {
312371
device_id
313372
}
314373

374+
fn device_from_service_id(&self, service_id: &str) -> Option<BluetoothDevice> {
375+
let device_id = match self.service_to_device.get(service_id) {
376+
Some(id) => id,
377+
None => return None,
378+
};
379+
match self.cached_devices.get(device_id) {
380+
Some(d) => Some(d.clone()),
381+
None => None,
382+
}
383+
}
384+
315385
// Service
316386

317387
fn get_and_cache_gatt_services(&mut self,
@@ -464,7 +534,9 @@ impl BluetoothManager {
464534
let mut adapter = get_adapter_or_return_error!(self, sender);
465535
if let Ok(ref session) = adapter.create_discovery_session() {
466536
if session.start_discovery().is_ok() {
467-
thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS));
537+
if !is_mock_adapter(&adapter) {
538+
thread::sleep(Duration::from_millis(DISCOVERY_TIMEOUT_MS));
539+
}
468540
}
469541
let _ = session.stop_discovery();
470542
}
@@ -481,7 +553,7 @@ impl BluetoothManager {
481553
}
482554

483555
// Step 8.
484-
if let Some(address) = self.select_device(matched_devices) {
556+
if let Some(address) = self.select_device(matched_devices, &adapter) {
485557
let device_id = match self.address_to_id.get(&address) {
486558
Some(id) => id.clone(),
487559
None => return drop(sender.send(Err(BluetoothError::NotFound))),
@@ -517,7 +589,12 @@ impl BluetoothManager {
517589
for _ in 0..MAXIMUM_TRANSACTION_TIME {
518590
match d.is_connected().unwrap_or(false) {
519591
true => return drop(sender.send(Ok(true))),
520-
false => thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS)),
592+
false => {
593+
if is_mock_adapter(&adapter) {
594+
break;
595+
}
596+
thread::sleep(Duration::from_millis(CONNECTION_TIMEOUT_MS));
597+
},
521598
}
522599
}
523600
return drop(sender.send(Err(BluetoothError::Network)));
@@ -617,11 +694,15 @@ impl BluetoothManager {
617694
Some(a) => a,
618695
None => return drop(sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
619696
};
697+
let device = match self.device_from_service_id(&service_id) {
698+
Some(device) => device,
699+
None => return drop(sender.send(Err(BluetoothError::NotFound))),
700+
};
620701
let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
621702
Some(s) => s,
622703
None => return drop(sender.send(Err(BluetoothError::NotFound))),
623704
};
624-
let services = primary_service.get_includes().unwrap_or(vec!());
705+
let services = primary_service.get_includes(device).unwrap_or(vec!());
625706
for service in services {
626707
if let Ok(service_uuid) = service.get_uuid() {
627708
if uuid == service_uuid {
@@ -644,11 +725,15 @@ impl BluetoothManager {
644725
Some(a) => a,
645726
None => return drop(sender.send(Err(BluetoothError::Type(ADAPTER_ERROR.to_string())))),
646727
};
728+
let device = match self.device_from_service_id(&service_id) {
729+
Some(device) => device,
730+
None => return drop(sender.send(Err(BluetoothError::NotFound))),
731+
};
647732
let primary_service = match self.get_gatt_service(&mut adapter, &service_id) {
648733
Some(s) => s,
649734
None => return drop(sender.send(Err(BluetoothError::NotFound))),
650735
};
651-
let services = primary_service.get_includes().unwrap_or(vec!());
736+
let services = primary_service.get_includes(device).unwrap_or(vec!());
652737
let mut services_vec = vec!();
653738
for service in services {
654739
if let Ok(service_uuid) = service.get_uuid() {

0 commit comments

Comments
 (0)