blob: 099c53602624bb4392b40100ac980370fff18fad [file] [log] [blame]
// Copyright 2020 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 assert_matches::assert_matches;
use fidl_fuchsia_bluetooth_host::{HostRequest, HostRequestStream, HostSetConnectableResponder};
use fidl_fuchsia_bluetooth_sys::{
self as sys, BrEdrSecurityMode, ConfigurationMarker, ConfigurationProxy,
ConfigurationRequestStream, LeSecurityMode,
};
use fuchsia_bluetooth::types::HostId;
use futures::future;
use futures::stream::TryStreamExt;
use crate::host_dispatcher::{test as hd_test, HostDispatcher};
use crate::services::configuration;
use crate::types;
#[cfg(test)]
async fn setup_configuration_test() -> types::Result<(
HostRequestStream,
HostDispatcher,
ConfigurationProxy,
ConfigurationRequestStream,
)> {
let dispatcher = hd_test::make_simple_test_dispatcher();
let (host_server, _, _gatt_server, _delegate) =
hd_test::create_and_add_test_host_to_dispatcher(HostId(42), &dispatcher).await?;
let (client, server) =
fidl::endpoints::create_proxy_and_stream::<ConfigurationMarker>().unwrap();
Ok((host_server, dispatcher, client, server))
}
#[cfg(test)]
macro_rules! handle_host_req_fut {
($host_server:ident, $host_request_variant:ident, $handle_request_payload:tt $(, $req_param_name:tt)*) => {
async move {
$host_server.try_for_each(move |req| {
if let HostRequest::$host_request_variant { $($req_param_name,)* .. } = req {
$handle_request_payload($($req_param_name),*);
} else {
panic!("unexpected request!");
}
future::ok(())
})
.await
.map_err(|e| e.into())
}
};
}
#[fuchsia::test]
async fn disable_le_privacy() {
let (host_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings { le_privacy: Some(false), ..Default::default() })
.await;
assert_matches!(response, Ok(sys::Settings { le_privacy: Some(false), .. }));
// The configuration client is dropped when this terminates, which causes the configuration
// stream to terminate. This causes run_configuration to terminate which drops the host
// dispatcher, which closes the host channel and finally causes run_host to terminate
Ok(())
};
let run_host = handle_host_req_fut!(
host_server,
EnablePrivacy,
(|enabled: bool| assert!(!enabled)),
enabled
);
future::try_join3(make_request, run_host, run_configuration).await.unwrap();
}
#[fuchsia::test]
async fn disable_le_background_scan() {
let (host_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings { le_background_scan: Some(false), ..Default::default() })
.await;
assert_matches!(response, Ok(sys::Settings { le_background_scan: Some(false), .. }));
Ok(())
};
let run_host = handle_host_req_fut!(
host_server,
EnableBackgroundScan,
(|enabled: bool| assert!(!enabled)),
enabled
);
future::try_join3(make_request, run_host, run_configuration).await.unwrap();
}
#[fuchsia::test]
async fn disable_connectable_mode() {
let (host_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings { bredr_connectable_mode: Some(false), ..Default::default() })
.await;
assert_matches!(response, Ok(sys::Settings { bredr_connectable_mode: Some(false), .. }));
Ok(())
};
let run_host = handle_host_req_fut!(
host_server,
SetConnectable,
(|enabled: bool, responder: HostSetConnectableResponder| {
assert!(!enabled);
assert_matches!(responder.send(Ok(())), Ok(()))
}),
enabled,
responder
);
future::try_join3(make_request, run_host, run_configuration).await.unwrap();
}
#[fuchsia::test]
async fn set_bredr_secure_connections_only() {
let (host_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings {
bredr_security_mode: Some(BrEdrSecurityMode::SecureConnectionsOnly),
..Default::default()
})
.await;
assert_matches!(
response,
Ok(sys::Settings {
bredr_security_mode: Some(BrEdrSecurityMode::SecureConnectionsOnly),
..
})
);
Ok(())
};
let run_host = handle_host_req_fut!(
host_server,
SetBrEdrSecurityMode,
(|mode: BrEdrSecurityMode| assert_eq!(BrEdrSecurityMode::SecureConnectionsOnly, mode)),
bredr_security_mode
);
future::try_join3(make_request, run_host, run_configuration).await.unwrap();
}
#[fuchsia::test]
async fn set_le_secure_connections_only() {
let (host_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings {
le_security_mode: Some(LeSecurityMode::SecureConnectionsOnly),
..Default::default()
})
.await;
assert_matches!(
response,
Ok(sys::Settings { le_security_mode: Some(LeSecurityMode::SecureConnectionsOnly), .. })
);
Ok(())
};
let run_host = handle_host_req_fut!(
host_server,
SetLeSecurityMode,
(|mode: LeSecurityMode| assert_eq!(LeSecurityMode::SecureConnectionsOnly, mode)),
le_security_mode
);
future::try_join3(make_request, run_host, run_configuration).await.unwrap();
}
#[fuchsia::test]
async fn configure_applies_to_multiple_devices() {
// `setup_configuration_test` adds the first host, and in this test we add a second
let (host1_server, dispatcher, config_client, server) =
setup_configuration_test().await.unwrap();
let host1_info = dispatcher.active_host().await.unwrap().info();
let host2_id = HostId(host1_info.id.0 + 1);
let (host2_server, _, _gatt_server, _bonding) =
hd_test::create_and_add_test_host_to_dispatcher(host2_id, &dispatcher).await.unwrap();
let run_configuration = configuration::run(dispatcher, server);
let make_request = async move {
let response = config_client
.update(&sys::Settings { le_privacy: Some(false), ..Default::default() })
.await;
assert_matches!(response, Ok(sys::Settings { le_privacy: Some(false), .. }));
// The configuration client is dropped when this terminates, which causes the configuration
// stream to terminate.
Ok(())
};
let run_host1 = handle_host_req_fut!(
host1_server,
EnablePrivacy,
(|enabled: bool| assert!(!enabled)),
enabled
);
let run_host2 = handle_host_req_fut!(
host2_server,
EnablePrivacy,
(|enabled: bool| assert!(!enabled)),
enabled
);
future::try_join4(run_configuration, make_request, run_host1, run_host2).await.unwrap();
}