use nmrs::{
ConnectionError, DeviceState, DeviceType, NetworkManager, StateReason, VpnCredentials, VpnType,
WifiSecurity, WireGuardPeer, reason_to_error,
};
use std::time::Duration;
use tokio::time::sleep;
async fn is_networkmanager_available() -> bool {
NetworkManager::new().await.is_ok()
}
async fn has_wifi_device(nm: &NetworkManager) -> bool {
nm.list_wireless_devices()
.await
.map(|d| !d.is_empty())
.unwrap_or(false)
}
async fn has_ethernet_device(nm: &NetworkManager) -> bool {
nm.list_wired_devices()
.await
.map(|d| !d.is_empty())
.unwrap_or(false)
}
macro_rules! require_networkmanager {
() => {
if !is_networkmanager_available().await {
eprintln!("Skipping test: NetworkManager not available");
return;
}
};
}
macro_rules! require_wifi {
($nm:expr) => {
if !has_wifi_device($nm).await {
eprintln!("Skipping test: No WiFi device available");
return;
}
};
}
macro_rules! require_ethernet {
($nm:expr) => {
if !has_ethernet_device($nm).await {
eprintln!("Skipping test: No Ethernet device available");
return;
}
};
}
#[tokio::test]
async fn test_networkmanager_initialization() {
require_networkmanager!();
let _nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
}
#[tokio::test]
async fn test_list_devices() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm.list_devices().await.expect("Failed to list devices");
assert!(!devices.is_empty(), "Expected at least one device");
for device in &devices {
assert!(!device.path.is_empty(), "Device path should not be empty");
assert!(
!device.interface.is_empty(),
"Device interface should not be empty"
);
}
}
#[tokio::test]
async fn test_wifi_enabled_get_set() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
let initial_state = nm
.wifi_enabled()
.await
.expect("Failed to get WiFi enabled state");
match nm.set_wifi_enabled(!initial_state).await {
Ok(_) => {
sleep(Duration::from_millis(500)).await;
let new_state = nm
.wifi_enabled()
.await
.expect("Failed to get WiFi enabled state after toggle");
if new_state == initial_state {
eprintln!(
"Warning: WiFi state didn't change (may lack permissions). Initial: {}, New: {}",
initial_state, new_state
);
return;
}
}
Err(e) => {
eprintln!("Failed to toggle WiFi (may lack permissions): {}", e);
return;
}
}
nm.set_wifi_enabled(initial_state)
.await
.expect("Failed to restore WiFi enabled state");
sleep(Duration::from_millis(500)).await;
let restored_state = nm
.wifi_enabled()
.await
.expect("Failed to get WiFi enabled state after restore");
assert_eq!(
restored_state, initial_state,
"WiFi state should be restored to original"
);
}
#[tokio::test]
async fn test_wifi_hardware_enabled() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to connect to NetworkManager");
require_wifi!(&nm);
let _ = nm
.wifi_hardware_enabled()
.await
.expect("Failed to get WiFi hardware enabled state");
}
#[tokio::test]
async fn test_wait_for_wifi_ready() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let result = nm.wait_for_wifi_ready().await;
match result {
Ok(_) => {}
Err(e) => {
eprintln!(
"WiFi not ready (this may be expected in some environments): {}",
e
);
}
}
}
#[tokio::test]
async fn test_scan_networks() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let result = nm.scan_networks().await;
match result {
Ok(_) => {
sleep(Duration::from_secs(2)).await;
}
Err(e) => {
eprintln!("Scan failed (may be expected in some environments): {}", e);
}
}
}
#[tokio::test]
async fn test_list_networks() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let _ = nm.scan_networks().await;
sleep(Duration::from_secs(2)).await;
let networks = nm.list_networks().await.expect("Failed to list networks");
for network in &networks {
assert!(
!network.ssid.is_empty() || network.ssid == "<hidden>",
"SSID should not be empty (unless hidden)"
);
assert!(
!network.device.is_empty(),
"Device path should not be empty"
);
}
}
#[tokio::test]
async fn test_current_ssid() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let current_ssid = nm.current_ssid().await;
if let Some(ssid) = current_ssid {
assert!(
!ssid.is_empty(),
"Current SSID should not be empty if connected"
);
}
}
#[tokio::test]
async fn test_current_connection_info() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let info = nm.current_connection_info().await;
if let Some((ssid, _frequency)) = info {
assert!(
!ssid.is_empty(),
"Current SSID should not be empty if connected"
);
}
}
#[tokio::test]
async fn test_show_details() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let _ = nm.scan_networks().await;
sleep(Duration::from_secs(2)).await;
let networks = nm.list_networks().await.expect("Failed to list networks");
if let Some(network) = networks.first() {
let result = nm.show_details(network).await;
match result {
Ok(details) => {
assert_eq!(details.ssid, network.ssid, "SSID should match");
assert!(!details.bssid.is_empty(), "BSSID should not be empty");
assert!(details.strength <= 100, "Strength should be <= 100");
assert!(!details.mode.is_empty(), "Mode should not be empty");
assert!(!details.security.is_empty(), "Security should not be empty");
assert!(!details.status.is_empty(), "Status should not be empty");
}
Err(e) => {
eprintln!("Failed to show details (may be expected): {}", e);
}
}
}
}
#[tokio::test]
async fn test_has_saved_connection() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
let result = nm
.has_saved_connection("__NONEXISTENT_TEST_SSID__")
.await
.expect("Failed to check saved connection");
assert!(
!result,
"Non-existent SSID should not have saved connection"
);
let _result = nm
.has_saved_connection("")
.await
.expect("Failed to check saved connection for empty SSID");
}
#[tokio::test]
async fn test_get_saved_connection_path() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
let result = nm
.get_saved_connection_path("__NONEXISTENT_TEST_SSID__")
.await
.expect("Failed to get saved connection path");
assert!(
result.is_none(),
"Non-existent SSID should not have saved connection path"
);
let result = nm
.get_saved_connection_path("")
.await
.expect("Failed to get saved connection path for empty SSID");
assert!(result.is_some() || result.is_none());
}
#[tokio::test]
async fn test_connect_open_network() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let _ = nm.scan_networks().await;
sleep(Duration::from_secs(2)).await;
let networks = nm.list_networks().await.expect("Failed to list networks");
let open_network = networks.iter().find(|n| !n.secured);
if let Some(network) = open_network {
let test_ssid = &network.ssid;
if test_ssid.is_empty() || test_ssid == "<hidden>" {
eprintln!("Skipping: Found open network but SSID is hidden/empty");
return;
}
let result = nm.connect(test_ssid, WifiSecurity::Open).await;
match result {
Ok(_) => {
sleep(Duration::from_secs(3)).await;
let current = nm.current_ssid().await;
if let Some(connected_ssid) = current {
eprintln!("Connected SSID: {}", connected_ssid);
}
}
Err(e) => {
eprintln!("Connection failed (may be expected): {}", e);
}
}
} else {
eprintln!("No open networks found for testing");
}
}
#[tokio::test]
async fn test_connect_psk_network_with_empty_password() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let _ = nm.scan_networks().await;
sleep(Duration::from_secs(2)).await;
let networks = nm.list_networks().await.expect("Failed to list networks");
let psk_network = networks.iter().find(|n| n.is_psk);
if let Some(network) = psk_network {
let test_ssid = &network.ssid;
if test_ssid.is_empty() || test_ssid == "<hidden>" {
eprintln!("Skipping: Found PSK network but SSID is hidden/empty");
return;
}
let has_saved = nm
.has_saved_connection(test_ssid)
.await
.expect("Failed to check saved connection");
if has_saved {
let result = nm
.connect(test_ssid, WifiSecurity::WpaPsk { psk: String::new() })
.await;
match result {
Ok(_) => {
sleep(Duration::from_secs(3)).await;
}
Err(e) => {
eprintln!("Connection with saved credentials failed: {}", e);
}
}
} else {
eprintln!("No saved connection for PSK network, skipping test");
}
} else {
eprintln!("No PSK networks found for testing");
}
}
#[tokio::test]
async fn test_forget_nonexistent_network() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
let result = nm.forget("__NONEXISTENT_TEST_SSID_TO_FORGET__").await;
assert!(
result.is_err(),
"Forgetting non-existent network should fail"
);
}
#[tokio::test]
async fn test_device_states() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm.list_devices().await.expect("Failed to list devices");
for device in &devices {
match device.state {
DeviceState::Unmanaged
| DeviceState::Unavailable
| DeviceState::Disconnected
| DeviceState::Prepare
| DeviceState::Config
| DeviceState::NeedAuth
| DeviceState::IpConfig
| DeviceState::IpCheck
| DeviceState::Secondaries
| DeviceState::Activated
| DeviceState::Deactivating
| DeviceState::Failed
| DeviceState::Other(_) => {}
_ => {
panic!("Invalid device state: {:?}", device.state);
}
}
}
}
#[tokio::test]
async fn test_device_types() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm.list_devices().await.expect("Failed to list devices");
for device in &devices {
match device.device_type {
DeviceType::Ethernet
| DeviceType::Wifi
| DeviceType::Bluetooth
| DeviceType::WifiP2P
| DeviceType::Loopback
| DeviceType::Other(_) => {
}
_ => {
panic!("Invalid device type: {:?}", device.device_type);
}
}
}
}
#[tokio::test]
async fn test_network_properties() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
let _ = nm.scan_networks().await;
sleep(Duration::from_secs(2)).await;
let networks = nm.list_networks().await.expect("Failed to list networks");
for network in &networks {
assert!(
!network.ssid.is_empty() || network.ssid == "<hidden>",
"SSID should not be empty"
);
assert!(
!network.device.is_empty(),
"Device path should not be empty"
);
if let Some(strength) = network.strength {
assert!(strength <= 100, "Strength should be <= 100");
}
if !network.secured {
assert!(!network.is_psk, "Unsecured network should not be PSK");
assert!(!network.is_eap, "Unsecured network should not be EAP");
}
}
}
#[tokio::test]
async fn test_multiple_scan_requests() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let _ = nm.wait_for_wifi_ready().await;
for i in 0..3 {
nm.wait_for_wifi_ready().await.expect("WiFi not ready");
let result = nm.scan_networks().await;
match result {
Ok(_) => eprintln!("Scan {} succeeded", i + 1),
Err(e) => eprintln!("Scan {} failed: {}", i + 1, e),
}
nm.wait_for_wifi_ready()
.await
.expect("WiFi did not recover");
sleep(Duration::from_secs(3)).await;
}
let networks = nm.list_networks().await.expect("Failed to list networks");
eprintln!("Found {} networks after multiple scans", networks.len());
}
#[tokio::test]
async fn test_concurrent_operations() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
nm.set_wifi_enabled(true)
.await
.expect("Failed to enable WiFi");
let (devices_result, wifi_enabled_result, networks_result) =
tokio::join!(nm.list_devices(), nm.wifi_enabled(), nm.list_networks());
assert!(devices_result.is_ok(), "list_devices should succeed");
assert!(wifi_enabled_result.is_ok(), "wifi_enabled should succeed");
let _ = networks_result;
}
#[test]
fn reason_to_error_auth_mapping() {
assert!(matches!(reason_to_error(9), ConnectionError::AuthFailed));
assert!(matches!(reason_to_error(7), ConnectionError::AuthFailed));
assert!(matches!(reason_to_error(17), ConnectionError::DhcpFailed));
assert!(matches!(reason_to_error(70), ConnectionError::NotFound));
}
#[test]
fn state_reason_conversion() {
assert_eq!(StateReason::from(9), StateReason::SupplicantFailed);
assert_eq!(StateReason::from(70), StateReason::SsidNotFound);
assert_eq!(StateReason::from(999), StateReason::Other(999));
}
#[test]
fn connection_error_display() {
let auth_err = ConnectionError::AuthFailed;
assert_eq!(format!("{}", auth_err), "authentication failed");
let not_found_err = ConnectionError::NotFound;
assert_eq!(format!("{}", not_found_err), "network not found");
let timeout_err = ConnectionError::Timeout;
assert_eq!(format!("{}", timeout_err), "connection timeout");
let stuck_err = ConnectionError::Stuck("config".into());
assert_eq!(
format!("{}", stuck_err),
"connection stuck in state: config"
);
}
#[tokio::test]
async fn forget_returns_no_saved_connection_error() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_wifi!(&nm);
let result = nm.forget("__NONEXISTENT_TEST_SSID__").await;
match result {
Err(ConnectionError::NoSavedConnection) => {
}
Err(e) => {
panic!("Expected NoSavedConnection error, got: {}", e);
}
Ok(_) => {
println!("Expected response, got success");
}
}
}
#[tokio::test]
async fn test_list_wired_devices() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm
.list_wired_devices()
.await
.expect("Failed to list wired devices");
for device in &devices {
assert!(!device.path.is_empty(), "Device path should not be empty");
assert!(
!device.interface.is_empty(),
"Device interface should not be empty"
);
assert_eq!(
device.device_type,
DeviceType::Ethernet,
"Device type should be Ethernet"
);
}
}
#[tokio::test]
async fn test_connect_wired() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
require_ethernet!(&nm);
let result = nm.connect_wired().await;
match result {
Ok(_) => {
eprintln!("Wired connection initiated successfully");
}
Err(e) => {
eprintln!("Wired connection failed (may be expected): {}", e);
}
}
}
fn create_test_vpn_creds(name: &str) -> VpnCredentials {
let peer = WireGuardPeer::new(
"HIgo9xNzJMWLKAShlKl6/bUT1VI9Q0SDBXGtLXkPFXc=",
"test.example.com:51820",
vec!["0.0.0.0/0".into(), "::/0".into()],
)
.with_persistent_keepalive(25);
VpnCredentials::new(
VpnType::WireGuard,
name,
"test.example.com:51820",
"YBk6X3pP8KjKz7+HFWzVHNqL3qTZq8hX9VxFQJ4zVmM=",
"10.100.0.2/24",
vec![peer],
)
.with_dns(vec!["1.1.1.1".into(), "8.8.8.8".into()])
.with_mtu(1420)
}
#[tokio::test]
async fn test_list_vpn_connections() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let result = nm.list_vpn_connections().await;
assert!(result.is_ok(), "Should be able to list VPN connections");
let vpns = result.unwrap();
eprintln!("Found {} VPN connection(s)", vpns.len());
for vpn in &vpns {
assert!(!vpn.name.is_empty(), "VPN name should not be empty");
eprintln!("VPN: {} ({:?})", vpn.name, vpn.vpn_type);
}
}
#[tokio::test]
async fn test_vpn_lifecycle_dry_run() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let creds = create_test_vpn_creds("test_vpn_lifecycle");
let result = nm.connect_vpn(creds).await;
match result {
Ok(_) => {
eprintln!("VPN connection succeeded (unexpected in test)");
let _ = nm.disconnect_vpn("test_vpn_lifecycle").await;
let _ = nm.forget_vpn("test_vpn_lifecycle").await;
}
Err(e) => {
eprintln!("VPN connection failed as expected: {}", e);
}
}
}
#[tokio::test]
async fn test_disconnect_nonexistent_vpn() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let result = nm.disconnect_vpn("nonexistent_vpn_connection_12345").await;
assert!(
result.is_ok(),
"Disconnecting non-existent VPN should succeed"
);
}
#[tokio::test]
async fn test_forget_nonexistent_vpn() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let result = nm.forget_vpn("nonexistent_vpn_connection_12345").await;
assert!(
result.is_ok(),
"Forgetting non-existent VPN should return error"
);
match result {
Err(ConnectionError::NoSavedConnection) => {
eprintln!("Correct error: NoSavedConnection");
}
Err(e) => {
panic!("Unexpected error type: {}", e);
}
Ok(_) => {
println!("Correct response: NoSavedConnection");
}
}
}
#[tokio::test]
async fn test_get_nonexistent_vpn_info() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let result = nm.get_vpn_info("nonexistent_vpn_connection_12345").await;
assert!(
result.is_err(),
"Getting info for non-existent VPN should return error"
);
match result {
Err(ConnectionError::NoVpnConnection) => {
eprintln!("Correct error: NoVpnConnection");
}
Err(e) => {
eprintln!("Error (acceptable): {}", e);
}
Ok(_) => {
panic!("Should have failed");
}
}
}
#[tokio::test]
async fn test_vpn_type() {
let wg = VpnType::WireGuard;
assert_eq!(format!("{:?}", wg), "WireGuard");
}
#[tokio::test]
async fn test_wireguard_peer_structure() {
let peer = WireGuardPeer::new(
"test_key",
"test.example.com:51820",
vec!["0.0.0.0/0".into()],
)
.with_preshared_key("psk")
.with_persistent_keepalive(25);
assert_eq!(peer.public_key, "test_key");
assert_eq!(peer.gateway, "test.example.com:51820");
assert_eq!(peer.allowed_ips.len(), 1);
assert_eq!(peer.preshared_key, Some("psk".into()));
assert_eq!(peer.persistent_keepalive, Some(25));
}
#[tokio::test]
async fn test_vpn_credentials_structure() {
let creds = create_test_vpn_creds("test_credentials");
assert_eq!(creds.name, "test_credentials");
assert_eq!(creds.vpn_type, VpnType::WireGuard);
assert_eq!(creds.peers.len(), 1);
assert_eq!(creds.address, "10.100.0.2/24");
assert!(creds.dns.is_some());
assert_eq!(creds.dns.as_ref().unwrap().len(), 2);
assert_eq!(creds.mtu, Some(1420));
}
#[allow(dead_code)]
async fn has_bluetooth_device(nm: &NetworkManager) -> bool {
nm.list_bluetooth_devices()
.await
.map(|d| !d.is_empty())
.unwrap_or(false)
}
#[allow(unused_macros)]
macro_rules! require_bluetooth {
($nm:expr) => {
if !has_bluetooth_device($nm).await {
eprintln!("Skipping test: No Bluetooth device available");
return;
}
};
}
#[tokio::test]
async fn test_list_bluetooth_devices() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm
.list_bluetooth_devices()
.await
.expect("Failed to list Bluetooth devices");
for device in &devices {
assert!(
!device.bdaddr.is_empty(),
"Bluetooth address should not be empty"
);
eprintln!(
"Bluetooth device: {} ({}) - {}",
device.alias.as_deref().unwrap_or("unknown"),
device.bdaddr,
device.bt_caps
);
}
}
#[test]
fn test_bluetooth_network_role() {
use nmrs::models::BluetoothNetworkRole;
let panu = BluetoothNetworkRole::PanU;
assert_eq!(format!("{}", panu), "PANU");
let dun = BluetoothNetworkRole::Dun;
assert_eq!(format!("{}", dun), "DUN");
}
#[test]
fn test_bluetooth_identity_structure() {
use nmrs::models::{BluetoothIdentity, BluetoothNetworkRole};
let identity =
BluetoothIdentity::new("00:1A:7D:DA:71:13".into(), BluetoothNetworkRole::PanU).unwrap();
assert_eq!(identity.bdaddr, "00:1A:7D:DA:71:13");
assert!(matches!(
identity.bt_device_type,
BluetoothNetworkRole::PanU
));
}
#[test]
fn test_bluetooth_device_structure() {
use nmrs::models::{BluetoothDevice, BluetoothNetworkRole};
let role = BluetoothNetworkRole::PanU as u32;
let device = BluetoothDevice::new(
"00:1A:7D:DA:71:13".into(),
Some("MyPhone".into()),
Some("Phone".into()),
role,
DeviceState::Activated,
);
assert_eq!(device.bdaddr, "00:1A:7D:DA:71:13");
assert_eq!(device.name, Some("MyPhone".into()));
assert_eq!(device.alias, Some("Phone".into()));
assert_eq!(device.state, DeviceState::Activated);
}
#[test]
fn test_bluetooth_device_display() {
use nmrs::models::{BluetoothDevice, BluetoothNetworkRole};
let role = BluetoothNetworkRole::PanU as u32;
let device = BluetoothDevice::new(
"00:1A:7D:DA:71:13".into(),
Some("MyPhone".into()),
Some("Phone".into()),
role,
DeviceState::Activated,
);
let display = format!("{}", device);
assert!(display.contains("Phone"));
assert!(display.contains("00:1A:7D:DA:71:13"));
}
#[tokio::test]
async fn test_device_is_bluetooth() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm.list_devices().await.expect("Failed to list devices");
for device in &devices {
if device.is_bluetooth() {
assert_eq!(device.device_type, DeviceType::Bluetooth);
eprintln!("Found Bluetooth device: {}", device.interface);
}
}
}
#[tokio::test]
async fn test_bluetooth_in_device_types() {
require_networkmanager!();
let nm = NetworkManager::new()
.await
.expect("Failed to create NetworkManager");
let devices = nm.list_devices().await.expect("Failed to list devices");
let bluetooth_devices: Vec<_> = devices
.iter()
.filter(|d| matches!(d.device_type, DeviceType::Bluetooth))
.collect();
if !bluetooth_devices.is_empty() {
eprintln!("Found {} Bluetooth device(s)", bluetooth_devices.len());
for device in bluetooth_devices {
eprintln!(" - {}: {}", device.interface, device.state);
}
} else {
eprintln!("No Bluetooth devices found (this is OK)");
}
}
#[test]
fn test_connection_error_no_bluetooth_device() {
let err = ConnectionError::NoBluetoothDevice;
assert_eq!(format!("{}", err), "Bluetooth device not found");
}
#[test]
fn test_bluetooth_network_role_from_u32() {
use nmrs::models::BluetoothNetworkRole;
assert!(matches!(
BluetoothNetworkRole::from(0),
BluetoothNetworkRole::PanU
));
assert!(matches!(
BluetoothNetworkRole::from(1),
BluetoothNetworkRole::Dun
));
assert!(matches!(
BluetoothNetworkRole::from(999),
BluetoothNetworkRole::PanU
));
}