extern crate bluenrg;
extern crate bluetooth_hci as hci;
extern crate embedded_hal as hal;
extern crate nb;
mod fixture;
use bluenrg::gap::*;
use fixture::{Fixture, RecordingSink};
use hci::types::{ConnectionIntervalBuilder, ExpectedConnectionLength, ScanWindow};
use std::time::Duration;
#[test]
fn set_nondiscoverable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.set_nondiscoverable())
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x81, 0xFC, 0]));
}
#[test]
fn set_limited_discoverable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_limited_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(2560),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert_eq!(
sink.written_data,
[
1, 0x82, 0xFC, 25, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 8, 0x08, 0x74, 0x65, 0x73,
0x74, 0x64, 0x65, 0x76, 4, 0x01, 0x02, 0x03, 0x04, 0xA0, 0x0F, 0xFF, 0xFF
]
);
}
#[test]
fn set_limited_discoverable_bad_adv_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_limited_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableDirectedHighDutyCycle,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(2560),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
AdvertisingType::ConnectableDirectedHighDutyCycle
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_limited_discoverable_bad_adv_interval() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_limited_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(1279),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingInterval(
Duration::from_millis(1280),
Duration::from_millis(1279)
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_limited_discoverable_bad_conn_interval() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_limited_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(1280),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (
Some(Duration::from_millis(5000)),
Some(Duration::from_millis(4999)),
),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadConnectionInterval(
Duration::from_millis(5000),
Duration::from_millis(4999)
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_discoverable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(2560),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x83, 0xFC, 25, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 8, 0x08, 0x74, 0x65, 0x73,
0x74, 0x64, 0x65, 0x76, 4, 0x01, 0x02, 0x03, 0x04, 0xA0, 0x0F, 0xFF, 0xFF
]));
}
#[test]
fn set_discoverable_bad_adv_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableDirectedHighDutyCycle,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(2560),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
AdvertisingType::ConnectableDirectedHighDutyCycle
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_discoverable_bad_adv_interval() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(1279),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (Some(Duration::from_millis(5000)), None),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingInterval(
Duration::from_millis(1280),
Duration::from_millis(1279)
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_discoverable_bad_conn_interval() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_discoverable(&DiscoverableParameters {
advertising_type: AdvertisingType::ConnectableUndirected,
advertising_interval: Some((
Duration::from_millis(1280),
Duration::from_millis(1280),
)),
address_type: OwnAddressType::Public,
filter_policy: AdvertisingFilterPolicy::AllowConnectionAndScan,
local_name: Some(LocalName::Shortened(b"testdev")),
advertising_data: &[0x01, 0x02, 0x03, 0x04],
conn_interval: (
Some(Duration::from_millis(5000)),
Some(Duration::from_millis(4999)),
),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadConnectionInterval(
Duration::from_millis(5000),
Duration::from_millis(4999)
))
);
}
assert!(!sink.wrote_header());
}
#[cfg(not(feature = "ms"))]
#[test]
fn set_direct_connectable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_direct_connectable(&DirectConnectableParameters {
own_address_type: OwnAddressType::Public,
initiator_address: BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x84, 0xFC, 8, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06]));
}
#[cfg(feature = "ms")]
#[test]
fn set_direct_connectable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_direct_connectable(&DirectConnectableParameters {
own_address_type: OwnAddressType::Public,
advertising_type: AdvertisingType::ConnectableDirectedHighDutyCycle,
initiator_address: BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])),
advertising_interval: (Duration::from_millis(20), Duration::from_millis(50)),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x84, 0xFC, 13, 0x00, 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x20, 0x00, 0x50,
0x00
]));
}
#[cfg(feature = "ms")]
#[test]
fn set_direct_connectable_bad_adv_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_direct_connectable(&DirectConnectableParameters {
own_address_type: OwnAddressType::Public,
advertising_type: AdvertisingType::ConnectableUndirected,
initiator_address: BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])),
advertising_interval: (Duration::from_millis(20), Duration::from_millis(50)),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
AdvertisingType::ConnectableUndirected
))
);
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn set_direct_connectable_bad_adv_interval() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
for (min, max) in [
(Duration::from_millis(19), Duration::from_millis(50)),
(Duration::from_millis(20), Duration::from_millis(10241)),
(Duration::from_millis(500), Duration::from_millis(499)),
]
.iter()
{
let err = fixture
.act(|controller| {
controller.set_direct_connectable(&DirectConnectableParameters {
own_address_type: OwnAddressType::Public,
advertising_type: AdvertisingType::ConnectableDirectedHighDutyCycle,
initiator_address: BdAddrType::Public(BdAddr([1, 2, 3, 4, 5, 6])),
advertising_interval: (*min, *max),
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingInterval(*min, *max))
);
}
}
assert!(!sink.wrote_header());
}
#[test]
fn set_io_capability() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.set_io_capability(IoCapability::None))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x85, 0xFC, 1, 0x03]));
}
#[test]
fn set_authentication_requirement() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_authentication_requirement(&AuthenticationRequirements {
mitm_protection_required: true,
out_of_band_auth: OutOfBandAuthentication::Enabled([
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE,
0xF,
]),
encryption_key_size_range: (8, 64),
fixed_pin: Pin::Fixed(123456),
bonding_required: true,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x86, 0xFC, 26, 0x01, 0x01, 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB,
0xC, 0xD, 0xE, 0xF, 8, 64, 0, 0x40, 0xe2, 0x01, 0x00, 0x1
]));
}
#[test]
fn set_authentication_requirement_2() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_authentication_requirement(&AuthenticationRequirements {
mitm_protection_required: false,
out_of_band_auth: OutOfBandAuthentication::Disabled,
encryption_key_size_range: (1, 255),
fixed_pin: Pin::Requested,
bonding_required: false,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x86, 0xFC, 26, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 1, 255, 1, 0x00, 0x00, 0x00, 0x00, 0x0
]));
}
#[test]
fn set_authentication_requirement_bad_key_size_range() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_authentication_requirement(&AuthenticationRequirements {
mitm_protection_required: false,
out_of_band_auth: OutOfBandAuthentication::Disabled,
encryption_key_size_range: (255, 1),
fixed_pin: Pin::Requested,
bonding_required: false,
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadEncryptionKeySizeRange(255, 1))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_authentication_requirement_bad_pin() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_authentication_requirement(&AuthenticationRequirements {
mitm_protection_required: false,
out_of_band_auth: OutOfBandAuthentication::Disabled,
encryption_key_size_range: (1, 255),
fixed_pin: Pin::Fixed(1000000),
bonding_required: false,
})
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::BadFixedPin(1000000)));
}
assert!(!sink.wrote_header());
}
#[test]
fn set_authorization_requirement() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_authorization_requirement(hci::ConnectionHandle(0x0201), true)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x87, 0xFC, 3, 0x01, 0x02, 0x01]));
}
#[test]
fn pass_key_response() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.pass_key_response(hci::ConnectionHandle(0x0201), 123456))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x88, 0xFC, 6, 0x01, 0x02, 0x40, 0xe2, 0x01, 0x00]));
}
#[test]
fn pass_key_response_bad_pin() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| controller.pass_key_response(hci::ConnectionHandle(0x0201), 1000000))
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::BadFixedPin(1000000)));
}
assert!(!sink.wrote_header());
}
#[test]
fn authorization_response() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.authorization_response(
hci::ConnectionHandle(0x0201),
Authorization::Authorized,
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x89, 0xFC, 3, 0x01, 0x02, 0x01]));
}
#[cfg(not(feature = "ms"))]
#[test]
fn init() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.init_gap(Role::PERIPHERAL | Role::BROADCASTER))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8A, 0xFC, 1, 0x03]));
}
#[cfg(feature = "ms")]
#[test]
fn init() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.init_gap(Role::PERIPHERAL | Role::BROADCASTER, true, 3))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8A, 0xFC, 3, 0x03, 0x01, 0x03]));
}
#[cfg(not(feature = "ms"))]
#[test]
fn set_nonconnectable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.set_nonconnectable(AdvertisingType::ScannableUndirected))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8B, 0xFC, 1, 0x02]));
}
#[cfg(not(feature = "ms"))]
#[test]
fn set_nonconnectable_bad_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_nonconnectable(AdvertisingType::ConnectableDirectedHighDutyCycle)
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
AdvertisingType::ConnectableDirectedHighDutyCycle
))
);
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn set_nonconnectable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_nonconnectable(
AdvertisingType::ScannableUndirected,
AddressType::ResolvablePrivate,
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8B, 0xFC, 2, 0x02, 0x02]));
}
#[cfg(feature = "ms")]
#[test]
fn set_nonconnectable_bad_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_nonconnectable(
AdvertisingType::ConnectableDirectedHighDutyCycle,
AddressType::ResolvablePrivate,
)
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
AdvertisingType::ConnectableDirectedHighDutyCycle
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn set_undirected_connectable() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_undirected_connectable(
AdvertisingFilterPolicy::AllowConnectionAndScan,
AddressType::ResolvablePrivate,
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8C, 0xFC, 2, 0x00, 0x02]));
}
#[test]
fn set_undirected_connectable_bad_advertising_filter_policy() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_undirected_connectable(
AdvertisingFilterPolicy::WhiteListConnectionAllowScan,
AddressType::ResolvablePrivate,
)
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingFilterPolicy(
AdvertisingFilterPolicy::WhiteListConnectionAllowScan
))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn peripheral_security_request() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.peripheral_security_request(&SecurityRequestParameters {
conn_handle: hci::ConnectionHandle(0x0201),
bonding: true,
mitm_protection: false,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8D, 0xFC, 4, 0x01, 0x02, 0x01, 0x00]));
}
#[test]
fn update_advertising_data() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.update_advertising_data(&[1, 2, 3]))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8E, 0xFC, 4, 3, 1, 2, 3]));
}
#[test]
fn update_advertising_data_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| controller.update_advertising_data(&[0; 32]))
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::BadAdvertisingDataLength(32)));
}
assert!(!sink.wrote_header());
}
#[test]
fn delete_ad_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.delete_ad_type(AdvertisingDataType::TxPowerLevel))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x8F, 0xFC, 1, 0x0A]));
}
#[test]
fn get_security_level() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.get_security_level())
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x90, 0xFC, 0]));
}
#[test]
fn set_event_mask() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_gap_event_mask(
EventFlags::LIMITED_DISCOVERABLE_TIMEOUT | EventFlags::PAIRING_COMPLETE,
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x91, 0xFC, 2, 0x03, 0x00]));
}
#[test]
fn configure_white_list() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.configure_white_list())
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x92, 0xFC, 0]));
}
#[test]
fn terminate() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.terminate(hci::ConnectionHandle(0x0201), hci::Status::AuthFailure)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x93, 0xFC, 3, 0x01, 0x02, 0x05]));
}
#[test]
fn terminate_bad_disconnection_reason() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.terminate(
hci::ConnectionHandle(0x0201),
hci::Status::CommandDisallowed,
)
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadTerminationReason(hci::Status::CommandDisallowed))
);
}
assert!(!sink.wrote_header());
}
#[test]
fn clear_security_database() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.clear_security_database())
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x94, 0xFC, 0]));
}
#[cfg(not(feature = "ms"))]
#[test]
fn allow_rebond() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture.act(|controller| controller.allow_rebond()).unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x95, 0xFC, 0]));
}
#[cfg(feature = "ms")]
#[test]
fn allow_rebond() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.allow_rebond(hci::ConnectionHandle(0x0201)))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x95, 0xFC, 2, 0x01, 0x02]));
}
#[test]
fn start_limited_discovery_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_limited_discovery_procedure(&DiscoveryProcedureParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x96, 0xFC, 6, 0x04, 0x00, 0x04, 0x00, 0x01, 0x01]));
}
#[test]
fn start_general_discovery_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_general_discovery_procedure(&DiscoveryProcedureParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x97, 0xFC, 6, 0x04, 0x00, 0x04, 0x00, 0x01, 0x01]));
}
#[test]
fn start_name_discovery_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_name_discovery_procedure(&NameDiscoveryProcedureParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
peer_address: hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x98, 0xFC, 24, 0x04, 0x00, 0x04, 0x00, 0x01, 1, 2, 3, 4, 5, 6, 1, 0x28, 0x00, 0xc8,
0x00, 10, 0, 0x58, 0x02, 0xF0, 0x00, 0x60, 0x09
]));
}
#[cfg(not(feature = "ms"))]
#[test]
fn start_auto_connection_establishment() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_auto_connection_establishment(
&AutoConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
reconnection_address: Some(hci::BdAddr([10, 20, 30, 40, 50, 60])),
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
},
)
})
.unwrap();
}
assert!(sink.wrote_header());
let expected = [
1, 0x99, 0xFC, 39, 0x04, 0x00, 0x04, 0x00, 0x01, 0x28, 0x00, 0xc8, 0x00, 10, 0, 0x58, 0x02,
0xF0, 0x00, 0x60, 0x09, 1, 10, 20, 30, 40, 50, 60, 2, 0, 1, 2, 3, 4, 5, 6, 1, 6, 5, 4, 3,
2, 1,
];
assert!(&sink.wrote(&expected));
}
#[cfg(feature = "ms")]
#[test]
fn start_auto_connection_establishment() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_auto_connection_establishment(
&AutoConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
},
)
})
.unwrap();
}
assert!(sink.wrote_header());
let expected = [
1, 0x99, 0xFC, 32, 0x04, 0x00, 0x04, 0x00, 0x01, 0x28, 0x00, 0xc8, 0x00, 10, 0, 0x58, 0x02,
0xF0, 0x00, 0x60, 0x09, 2, 0, 1, 2, 3, 4, 5, 6, 1, 6, 5, 4, 3, 2, 1,
];
assert!(sink.wrote(&expected));
}
#[cfg(not(feature = "ms"))]
#[test]
fn start_auto_connection_establishment_white_list_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.start_auto_connection_establishment(
&AutoConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
reconnection_address: None,
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 33],
},
)
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::WhiteListTooLong));
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn start_auto_connection_establishment_white_list_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.start_auto_connection_establishment(
&AutoConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 34],
},
)
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::WhiteListTooLong));
}
assert!(!sink.wrote_header());
}
#[cfg(not(feature = "ms"))]
#[test]
fn start_general_connection_establishment() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_general_connection_establishment(
&GeneralConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
reconnection_address: Some(hci::BdAddr([1, 2, 3, 4, 5, 6])),
},
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(
sink.wrote(&[1, 0x9A, 0xFC, 13, 0x04, 0x00, 0x04, 0x00, 0x01, 0x1, 0x1, 1, 2, 3, 4, 5, 6])
);
}
#[cfg(feature = "ms")]
#[test]
fn start_general_connection_establishment() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_general_connection_establishment(
&GeneralConnectionEstablishmentParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
},
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x9A, 0xFC, 6, 0x04, 0x00, 0x04, 0x00, 0x01, 0x1]));
}
#[test]
fn start_selective_connection_establishment() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_selective_connection_establishment(
&SelectiveConnectionEstablishmentParameters {
scan_type: hci::host::ScanType::Active,
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
},
)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x9B, 0xFC, 22, 0x01, 0x04, 0x00, 0x04, 0x00, 0x01, 0x01, 0x02, 0x00, 1, 2, 3, 4, 5, 6,
0x01, 6, 5, 4, 3, 2, 1
]));
}
#[test]
fn start_selective_connection_establishment_white_list_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.start_selective_connection_establishment(
&SelectiveConnectionEstablishmentParameters {
scan_type: hci::host::ScanType::Passive,
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
own_address_type: hci::host::OwnAddressType::Random,
filter_duplicates: true,
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 36],
},
)
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::WhiteListTooLong));
}
assert!(!sink.wrote_header());
}
#[test]
fn create_connection() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.create_connection(&ConnectionParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
peer_address: hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
own_address_type: hci::host::OwnAddressType::Random,
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x9C, 0xFC, 24, 0x04, 0x00, 0x04, 0x00, 0x00, 1, 2, 3, 4, 5, 6, 0x01, 0x28, 0x00, 0xc8,
0x00, 10, 0, 0x58, 0x02, 0xF0, 0x00, 0x60, 0x09
]));
}
#[test]
fn terminate_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.terminate_procedure(Procedure::LIMITED_DISCOVERY))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x9D, 0xFC, 1, 0x01]));
}
#[test]
fn terminate_multiple_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller
.terminate_procedure(Procedure::LIMITED_DISCOVERY | Procedure::OBSERVATION)
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x9D, 0xFC, 1, 0x81]));
}
#[test]
fn terminate_no_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| controller.terminate_procedure(Procedure::empty()))
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::NoProcedure));
}
assert!(!sink.wrote_header());
}
#[test]
fn start_connection_update() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_connection_update(&ConnectionUpdateParameters {
conn_handle: hci::ConnectionHandle(0x0201),
conn_interval: ConnectionIntervalBuilder::new()
.with_range(Duration::from_millis(50), Duration::from_millis(250))
.with_latency(10)
.with_supervision_timeout(Duration::from_millis(6000))
.build()
.unwrap(),
expected_connection_length: ExpectedConnectionLength::new(
Duration::from_millis(150),
Duration::from_millis(1500),
)
.unwrap(),
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[
1, 0x9E, 0xFC, 14, 0x01, 0x02, 0x28, 0x00, 0xc8, 0x00, 10, 0, 0x58, 0x02, 0xF0, 0x00, 0x60,
0x09
]));
}
#[test]
fn send_pairing_request() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.send_pairing_request(&PairingRequest {
conn_handle: hci::ConnectionHandle(0x0201),
force_rebond: true,
force_reencrypt: true,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0x9F, 0xFC, 3, 0x01, 0x02, 0x03]));
}
#[test]
fn resolve_private_address() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.resolve_private_address(hci::BdAddr([1, 2, 3, 4, 5, 6])))
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0xA0, 0xFC, 6, 1, 2, 3, 4, 5, 6]));
}
#[test]
fn get_bonded_devices() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| controller.get_bonded_devices())
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0xA3, 0xFC, 0]));
}
#[cfg(feature = "ms")]
#[test]
fn set_broadcast_mode() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ScannableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
})
})
.unwrap();
}
assert!(sink.wrote_header());
let expected = [
1, 0xA1, 0xFC, 32, 0xA0, 0x00, 0x40, 0x06, 0x02, 0x00, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
2, 0x00, 1, 2, 3, 4, 5, 6, 0x01, 6, 5, 4, 3, 2, 1,
];
assert!(sink.wrote(&expected));
}
#[cfg(feature = "ms")]
#[test]
fn set_broadcast_mode_bad_advertising_type() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ConnectableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
})
})
.err()
.unwrap();
assert_eq!(
err,
nb::Error::Other(Error::BadAdvertisingType(
hci::types::AdvertisingType::ConnectableUndirected
))
);
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn set_broadcast_mode_advertising_data_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ScannableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[0; 32],
white_list: &[
hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])),
hci::host::PeerAddrType::RandomDeviceAddress(hci::BdAddr([
6, 5, 4, 3, 2, 1,
])),
],
})
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::BadAdvertisingDataLength(32)));
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn set_broadcast_mode_white_list_too_long() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ScannableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[0; 31],
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 32],
})
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::WhiteListTooLong));
}
assert!(!sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn set_broadcast_mode_white_list_too_long_no_adv_data() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
let err = fixture
.act(|controller| {
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ScannableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[],
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 35],
})?;
controller.set_broadcast_mode(&BroadcastModeParameters {
advertising_interval: hci::types::AdvertisingInterval::for_type(
hci::types::AdvertisingType::ScannableUndirected,
)
.with_range(Duration::from_millis(100), Duration::from_millis(1000))
.unwrap(),
own_address_type: AddressType::Public,
advertising_data: &[],
white_list: &[hci::host::PeerAddrType::PublicDeviceAddress(hci::BdAddr([
1, 2, 3, 4, 5, 6,
])); 36],
})
})
.err()
.unwrap();
assert_eq!(err, nb::Error::Other(Error::WhiteListTooLong));
}
assert!(sink.wrote_header());
}
#[cfg(feature = "ms")]
#[test]
fn start_observation_procedure() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.start_observation_procedure(&ObservationProcedureParameters {
scan_window: ScanWindow::start_every(Duration::from_micros(2500))
.unwrap()
.open_for(Duration::from_micros(2500))
.unwrap(),
scan_type: hci::host::ScanType::Passive,
own_address_type: AddressType::Random,
filter_duplicates: true,
})
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0xA2, 0xFC, 7, 0x04, 0x00, 0x04, 0x00, 0x00, 0x01, 0x01]));
}
#[test]
fn is_device_bonded() {
let mut sink = RecordingSink::new();
{
let mut fixture = Fixture::new(&mut sink);
fixture
.act(|controller| {
controller.is_device_bonded(hci::host::PeerAddrType::PublicDeviceAddress(
hci::BdAddr([1, 2, 3, 4, 5, 6]),
))
})
.unwrap();
}
assert!(sink.wrote_header());
assert!(sink.wrote(&[1, 0xA4, 0xFC, 7, 0x00, 1, 2, 3, 4, 5, 6]));
}