#![allow(clippy::result_large_err)]
use std::error::Error;
use tonic::{Code, Status};
use tonic_mock::{
grpc_mock::{
create_grpc_uri, decode_grpc_message, encode_grpc_request, encode_grpc_response,
mock_grpc_call,
},
test_utils::{TestRequest, TestResponse},
};
trait EchoService {
fn echo(&self, request: TestRequest) -> Result<TestResponse, Status>;
}
struct MockEchoService;
impl EchoService for MockEchoService {
fn echo(&self, request: TestRequest) -> Result<TestResponse, Status> {
let id_str = String::from_utf8_lossy(&request.id).to_string();
if id_str.contains("error") {
return Err(Status::new(
Code::InvalidArgument,
"Invalid ID: contains 'error'",
));
}
let data_str = String::from_utf8_lossy(&request.data).to_string();
Ok(TestResponse::new(
200,
format!("Echo: {} - {}", id_str, data_str),
))
}
}
fn main() -> Result<(), Box<dyn Error>> {
println!("=== gRPC Mock Example ===\n");
manual_request_response_example()?;
mock_grpc_call_example()?;
error_handling_example()?;
println!("\nAll examples completed successfully!");
Ok(())
}
fn manual_request_response_example() -> Result<(), Box<dyn Error>> {
println!("Example 1: Manual request/response encoding");
let request = TestRequest::new("request-1", "Hello, gRPC!");
println!("- Creating request with ID: 'request-1'");
let uri = create_grpc_uri("echo.EchoService", "Echo");
println!("- Created URI: {}", uri);
let encoded_request = encode_grpc_request(request);
println!("- Encoded request to {} bytes", encoded_request.len());
let decoded_request: TestRequest = decode_grpc_message(&encoded_request)?;
println!(
"- Decoded request message: id={}, data={}",
String::from_utf8_lossy(&decoded_request.id),
String::from_utf8_lossy(&decoded_request.data)
);
let service = MockEchoService;
let response = service.echo(decoded_request)?;
println!("- Service generated response: {}", response.message);
let encoded_response = encode_grpc_response(response);
println!("- Encoded response to {} bytes", encoded_response.len());
println!("- Example 1 completed\n");
Ok(())
}
fn mock_grpc_call_example() -> Result<(), Box<dyn Error>> {
println!("Example 2: Using mock_grpc_call helper");
let request = TestRequest::new("request-2", "Testing mock_grpc_call");
println!("- Creating request with ID: 'request-2'");
let response = mock_grpc_call("echo.EchoService", "Echo", request, |req: TestRequest| {
println!(
"- Handler received request: id={}, data={}",
String::from_utf8_lossy(&req.id),
String::from_utf8_lossy(&req.data)
);
let id_str = String::from_utf8_lossy(&req.id).to_string();
let data_str = String::from_utf8_lossy(&req.data).to_string();
Ok(TestResponse::new(
200,
format!("Processed: {} - {}", id_str, data_str),
))
})?;
println!(
"- Received response: code={}, message={}",
response.code, response.message
);
println!("- Example 2 completed\n");
Ok(())
}
fn error_handling_example() -> Result<(), Box<dyn Error>> {
println!("Example 3: Error handling");
let request = TestRequest::new("error-id", "This will cause an error");
println!("- Creating request with ID: 'error-id'");
let result = mock_grpc_call("echo.EchoService", "Echo", request, |req: TestRequest| {
let service = MockEchoService;
service.echo(req)
});
match result {
Ok(response) => {
println!("- Unexpected success: {}", response.message);
Ok(())
}
Err(status) => {
println!(
"- Received expected error: {} - {}",
status.code(),
status.message()
);
println!("- Example 3 completed");
Ok(())
}
}
}