mockforge_grpc/lib.rs
1//! # MockForge gRPC
2//!
3//! Flexible gRPC mocking library with dynamic service discovery and HTTP bridge.
4//!
5//! This crate provides comprehensive gRPC mocking capabilities with:
6//!
7//! - **Dynamic Service Discovery**: Auto-discover and mock services from `.proto` files
8//! - **HTTP Bridge**: Expose gRPC services as REST APIs with OpenAPI documentation
9//! - **gRPC Reflection**: Built-in server reflection for service discovery
10//! - **Streaming Support**: Full support for unary, server, client, and bidirectional streaming
11//! - **Protocol Buffer Parsing**: Runtime parsing of `.proto` files without code generation
12//!
13//! ## Overview
14//!
15//! MockForge gRPC eliminates the need to hardcode service implementations. Simply provide
16//! `.proto` files, and MockForge will automatically:
17//!
18//! 1. Parse protobuf definitions
19//! 2. Generate mock service implementations
20//! 3. Handle all RPC methods (unary and streaming)
21//! 4. Optionally expose as REST APIs via HTTP Bridge
22//!
23//! ## Quick Start
24//!
25//! ### Basic gRPC Server
26//!
27//! ```rust,no_run
28//! use mockforge_grpc::start;
29//!
30//! #[tokio::main]
31//! async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
32//! // Start gRPC server on port 50051
33//! // Automatically discovers .proto files in ./proto directory
34//! start(50051).await?;
35//! Ok(())
36//! }
37//! ```
38//!
39//! ### With Custom Configuration
40//!
41//! ```rust,no_run
42//! use mockforge_grpc::{start_with_config, DynamicGrpcConfig};
43//! use mockforge_grpc::dynamic::http_bridge::HttpBridgeConfig;
44//! use mockforge_core::LatencyProfile;
45//!
46//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
47//! let config = DynamicGrpcConfig {
48//! proto_dir: "./my-protos".to_string(),
49//! enable_reflection: true,
50//! excluded_services: vec!["ExperimentalService".to_string()],
51//! http_bridge: Some(HttpBridgeConfig {
52//! enabled: true,
53//! base_path: "/api".to_string(),
54//! ..Default::default()
55//! }),
56//! ..Default::default()
57//! };
58//!
59//! let latency = Some(LatencyProfile::with_normal_distribution(120, 35.0));
60//! start_with_config(50051, latency, config).await?;
61//! # Ok(())
62//! # }
63//! ```
64//!
65//! ### HTTP Bridge Mode
66//!
67//! Expose gRPC services as REST APIs:
68//!
69//! ```rust,no_run
70//! use mockforge_grpc::{start_with_config, DynamicGrpcConfig};
71//! use mockforge_grpc::dynamic::http_bridge::HttpBridgeConfig;
72//!
73//! # async fn example() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
74//! let config = DynamicGrpcConfig {
75//! proto_dir: "./proto".to_string(),
76//! http_bridge: Some(HttpBridgeConfig {
77//! enabled: true,
78//! base_path: "/api".to_string(),
79//! ..Default::default()
80//! }),
81//! ..Default::default()
82//! };
83//!
84//! start_with_config(50051, None, config).await?;
85//! // Now accessible via:
86//! // - gRPC: localhost:50051
87//! // - REST: http://localhost:8080/api/{service}/{method}
88//! // - OpenAPI: http://localhost:8080/api/docs
89//! # Ok(())
90//! # }
91//! ```
92//!
93//! ## Dynamic Service Discovery
94//!
95//! MockForge automatically discovers and mocks all services defined in your `.proto` files:
96//!
97//! ```protobuf
98//! // user.proto
99//! service UserService {
100//! rpc GetUser(GetUserRequest) returns (GetUserResponse);
101//! rpc ListUsers(ListUsersRequest) returns (stream User);
102//! rpc CreateUser(stream CreateUserRequest) returns (CreateUserResponse);
103//! rpc Chat(stream ChatMessage) returns (stream ChatMessage);
104//! }
105//! ```
106//!
107//! All four method types (unary, server streaming, client streaming, bidirectional) are
108//! automatically supported without any code generation or manual implementation.
109//!
110//! ## gRPC Reflection
111//!
112//! Enable reflection for service discovery by gRPC clients:
113//!
114//! ```bash
115//! # List services
116//! grpcurl -plaintext localhost:50051 list
117//!
118//! # Describe a service
119//! grpcurl -plaintext localhost:50051 describe UserService
120//!
121//! # Call a method
122//! grpcurl -plaintext -d '{"user_id": "123"}' localhost:50051 UserService/GetUser
123//! ```
124//!
125//! ## HTTP Bridge
126//!
127//! The HTTP Bridge automatically converts gRPC services to REST endpoints:
128//!
129//! ```bash
130//! # gRPC call
131//! grpcurl -d '{"user_id": "123"}' localhost:50051 UserService/GetUser
132//!
133//! # Equivalent HTTP call
134//! curl -X POST http://localhost:8080/api/userservice/getuser \
135//! -H "Content-Type: application/json" \
136//! -d '{"user_id": "123"}'
137//!
138//! # OpenAPI documentation
139//! curl http://localhost:8080/api/docs
140//! ```
141//!
142//! ## Advanced Data Synthesis
143//!
144//! Generate realistic mock data using intelligent field inference:
145//!
146//! - Detects field types from names (`email`, `phone`, `id`, etc.)
147//! - Maintains referential integrity across related messages
148//! - Supports deterministic seeding for reproducible tests
149//!
150//! ## Key Modules
151//!
152//! - [`dynamic`]: Dynamic service discovery and mocking
153//! - [`reflection`]: gRPC reflection protocol implementation
154//! - [`registry`]: Service and method registry
155//!
156//! ## Examples
157//!
158//! See the [examples directory](https://github.com/SaaSy-Solutions/mockforge/tree/main/examples)
159//! for complete working examples.
160//!
161//! ## Related Crates
162//!
163//! - [`mockforge-core`](https://docs.rs/mockforge-core): Core mocking functionality
164//! - [`mockforge-data`](https://docs.rs/mockforge-data): Synthetic data generation
165//!
166//! ## Documentation
167//!
168//! - [MockForge Book](https://docs.mockforge.dev/)
169//! - [gRPC Mocking Guide](https://docs.mockforge.dev/user-guide/grpc-mocking.html)
170//! - [API Reference](https://docs.rs/mockforge-grpc)
171
172use mockforge_core::LatencyProfile;
173
174pub mod dynamic;
175pub mod reflection;
176pub mod registry;
177
178// Include generated proto code
179pub mod generated {
180 // Include all generated proto files
181 tonic::include_proto!("mockforge.greeter");
182}
183
184pub use dynamic::proto_parser::ProtoService;
185pub use dynamic::service_generator::MockResponse;
186pub use dynamic::{DynamicGrpcConfig, ServiceRegistry};
187pub use reflection::{MockReflectionProxy, ProxyConfig, ReflectionProxy};
188pub use registry::GrpcProtoRegistry;
189
190/// Start gRPC server with default configuration
191pub async fn start(port: u16) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
192 start_with_latency(port, None).await
193}
194
195/// Start gRPC server with latency configuration
196pub async fn start_with_latency(
197 port: u16,
198 latency_profile: Option<LatencyProfile>,
199) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
200 let config = DynamicGrpcConfig::default();
201 start_with_config(port, latency_profile, config).await
202}
203
204/// Start gRPC server with custom configuration
205pub async fn start_with_config(
206 port: u16,
207 latency_profile: Option<LatencyProfile>,
208 config: DynamicGrpcConfig,
209) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
210 dynamic::start_dynamic_server(port, config, latency_profile).await
211}
212
213#[cfg(test)]
214mod tests {
215 use super::*;
216
217 #[test]
218 fn test_dynamic_grpc_config_default() {
219 let _config = DynamicGrpcConfig::default();
220 // Config should be created successfully
221 }
222
223 #[test]
224 fn test_latency_profile_creation() {
225 let profile = LatencyProfile::default();
226 assert_eq!(profile.base_ms, 50);
227 assert_eq!(profile.jitter_ms, 20);
228 assert_eq!(profile.min_ms, 0);
229 }
230
231 #[test]
232 fn test_latency_profile_custom() {
233 let profile = LatencyProfile::new(100, 25);
234
235 assert_eq!(profile.base_ms, 100);
236 assert_eq!(profile.jitter_ms, 25);
237 assert_eq!(profile.min_ms, 0);
238 }
239}