rsufw 0.1.0

Linux-only Rust library for managing UFW firewall rules
Documentation
/// Tests for status-related public API: Protocol, RuleStatus, UfwError Display.
use std::error::Error;
use std::io;

use rsufw::{Protocol, RuleStatus, UfwError};

// ---------------------------------------------------------------------------
// Protocol helpers
// ---------------------------------------------------------------------------

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

#[test]
fn protocol_is_tcp() {
    assert!(Protocol::Tcp.is_tcp());
    assert!(!Protocol::Udp.is_tcp());
    assert!(!Protocol::Both.is_tcp());
}

#[test]
fn protocol_is_udp() {
    assert!(!Protocol::Tcp.is_udp());
    assert!(Protocol::Udp.is_udp());
    assert!(!Protocol::Both.is_udp());
}

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

#[test]
fn protocol_equality() {
    assert_eq!(Protocol::Tcp, Protocol::Tcp);
    assert_ne!(Protocol::Tcp, Protocol::Udp);
}

#[test]
fn protocol_clone() {
    let a = Protocol::Tcp;
    let b = a;
    assert_eq!(a, b);
}

#[test]
fn protocol_debug() {
    let s = format!("{:?}", Protocol::Tcp);
    assert!(!s.is_empty());
}

// ---------------------------------------------------------------------------
// RuleStatus
// ---------------------------------------------------------------------------

#[test]
fn rule_status_equality() {
    assert_eq!(RuleStatus::Allowed, RuleStatus::Allowed);
    assert_ne!(RuleStatus::Allowed, RuleStatus::Denied);
    assert_ne!(RuleStatus::Allowed, RuleStatus::None);
    assert_eq!(RuleStatus::Denied, RuleStatus::Denied);
    assert_eq!(RuleStatus::None, RuleStatus::None);
}

#[test]
fn rule_status_debug() {
    let s = format!("{:?}", RuleStatus::Allowed);
    assert!(!s.is_empty());
}

#[test]
fn rule_status_clone() {
    let a = RuleStatus::Allowed;
    let b = a;
    assert_eq!(a, b);
}

// ---------------------------------------------------------------------------
// UfwError Display — every constructable variant
// ---------------------------------------------------------------------------

#[test]
fn error_empty_output_display() {
    let err = UfwError::EmptyOutput;
    let msg = err.to_string();
    assert!(!msg.is_empty(), "EmptyOutput Display should not be empty");
    assert_eq!(msg, "empty output from ufw");
}

#[test]
fn error_unexpected_status_line_display() {
    let err = UfwError::UnexpectedStatusLine("weird".into());
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("weird"));
}

#[test]
fn error_invalid_ipv4_display() {
    let err = UfwError::InvalidIpv4("bad".into());
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("bad"));
}

#[test]
fn error_invalid_ipv6_display() {
    let err = UfwError::InvalidIpv6("bad".into());
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("bad"));
}

#[test]
fn error_parse_error_display() {
    let err = UfwError::ParseError("something".into());
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("something"));
}

#[test]
fn error_command_failed_display_with_code() {
    let err = UfwError::CommandFailed {
        program: "test".into(),
        args: vec!["arg1".into(), "arg2".into()],
        stderr: "went wrong".into(),
        code: Some(1),
    };
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("test"));
    assert!(msg.contains("arg1"));
    assert!(msg.contains("arg2"));
    assert!(msg.contains("1"));
    assert!(msg.contains("went wrong"));
}

#[test]
fn error_command_failed_display_no_code() {
    let err = UfwError::CommandFailed {
        program: "test".into(),
        args: vec![],
        stderr: "signal".into(),
        code: None,
    };
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("signal"));
}

#[test]
fn error_io_display() {
    let io_err = io::Error::other("disk failure");
    let err = UfwError::Io(io_err);
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("I/O error"));
}

#[test]
fn error_utf8_display() {
    let bytes = vec![0xFF, 0xFE];
    let utf8_err = String::from_utf8(bytes).expect_err("invalid utf-8");
    let err = UfwError::Utf8(utf8_err);
    let msg = err.to_string();
    assert!(!msg.is_empty());
    assert!(msg.contains("UTF-8 error"));
}

// ---------------------------------------------------------------------------
// UfwError source()
// ---------------------------------------------------------------------------

#[test]
fn error_source_for_io() {
    let io_err = io::Error::other("test");
    let err = UfwError::Io(io_err);
    assert!(err.source().is_some());
}

#[test]
fn error_source_for_non_wrapping_variants() {
    let err = UfwError::EmptyOutput;
    assert!(err.source().is_none());

    let err = UfwError::ParseError("x".into());
    assert!(err.source().is_none());
}

// ---------------------------------------------------------------------------
// Firewall construction
// ---------------------------------------------------------------------------

#[test]
fn firewall_new() {
    let _fw = rsufw::Firewall::new();
}

#[test]
fn firewall_default() {
    let _fw: rsufw::Firewall = Default::default();
}