mod common;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::Arc;
use net_kit::Net;
#[test]
fn operations_before_start_are_well_defined() {
let net = Net::new();
assert_eq!(
net.local_network_reachability().unwrap(),
net_kit::NetworkStatus::Unavailable
);
assert!(net.register(Box::new(|_| {})).unwrap().is_none());
assert!(net.clear_all_listener().is_err());
assert!(net.shutdown().is_ok());
}
#[test]
fn stale_handle_after_shutdown_is_rejected() {
let rt = common::build_runtime();
let net = Net::new();
rt.block_on(async { net.start().await.unwrap() });
let handle = net.register(Box::new(|_| {})).unwrap().unwrap();
net.shutdown().unwrap();
assert!(!net.unregister(handle).unwrap());
}
#[test]
fn panicking_listener_does_not_poison_api() {
let rt = common::build_runtime();
let net = Net::new();
rt.block_on(async { net.start().await.unwrap() });
let panic_handle = net
.register(Box::new(|_| panic!("listener intentionally panics")))
.unwrap()
.expect("register ok");
let normal = net
.register(Box::new(|_| {}))
.unwrap()
.expect("second register ok");
assert_ne!(panic_handle, normal);
assert!(net.unregister(panic_handle).unwrap());
assert!(net.unregister(normal).unwrap());
let _ = net.local_network_reachability();
net.clear_all_listener().unwrap();
net.shutdown().expect("shutdown remains possible");
}
#[test]
fn slow_listener_does_not_block_public_api() {
let rt = common::build_runtime();
let net = Net::new();
rt.block_on(async { net.start().await.unwrap() });
let invoked = Arc::new(AtomicUsize::new(0));
let invoked_clone = Arc::clone(&invoked);
let slow = net
.register(Box::new(move |_| {
invoked_clone.fetch_add(1, Ordering::SeqCst);
std::thread::sleep(std::time::Duration::from_millis(100));
}))
.unwrap()
.unwrap();
let _ = net.local_network_reachability();
assert!(net.register(Box::new(|_| {})).unwrap().is_some());
assert!(net.unregister(slow).unwrap());
net.shutdown().unwrap();
}