Skip to main content

mockforge_tcp/
protocol_server.rs

1//! Unified protocol server implementation for the TCP mock server.
2
3use std::sync::Arc;
4
5use async_trait::async_trait;
6use mockforge_core::protocol_abstraction::Protocol;
7use mockforge_core::protocol_server::MockProtocolServer;
8
9use crate::server::TcpServer;
10use crate::spec_registry::TcpSpecRegistry;
11use crate::TcpConfig;
12
13/// A `MockProtocolServer` wrapper around [`TcpServer`].
14///
15/// Constructs the TCP server and spec registry, then delegates to
16/// [`TcpServer::start`] with shutdown-signal integration.
17pub struct TcpMockServer {
18    config: TcpConfig,
19}
20
21impl TcpMockServer {
22    /// Create a new `TcpMockServer` with the given configuration.
23    pub fn new(config: TcpConfig) -> Self {
24        Self { config }
25    }
26}
27
28#[async_trait]
29impl MockProtocolServer for TcpMockServer {
30    fn protocol(&self) -> Protocol {
31        Protocol::Tcp
32    }
33
34    async fn start(
35        &self,
36        mut shutdown: tokio::sync::watch::Receiver<()>,
37    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
38        let spec_registry = Arc::new(TcpSpecRegistry::new());
39        let server = TcpServer::new(self.config.clone(), spec_registry)
40            .map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)?;
41
42        tokio::select! {
43            result = server.start() => {
44                result.map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)
45            }
46            _ = shutdown.changed() => {
47                tracing::info!("Shutting down TCP server on port {}", self.config.port);
48                Ok(())
49            }
50        }
51    }
52
53    fn port(&self) -> u16 {
54        self.config.port
55    }
56
57    fn description(&self) -> String {
58        format!("TCP server on {}:{}", self.config.host, self.config.port)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_tcp_mock_server_protocol() {
68        let server = TcpMockServer::new(TcpConfig::default());
69        assert_eq!(server.protocol(), Protocol::Tcp);
70    }
71
72    #[test]
73    fn test_tcp_mock_server_port() {
74        let config = TcpConfig {
75            port: 9999,
76            ..Default::default()
77        };
78        let server = TcpMockServer::new(config);
79        assert_eq!(server.port(), 9999);
80    }
81
82    #[test]
83    fn test_tcp_mock_server_description() {
84        let config = TcpConfig {
85            host: "127.0.0.1".to_string(),
86            port: 9999,
87            ..Default::default()
88        };
89        let server = TcpMockServer::new(config);
90        assert_eq!(server.description(), "TCP server on 127.0.0.1:9999");
91    }
92}