Skip to main content

mockforge_tcp/
lib.rs

1//! TCP server mocking for MockForge
2//!
3//! This crate provides TCP server functionality for MockForge, allowing you to mock
4//! raw TCP connections for testing purposes.
5//!
6//! # Example
7//!
8//! ```no_run
9//! use mockforge_tcp::{TcpServer, TcpConfig, TcpSpecRegistry};
10//! use std::sync::Arc;
11//!
12//! #[tokio::main]
13//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
14//!     let config = TcpConfig::default();
15//!     let registry = Arc::new(TcpSpecRegistry::new());
16//!
17//!     let server = TcpServer::new(config, registry)?;
18//!     server.start().await?;
19//!
20//!     Ok(())
21//! }
22//! ```
23
24mod fixtures;
25/// Unified protocol server lifecycle implementation
26pub mod protocol_server;
27mod server;
28mod spec_registry;
29
30pub use fixtures::*;
31pub use server::*;
32pub use spec_registry::*;
33
34/// TCP server configuration
35#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
36pub struct TcpConfig {
37    /// Server port (default: 9999)
38    pub port: u16,
39    /// Host address (default: 0.0.0.0)
40    pub host: String,
41    /// Directory containing fixture files
42    pub fixtures_dir: Option<std::path::PathBuf>,
43    /// Connection timeout in seconds
44    pub timeout_secs: u64,
45    /// Maximum connections
46    pub max_connections: usize,
47    /// Buffer size for reading data (bytes)
48    pub read_buffer_size: usize,
49    /// Buffer size for writing data (bytes)
50    pub write_buffer_size: usize,
51    /// Enable TLS/SSL support
52    pub enable_tls: bool,
53    /// Path to TLS certificate file
54    pub tls_cert_path: Option<std::path::PathBuf>,
55    /// Path to TLS private key file
56    pub tls_key_path: Option<std::path::PathBuf>,
57    /// Echo mode: echo back received data (if no fixture matches)
58    pub echo_mode: bool,
59    /// Delimiter for message boundaries (None = stream mode, Some = frame by delimiter)
60    pub delimiter: Option<Vec<u8>>,
61}
62
63impl Default for TcpConfig {
64    fn default() -> Self {
65        Self {
66            port: 9999,
67            host: "0.0.0.0".to_string(),
68            fixtures_dir: Some(std::path::PathBuf::from("./fixtures/tcp")),
69            timeout_secs: 300,
70            max_connections: 100,
71            read_buffer_size: 8192,
72            write_buffer_size: 8192,
73            enable_tls: false,
74            tls_cert_path: None,
75            tls_key_path: None,
76            echo_mode: true,
77            delimiter: None, // Stream mode by default
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use super::*;
85    use mockforge_core::protocol_abstraction::Protocol;
86
87    #[test]
88    fn test_default_config() {
89        let config = TcpConfig::default();
90        assert_eq!(config.port, 9999);
91        assert_eq!(config.host, "0.0.0.0");
92        assert!(config.echo_mode);
93    }
94
95    #[test]
96    fn test_protocol_display() {
97        assert_eq!(Protocol::Tcp.to_string(), "TCP");
98    }
99
100    #[test]
101    fn test_config_default_values() {
102        let config = TcpConfig::default();
103        assert_eq!(config.timeout_secs, 300);
104        assert_eq!(config.max_connections, 100);
105        assert_eq!(config.read_buffer_size, 8192);
106        assert_eq!(config.write_buffer_size, 8192);
107        assert!(!config.enable_tls);
108        assert!(config.tls_cert_path.is_none());
109        assert!(config.tls_key_path.is_none());
110        assert!(config.delimiter.is_none());
111    }
112
113    #[test]
114    fn test_config_fixtures_dir() {
115        let config = TcpConfig::default();
116        assert!(config.fixtures_dir.is_some());
117        let fixtures_dir = config.fixtures_dir.unwrap();
118        assert_eq!(fixtures_dir, std::path::PathBuf::from("./fixtures/tcp"));
119    }
120
121    #[test]
122    fn test_config_clone() {
123        let config = TcpConfig {
124            port: 8080,
125            host: "127.0.0.1".to_string(),
126            fixtures_dir: None,
127            timeout_secs: 60,
128            max_connections: 50,
129            read_buffer_size: 4096,
130            write_buffer_size: 4096,
131            enable_tls: true,
132            tls_cert_path: Some(std::path::PathBuf::from("/path/to/cert")),
133            tls_key_path: Some(std::path::PathBuf::from("/path/to/key")),
134            echo_mode: false,
135            delimiter: Some(b"\n".to_vec()),
136        };
137
138        let cloned = config.clone();
139        assert_eq!(config.port, cloned.port);
140        assert_eq!(config.host, cloned.host);
141        assert_eq!(config.enable_tls, cloned.enable_tls);
142        assert_eq!(config.delimiter, cloned.delimiter);
143    }
144
145    #[test]
146    fn test_config_debug() {
147        let config = TcpConfig::default();
148        let debug = format!("{:?}", config);
149        assert!(debug.contains("TcpConfig"));
150        assert!(debug.contains("9999"));
151    }
152
153    #[test]
154    fn test_config_serialize() {
155        let config = TcpConfig::default();
156        let json = serde_json::to_string(&config).unwrap();
157        assert!(json.contains("\"port\":9999"));
158        assert!(json.contains("\"echo_mode\":true"));
159    }
160
161    #[test]
162    fn test_config_deserialize() {
163        let json = r#"{
164            "port": 8080,
165            "host": "localhost",
166            "fixtures_dir": null,
167            "timeout_secs": 120,
168            "max_connections": 200,
169            "read_buffer_size": 16384,
170            "write_buffer_size": 16384,
171            "enable_tls": false,
172            "tls_cert_path": null,
173            "tls_key_path": null,
174            "echo_mode": false,
175            "delimiter": null
176        }"#;
177
178        let config: TcpConfig = serde_json::from_str(json).unwrap();
179        assert_eq!(config.port, 8080);
180        assert_eq!(config.host, "localhost");
181        assert_eq!(config.timeout_secs, 120);
182        assert!(!config.echo_mode);
183    }
184
185    #[test]
186    fn test_config_with_delimiter() {
187        let config = TcpConfig {
188            delimiter: Some(b"\r\n".to_vec()),
189            ..Default::default()
190        };
191
192        assert_eq!(config.delimiter, Some(b"\r\n".to_vec()));
193    }
194}