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