blob: a7fa4d4b6d3069e362e46c0eb764be22c13c2339 [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, Error},
bt_test_harness::deprecated::control::{
activate_fake_host, expectation, ControlHarness, ControlState, FAKE_HCI_ADDRESS,
},
fidl_fuchsia_bluetooth_test::{AdvertisingData, LowEnergyPeerParameters},
fuchsia_bluetooth::{
expectation::{
asynchronous::{ExpectableExt, ExpectableState, ExpectableStateExt},
Predicate,
},
hci_emulator::Emulator,
types::Address,
},
test_harness::run_suite,
};
use crate::tests::timeout_duration;
async fn test_set_active_host(control: ControlHarness) -> Result<(), Error> {
let initial_hosts: Vec<String> = control.read().hosts.keys().cloned().collect();
let initial_hosts_ = initial_hosts.clone();
let mut fake_hci_0 = Emulator::create_and_publish("bt-hci-integration-control-0").await?;
let mut fake_hci_1 = Emulator::create_and_publish("bt-hci-integration-control-1").await?;
let state = control
.when_satisfied(
Predicate::<ControlState>::predicate(
move |control| {
let added_fake_hosts = control.hosts.iter().filter(|(id, host)| {
host.address == FAKE_HCI_ADDRESS && !initial_hosts_.contains(id)
});
added_fake_hosts.count() > 1
},
"Both Fake Hosts Added",
),
timeout_duration(),
)
.await?;
let fake_hosts: Vec<String> = state
.hosts
.iter()
.filter(|(id, host)| host.address == FAKE_HCI_ADDRESS && !initial_hosts.contains(id))
.map(|(id, _)| id.clone())
.collect();
for host in fake_hosts.iter() {
let fut = control.aux().set_active_adapter(host);
fut.await?;
control
.when_satisfied(expectation::active_host_is(host.to_string()), timeout_duration())
.await?;
}
fake_hci_0.destroy_and_wait().await?;
fake_hci_1.destroy_and_wait().await?;
for host in fake_hosts {
control.when_satisfied(expectation::host_not_present(host), timeout_duration()).await?;
}
Ok(())
}
async fn test_disconnect(control: ControlHarness) -> Result<(), Error> {
let (_host, mut hci) = activate_fake_host(control.clone(), "bt-hci-integration").await?;
// Insert a fake peer to test connection and disconnection.
let peer_address = Address::Random([1, 0, 0, 0, 0, 0]);
let peer_params = LowEnergyPeerParameters {
address: Some(peer_address.into()),
connectable: Some(true),
advertisement: Some(AdvertisingData {
data: vec![0x02, 0x01, 0x02], // Flags field set to "general discoverable"
}),
scan_response: None,
..LowEnergyPeerParameters::EMPTY
};
let (_peer, remote) = fidl::endpoints::create_proxy()?;
let _ = hci
.emulator()
.add_low_energy_peer(peer_params, remote)
.await?
.map_err(|e| format_err!("Failed to register fake peer: {:#?}", e))?;
let fut = control.aux().request_discovery(true);
fut.await?;
let state = control
.when_satisfied(
expectation::peer_with_address(&peer_address.to_string()),
timeout_duration(),
)
.await?;
// TODO(armansito): Generalize Emulator/Peer state tracking from low_energy_peripheral tests and
// verify the controller state here.
// We can safely unwrap here as this is guarded by the previous expectation
let peer = state.peers.iter().find(|(_, p)| &p.address == &peer_address.to_string()).unwrap().0;
let fut = control.aux().connect(peer);
fut.await?;
control.when_satisfied(expectation::peer_connected(peer, true), timeout_duration()).await?;
let fut = control.aux().disconnect(peer);
fut.await?;
control.when_satisfied(expectation::peer_connected(peer, false), timeout_duration()).await?;
hci.destroy_and_wait().await?;
Ok(())
}
/// Run all test cases.
pub fn run_all() -> Result<(), Error> {
run_suite!("control.Control", [test_set_active_host, test_disconnect])
}