pmat 3.11.0

PMAT - Zero-config AI context generation and code quality toolkit (CLI, MCP, HTTP)
// Tests for the main binary functionality
// We can't directly test the main function, but we can test the logic it uses

#[cfg(test)]
mod binary_main_tests {
    use std::env;
    use std::io::IsTerminal;

    // Test the execution mode detection logic similar to what's in main
    fn detect_execution_mode_test() -> String {
        let is_mcp = !std::io::stdin().is_terminal() && std::env::args().len() == 1
            || std::env::var("MCP_VERSION").is_ok();

        if is_mcp {
            "Mcp".to_string()
        } else {
            "Cli".to_string()
        }
    }

    #[test]
    fn test_execution_mode_detection_with_mcp_version() {
        // Set MCP_VERSION environment variable
        env::set_var("MCP_VERSION", "1.0.0");

        let mode = detect_execution_mode_test();
        assert_eq!(mode, "Mcp");

        // Clean up
        env::remove_var("MCP_VERSION");
    }

    #[test]
    fn test_execution_mode_detection_without_mcp_version() {
        // Ensure MCP_VERSION is not set
        env::remove_var("MCP_VERSION");

        // In test environment, this will typically be CLI mode
        let mode = detect_execution_mode_test();
        // Don't assert specific mode since it depends on terminal state,
        // but ensure the function doesn't panic
        assert!(mode == "Cli" || mode == "Mcp");
    }

    #[test]
    fn test_env_filter_creation() {
        use tracing_subscriber::EnvFilter;

        // Test the environment filter logic from main
        let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));

        // Should not panic and should create a valid filter
        assert!(format!("{filter:?}").contains("info") || !format!("{filter:?}").is_empty());
    }

    #[test]
    fn test_server_creation_logic() {
        use pmat::stateless_server::StatelessTemplateServer;
        use std::sync::Arc;

        // Test the server creation logic from main
        let server_result = StatelessTemplateServer::new();
        assert!(server_result.is_ok());

        let server = Arc::new(server_result.unwrap());
        assert!(Arc::strong_count(&server) > 0);
    }

    #[test]
    #[ignore = "Environment variable manipulation unsafe in parallel tests"]
    fn test_mcp_version_environment_variable() {
        // Test various MCP_VERSION values
        let test_values = vec!["1.0.0", "2.0.0", "latest", ""];

        for value in test_values {
            env::set_var("MCP_VERSION", value);
            assert!(env::var("MCP_VERSION").is_ok());
            env::remove_var("MCP_VERSION");
        }
    }

    #[test]
    fn test_argument_count_behavior() {
        let args: Vec<String> = env::args().collect();

        // Test that we can detect argument count (used in main's mode detection)
        assert!(!args.is_empty()); // At least the program name

        // Simulate the condition from main
        let single_arg = args.len() == 1;
        // Just verify we can check the condition without panic
        let _ = single_arg;
    }

    #[tokio::test]
    async fn test_async_runtime_setup() {
        // Test that we can set up the tokio runtime (main is async)
        let result = tokio::spawn(async {
            // Simulate some async work like in main
            let server_result = pmat::stateless_server::StatelessTemplateServer::new();
            server_result.is_ok()
        })
        .await;

        assert!(result.is_ok());
        assert!(result.unwrap());
    }

    #[test]
    fn test_tracing_initialization() {
        use tracing_subscriber::{fmt, EnvFilter};

        // Test that tracing can be initialized (similar to main)
        let result = std::panic::catch_unwind(|| {
            // Don't actually initialize to avoid conflicts, just test the builder
            let _subscriber = fmt().with_env_filter(
                EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")),
            );
        });

        assert!(result.is_ok());
    }

    #[test]
    fn test_terminal_detection() {
        // Test terminal detection logic used in main
        let is_terminal = std::io::IsTerminal::is_terminal(&std::io::stdin());

        // Should not panic and return a boolean
        // Just verify we can check terminal state without panic
        let _ = is_terminal;
    }

    #[test]
    fn test_error_handling_setup() {
        use anyhow::Result;

        // Test that Result<()> type works (main returns Result<()>)
        let test_result: Result<()> = Ok(());
        assert!(test_result.is_ok());

        let error_result: Result<()> = Err(anyhow::anyhow!("Test error"));
        assert!(error_result.is_err());
    }
}