Skip to main content

rust_serv/server/
server.rs

1use crate::config::Config;
2use crate::error::Result;
3use crate::handler::Handler;
4use crate::server::tls::{load_tls_config, validate_tls_config};
5use hyper::server::conn::http1;
6use hyper::Response;
7use hyper::body::Bytes;
8use http_body_util::Full;
9use hyper_util::rt::TokioIo;
10use std::net::SocketAddr;
11use std::sync::Arc;
12use std::time::Duration;
13use tokio::net::TcpListener;
14
15/// Health check response
16#[allow(dead_code)]
17fn health_check_response() -> Response<Full<Bytes>> {
18    Response::builder()
19        .status(200)
20        .header("Content-Type", "application/json")
21        .body(Full::new(Bytes::from(r#"{"status":"ok","service":"rust-serv"}"#)))
22        .unwrap()
23}
24
25/// HTTP Server
26pub struct Server {
27    config: Arc<Config>,
28    shutdown_signal: Arc<tokio::sync::Notify>,
29}
30
31impl Server {
32    /// Create a new server with given configuration
33    pub fn new(config: Config) -> Self {
34        Self {
35            config: Arc::new(config),
36            shutdown_signal: Arc::new(tokio::sync::Notify::new()),
37        }
38    }
39
40    /// Start server
41    pub async fn run(&self) -> Result<()> {
42        let scheme = if self.config.enable_tls { "https" } else { "http" };
43        let addr: SocketAddr = format!("0.0.0.0:{}", self.config.port).parse()?;
44        let listener = TcpListener::bind(addr).await?;
45
46        println!("Server listening on {}://{}", scheme, addr);
47
48        let handler = Handler::new(self.config.clone());
49
50        // Setup signal handling for graceful shutdown
51        #[cfg(unix)]
52        use tokio::signal::unix::{signal, SignalKind};
53        let mut sigterm = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM handler");
54        let mut sigint = signal(SignalKind::interrupt()).expect("Failed to setup SIGINT handler");
55
56        // Create connection semaphore for max connections
57        let max_connections = Arc::new(tokio::sync::Semaphore::new(self.config.max_connections));
58
59        // Setup TLS if enabled
60        let tls_config = if self.config.enable_tls {
61            let cert_path = self.config.tls_cert.as_ref().ok_or_else(|| {
62                crate::error::Error::Internal("tls_cert must be specified when enable_tls is true".to_string())
63            })?;
64            let key_path = self.config.tls_key.as_ref().ok_or_else(|| {
65                crate::error::Error::Internal("tls_key must be specified when enable_tls is true".to_string())
66            })?;
67
68            // Validate TLS configuration
69            validate_tls_config(Some(cert_path), Some(key_path))?;
70
71            let cert_path = std::path::Path::new(cert_path);
72            let key_path = std::path::Path::new(key_path);
73
74            // Load TLS configuration
75            Some(load_tls_config(&cert_path, &key_path)?.clone())
76        } else {
77            None
78        };
79
80        loop {
81            tokio::select! {
82                // Accept new connection
83                accept_result = listener.accept() => {
84                    let (stream, _) = accept_result?;
85                    let max_conn = max_connections.clone();
86
87                    // Check connection limit
88                    let _permit = match max_conn.try_acquire() {
89                        Ok(p) => p,
90                        Err(_) => {
91                            // Too many connections, close immediately
92                            drop(stream);
93                            continue;
94                        }
95                    };
96
97                    let handler = Arc::new(handler.clone());
98                    let config = self.config.clone();
99                    let tls_config_clone = tls_config.clone();
100
101                    tokio::task::spawn(async move {
102                        // Set connection timeout
103                        let timeout = Duration::from_secs(config.connection_timeout_secs);
104
105                        let result = tokio::time::timeout(timeout, async {
106                            // Handle TLS or plain connection
107                            if let Some(tls_config) = tls_config_clone {
108                                // TLS connection
109                                let tls_acceptor = tokio_rustls::TlsAcceptor::from(tls_config);
110                                let tls_stream = match tls_acceptor.accept(stream).await {
111                                    Ok(stream) => stream,
112                                    Err(e) => {
113                                        eprintln!("TLS handshake failed: {}", e);
114                                        return;
115                                    }
116                                };
117
118                                let io = TokioIo::new(tls_stream);
119                                Self::serve_connection(io, handler).await;
120                            } else {
121                                // Plain HTTP connection
122                                let io = TokioIo::new(stream);
123                                Self::serve_connection(io, handler).await;
124                            }
125                        }).await;
126
127                        match result {
128                            Ok(_) => {}
129                            Err(_) => {
130                                // Connection timeout, close gracefully
131                            }
132                        }
133
134                        // Permit is automatically dropped here
135                    });
136                }
137
138                // Handle shutdown signal
139                _ = sigterm.recv() => {
140                    println!("Received SIGTERM, shutting down gracefully...");
141                    break;
142                }
143
144                _ = sigint.recv() => {
145                    println!("Received SIGINT, shutting down gracefully...");
146                    break;
147                }
148            }
149        }
150
151        println!("Server shutdown complete");
152        Ok(())
153    }
154
155    /// Serve a single HTTP connection
156    async fn serve_connection<Io: hyper::rt::Read + hyper::rt::Write + Unpin>(
157        io: Io,
158        handler: Arc<Handler>,
159    ) {
160        let handler = handler.clone();
161
162        http1::Builder::new()
163            .serve_connection(io, hyper::service::service_fn(move |req| {
164                let handler = handler.clone();
165                async move {
166                    handler.handle_request(req).await
167                }
168            }))
169            .await
170            .ok(); // Ignore connection errors
171    }
172
173    /// Shutdown the server
174    pub fn shutdown(&self) {
175        self.shutdown_signal.notify_one();
176    }
177}
178
179#[cfg(test)]
180mod tests {
181    use super::*;
182
183    #[test]
184    fn test_server_creation() {
185        let config = Config::default();
186        let server = Server::new(config);
187        assert_eq!(server.config.port, 8080);
188    }
189
190    #[test]
191    fn test_server_with_custom_config() {
192        let config = Config {
193            port: 3000,
194            root: "/tmp".into(),
195            enable_indexing: false,
196            enable_compression: false,
197            log_level: "warn".into(),
198            enable_tls: false,
199            tls_cert: None,
200            tls_key: None,
201            connection_timeout_secs: 30,
202            max_connections: 1000,
203            enable_health_check: true,
204            enable_cors: true,
205            cors_allowed_origins: vec!["*".to_string()],
206            cors_allowed_methods: vec!["GET".to_string()],
207            cors_allowed_headers: vec![],
208            cors_allow_credentials: false,
209            cors_exposed_headers: vec![],
210            cors_max_age: Some(86400),
211            enable_security: true,
212            rate_limit_max_requests: 100,
213            rate_limit_window_secs: 60,
214            ip_allowlist: vec![],
215            ip_blocklist: vec![],
216            max_body_size: 10 * 1024 * 1024,
217            max_headers: 100,
218            management: None,
219            auto_tls: None,
220        };
221        let server = Server::new(config);
222        assert_eq!(server.config.port, 3000);
223        assert_eq!(server.config.root, std::path::PathBuf::from("/tmp"));
224    }
225
226    #[test]
227    fn test_server_clone_config() {
228        let config = Config::default();
229        let server = Server::new(config);
230        // Config should be Arc wrapped
231        let _ = server.config.clone();
232    }
233
234    #[test]
235    fn test_server_address_parsing() {
236        // Test that address format is correct
237        let addr_str = format!("0.0.0.0:{}", 8080);
238        let addr: std::net::SocketAddr = addr_str.parse().unwrap();
239        assert_eq!(addr.port(), 8080);
240        assert_eq!(addr.ip(), std::net::Ipv4Addr::new(0, 0, 0, 0));
241    }
242
243    #[test]
244    fn test_server_ipv6_address_parsing() {
245        // Test IPv6 address parsing
246        let addr_str = "[::1]:8080";
247        let addr: std::net::SocketAddr = addr_str.parse().unwrap();
248        assert_eq!(addr.port(), 8080);
249        assert!(addr.is_ipv6());
250    }
251
252    #[test]
253    fn test_health_check_response() {
254        let response = health_check_response();
255        assert_eq!(response.status(), 200);
256        // Check Content-Type header
257        assert_eq!(response.headers().get("Content-Type").unwrap(), "application/json");
258    }
259
260    #[test]
261    fn test_shutdown_signal() {
262        let config = Config::default();
263        let server = Server::new(config);
264        // Should not panic
265        server.shutdown();
266    }
267
268    #[test]
269    fn test_server_with_tls_config() {
270        let config = Config {
271            port: 443,
272            root: "/var/www".into(),
273            enable_indexing: true,
274            enable_compression: true,
275            log_level: "info".into(),
276            enable_tls: true,
277            tls_cert: Some("/path/to/cert.pem".to_string()),
278            tls_key: Some("/path/to/key.pem".to_string()),
279            connection_timeout_secs: 30,
280            max_connections: 1000,
281            enable_health_check: true,
282            enable_cors: true,
283            cors_allowed_origins: vec!["*".to_string()],
284            cors_allowed_methods: vec!["GET".to_string()],
285            cors_allowed_headers: vec![],
286            cors_allow_credentials: false,
287            cors_exposed_headers: vec![],
288            cors_max_age: Some(86400),
289            enable_security: true,
290            rate_limit_max_requests: 100,
291            rate_limit_window_secs: 60,
292            ip_allowlist: vec![],
293            ip_blocklist: vec![],
294            max_body_size: 10 * 1024 * 1024,
295            max_headers: 100,
296            management: None,
297            auto_tls: None,
298        };
299        let server = Server::new(config);
300        assert_eq!(server.config.port, 443);
301        assert!(server.config.enable_tls);
302        assert_eq!(server.config.tls_cert, Some("/path/to/cert.pem".to_string()));
303        assert_eq!(server.config.tls_key, Some("/path/to/key.pem".to_string()));
304    }
305
306    #[test]
307    fn test_tls_config_missing_cert() {
308        let config = Config {
309            port: 443,
310            root: "/var/www".into(),
311            enable_indexing: true,
312            enable_compression: true,
313            log_level: "info".into(),
314            enable_tls: true,
315            tls_cert: None, // Missing cert
316            tls_key: Some("/path/to/key.pem".to_string()),
317            connection_timeout_secs: 30,
318            max_connections: 1000,
319            enable_health_check: true,
320            enable_cors: true,
321            cors_allowed_origins: vec!["*".to_string()],
322            cors_allowed_methods: vec!["GET".to_string()],
323            cors_allowed_headers: vec![],
324            cors_allow_credentials: false,
325            cors_exposed_headers: vec![],
326            cors_max_age: Some(86400),
327            enable_security: true,
328            rate_limit_max_requests: 100,
329            rate_limit_window_secs: 60,
330            ip_allowlist: vec![],
331            ip_blocklist: vec![],
332            max_body_size: 10 * 1024 * 1024,
333            max_headers: 100,
334            management: None,
335            auto_tls: None,
336        };
337        let server = Server::new(config);
338        assert_eq!(server.config.port, 443);
339        assert!(server.config.enable_tls);
340        assert!(server.config.tls_cert.is_none());
341    }
342
343    #[test]
344    fn test_tls_config_missing_key() {
345        let config = Config {
346            port: 443,
347            root: "/var/www".into(),
348            enable_indexing: true,
349            enable_compression: true,
350            log_level: "info".into(),
351            enable_tls: true,
352            tls_cert: Some("/path/to/cert.pem".to_string()),
353            tls_key: None, // Missing key
354            connection_timeout_secs: 30,
355            max_connections: 1000,
356            enable_health_check: true,
357            enable_cors: true,
358            cors_allowed_origins: vec!["*".to_string()],
359            cors_allowed_methods: vec!["GET".to_string()],
360            cors_allowed_headers: vec![],
361            cors_allow_credentials: false,
362            cors_exposed_headers: vec![],
363            cors_max_age: Some(86400),
364            enable_security: true,
365            rate_limit_max_requests: 100,
366            rate_limit_window_secs: 60,
367            ip_allowlist: vec![],
368            ip_blocklist: vec![],
369            max_body_size: 10 * 1024 * 1024,
370            max_headers: 100,
371            management: None,
372            auto_tls: None,
373        };
374        let server = Server::new(config);
375        assert_eq!(server.config.port, 443);
376        assert!(server.config.tls_key.is_none());
377    }
378
379    #[test]
380    fn test_max_connections_default() {
381        let config = Config::default();
382        assert_eq!(config.max_connections, 1000);
383    }
384
385    #[test]
386    fn test_connection_timeout_default() {
387        let config = Config::default();
388        assert_eq!(config.connection_timeout_secs, 30);
389    }
390
391    #[tokio::test]
392    async fn test_scheme_selection() {
393        // Test HTTP scheme when TLS is disabled
394        let config = Config {
395            enable_tls: false,
396            ..Config::default()
397        };
398        let server = Server::new(config);
399        assert!(!server.config.enable_tls);
400
401    }
402
403    #[tokio::test]
404    async fn test_scheme_selection_https() {
405        // Test HTTPS scheme when TLS is enabled
406        let config = Config {
407            enable_tls: true,
408            tls_cert: Some("/path/cert.pem".to_string()),
409            tls_key: Some("/path/key.pem".to_string()),
410            ..Config::default()
411        };
412        let server = Server::new(config);
413        assert!(server.config.enable_tls);
414    }
415
416    #[tokio::test]
417    async fn test_bind_address() {
418        // Test that address parsing works correctly
419        let port = 9090;
420        let addr_str = format!("0.0.0.0:{}", port);
421        let addr: SocketAddr = addr_str.parse().unwrap();
422        assert_eq!(addr.port(), port);
423    }
424
425    #[tokio::test]
426    async fn test_shutdown_notify() {
427        let config = Config::default();
428        let server = Server::new(config);
429
430        // Clone the signal before shutdown
431        let _signal = server.shutdown_signal.clone();
432
433        // Shutdown should notify
434        server.shutdown();
435
436        // The notify should have been triggered
437        // (we can't easily test the without async, but the call shouldn't panic)
438    }
439
440    #[tokio::test]
441    async fn test_connection_limit_enforcement() {
442        // Note: AsyncReadExt and AsyncWriteExt imported but not used in this test
443
444        // Create a config with max_connections = 2
445        let config = Config {
446            port: 0, // Use random port
447            max_connections: 2,
448            ..Config::default()
449        };
450
451        // Start server in background
452        let _server = Server::new(config.clone());
453        let _addr = format!("0.0.0.0:{}", config.port);
454
455        // Create a listener to get actual port
456        let listener = TcpListener::bind("0.0.0.0:0").await.unwrap();
457        let actual_addr = listener.local_addr().unwrap();
458        drop(listener);
459
460        // Create config with actual port
461        let config = Config {
462            port: actual_addr.port(),
463            max_connections: 2,
464            ..Config::default()
465        };
466
467        let server = Server::new(config);
468
469        // Run server in background
470        let server_handle = tokio::spawn(async move {
471            // Run for a short time
472            let _ = tokio::time::timeout(
473                tokio::time::Duration::from_millis(100),
474                server.run()
475            ).await;
476        });
477
478        // Give server time to start
479        tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
480
481        // Verify semaphore was created correctly
482        let max_connections = Arc::new(tokio::sync::Semaphore::new(2));
483        assert_eq!(max_connections.available_permits(), 2);
484
485        // Test acquiring permits
486        let p1 = max_connections.try_acquire().unwrap();
487        let p2 = max_connections.try_acquire().unwrap();
488
489        // Third should fail
490        assert!(max_connections.try_acquire().is_err());
491
492        drop(p1);
493        drop(p2);
494        drop(server_handle);
495    }
496
497    #[tokio::test]
498    async fn test_connection_timeout() {
499        // Test that timeout duration is set correctly
500        let config = Config {
501            connection_timeout_secs: 5,
502            ..Config::default()
503        };
504
505        let timeout = Duration::from_secs(config.connection_timeout_secs);
506        assert_eq!(timeout, Duration::from_secs(5));
507
508        // Test that a very short timeout would work
509        let short_config = Config {
510            connection_timeout_secs: 1,
511            ..Config::default()
512        };
513        let short_timeout = Duration::from_secs(short_config.connection_timeout_secs);
514        assert_eq!(short_timeout, Duration::from_secs(1));
515    }
516
517    #[tokio::test]
518    async fn test_tls_handshake_failure_handling() {
519        // Test that TLS config validation works
520        let config = Config {
521            enable_tls: true,
522            tls_cert: Some("/nonexistent/cert.pem".to_string()),
523            tls_key: Some("/nonexistent/key.pem".to_string()),
524            ..Config::default()
525        };
526
527        // Validation should fail for nonexistent files
528        let result = validate_tls_config(
529            config.tls_cert.as_deref(),
530            config.tls_key.as_deref()
531        );
532        assert!(result.is_err());
533    }
534
535    #[tokio::test]
536    async fn test_concurrent_connections() {
537        use std::sync::atomic::{AtomicUsize, Ordering};
538
539        // Test concurrent connection counting
540        let counter = Arc::new(AtomicUsize::new(0));
541        let max_connections = 10;
542
543        let counter_clone = counter.clone();
544        let handles: Vec<_> = (0..5).map(|_| {
545            let counter = counter_clone.clone();
546            tokio::spawn(async move {
547                // Simulate connection
548                let prev = counter.fetch_add(1, Ordering::SeqCst);
549                assert!(prev < max_connections);
550                tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
551                counter.fetch_sub(1, Ordering::SeqCst);
552            })
553        }).collect();
554
555        for handle in handles {
556            handle.await.unwrap();
557        }
558
559        assert_eq!(counter.load(Ordering::SeqCst), 0);
560    }
561
562    #[test]
563    fn test_graceful_shutdown_signal() {
564        let config = Config::default();
565        let server = Server::new(config);
566
567        // Verify shutdown signal exists
568        let _signal = server.shutdown_signal.clone();
569
570        // Call shutdown multiple times (should not panic)
571        server.shutdown();
572        server.shutdown();
573        server.shutdown();
574    }
575
576    #[test]
577    fn test_server_config_variations() {
578        // Test with different config combinations
579        let configs = vec![
580            Config {
581                port: 80,
582                max_connections: 100,
583                connection_timeout_secs: 10,
584                enable_tls: false,
585                ..Config::default()
586            },
587            Config {
588                port: 443,
589                max_connections: 500,
590                connection_timeout_secs: 60,
591                enable_tls: true,
592                tls_cert: Some("/cert.pem".to_string()),
593                tls_key: Some("/key.pem".to_string()),
594                ..Config::default()
595            },
596            Config {
597                port: 8080,
598                max_connections: 1000,
599                connection_timeout_secs: 30,
600                enable_tls: false,
601                ..Config::default()
602            },
603        ];
604
605        for config in configs {
606            let server = Server::new(config.clone());
607            assert_eq!(server.config.port, config.port);
608            assert_eq!(server.config.max_connections, config.max_connections);
609        }
610    }
611
612    #[test]
613    fn test_connection_semaphore_creation() {
614        // Test that semaphore is created with correct capacity
615        let permits = 100;
616        let semaphore = Arc::new(tokio::sync::Semaphore::new(permits));
617        assert_eq!(semaphore.available_permits(), permits);
618
619        // Test try_acquire
620        let p1 = semaphore.try_acquire().unwrap();
621        assert_eq!(semaphore.available_permits(), permits - 1);
622
623        let p2 = semaphore.try_acquire().unwrap();
624        assert_eq!(semaphore.available_permits(), permits - 2);
625
626        drop(p1);
627        assert_eq!(semaphore.available_permits(), permits - 1);
628
629        drop(p2);
630        assert_eq!(semaphore.available_permits(), permits);
631    }
632
633    #[test]
634    fn test_tls_config_validation_both_paths() {
635        // Both paths provided but not existing
636        let result = validate_tls_config(
637            Some("/nonexistent/cert.pem"),
638            Some("/nonexistent/key.pem")
639        );
640        assert!(result.is_err());
641
642        // Missing cert
643        let result = validate_tls_config(None, Some("/nonexistent/key.pem"));
644        assert!(result.is_err());
645
646        // Missing key
647        let result = validate_tls_config(Some("/nonexistent/cert.pem"), None);
648        assert!(result.is_err());
649
650        // Both missing
651        let result = validate_tls_config(None, None);
652        assert!(result.is_ok()); // No TLS, valid
653    }
654
655    // NEW TESTS ADDED FOR COVERAGE IMPROVEMENT
656
657    #[test]
658    fn test_health_check_response_body() {
659        let response = health_check_response();
660        assert_eq!(response.status(), 200);
661        
662        // Verify the body type is correct
663        // health_check_response returns Full<Bytes>
664        let _body_ref = response.body();
665        
666        // Verify Content-Type header is set correctly
667        assert!(response.headers().contains_key("Content-Type"));
668        assert_eq!(
669            response.headers().get("Content-Type").unwrap(),
670            "application/json"
671        );
672    }
673
674    #[test]
675    fn test_server_with_zero_connections() {
676        // Edge case: max_connections = 0
677        let config = Config {
678            max_connections: 0,
679            ..Config::default()
680        };
681        let server = Server::new(config);
682        assert_eq!(server.config.max_connections, 0);
683    }
684
685    #[test]
686    fn test_server_with_zero_timeout() {
687        // Edge case: connection_timeout_secs = 0
688        let config = Config {
689            connection_timeout_secs: 0,
690            ..Config::default()
691        };
692        let server = Server::new(config);
693        assert_eq!(server.config.connection_timeout_secs, 0);
694    }
695
696    #[test]
697    fn test_server_config_clone() {
698        let config = Config {
699            port: 9999,
700            root: "/custom".into(),
701            enable_tls: true,
702            tls_cert: Some("/cert.pem".to_string()),
703            tls_key: Some("/key.pem".to_string()),
704            ..Config::default()
705        };
706        let server = Server::new(config.clone());
707        
708        // Verify Arc works correctly
709        let config_ref = server.config.clone();
710        assert_eq!(config_ref.port, 9999);
711        assert_eq!(config_ref.root, std::path::PathBuf::from("/custom"));
712    }
713
714    #[test]
715    fn test_address_format_variations() {
716        // Test different valid address formats
717        let test_cases = vec![
718            ("0.0.0.0:8080", 8080u16, false),
719            ("127.0.0.1:3000", 3000u16, false),
720            ("192.168.1.1:443", 443u16, false),
721            ("[::1]:8080", 8080u16, true),
722            ("[::]:9000", 9000u16, true),
723        ];
724
725        for (addr_str, expected_port, is_ipv6) in test_cases {
726            let addr: SocketAddr = addr_str.parse().unwrap();
727            assert_eq!(addr.port(), expected_port, "Port mismatch for {}", addr_str);
728            assert_eq!(addr.is_ipv6(), is_ipv6, "IPv6 mismatch for {}", addr_str);
729        }
730    }
731
732    #[test]
733    fn test_address_parsing_error() {
734        // Test invalid address formats
735        let invalid_addrs = vec![
736            "not_an_address",
737            "999.999.999.999:8080",
738            "",
739            ":8080",
740            "localhost",
741        ];
742
743        for addr in invalid_addrs {
744            let result: std::result::Result<SocketAddr, _> = addr.parse();
745            assert!(result.is_err(), "Should fail for: {}", addr);
746        }
747    }
748
749    #[tokio::test]
750    async fn test_semaphore_try_acquire_behavior() {
751        let max_conn = Arc::new(tokio::sync::Semaphore::new(1));
752        
753        // First acquire should succeed
754        let permit = max_conn.try_acquire();
755        assert!(permit.is_ok());
756        
757        // Second acquire should fail (no permits available)
758        let permit2 = max_conn.try_acquire();
759        assert!(permit2.is_err());
760        
761        // After dropping, should be able to acquire again
762        drop(permit);
763        let permit3 = max_conn.try_acquire();
764        assert!(permit3.is_ok());
765    }
766
767    #[tokio::test]
768    async fn test_duration_conversions() {
769        // Test various timeout durations
770        let test_cases = vec![
771            (1u64, Duration::from_secs(1)),
772            (30u64, Duration::from_secs(30)),
773            (60u64, Duration::from_secs(60)),
774            (3600u64, Duration::from_secs(3600)),
775        ];
776
777        for (secs, expected) in test_cases {
778            let duration = Duration::from_secs(secs);
779            assert_eq!(duration, expected);
780        }
781    }
782
783    #[test]
784    fn test_handler_clone_in_server() {
785        let config = Config::default();
786        let handler = Handler::new(Arc::new(config));
787        
788        // Handler should be cloneable
789        let _handler_clone = handler.clone();
790    }
791
792    #[tokio::test]
793    async fn test_serve_connection_basic() {
794        // Test that serve_connection function exists and has correct signature
795        // We can't easily test the actual HTTP serving without a full integration test,
796        // but we can verify the method structure
797        let config = Config::default();
798        let handler = Arc::new(Handler::new(Arc::new(config)));
799        
800        // Just verify handler is cloneable for use in serve_connection
801        let _handler_for_connection = handler.clone();
802    }
803
804    #[test]
805    fn test_tls_config_error_messages() {
806        // Test that proper error messages are generated
807        let result = validate_tls_config(
808            Some("/nonexistent/cert.pem"),
809            Some("/nonexistent/key.pem")
810        );
811        
812        if let Err(e) = result {
813            let msg = e.to_string();
814            assert!(msg.contains("not found") || msg.contains("No such file"));
815        }
816    }
817
818    #[test]
819    fn test_run_method_error_paths() {
820        // Test that run method handles various error conditions
821        // This tests the error paths in run() without actually running the server
822        
823        // TLS config with missing cert
824        let config_with_missing_cert = Config {
825            enable_tls: true,
826            tls_cert: None,
827            tls_key: Some("/key.pem".to_string()),
828            ..Config::default()
829        };
830        let server = Server::new(config_with_missing_cert);
831        assert!(server.config.enable_tls);
832        assert!(server.config.tls_cert.is_none());
833
834        // TLS config with missing key
835        let config_with_missing_key = Config {
836            enable_tls: true,
837            tls_cert: Some("/cert.pem".to_string()),
838            tls_key: None,
839            ..Config::default()
840        };
841        let server = Server::new(config_with_missing_key);
842        assert!(server.config.tls_key.is_none());
843    }
844
845    #[tokio::test]
846    async fn test_connection_timeout_zero() {
847        let config = Config {
848            connection_timeout_secs: 0,
849            ..Config::default()
850        };
851        
852        let timeout = Duration::from_secs(config.connection_timeout_secs);
853        assert_eq!(timeout, Duration::from_secs(0));
854        
855        // Zero timeout should be valid (immediate timeout)
856        let result = tokio::time::timeout(timeout, async {
857            tokio::task::yield_now().await;
858        }).await;
859        
860        // Should complete successfully since task finishes before timeout
861        assert!(result.is_ok());
862    }
863
864    #[test]
865    fn test_shutdown_signal_multiple() {
866        let config = Config::default();
867        let server = Server::new(config);
868        
869        // Verify the notify can be called multiple times
870        server.shutdown_signal.notify_one();
871        server.shutdown_signal.notify_one();
872        server.shutdown_signal.notify_one();
873    }
874
875    #[tokio::test]
876    async fn test_signal_notification_awaits() {
877        let notify = Arc::new(tokio::sync::Notify::new());
878        let notify_clone = notify.clone();
879        
880        // Spawn a task that waits for notification
881        let handle = tokio::spawn(async move {
882            notify_clone.notified().await;
883        });
884        
885        // Give it time to start waiting
886        tokio::time::sleep(Duration::from_millis(10)).await;
887        
888        // Notify
889        notify.notify_one();
890        
891        // Should complete
892        let result = tokio::time::timeout(Duration::from_secs(1), handle).await;
893        assert!(result.is_ok());
894    }
895
896    #[test]
897    fn test_config_edge_cases() {
898        // Test very large values
899        let config = Config {
900            port: 65535, // Max port number
901            max_connections: 100000,
902            connection_timeout_secs: u64::MAX,
903            ..Config::default()
904        };
905        let server = Server::new(config);
906        assert_eq!(server.config.port, 65535);
907        assert_eq!(server.config.max_connections, 100000);
908    }
909
910    #[test]
911    fn test_config_minimum_values() {
912        let config = Config {
913            port: 1, // Minimum valid port
914            max_connections: 1,
915            connection_timeout_secs: 1,
916            ..Config::default()
917        };
918        let server = Server::new(config);
919        assert_eq!(server.config.port, 1);
920        assert_eq!(server.config.max_connections, 1);
921        assert_eq!(server.config.connection_timeout_secs, 1);
922    }
923
924    #[test]
925    fn test_tls_enabled_variations() {
926        // Test all TLS configuration variations
927        let configs = vec![
928            (false, None, None, "no_tls"),
929            (true, Some("cert.pem"), Some("key.pem"), "full_tls"),
930            (true, Some("cert.pem"), None, "missing_key"),
931            (true, None, Some("key.pem"), "missing_cert"),
932            (true, None, None, "both_missing"),
933        ];
934
935        for (enable_tls, cert, key, _desc) in configs {
936            let config = Config {
937                enable_tls,
938                tls_cert: cert.map(|s| s.to_string()),
939                tls_key: key.map(|s| s.to_string()),
940                ..Config::default()
941            };
942            let server = Server::new(config);
943            assert_eq!(server.config.enable_tls, enable_tls);
944        }
945    }
946
947    #[tokio::test]
948    async fn test_hyper_service_fn_usage() {
949        // Test that the service_fn closure works correctly
950        let config = Config::default();
951        let handler = Handler::new(Arc::new(config));
952        let handler = Arc::new(handler);
953        
954        // Clone handler like serve_connection does
955        let handler_for_request = handler.clone();
956        
957        // Just verify it clones correctly
958        assert!(Arc::strong_count(&handler) > 0);
959        drop(handler_for_request);
960    }
961
962    #[test]
963    fn test_http_response_builder() {
964        // Test Response builder directly
965        let response = Response::builder()
966            .status(200)
967            .header("Content-Type", "application/json")
968            .body(Full::new(Bytes::from(r#"{"test":"data"}"#)))
969            .unwrap();
970        
971        assert_eq!(response.status(), 200);
972        assert_eq!(
973            response.headers().get("Content-Type").unwrap(),
974            "application/json"
975        );
976    }
977
978    #[test]
979    fn test_http_response_builder_error_cases() {
980        // Test invalid status codes (should still work, but verify builder)
981        let response = Response::builder()
982            .status(500)
983            .body(Full::new(Bytes::from("error")))
984            .unwrap();
985        
986        assert_eq!(response.status(), 500);
987    }
988
989    #[test]
990    fn test_bytes_creation() {
991        // Test Bytes creation for body
992        let bytes1 = Bytes::from(r#"{"status":"ok"}"#);
993        assert_eq!(bytes1.len(), 15);
994        
995        let bytes2 = Bytes::from_static(b"test");
996        assert_eq!(bytes2.len(), 4);
997        
998        let bytes3 = Bytes::new();
999        assert!(bytes3.is_empty());
1000    }
1001
1002    #[tokio::test]
1003    async fn test_tokio_timeout_behavior() {
1004        // Test tokio::time::timeout directly
1005        let short_timeout = Duration::from_millis(10);
1006        let long_task = Duration::from_millis(100);
1007        
1008        let result = tokio::time::timeout(short_timeout, async {
1009            tokio::time::sleep(long_task).await;
1010        }).await;
1011        
1012        assert!(result.is_err(), "Should timeout");
1013        
1014        // Test successful completion
1015        let long_timeout = Duration::from_secs(1);
1016        let short_task = Duration::from_millis(10);
1017        
1018        let result = tokio::time::timeout(long_timeout, async {
1019            tokio::time::sleep(short_task).await;
1020        }).await;
1021        
1022        assert!(result.is_ok(), "Should complete successfully");
1023    }
1024
1025    #[tokio::test]
1026    async fn test_semaphore_fairness() {
1027        let semaphore = Arc::new(tokio::sync::Semaphore::new(3));
1028        
1029        // Acquire all permits
1030        let p1 = semaphore.try_acquire().unwrap();
1031        let p2 = semaphore.try_acquire().unwrap();
1032        let p3 = semaphore.try_acquire().unwrap();
1033        
1034        // Should have no more permits
1035        assert!(semaphore.try_acquire().is_err());
1036        
1037        // Drop in different order
1038        drop(p2);
1039        assert_eq!(semaphore.available_permits(), 1);
1040        
1041        drop(p1);
1042        assert_eq!(semaphore.available_permits(), 2);
1043        
1044        drop(p3);
1045        assert_eq!(semaphore.available_permits(), 3);
1046    }
1047
1048    #[test]
1049    fn test_full_config_all_fields() {
1050        // Create a config with every field explicitly set
1051        let config = Config {
1052            port: 9090,
1053            root: "/web/root".into(),
1054            enable_indexing: true,
1055            enable_compression: true,
1056            log_level: "debug".into(),
1057            enable_tls: true,
1058            tls_cert: Some("/path/to/cert".into()),
1059            tls_key: Some("/path/to/key".into()),
1060            connection_timeout_secs: 120,
1061            max_connections: 5000,
1062            enable_health_check: true,
1063            enable_cors: true,
1064            cors_allowed_origins: vec!["*".into(), "localhost".into()],
1065            cors_allowed_methods: vec!["GET".into(), "POST".into()],
1066            cors_allowed_headers: vec!["Content-Type".into()],
1067            cors_allow_credentials: true,
1068            cors_exposed_headers: vec!["X-Custom".into()],
1069            cors_max_age: Some(3600),
1070            enable_security: true,
1071            rate_limit_max_requests: 1000,
1072            rate_limit_window_secs: 120,
1073            ip_allowlist: vec!["127.0.0.1".into()],
1074            ip_blocklist: vec!["10.0.0.1".into()],
1075            max_body_size: 50 * 1024 * 1024,
1076            max_headers: 200,
1077            management: None,
1078            auto_tls: None,
1079        };
1080        
1081        let server = Server::new(config.clone());
1082        
1083        assert_eq!(server.config.port, 9090);
1084        assert_eq!(server.config.root, std::path::PathBuf::from("/web/root"));
1085        assert_eq!(server.config.log_level, "debug");
1086        assert_eq!(server.config.connection_timeout_secs, 120);
1087        assert_eq!(server.config.max_connections, 5000);
1088        assert_eq!(server.config.max_body_size, 50 * 1024 * 1024);
1089        assert_eq!(server.config.max_headers, 200);
1090    }
1091
1092    #[tokio::test]
1093    async fn test_run_method_with_tls_validation_error() {
1094        // Test the error path when TLS files don't exist
1095        let config = Config {
1096            enable_tls: true,
1097            tls_cert: Some("/definitely/not/existing/cert.pem".to_string()),
1098            tls_key: Some("/definitely/not/existing/key.pem".to_string()),
1099            port: 0,
1100            ..Config::default()
1101        };
1102        
1103        let server = Server::new(config);
1104        
1105        // Verify TLS is enabled (run() would fail with validation error)
1106        assert!(server.config.enable_tls);
1107        assert!(server.config.tls_cert.is_some());
1108    }
1109
1110    #[test]
1111    fn test_server_arc_behavior() {
1112        let config = Config::default();
1113        let server = Server::new(config);
1114        
1115        // Test that we can clone the Arc
1116        let config1 = server.config.clone();
1117        let config2 = server.config.clone();
1118        
1119        // Both should point to same data
1120        assert_eq!(config1.port, config2.port);
1121        assert_eq!(Arc::strong_count(&server.config), 3); // original + 2 clones
1122        
1123        drop(config1);
1124        assert_eq!(Arc::strong_count(&server.config), 2);
1125    }
1126
1127    #[test]
1128    fn test_socket_addr_display() {
1129        let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
1130        assert_eq!(addr.to_string(), "127.0.0.1:8080");
1131        
1132        let addr_v6: SocketAddr = "[::1]:8080".parse().unwrap();
1133        assert_eq!(addr_v6.to_string(), "[::1]:8080");
1134    }
1135
1136    #[test]
1137    fn test_health_check_response_headers() {
1138        let response = health_check_response();
1139        
1140        // Verify all expected headers
1141        let headers = response.headers();
1142        assert!(headers.contains_key("Content-Type"));
1143        assert_eq!(headers.get("Content-Type").unwrap(), "application/json");
1144        
1145        // Verify status
1146        assert_eq!(response.status().as_u16(), 200);
1147    }
1148
1149    #[tokio::test]
1150    async fn test_concurrent_semaphore_operations() {
1151        use std::sync::atomic::{AtomicUsize, Ordering};
1152        
1153        let semaphore = Arc::new(tokio::sync::Semaphore::new(5));
1154        let counter = Arc::new(AtomicUsize::new(0));
1155        let max_observed = Arc::new(AtomicUsize::new(0));
1156        
1157        let mut handles = vec![];
1158        
1159        for _ in 0..10 {
1160            let sem = semaphore.clone();
1161            let cnt = counter.clone();
1162            let max = max_observed.clone();
1163            
1164            let handle = tokio::spawn(async move {
1165                if let Ok(_permit) = sem.try_acquire() {
1166                    let current = cnt.fetch_add(1, Ordering::SeqCst) + 1;
1167                    
1168                    // Update max observed
1169                    let mut max_val = max.load(Ordering::SeqCst);
1170                    while current > max_val {
1171                        match max.compare_exchange_weak(
1172                            max_val,
1173                            current,
1174                            Ordering::SeqCst,
1175                            Ordering::SeqCst,
1176                        ) {
1177                            Ok(_) => break,
1178                            Err(actual) => max_val = actual,
1179                        }
1180                    }
1181                    
1182                    tokio::time::sleep(Duration::from_millis(10)).await;
1183                    cnt.fetch_sub(1, Ordering::SeqCst);
1184                }
1185            });
1186            
1187            handles.push(handle);
1188        }
1189        
1190        for handle in handles {
1191            handle.await.unwrap();
1192        }
1193        
1194        // Max observed should not exceed permit count
1195        assert!(max_observed.load(Ordering::SeqCst) <= 5);
1196    }
1197
1198    #[test]
1199    fn test_config_with_empty_strings() {
1200        let config = Config {
1201            log_level: "".into(),
1202            root: "".into(),
1203            ..Config::default()
1204        };
1205        let server = Server::new(config);
1206        assert!(server.config.log_level.is_empty());
1207        assert!(server.config.root.as_os_str().is_empty());
1208    }
1209
1210    #[test]
1211    fn test_config_with_special_chars_in_paths() {
1212        let config = Config {
1213            tls_cert: Some("/path with spaces/cert.pem".into()),
1214            tls_key: Some("/path-with-dashes/key.pem".into()),
1215            ..Config::default()
1216        };
1217        let server = Server::new(config);
1218        assert_eq!(server.config.tls_cert, Some("/path with spaces/cert.pem".to_string()));
1219        assert_eq!(server.config.tls_key, Some("/path-with-dashes/key.pem".to_string()));
1220    }
1221
1222    #[test]
1223    fn test_tls_error_display() {
1224        use crate::error::Error;
1225        
1226        let err = Error::Internal("TLS test error".to_string());
1227        assert!(err.to_string().contains("TLS test error"));
1228    }
1229
1230    #[test]
1231    fn test_path_conversions() {
1232        use std::path::Path;
1233        
1234        let path_str = "/tmp/test/path";
1235        let path = Path::new(path_str);
1236        assert_eq!(path.to_str().unwrap(), path_str);
1237        
1238        let path_buf: std::path::PathBuf = path_str.into();
1239        assert_eq!(path_buf, std::path::PathBuf::from(path_str));
1240    }
1241}