product-os-server 0.0.55

Product OS : Server provides a full functioning advanced server capable of acting as a web server, command and control distributed network, authentication server, crawling server and more. Fully featured with high level of flexibility.
Documentation
//! Server Lifecycle Tests
//! 
//! Tests for server initialization, configuration, and lifecycle management.

#![cfg(feature = "executor_tokio")]

use product_os_server::ProductOSServer;
use product_os_async_executor::TokioExecutor;
use product_os_server::{ServerConfig, Network};
#[cfg(feature = "security_certificates")]
use product_os_server::Certificate;

/// Test server creation with minimal configuration
#[tokio::test]
async fn test_minimal_server_creation() {
    let config = ServerConfig::new();
    let _server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
}

/// Test server creation with custom network configuration
#[tokio::test]
async fn test_custom_network_config() {
    let mut config = ServerConfig::new();
    config.network = Network {
        protocol: "http".to_string(),
        secure: false,
        host: "test-host".to_string(),
        port: 8080,
        insecure_port: 8080,
        allow_insecure: true,
        insecure_use_different_port: true,
        insecure_force_secure: false,
        listen_all_interfaces: false,
        connect_info: false,
    };
    
    let _server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
}

/// Test server with security disabled
#[tokio::test]
async fn test_server_without_security() {
    let mut config = ServerConfig::new();
    config.security = None;
    
    let _server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
}

/// Test server with compression disabled
#[tokio::test]
async fn test_server_without_compression() {
    let mut config = ServerConfig::new();
    config.compression = None;
    
    let _server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
}

/// Test router can be replaced
#[tokio::test]
async fn test_router_replacement() {
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    server.set_router(product_os_server::ProductOSRouter::new());
}

/// Test multiple handlers can be added
#[tokio::test]
async fn test_multiple_handlers() {
    use product_os_server::{StatusCode, Response, Body};
    
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    async fn handler1() -> Result<Response<Body>, StatusCode> {
        Ok(Response::new(Body::empty()))
    }
    
    async fn handler2() -> Result<Response<Body>, StatusCode> {
        Ok(Response::new(Body::empty()))
    }
    
    async fn handler3() -> Result<Response<Body>, StatusCode> {
        Ok(Response::new(Body::empty()))
    }
    
    server.add_get("/api/v1/test1", handler1);
    server.add_get("/api/v1/test2", handler2);
    server.add_post("/api/v1/test3", handler3);
}

/// Test configuration can be updated after creation
#[tokio::test]
async fn test_config_update() {
    let config1 = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config1);
    
    let mut config2 = ServerConfig::new();
    config2.network.port = 9090;
    
    server.update_config(config2.clone());
    
    let retrieved_config = server.get_config();
    assert_eq!(retrieved_config.network.port, 9090);
}

/// Test logging level can be changed
#[tokio::test]
async fn test_logging_level_changes() {
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    server.set_logging(tracing::Level::DEBUG);
    server.set_logging(tracing::Level::WARN);
    server.set_logging(tracing::Level::ERROR);
}

/// Test base URL matches configuration
#[tokio::test]
#[allow(deprecated)]
async fn test_base_url_correctness() {
    let mut config = ServerConfig::new();
    config.network.protocol = "http".to_string();
    config.network.host = "localhost".to_string();
    config.network.port = 3000;
    
    let server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    let base_url = server.get_base_url();
    
    assert!(base_url.to_string().contains("localhost"));
}

#[cfg(feature = "compression")]
#[tokio::test]
async fn test_compression_configuration() {
    use product_os_server::Compression;
    
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    // Enable all compression types
    let compression = Compression {
        enable: true,
        gzip: true,
        deflate: true,
        brotli: true,
    };
    server.set_compression(Some(compression));
    
    // Enable only gzip
    let compression = Compression {
        enable: true,
        gzip: true,
        deflate: false,
        brotli: false,
    };
    server.set_compression(Some(compression));
    
    // Disable compression
    server.set_compression(None);
}

/// Test server with custom state maintains state
#[tokio::test]
async fn test_stateful_server() {
    use std::sync::Arc;
    use parking_lot::Mutex;
    
    #[derive(Clone)]
    struct AppState {
        counter: Arc<Mutex<i32>>,
    }
    
    let state = AppState {
        counter: Arc::new(Mutex::new(0)),
    };
    
    let config = ServerConfig::new();
    let _server: ProductOSServer<AppState, TokioExecutor, _> = 
        ProductOSServer::new_with_state_with_config(config, state.clone());
    
    // State should remain accessible
    *state.counter.lock() += 1;
    assert_eq!(*state.counter.lock(), 1);
}

/// Test certificate configuration updates
#[cfg(feature = "security_certificates")]
#[tokio::test]
async fn test_certificate_updates() {
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    // Set to None
    server.set_certificate(&None);
    
    // Set to Some configuration
    let cert_config = Certificate {
        file_kind: None,
        files: None,
        entries: None,
        names: Some(vec!["localhost".to_string()]),
        serial: None,
        valid_for: None,
    };
    server.set_certificate(&Some(cert_config));
}

#[cfg(feature = "controller")]
#[tokio::test]
async fn test_controller_lifecycle() {
    let mut config = ServerConfig::new();
    
    // Enable command control
    config.command_control = Some(serde_json::to_value(product_os_command_control::CommandControl {
        enable: false,
        ..Default::default()
    }).unwrap());
    
    let _server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
}

/// Test security headers can be configured
#[tokio::test]
async fn test_security_configuration() {
    use product_os_security::Security;
    
    let config = ServerConfig::new();
    let mut server: ProductOSServer<(), TokioExecutor, _> = ProductOSServer::new_with_config(config);
    
    let security = Security {
        enable: true,
        csrf: false,
        csp: None,
    };
    
    server.set_security(Some(security));
}