#![allow(dead_code)]
#![allow(unused_variables)]
use server_less::grpc;
#[derive(Clone)]
struct UserService;
#[grpc(package = "users.v1")]
impl UserService {
pub fn get_user(&self, id: String) -> String {
id
}
pub fn list_users(&self) -> Vec<String> {
vec![]
}
pub fn create_user(&self, name: String, email: String) -> String {
name
}
pub fn delete_user(&self, id: String) -> bool {
true
}
pub fn update_user(&self, id: String, email: Option<String>) -> String {
id
}
}
#[test]
fn test_proto_schema_generated() {
let proto = UserService::grpc_schema();
assert!(proto.contains("package users.v1;"), "Should have package");
assert!(proto.contains("service UserService"), "Should have service");
}
#[test]
fn test_proto_rpc_methods() {
let proto = UserService::grpc_schema();
assert!(proto.contains("rpc GetUser"), "Should have GetUser rpc");
assert!(proto.contains("rpc ListUsers"), "Should have ListUsers rpc");
assert!(
proto.contains("rpc CreateUser"),
"Should have CreateUser rpc"
);
assert!(
proto.contains("rpc DeleteUser"),
"Should have DeleteUser rpc"
);
assert!(
proto.contains("rpc UpdateUser"),
"Should have UpdateUser rpc"
);
}
#[test]
fn test_proto_messages() {
let proto = UserService::grpc_schema();
assert!(
proto.contains("message GetUserRequest"),
"Should have GetUserRequest"
);
assert!(
proto.contains("message CreateUserRequest"),
"Should have CreateUserRequest"
);
assert!(
proto.contains("message GetUserResponse"),
"Should have GetUserResponse"
);
assert!(
proto.contains("message CreateUserResponse"),
"Should have CreateUserResponse"
);
}
#[test]
fn test_proto_fields() {
let proto = UserService::grpc_schema();
assert!(
proto.contains("string name = 1"),
"CreateUser should have name field"
);
assert!(
proto.contains("string email = 2"),
"CreateUser should have email field"
);
}
#[test]
fn test_proto_optional_fields() {
let proto = UserService::grpc_schema();
assert!(
proto.contains("optional"),
"Should have optional field for Option<T>"
);
}
#[test]
fn test_proto_doc_comments() {
let proto = UserService::grpc_schema();
assert!(
proto.contains("// Get user by ID"),
"Should preserve doc comments"
);
}
#[derive(Clone)]
struct SimpleService;
#[grpc]
impl SimpleService {
pub fn do_thing(&self) -> String {
"done".to_string()
}
}
#[test]
fn test_proto_default_package() {
let proto = SimpleService::grpc_schema();
assert!(
proto.contains("package simple_service;"),
"Should have default package, got:\n{}",
proto
);
}
#[derive(Clone)]
struct TypeService;
#[grpc]
impl TypeService {
pub fn get_int(&self) -> i32 {
42
}
pub fn get_float(&self) -> f64 {
3.5
}
pub fn get_bool(&self) -> bool {
true
}
pub fn do_nothing(&self) {}
}
#[test]
fn test_proto_return_types() {
let proto = TypeService::grpc_schema();
assert!(proto.contains("int32 result"), "Should map i32 to int32");
assert!(proto.contains("double result"), "Should map f64 to double");
assert!(proto.contains("bool result"), "Should map bool to bool");
}
#[derive(Clone)]
struct ValidatedService;
#[grpc(
package = "validated.v1",
schema = "../fixtures/validated_service.proto"
)]
impl ValidatedService {
pub fn get_greeting(&self) -> String {
"hello".to_string()
}
pub fn create_item(&self, name: String) -> String {
name
}
}
#[test]
fn test_schema_validation_passes() {
ValidatedService::assert_schema_matches();
}
#[test]
fn test_schema_validation_result() {
let result = ValidatedService::validate_schema();
assert!(result.is_ok(), "Validation should pass: {:?}", result);
}
#[derive(Clone)]
struct MismatchedService;
#[grpc(
package = "validated.v1",
schema = "../fixtures/validated_service.proto"
)]
impl MismatchedService {
pub fn different_method(&self) -> String {
"different".to_string()
}
}
#[test]
fn test_schema_validation_fails_on_mismatch() {
let result = MismatchedService::validate_schema();
assert!(
result.is_err(),
"Validation should fail for mismatched service"
);
let err = result.unwrap_err();
assert!(err.has_differences(), "Error should have differences");
}
use futures::Stream;
#[derive(Clone)]
struct StreamingService;
#[grpc(package = "streaming.v1")]
impl StreamingService {
pub fn get_item(&self, id: String) -> String {
id
}
pub fn stream_items(&self) -> impl Stream<Item = String> + use<> {
futures::stream::iter(vec!["a".to_string(), "b".to_string()])
}
pub fn stream_numbers(&self, count: i32) -> impl Stream<Item = i32> + use<> {
futures::stream::iter(0..count)
}
}
#[test]
fn test_streaming_rpc_generates_stream_keyword() {
let proto = StreamingService::grpc_schema();
assert!(
proto.contains("rpc GetItem(GetItemRequest) returns (GetItemResponse);"),
"Unary method should not have stream. Proto:\n{}",
proto
);
assert!(
proto.contains("rpc StreamItems(StreamItemsRequest) returns (stream StreamItemsResponse);"),
"Stream method should have 'stream' keyword. Proto:\n{}",
proto
);
assert!(
proto.contains(
"rpc StreamNumbers(StreamNumbersRequest) returns (stream StreamNumbersResponse);"
),
"Stream method should have 'stream' keyword. Proto:\n{}",
proto
);
}
#[test]
fn test_streaming_response_message() {
let proto = StreamingService::grpc_schema();
assert!(
proto.contains("message StreamItemsResponse"),
"Should have response message. Proto:\n{}",
proto
);
assert!(
proto.contains("string result = 1;") || proto.contains("int32 result = 1;"),
"Response should have result field with correct type. Proto:\n{}",
proto
);
}