blob: 3b65add013597deb639a4a01ccd17383155cafd2 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
anyhow::{format_err, Context as _, Error},
fidl_fuchsia_bluetooth_sys as sys,
fuchsia_bluetooth::expectation::{asynchronous::ExpectableStateExt, Predicate as P},
fuchsia_bluetooth::types::{Address, BondingData, Identity, LeData, OneOrBoth, PeerId},
fuchsia_zircon::{Duration, DurationNum},
std::collections::HashSet,
};
use crate::harness::{
bootstrap::BootstrapHarness,
control::{ControlHarness, ControlState},
};
const TIMEOUT_SECONDS: i64 = 60;
fn bootstrap_timeout() -> Duration {
TIMEOUT_SECONDS.seconds()
}
/// An example identity for an Hci Emulator backed host
fn example_emulator_identity() -> Identity {
// Hci Emulators currently default to address 0
let emulator_address = Address::Public([0, 0, 0, 0, 0, 0]);
let host_data = sys::HostData {
irk: Some(sys::Key { value: [16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }),
};
let csrk = sys::PeerKey {
data: sys::Key { value: [0; 16] },
security: sys::SecurityProperties {
authenticated: false,
secure_connections: true,
encryption_key_size: 0,
},
};
let le_data = LeData {
address: emulator_address,
connection_parameters: None,
services: vec![],
ltk: None,
irk: None,
csrk: Some(csrk),
};
let bonds = vec![BondingData {
identifier: PeerId(42),
local_address: emulator_address,
name: None,
data: OneOrBoth::Left(le_data),
}];
Identity { host: host_data, bonds }
}
async fn test_add_and_commit_identities(
harnesses: (BootstrapHarness, ControlHarness),
) -> Result<(), Error> {
let (bootstrap, control) = harnesses;
let bootstrap = bootstrap.aux().clone();
let control_proxy = control.aux().clone();
// We avoid using an assert here because the unwinding causes the ActivatedFakeHost to
// panic during the unwindw which then just aborts. This provides a much clearer and more
// graceful failure case
let initial_devices = control_proxy.get_known_remote_devices().await.ok();
if initial_devices != Some(vec![]) {
return Err(format_err!(
"Failed: Initial devices not empty! Expected empty, found: {:?}",
initial_devices
));
}
let identity = example_emulator_identity();
let expected_devices: HashSet<String> =
identity.bonds.iter().map(|b| b.identifier.to_string()).collect();
let identities: Vec<sys::Identity> = vec![identity.into()];
bootstrap.add_identities(&mut identities.into_iter()).context("Error adding identities")?;
bootstrap.commit().await?.map_err(|e| format_err!("Error committing bonds: {:?}", e))?;
let pred = P::<ControlState>::new(
move |control| expected_devices == control.peers.keys().cloned().collect(),
Some("known device identifiers == expected device identifiers"),
);
control.when_satisfied(pred, bootstrap_timeout()).await?;
Ok(())
}
pub fn run_all() -> Result<(), Error> {
run_suite!("sys.Bootstrap", [test_add_and_commit_identities])
}