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#[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
25pub struct Server {
27 config: Arc<Config>,
28 shutdown_signal: Arc<tokio::sync::Notify>,
29}
30
31impl Server {
32 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 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 #[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 let max_connections = Arc::new(tokio::sync::Semaphore::new(self.config.max_connections));
58
59 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_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 Some(load_tls_config(&cert_path, &key_path)?.clone())
76 } else {
77 None
78 };
79
80 loop {
81 tokio::select! {
82 accept_result = listener.accept() => {
84 let (stream, _) = accept_result?;
85 let max_conn = max_connections.clone();
86
87 let _permit = match max_conn.try_acquire() {
89 Ok(p) => p,
90 Err(_) => {
91 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 let timeout = Duration::from_secs(config.connection_timeout_secs);
104
105 let result = tokio::time::timeout(timeout, async {
106 if let Some(tls_config) = tls_config_clone {
108 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 let io = TokioIo::new(stream);
123 Self::serve_connection(io, handler).await;
124 }
125 }).await;
126
127 match result {
128 Ok(_) => {}
129 Err(_) => {
130 }
132 }
133
134 });
136 }
137
138 _ = 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 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(); }
172
173 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 let _ = server.config.clone();
232 }
233
234 #[test]
235 fn test_server_address_parsing() {
236 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 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 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 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, 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, 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 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 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 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 let _signal = server.shutdown_signal.clone();
432
433 server.shutdown();
435
436 }
439
440 #[tokio::test]
441 async fn test_connection_limit_enforcement() {
442 let config = Config {
446 port: 0, max_connections: 2,
448 ..Config::default()
449 };
450
451 let _server = Server::new(config.clone());
453 let _addr = format!("0.0.0.0:{}", config.port);
454
455 let listener = TcpListener::bind("0.0.0.0:0").await.unwrap();
457 let actual_addr = listener.local_addr().unwrap();
458 drop(listener);
459
460 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 let server_handle = tokio::spawn(async move {
471 let _ = tokio::time::timeout(
473 tokio::time::Duration::from_millis(100),
474 server.run()
475 ).await;
476 });
477
478 tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
480
481 let max_connections = Arc::new(tokio::sync::Semaphore::new(2));
483 assert_eq!(max_connections.available_permits(), 2);
484
485 let p1 = max_connections.try_acquire().unwrap();
487 let p2 = max_connections.try_acquire().unwrap();
488
489 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 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 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 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 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 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 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 let _signal = server.shutdown_signal.clone();
569
570 server.shutdown();
572 server.shutdown();
573 server.shutdown();
574 }
575
576 #[test]
577 fn test_server_config_variations() {
578 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 let permits = 100;
616 let semaphore = Arc::new(tokio::sync::Semaphore::new(permits));
617 assert_eq!(semaphore.available_permits(), permits);
618
619 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 let result = validate_tls_config(
637 Some("/nonexistent/cert.pem"),
638 Some("/nonexistent/key.pem")
639 );
640 assert!(result.is_err());
641
642 let result = validate_tls_config(None, Some("/nonexistent/key.pem"));
644 assert!(result.is_err());
645
646 let result = validate_tls_config(Some("/nonexistent/cert.pem"), None);
648 assert!(result.is_err());
649
650 let result = validate_tls_config(None, None);
652 assert!(result.is_ok()); }
654
655 #[test]
658 fn test_health_check_response_body() {
659 let response = health_check_response();
660 assert_eq!(response.status(), 200);
661
662 let _body_ref = response.body();
665
666 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 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 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 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 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 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 let permit = max_conn.try_acquire();
755 assert!(permit.is_ok());
756
757 let permit2 = max_conn.try_acquire();
759 assert!(permit2.is_err());
760
761 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 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 let _handler_clone = handler.clone();
790 }
791
792 #[tokio::test]
793 async fn test_serve_connection_basic() {
794 let config = Config::default();
798 let handler = Arc::new(Handler::new(Arc::new(config)));
799
800 let _handler_for_connection = handler.clone();
802 }
803
804 #[test]
805 fn test_tls_config_error_messages() {
806 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 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 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 let result = tokio::time::timeout(timeout, async {
857 tokio::task::yield_now().await;
858 }).await;
859
860 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 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 let handle = tokio::spawn(async move {
882 notify_clone.notified().await;
883 });
884
885 tokio::time::sleep(Duration::from_millis(10)).await;
887
888 notify.notify_one();
890
891 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 let config = Config {
900 port: 65535, 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, 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 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 let config = Config::default();
951 let handler = Handler::new(Arc::new(config));
952 let handler = Arc::new(handler);
953
954 let handler_for_request = handler.clone();
956
957 assert!(Arc::strong_count(&handler) > 0);
959 drop(handler_for_request);
960 }
961
962 #[test]
963 fn test_http_response_builder() {
964 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 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 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 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 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 let p1 = semaphore.try_acquire().unwrap();
1031 let p2 = semaphore.try_acquire().unwrap();
1032 let p3 = semaphore.try_acquire().unwrap();
1033
1034 assert!(semaphore.try_acquire().is_err());
1036
1037 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 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 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 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 let config1 = server.config.clone();
1117 let config2 = server.config.clone();
1118
1119 assert_eq!(config1.port, config2.port);
1121 assert_eq!(Arc::strong_count(&server.config), 3); 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 let headers = response.headers();
1142 assert!(headers.contains_key("Content-Type"));
1143 assert_eq!(headers.get("Content-Type").unwrap(), "application/json");
1144
1145 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 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 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}