infrarust_server_manager 1.6.3

A Minecraft server manager that handles API monitoring and system commands
Documentation
use infrarust_server_manager::{
    ApiProvider, ApiServerStatus, CrashDetector, MockApiProvider, ServerManager, ServerState,
};

use std::time::Duration;
use tokio::time;

fn create_test_manager() -> (ServerManager<MockApiProvider>, MockApiProvider) {
    let mock_api = MockApiProvider::new().with_server(
        "test-server",
        ApiServerStatus {
            id: "test-server".to_string(),
            name: "Test Server".to_string(),
            status: ServerState::Stopped,
            is_running: false,
            is_crashed: false,
            error: None,
        },
    );

    let server_manager =
        ServerManager::new(mock_api.clone()).with_check_interval(Duration::from_millis(100));

    (server_manager, mock_api)
}

#[tokio::test]
async fn test_start_server() {
    let (server_manager, mock_api) = create_test_manager();

    let initial_status = mock_api.get_server_status("test-server").await.unwrap();
    assert!(!initial_status.is_running);
    assert!(initial_status.error.is_none());

    server_manager.start_server("test-server").await.unwrap();

    let status = mock_api.get_server_status("test-server").await.unwrap();
    assert!(status.is_running);
    assert!(status.error.is_none());
    assert_eq!(status.status, ServerState::Running);
    assert!(!status.is_crashed);
}

#[tokio::test]
async fn test_stop_server() {
    let (server_manager, mock_api) = create_test_manager();

    mock_api.set_server_running("test-server");
    let initial_status = mock_api.get_server_status("test-server").await.unwrap();
    assert!(initial_status.is_running);

    server_manager.stop_server("test-server").await.unwrap();

    let status = mock_api.get_server_status("test-server").await.unwrap();
    assert!(!status.is_running);
    assert!(status.error.is_none());
    assert_eq!(status.status, ServerState::Stopped);
    assert!(!status.is_crashed);
}

#[tokio::test]
async fn test_restart_server() {
    let (server_manager, mock_api) = create_test_manager();

    mock_api.set_server_running("test-server");

    server_manager.restart_server("test-server").await.unwrap();

    let status = mock_api.get_server_status("test-server").await.unwrap();
    assert!(status.is_running);
    assert!(status.error.is_none());
    assert_eq!(status.status, ServerState::Running);
    assert!(!status.is_crashed);
}

#[tokio::test]
async fn test_crash_detection() {
    let detector = CrashDetector::new(2, Duration::from_millis(500));

    let mock_api = MockApiProvider::new().with_server(
        "crash-server",
        ApiServerStatus {
            id: "crash-server".to_string(),
            name: "Crash Test Server".to_string(),
            status: ServerState::Running,
            is_running: true,
            is_crashed: false,
            error: None,
        },
    );

    let server_manager = ServerManager::new(mock_api.clone()).with_crash_detector(detector);

    mock_api.set_server_crashed("crash-server");

    time::sleep(Duration::from_millis(100)).await;

    tokio::spawn(async move {
        let _ = server_manager.monitor_server("crash-server").await;
    });

    time::sleep(Duration::from_millis(200)).await;

    let api_status = mock_api.get_server_status("crash-server").await.unwrap();
    assert!(!api_status.is_running);
    assert!(api_status.is_crashed);
    assert_eq!(api_status.status, ServerState::Crashed);
    assert!(api_status.error.is_some());
    let error = api_status.error.unwrap();
    assert!(error.contains("crash"), "Expected crash message in error");
}

#[tokio::test]
async fn test_execute_system_command() {
    let (server_manager, _) = create_test_manager();

    #[cfg(target_os = "windows")]
    let command = "echo Hello, World!";
    #[cfg(target_os = "linux")]
    let command = "echo 'Hello, World!'";

    let result = server_manager.execute_system_command(command);
    assert!(
        result.is_ok(),
        "Command execution failed: {:?}",
        result.err()
    );

    let output = result.unwrap();
    assert!(
        output.contains("Hello, World!"),
        "Command output doesn't contain expected text"
    );
}