sal-net 0.1.0

SAL Network - Network connectivity utilities for TCP, HTTP, and SSH
Documentation
use reqwest::StatusCode;
use sal_net::HttpConnector;
use std::time::Duration;

#[tokio::test]
async fn test_http_connector_new() {
    let result = HttpConnector::new();
    assert!(result.is_ok());
}

#[tokio::test]
async fn test_http_connector_with_timeout() {
    let timeout = Duration::from_secs(10);
    let result = HttpConnector::with_timeout(timeout);
    assert!(result.is_ok());
}

#[tokio::test]
async fn test_http_connector_default() {
    let connector = HttpConnector::default();

    // Test that default connector actually works
    let result = connector.check_url("https://httpbin.org/status/200").await;

    // Should either work or fail gracefully (network dependent)
    match result {
        Ok(_) => {}  // Network request succeeded
        Err(_) => {} // Network might not be available, that's ok
    }
}

#[tokio::test]
async fn test_check_url_valid() {
    let connector = HttpConnector::new().unwrap();

    // Use a reliable public URL
    let result = connector.check_url("https://httpbin.org/status/200").await;

    // Note: This test depends on external network, might fail in isolated environments
    match result {
        Ok(is_reachable) => {
            // If we can reach the internet, it should be true
            // If not, we just verify the function doesn't panic
            println!("URL reachable: {}", is_reachable);
        }
        Err(e) => {
            // Network might not be available, that's okay for testing
            println!("Network error (expected in some environments): {}", e);
        }
    }
}

#[tokio::test]
async fn test_check_url_invalid() {
    let connector = HttpConnector::new().unwrap();

    // Use an invalid URL format
    let result = connector.check_url("not-a-valid-url").await;

    assert!(result.is_err()); // Should fail due to invalid URL format
}

#[tokio::test]
async fn test_check_url_unreachable() {
    let connector = HttpConnector::new().unwrap();

    // Use a URL that should not exist
    let result = connector
        .check_url("https://this-domain-definitely-does-not-exist-12345.com")
        .await;

    assert!(result.is_ok());
    assert!(!result.unwrap()); // Should be unreachable
}

#[tokio::test]
async fn test_check_status_valid() {
    let connector = HttpConnector::new().unwrap();

    // Use httpbin for reliable testing
    let result = connector
        .check_status("https://httpbin.org/status/200")
        .await;

    match result {
        Ok(Some(status)) => {
            assert_eq!(status, StatusCode::OK);
        }
        Ok(None) => {
            // Network might not be available
            println!("No status returned (network might not be available)");
        }
        Err(e) => {
            // Network error, acceptable in test environments
            println!("Network error: {}", e);
        }
    }
}

#[tokio::test]
async fn test_check_status_404() {
    let connector = HttpConnector::new().unwrap();

    let result = connector
        .check_status("https://httpbin.org/status/404")
        .await;

    match result {
        Ok(Some(status)) => {
            assert_eq!(status, StatusCode::NOT_FOUND);
        }
        Ok(None) => {
            println!("No status returned (network might not be available)");
        }
        Err(e) => {
            println!("Network error: {}", e);
        }
    }
}

#[tokio::test]
async fn test_check_status_invalid_url() {
    let connector = HttpConnector::new().unwrap();

    let result = connector.check_status("not-a-valid-url").await;

    assert!(result.is_err()); // Should fail due to invalid URL
}

#[tokio::test]
async fn test_get_content_valid() {
    let connector = HttpConnector::new().unwrap();

    let result = connector.get_content("https://httpbin.org/json").await;

    match result {
        Ok(content) => {
            assert!(!content.is_empty());
            // httpbin.org/json returns JSON, so it should contain braces
            assert!(content.contains("{") && content.contains("}"));
        }
        Err(e) => {
            // Network might not be available
            println!("Network error: {}", e);
        }
    }
}

#[tokio::test]
async fn test_get_content_404() {
    let connector = HttpConnector::new().unwrap();

    let result = connector
        .get_content("https://httpbin.org/status/404")
        .await;

    // Should fail because 404 is not a success status
    assert!(result.is_err());
}

#[tokio::test]
async fn test_get_content_invalid_url() {
    let connector = HttpConnector::new().unwrap();

    let result = connector.get_content("not-a-valid-url").await;

    assert!(result.is_err()); // Should fail due to invalid URL
}

#[tokio::test]
async fn test_verify_status_success() {
    let connector = HttpConnector::new().unwrap();

    let result = connector
        .verify_status("https://httpbin.org/status/200", StatusCode::OK)
        .await;

    match result {
        Ok(matches) => {
            assert!(matches); // Should match 200 OK
        }
        Err(e) => {
            println!("Network error: {}", e);
        }
    }
}

#[tokio::test]
async fn test_verify_status_mismatch() {
    let connector = HttpConnector::new().unwrap();

    let result = connector
        .verify_status("https://httpbin.org/status/200", StatusCode::NOT_FOUND)
        .await;

    match result {
        Ok(matches) => {
            assert!(!matches); // Should not match (200 != 404)
        }
        Err(e) => {
            println!("Network error: {}", e);
        }
    }
}

#[tokio::test]
async fn test_verify_status_unreachable() {
    let connector = HttpConnector::new().unwrap();

    let result = connector
        .verify_status(
            "https://this-domain-definitely-does-not-exist-12345.com",
            StatusCode::OK,
        )
        .await;

    assert!(result.is_ok());
    assert!(!result.unwrap()); // Should not match because URL is unreachable
}