rsufw 0.1.0

Linux-only Rust library for managing UFW firewall rules
Documentation
/// Verify that the public API compiles and matches expected signatures.
/// These tests do not run real UFW commands.
use rsufw::{Firewall, IpRule, PortRule, Protocol, RuleStatus, UfwError};

#[test]
fn test_public_types_are_send() {
    fn assert_send<T: Send>() {}
    assert_send::<Firewall>();
    assert_send::<UfwError>();
    assert_send::<Protocol>();
    assert_send::<RuleStatus>();
    assert_send::<PortRule>();
    assert_send::<IpRule>();
}

#[test]
fn test_firewall_methods_signatures() {
    // Use function pointers to verify method signatures without executing
    let _: fn(&Firewall) -> Result<bool, UfwError> = Firewall::is_installed;
    let _: fn(&Firewall) -> Result<bool, UfwError> = Firewall::is_enabled;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::enable;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::disable;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::reload;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::reset;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::default_deny_incoming;
    let _: fn(&Firewall) -> Result<(), UfwError> = Firewall::default_allow_outgoing;
    let _: fn(&Firewall) -> Result<String, UfwError> = Firewall::raw_status;
}

#[test]
fn test_firewall_listing_methods() {
    let _: fn(&Firewall) -> Result<Vec<PortRule>, UfwError> = Firewall::ports;
    let _: fn(&Firewall) -> Result<Vec<IpRule>, UfwError> = Firewall::ips;
}

#[test]
fn test_port_builder_chain_compiles() {
    let fw = Firewall::new();
    // Full builder chains without execution
    let _ = fw.port(22).allow().tcp();
    let _ = fw.port(22).allow().udp();
    let _ = fw.port(22).allow().both();
    let _ = fw.port(22).deny().tcp();
    let _ = fw.port(22).deny().udp();
    let _ = fw.port(22).deny().both();
    let _ = fw.port(22).delete().tcp();
    let _ = fw.port(22).delete().udp();
    let _ = fw.port(22).delete().both();
    // Status builder compiles
    let _ = fw.port(22).status();
    // Function pointer: apply returns Result<(), UfwError>
    let _: fn(&rsufw::builders::port_builder::PortFinalizer) -> Result<(), UfwError> =
        rsufw::builders::port_builder::PortFinalizer::apply;
}

#[test]
fn test_ipv4_builder_chain_compiles() {
    let fw = Firewall::new();
    let _ = fw.ipv4("192.168.1.10").map(|b| b.allow().tcp());
    let _ = fw.ipv4("192.168.1.10").map(|b| b.allow().udp());
    let _ = fw.ipv4("192.168.1.10").map(|b| b.allow().both());
    let _ = fw.ipv4("192.168.1.10").map(|b| b.deny().tcp());
    let _ = fw.ipv4("192.168.1.10").map(|b| b.deny().both());
    let _ = fw.ipv4("192.168.1.10").map(|b| b.delete().both());
    // Status builder compiles
    let _ = fw.ipv4("192.168.1.10").map(|b| b.status());
}

#[test]
fn test_ipv6_builder_chain_compiles() {
    let fw = Firewall::new();
    let _ = fw.ipv6("::1").map(|b| b.allow().tcp());
    let _ = fw.ipv6("::1").map(|b| b.allow().udp());
    let _ = fw.ipv6("::1").map(|b| b.allow().both());
    let _ = fw.ipv6("::1").map(|b| b.deny().tcp());
    let _ = fw.ipv6("::1").map(|b| b.deny().both());
    let _ = fw.ipv6("::1").map(|b| b.delete().both());
    // Status builder compiles
    let _ = fw.ipv6("::1").map(|b| b.status());
}

#[test]
fn test_ipv4_validation() {
    let fw = Firewall::new();
    assert!(fw.ipv4("192.168.1.10").is_ok());
    assert!(fw.ipv4("not-an-ip").is_err());
    assert!(fw.ipv4("::1").is_err());
}

#[test]
fn test_ipv6_validation() {
    let fw = Firewall::new();
    assert!(fw.ipv6("::1").is_ok());
    assert!(fw.ipv6("2001:db8::1").is_ok());
    assert!(fw.ipv6("not-an-ip").is_err());
    assert!(fw.ipv6("192.168.1.10").is_err());
}

#[test]
fn test_protocol_display() {
    assert_eq!(Protocol::Tcp.to_string(), "tcp");
    assert_eq!(Protocol::Udp.to_string(), "udp");
    assert_eq!(Protocol::Both.to_string(), "both");
}