mirror of
https://github.com/jmcorgan/fips.git
synced 2026-08-10 16:43:12 +00:00
test(node): pin transport restart backoff and BLE start re-entrancy
- Pure-policy tests on PendingTransport: backoff doubling, cap saturation (checked_shl/saturating_mul, never overflows or panics), never-gives-up past the cap, and the is_due boundary - BleTransport::start_async re-entrancy after a listen failure: first call errs and leaves state Failed, second call succeeds and leaves state Up — the claim the whole supervisor rests on - Document the operational-but-dark case (advertise/scan failures are logged and swallowed) as a Limitations note on start_async; only a listener failure is recovered by restart supervision
This commit is contained in:
@@ -268,10 +268,12 @@ mod node_integration_tests {
|
||||
let io = MockBleIo::new("hci0", test_addr(1));
|
||||
io.fail_next_listens(1);
|
||||
|
||||
let mut config = BleConfig::default();
|
||||
config.accept_connections = Some(true);
|
||||
config.scan = Some(false);
|
||||
config.advertise = Some(false);
|
||||
let config = BleConfig {
|
||||
accept_connections: Some(true),
|
||||
scan: Some(false),
|
||||
advertise: Some(false),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let (tx, _rx) = tokio::sync::mpsc::channel(64);
|
||||
let mut transport = BleTransport::new(TransportId::new(1), None, config, io, tx);
|
||||
@@ -309,8 +311,10 @@ mod node_integration_tests {
|
||||
// errors out on bind-address parsing — reproduce that exact shape
|
||||
// with an unparseable bind address, then feed the failed handle to
|
||||
// `quarantine_transport` and confirm it is dropped, not retained.
|
||||
let mut udp_config = crate::config::UdpConfig::default();
|
||||
udp_config.bind_addr = Some("not-an-address".to_string());
|
||||
let udp_config = crate::config::UdpConfig {
|
||||
bind_addr: Some("not-an-address".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let (packet_tx, _packet_rx) = crate::transport::packet_channel(64);
|
||||
let mut udp = crate::transport::udp::UdpTransport::new(
|
||||
TransportId::new(3),
|
||||
|
||||
@@ -177,6 +177,17 @@ impl<I: BleIo> BleTransport<I> {
|
||||
|
||||
/// Start the transport asynchronously.
|
||||
pub async fn start_async(&mut self) -> Result<(), TransportError> {
|
||||
// Limitations: only a failure to begin listening marks the transport
|
||||
// `Failed` and returns `Err` — that is the one case restart
|
||||
// supervision (`node::transport_restart`) can recover. A failure to
|
||||
// begin advertising or scanning, below, is logged and swallowed, and
|
||||
// the transport still proceeds to the operational state — so a
|
||||
// transport can report itself operational while neither advertising
|
||||
// nor scanning is actually running underneath it. Closing this gap
|
||||
// would mean re-running the advertise/scan calls on a transport that
|
||||
// already owns a live acceptor and a spawned accept loop, which is a
|
||||
// larger change than this fix covers, so it is deferred rather than
|
||||
// attempted here.
|
||||
if !self.state.can_start() {
|
||||
return Err(TransportError::AlreadyStarted);
|
||||
}
|
||||
@@ -1163,6 +1174,24 @@ mod tests {
|
||||
assert_eq!(transport.state(), TransportState::Down);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_start_async_is_reentrant_after_listen_failure() {
|
||||
// The whole restart supervisor rests on this: `can_start()`
|
||||
// permitting a retry is worthless if `start_async` cannot actually
|
||||
// run twice on the same transport.
|
||||
let io = MockBleIo::new("hci0", test_addr(1));
|
||||
io.fail_next_listens(1);
|
||||
let (mut transport, _rx) = make_transport(io);
|
||||
|
||||
assert!(transport.start_async().await.is_err());
|
||||
assert_eq!(transport.state(), TransportState::Failed);
|
||||
|
||||
// The injected failure was one-shot — the second call is a real
|
||||
// retry, not a repeat of the same failure.
|
||||
transport.start_async().await.unwrap();
|
||||
assert_eq!(transport.state(), TransportState::Up);
|
||||
}
|
||||
|
||||
#[tokio::test(start_paused = true)]
|
||||
async fn test_scan_discovers_peers() {
|
||||
let io = MockBleIo::new("hci0", test_addr(1));
|
||||
|
||||
Reference in New Issue
Block a user