spikard 0.12.0 → 0.15.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Steepfile +6 -0
- data/ext/spikard_rb/extconf.rb +1 -2
- data/ext/spikard_rb/{Cargo.lock → native/Cargo.lock} +897 -451
- data/ext/spikard_rb/native/Cargo.toml +24 -0
- data/ext/spikard_rb/src/lib.rs +5366 -3
- data/lib/spikard/native.rb +86 -0
- data/lib/spikard/version.rb +6 -1
- data/lib/spikard.rb +8 -45
- data/lib/spikard_rb.so +0 -0
- data/sig/types.rbs +427 -0
- metadata +14 -242
- data/LICENSE +0 -1
- data/README.md +0 -267
- data/ext/spikard_rb/Cargo.toml +0 -17
- data/lib/spikard/app.rb +0 -428
- data/lib/spikard/background.rb +0 -58
- data/lib/spikard/config.rb +0 -506
- data/lib/spikard/converters.rb +0 -13
- data/lib/spikard/grpc.rb +0 -182
- data/lib/spikard/handler_wrapper.rb +0 -113
- data/lib/spikard/provide.rb +0 -214
- data/lib/spikard/response.rb +0 -173
- data/lib/spikard/schema.rb +0 -243
- data/lib/spikard/sse.rb +0 -111
- data/lib/spikard/streaming_response.rb +0 -44
- data/lib/spikard/testing.rb +0 -432
- data/lib/spikard/upload_file.rb +0 -131
- data/lib/spikard/websocket.rb +0 -59
- data/sig/spikard.rbs +0 -719
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +0 -80
- data/vendor/crates/spikard-bindings-shared/examples/config_extraction.rs +0 -132
- data/vendor/crates/spikard-bindings-shared/src/config_extractor.rs +0 -905
- data/vendor/crates/spikard-bindings-shared/src/conversion_traits.rs +0 -210
- data/vendor/crates/spikard-bindings-shared/src/di_traits.rs +0 -252
- data/vendor/crates/spikard-bindings-shared/src/error_response.rs +0 -404
- data/vendor/crates/spikard-bindings-shared/src/grpc_metadata.rs +0 -199
- data/vendor/crates/spikard-bindings-shared/src/handler_base.rs +0 -252
- data/vendor/crates/spikard-bindings-shared/src/json_conversion.rs +0 -829
- data/vendor/crates/spikard-bindings-shared/src/lazy_cache.rs +0 -587
- data/vendor/crates/spikard-bindings-shared/src/lib.rs +0 -33
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_base.rs +0 -298
- data/vendor/crates/spikard-bindings-shared/src/lifecycle_executor.rs +0 -594
- data/vendor/crates/spikard-bindings-shared/src/response_builder.rs +0 -743
- data/vendor/crates/spikard-bindings-shared/src/response_interpreter.rs +0 -944
- data/vendor/crates/spikard-bindings-shared/src/test_client_base.rs +0 -260
- data/vendor/crates/spikard-bindings-shared/src/validation_helpers.rs +0 -369
- data/vendor/crates/spikard-bindings-shared/tests/config_extractor_behavior.rs +0 -192
- data/vendor/crates/spikard-bindings-shared/tests/error_response_edge_cases.rs +0 -383
- data/vendor/crates/spikard-bindings-shared/tests/full_coverage.rs +0 -459
- data/vendor/crates/spikard-bindings-shared/tests/handler_base_integration.rs +0 -280
- data/vendor/crates/spikard-bindings-shared/tests/integration_tests.rs +0 -669
- data/vendor/crates/spikard-core/Cargo.toml +0 -60
- data/vendor/crates/spikard-core/src/bindings/mod.rs +0 -3
- data/vendor/crates/spikard-core/src/bindings/response.rs +0 -130
- data/vendor/crates/spikard-core/src/debug.rs +0 -127
- data/vendor/crates/spikard-core/src/di/container.rs +0 -702
- data/vendor/crates/spikard-core/src/di/dependency.rs +0 -273
- data/vendor/crates/spikard-core/src/di/error.rs +0 -118
- data/vendor/crates/spikard-core/src/di/factory.rs +0 -538
- data/vendor/crates/spikard-core/src/di/graph.rs +0 -507
- data/vendor/crates/spikard-core/src/di/mod.rs +0 -192
- data/vendor/crates/spikard-core/src/di/resolved.rs +0 -428
- data/vendor/crates/spikard-core/src/di/value.rs +0 -282
- data/vendor/crates/spikard-core/src/errors.rs +0 -72
- data/vendor/crates/spikard-core/src/http.rs +0 -492
- data/vendor/crates/spikard-core/src/lib.rs +0 -29
- data/vendor/crates/spikard-core/src/lifecycle.rs +0 -1273
- data/vendor/crates/spikard-core/src/metadata.rs +0 -378
- data/vendor/crates/spikard-core/src/parameters.rs +0 -2546
- data/vendor/crates/spikard-core/src/problem.rs +0 -358
- data/vendor/crates/spikard-core/src/request_data.rs +0 -1146
- data/vendor/crates/spikard-core/src/router.rs +0 -530
- data/vendor/crates/spikard-core/src/schema_registry.rs +0 -197
- data/vendor/crates/spikard-core/src/type_hints.rs +0 -311
- data/vendor/crates/spikard-core/src/validation/error_mapper.rs +0 -710
- data/vendor/crates/spikard-core/src/validation/mod.rs +0 -470
- data/vendor/crates/spikard-core/tests/bindings_response_tests.rs +0 -136
- data/vendor/crates/spikard-core/tests/di_dependency_defaults.rs +0 -37
- data/vendor/crates/spikard-core/tests/error_mapper.rs +0 -761
- data/vendor/crates/spikard-core/tests/parameters_edge_cases.rs +0 -106
- data/vendor/crates/spikard-core/tests/parameters_full.rs +0 -701
- data/vendor/crates/spikard-core/tests/parameters_schema_and_formats.rs +0 -301
- data/vendor/crates/spikard-core/tests/request_data_roundtrip.rs +0 -67
- data/vendor/crates/spikard-core/tests/validation_coverage.rs +0 -250
- data/vendor/crates/spikard-core/tests/validation_error_paths.rs +0 -45
- data/vendor/crates/spikard-http/Cargo.toml +0 -87
- data/vendor/crates/spikard-http/examples/sse-notifications.rs +0 -148
- data/vendor/crates/spikard-http/examples/websocket-chat.rs +0 -92
- data/vendor/crates/spikard-http/src/auth.rs +0 -301
- data/vendor/crates/spikard-http/src/background.rs +0 -1860
- data/vendor/crates/spikard-http/src/bindings/mod.rs +0 -3
- data/vendor/crates/spikard-http/src/bindings/response.rs +0 -1
- data/vendor/crates/spikard-http/src/body_metadata.rs +0 -8
- data/vendor/crates/spikard-http/src/cors.rs +0 -1026
- data/vendor/crates/spikard-http/src/debug.rs +0 -128
- data/vendor/crates/spikard-http/src/di_handler.rs +0 -1672
- data/vendor/crates/spikard-http/src/grpc/framing.rs +0 -469
- data/vendor/crates/spikard-http/src/grpc/handler.rs +0 -1122
- data/vendor/crates/spikard-http/src/grpc/mod.rs +0 -434
- data/vendor/crates/spikard-http/src/grpc/service.rs +0 -622
- data/vendor/crates/spikard-http/src/grpc/streaming.rs +0 -319
- data/vendor/crates/spikard-http/src/handler_response.rs +0 -901
- data/vendor/crates/spikard-http/src/handler_trait.rs +0 -1015
- data/vendor/crates/spikard-http/src/handler_trait_tests.rs +0 -290
- data/vendor/crates/spikard-http/src/jsonrpc/http_handler.rs +0 -502
- data/vendor/crates/spikard-http/src/jsonrpc/method_registry.rs +0 -648
- data/vendor/crates/spikard-http/src/jsonrpc/mod.rs +0 -58
- data/vendor/crates/spikard-http/src/jsonrpc/protocol.rs +0 -1207
- data/vendor/crates/spikard-http/src/jsonrpc/router.rs +0 -2262
- data/vendor/crates/spikard-http/src/lib.rs +0 -548
- data/vendor/crates/spikard-http/src/lifecycle/adapter.rs +0 -230
- data/vendor/crates/spikard-http/src/lifecycle.rs +0 -1193
- data/vendor/crates/spikard-http/src/middleware/mod.rs +0 -560
- data/vendor/crates/spikard-http/src/middleware/multipart.rs +0 -912
- data/vendor/crates/spikard-http/src/middleware/urlencoded.rs +0 -513
- data/vendor/crates/spikard-http/src/middleware/validation.rs +0 -768
- data/vendor/crates/spikard-http/src/openapi/mod.rs +0 -309
- data/vendor/crates/spikard-http/src/openapi/parameter_extraction.rs +0 -535
- data/vendor/crates/spikard-http/src/openapi/schema_conversion.rs +0 -1363
- data/vendor/crates/spikard-http/src/openapi/spec_generation.rs +0 -667
- data/vendor/crates/spikard-http/src/query_parser.rs +0 -793
- data/vendor/crates/spikard-http/src/response.rs +0 -720
- data/vendor/crates/spikard-http/src/server/fast_router.rs +0 -186
- data/vendor/crates/spikard-http/src/server/grpc_routing.rs +0 -858
- data/vendor/crates/spikard-http/src/server/handler.rs +0 -1661
- data/vendor/crates/spikard-http/src/server/lifecycle_execution.rs +0 -253
- data/vendor/crates/spikard-http/src/server/mod.rs +0 -1649
- data/vendor/crates/spikard-http/src/server/request_extraction.rs +0 -871
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +0 -618
- data/vendor/crates/spikard-http/src/sse.rs +0 -1409
- data/vendor/crates/spikard-http/src/testing/form.rs +0 -52
- data/vendor/crates/spikard-http/src/testing/multipart.rs +0 -64
- data/vendor/crates/spikard-http/src/testing/test_client.rs +0 -787
- data/vendor/crates/spikard-http/src/testing.rs +0 -617
- data/vendor/crates/spikard-http/src/websocket.rs +0 -1477
- data/vendor/crates/spikard-http/tests/auth_integration.rs +0 -645
- data/vendor/crates/spikard-http/tests/background_behavior.rs +0 -832
- data/vendor/crates/spikard-http/tests/common/grpc_helpers.rs +0 -1012
- data/vendor/crates/spikard-http/tests/common/handlers.rs +0 -309
- data/vendor/crates/spikard-http/tests/common/mod.rs +0 -33
- data/vendor/crates/spikard-http/tests/common/test_builders.rs +0 -628
- data/vendor/crates/spikard-http/tests/di_handler_error_responses.rs +0 -162
- data/vendor/crates/spikard-http/tests/di_integration.rs +0 -192
- data/vendor/crates/spikard-http/tests/doc_snippets.rs +0 -5
- data/vendor/crates/spikard-http/tests/grpc_bidirectional_streaming.rs +0 -430
- data/vendor/crates/spikard-http/tests/grpc_client_streaming.rs +0 -738
- data/vendor/crates/spikard-http/tests/grpc_error_handling_test.rs +0 -652
- data/vendor/crates/spikard-http/tests/grpc_integration_test.rs +0 -334
- data/vendor/crates/spikard-http/tests/grpc_metadata_test.rs +0 -532
- data/vendor/crates/spikard-http/tests/grpc_server_integration.rs +0 -495
- data/vendor/crates/spikard-http/tests/grpc_server_streaming.rs +0 -974
- data/vendor/crates/spikard-http/tests/lifecycle_execution.rs +0 -1093
- data/vendor/crates/spikard-http/tests/middleware_stack_integration.rs +0 -389
- data/vendor/crates/spikard-http/tests/multipart_behavior.rs +0 -656
- data/vendor/crates/spikard-http/tests/request_extraction_full.rs +0 -513
- data/vendor/crates/spikard-http/tests/server_auth_middleware_behavior.rs +0 -328
- data/vendor/crates/spikard-http/tests/server_config_builder.rs +0 -314
- data/vendor/crates/spikard-http/tests/server_configured_router_behavior.rs +0 -200
- data/vendor/crates/spikard-http/tests/server_cors_preflight.rs +0 -83
- data/vendor/crates/spikard-http/tests/server_handler_wrappers.rs +0 -464
- data/vendor/crates/spikard-http/tests/server_method_router_additional_behavior.rs +0 -286
- data/vendor/crates/spikard-http/tests/server_method_router_coverage.rs +0 -118
- data/vendor/crates/spikard-http/tests/server_middleware_behavior.rs +0 -99
- data/vendor/crates/spikard-http/tests/server_middleware_branches.rs +0 -204
- data/vendor/crates/spikard-http/tests/server_openapi_jsonrpc_static.rs +0 -421
- data/vendor/crates/spikard-http/tests/server_router_behavior.rs +0 -121
- data/vendor/crates/spikard-http/tests/sse_behavior.rs +0 -620
- data/vendor/crates/spikard-http/tests/sse_full_behavior.rs +0 -584
- data/vendor/crates/spikard-http/tests/sse_handler_behavior.rs +0 -130
- data/vendor/crates/spikard-http/tests/test_client_requests.rs +0 -167
- data/vendor/crates/spikard-http/tests/testing_helpers.rs +0 -87
- data/vendor/crates/spikard-http/tests/testing_module_coverage.rs +0 -155
- data/vendor/crates/spikard-http/tests/urlencoded_content_type.rs +0 -82
- data/vendor/crates/spikard-http/tests/websocket_behavior.rs +0 -663
- data/vendor/crates/spikard-http/tests/websocket_full_behavior.rs +0 -440
- data/vendor/crates/spikard-http/tests/websocket_integration.rs +0 -150
- data/vendor/crates/spikard-rb/Cargo.toml +0 -68
- data/vendor/crates/spikard-rb/build.rs +0 -200
- data/vendor/crates/spikard-rb/src/background.rs +0 -63
- data/vendor/crates/spikard-rb/src/config/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/config/server_config.rs +0 -401
- data/vendor/crates/spikard-rb/src/conversion.rs +0 -688
- data/vendor/crates/spikard-rb/src/di/builder.rs +0 -100
- data/vendor/crates/spikard-rb/src/di/mod.rs +0 -375
- data/vendor/crates/spikard-rb/src/grpc/handler.rs +0 -834
- data/vendor/crates/spikard-rb/src/grpc/mod.rs +0 -13
- data/vendor/crates/spikard-rb/src/gvl.rs +0 -80
- data/vendor/crates/spikard-rb/src/handler.rs +0 -699
- data/vendor/crates/spikard-rb/src/integration/mod.rs +0 -3
- data/vendor/crates/spikard-rb/src/lib.rs +0 -2264
- data/vendor/crates/spikard-rb/src/lifecycle.rs +0 -303
- data/vendor/crates/spikard-rb/src/metadata/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/metadata/route_extraction.rs +0 -507
- data/vendor/crates/spikard-rb/src/request.rs +0 -439
- data/vendor/crates/spikard-rb/src/runtime/mod.rs +0 -5
- data/vendor/crates/spikard-rb/src/runtime/server_runner.rs +0 -344
- data/vendor/crates/spikard-rb/src/server.rs +0 -307
- data/vendor/crates/spikard-rb/src/sse.rs +0 -231
- data/vendor/crates/spikard-rb/src/testing/client.rs +0 -698
- data/vendor/crates/spikard-rb/src/testing/mod.rs +0 -7
- data/vendor/crates/spikard-rb/src/testing/sse.rs +0 -108
- data/vendor/crates/spikard-rb/src/testing/websocket.rs +0 -573
- data/vendor/crates/spikard-rb/src/websocket.rs +0 -475
- data/vendor/crates/spikard-rb-macros/Cargo.toml +0 -25
- data/vendor/crates/spikard-rb-macros/src/lib.rs +0 -51
|
@@ -1,652 +0,0 @@
|
|
|
1
|
-
//! Comprehensive gRPC error handling tests
|
|
2
|
-
//!
|
|
3
|
-
//! Tests all 17 standard gRPC status codes including:
|
|
4
|
-
//! - `OK` (0)
|
|
5
|
-
//! - `CANCELLED` (1)
|
|
6
|
-
//! - `UNKNOWN` (2)
|
|
7
|
-
//! - `INVALID_ARGUMENT` (3)
|
|
8
|
-
//! - `DEADLINE_EXCEEDED` (4)
|
|
9
|
-
//! - `NOT_FOUND` (5)
|
|
10
|
-
//! - `ALREADY_EXISTS` (6)
|
|
11
|
-
//! - `PERMISSION_DENIED` (7)
|
|
12
|
-
//! - `RESOURCE_EXHAUSTED` (8)
|
|
13
|
-
//! - `FAILED_PRECONDITION` (9)
|
|
14
|
-
//! - `ABORTED` (10)
|
|
15
|
-
//! - `OUT_OF_RANGE` (11)
|
|
16
|
-
//! - `UNIMPLEMENTED` (12)
|
|
17
|
-
//! - `INTERNAL` (13)
|
|
18
|
-
//! - `UNAVAILABLE` (14)
|
|
19
|
-
//! - `DATA_LOSS` (15)
|
|
20
|
-
//! - `UNAUTHENTICATED` (16)
|
|
21
|
-
|
|
22
|
-
use crate::common::grpc_helpers::*;
|
|
23
|
-
use bytes::Bytes;
|
|
24
|
-
use std::sync::Arc;
|
|
25
|
-
use tonic::Code;
|
|
26
|
-
|
|
27
|
-
mod common;
|
|
28
|
-
|
|
29
|
-
/// Test OK status (success case)
|
|
30
|
-
#[tokio::test]
|
|
31
|
-
async fn test_status_ok_success() {
|
|
32
|
-
struct SuccessHandler;
|
|
33
|
-
impl spikard_http::grpc::GrpcHandler for SuccessHandler {
|
|
34
|
-
fn call(
|
|
35
|
-
&self,
|
|
36
|
-
_request: spikard_http::grpc::GrpcRequestData,
|
|
37
|
-
) -> std::pin::Pin<Box<dyn std::future::Future<Output = spikard_http::grpc::GrpcHandlerResult> + Send>>
|
|
38
|
-
{
|
|
39
|
-
Box::pin(async {
|
|
40
|
-
Ok(spikard_http::grpc::GrpcResponseData {
|
|
41
|
-
payload: Bytes::from(r#"{"result": "success"}"#),
|
|
42
|
-
metadata: tonic::metadata::MetadataMap::new(),
|
|
43
|
-
})
|
|
44
|
-
})
|
|
45
|
-
}
|
|
46
|
-
fn service_name(&self) -> &'static str {
|
|
47
|
-
"test.SuccessService"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let server = GrpcTestServer::new();
|
|
52
|
-
|
|
53
|
-
server.register_service(Arc::new(SuccessHandler));
|
|
54
|
-
|
|
55
|
-
let response = send_unary_request(
|
|
56
|
-
&server,
|
|
57
|
-
"test.SuccessService",
|
|
58
|
-
"DoWork",
|
|
59
|
-
Bytes::from("{}"),
|
|
60
|
-
create_test_metadata(),
|
|
61
|
-
)
|
|
62
|
-
.await;
|
|
63
|
-
|
|
64
|
-
assert!(response.is_ok());
|
|
65
|
-
let resp = response.unwrap();
|
|
66
|
-
assert_grpc_response(&resp, &serde_json::json!({"result": "success"}));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/// Test CANCELLED status code
|
|
70
|
-
#[tokio::test]
|
|
71
|
-
async fn test_status_cancelled() {
|
|
72
|
-
let server = GrpcTestServer::new();
|
|
73
|
-
|
|
74
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
75
|
-
"test.CancelledService",
|
|
76
|
-
Code::Cancelled,
|
|
77
|
-
"Request was cancelled by the client",
|
|
78
|
-
));
|
|
79
|
-
server.register_service(handler);
|
|
80
|
-
|
|
81
|
-
let result = send_unary_request(
|
|
82
|
-
&server,
|
|
83
|
-
"test.CancelledService",
|
|
84
|
-
"CancelledOperation",
|
|
85
|
-
Bytes::from("{}"),
|
|
86
|
-
create_test_metadata(),
|
|
87
|
-
)
|
|
88
|
-
.await;
|
|
89
|
-
|
|
90
|
-
// Verify error occurred
|
|
91
|
-
assert!(result.is_err());
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/// Test UNKNOWN status code
|
|
95
|
-
#[tokio::test]
|
|
96
|
-
async fn test_status_unknown() {
|
|
97
|
-
let server = GrpcTestServer::new();
|
|
98
|
-
|
|
99
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
100
|
-
"test.UnknownService",
|
|
101
|
-
Code::Unknown,
|
|
102
|
-
"Unknown error occurred",
|
|
103
|
-
));
|
|
104
|
-
server.register_service(handler);
|
|
105
|
-
|
|
106
|
-
let result = send_unary_request(
|
|
107
|
-
&server,
|
|
108
|
-
"test.UnknownService",
|
|
109
|
-
"UnknownMethod",
|
|
110
|
-
Bytes::from("{}"),
|
|
111
|
-
create_test_metadata(),
|
|
112
|
-
)
|
|
113
|
-
.await;
|
|
114
|
-
|
|
115
|
-
assert!(result.is_err());
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/// Test `INVALID_ARGUMENT` status code
|
|
119
|
-
#[tokio::test]
|
|
120
|
-
async fn test_status_invalid_argument() {
|
|
121
|
-
let server = GrpcTestServer::new();
|
|
122
|
-
|
|
123
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
124
|
-
"test.ValidationService",
|
|
125
|
-
Code::InvalidArgument,
|
|
126
|
-
"Field 'email' must be a valid email address",
|
|
127
|
-
));
|
|
128
|
-
server.register_service(handler);
|
|
129
|
-
|
|
130
|
-
let result = send_unary_request(
|
|
131
|
-
&server,
|
|
132
|
-
"test.ValidationService",
|
|
133
|
-
"ValidateInput",
|
|
134
|
-
Bytes::from("{}"),
|
|
135
|
-
create_test_metadata(),
|
|
136
|
-
)
|
|
137
|
-
.await;
|
|
138
|
-
|
|
139
|
-
assert!(result.is_err());
|
|
140
|
-
// Error verified
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/// Test `DEADLINE_EXCEEDED` status code
|
|
144
|
-
#[tokio::test]
|
|
145
|
-
async fn test_status_deadline_exceeded() {
|
|
146
|
-
let server = GrpcTestServer::new();
|
|
147
|
-
|
|
148
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
149
|
-
"test.TimeoutService",
|
|
150
|
-
Code::DeadlineExceeded,
|
|
151
|
-
"Request took too long to process (timeout)",
|
|
152
|
-
));
|
|
153
|
-
server.register_service(handler);
|
|
154
|
-
|
|
155
|
-
let result = send_unary_request(
|
|
156
|
-
&server,
|
|
157
|
-
"test.TimeoutService",
|
|
158
|
-
"SlowOperation",
|
|
159
|
-
Bytes::from("{}"),
|
|
160
|
-
create_test_metadata(),
|
|
161
|
-
)
|
|
162
|
-
.await;
|
|
163
|
-
|
|
164
|
-
assert!(result.is_err());
|
|
165
|
-
// Error verified
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
/// Test `NOT_FOUND` status code
|
|
169
|
-
#[tokio::test]
|
|
170
|
-
async fn test_status_not_found() {
|
|
171
|
-
let server = GrpcTestServer::new();
|
|
172
|
-
|
|
173
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
174
|
-
"test.NotFoundService",
|
|
175
|
-
Code::NotFound,
|
|
176
|
-
"User with ID 12345 does not exist",
|
|
177
|
-
));
|
|
178
|
-
server.register_service(handler);
|
|
179
|
-
|
|
180
|
-
let result = send_unary_request(
|
|
181
|
-
&server,
|
|
182
|
-
"test.NotFoundService",
|
|
183
|
-
"GetUser",
|
|
184
|
-
Bytes::from("{}"),
|
|
185
|
-
create_test_metadata(),
|
|
186
|
-
)
|
|
187
|
-
.await;
|
|
188
|
-
|
|
189
|
-
assert!(result.is_err());
|
|
190
|
-
// Error verified
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/// Test `ALREADY_EXISTS` status code
|
|
194
|
-
#[tokio::test]
|
|
195
|
-
async fn test_status_already_exists() {
|
|
196
|
-
let server = GrpcTestServer::new();
|
|
197
|
-
|
|
198
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
199
|
-
"test.CreateService",
|
|
200
|
-
Code::AlreadyExists,
|
|
201
|
-
"User with email 'john@example.com' already exists",
|
|
202
|
-
));
|
|
203
|
-
server.register_service(handler);
|
|
204
|
-
|
|
205
|
-
let result = send_unary_request(
|
|
206
|
-
&server,
|
|
207
|
-
"test.CreateService",
|
|
208
|
-
"CreateUser",
|
|
209
|
-
Bytes::from("{}"),
|
|
210
|
-
create_test_metadata(),
|
|
211
|
-
)
|
|
212
|
-
.await;
|
|
213
|
-
|
|
214
|
-
assert!(result.is_err());
|
|
215
|
-
// Error verified
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/// Test `PERMISSION_DENIED` status code
|
|
219
|
-
#[tokio::test]
|
|
220
|
-
async fn test_status_permission_denied() {
|
|
221
|
-
let server = GrpcTestServer::new();
|
|
222
|
-
|
|
223
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
224
|
-
"test.AuthService",
|
|
225
|
-
Code::PermissionDenied,
|
|
226
|
-
"User does not have permission to delete resources",
|
|
227
|
-
));
|
|
228
|
-
server.register_service(handler);
|
|
229
|
-
|
|
230
|
-
let result = send_unary_request(
|
|
231
|
-
&server,
|
|
232
|
-
"test.AuthService",
|
|
233
|
-
"DeleteResource",
|
|
234
|
-
Bytes::from("{}"),
|
|
235
|
-
create_test_metadata(),
|
|
236
|
-
)
|
|
237
|
-
.await;
|
|
238
|
-
|
|
239
|
-
assert!(result.is_err());
|
|
240
|
-
// Error verified
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/// Test `RESOURCE_EXHAUSTED` status code
|
|
244
|
-
#[tokio::test]
|
|
245
|
-
async fn test_status_resource_exhausted() {
|
|
246
|
-
let server = GrpcTestServer::new();
|
|
247
|
-
|
|
248
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
249
|
-
"test.QuotaService",
|
|
250
|
-
Code::ResourceExhausted,
|
|
251
|
-
"API rate limit exceeded. Maximum 100 requests per minute.",
|
|
252
|
-
));
|
|
253
|
-
server.register_service(handler);
|
|
254
|
-
|
|
255
|
-
let result = send_unary_request(
|
|
256
|
-
&server,
|
|
257
|
-
"test.QuotaService",
|
|
258
|
-
"MakeRequest",
|
|
259
|
-
Bytes::from("{}"),
|
|
260
|
-
create_test_metadata(),
|
|
261
|
-
)
|
|
262
|
-
.await;
|
|
263
|
-
|
|
264
|
-
assert!(result.is_err());
|
|
265
|
-
// Error verified
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/// Test `FAILED_PRECONDITION` status code
|
|
269
|
-
#[tokio::test]
|
|
270
|
-
async fn test_status_failed_precondition() {
|
|
271
|
-
let server = GrpcTestServer::new();
|
|
272
|
-
|
|
273
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
274
|
-
"test.OrderService",
|
|
275
|
-
Code::FailedPrecondition,
|
|
276
|
-
"Cannot process order: inventory for product is out of stock",
|
|
277
|
-
));
|
|
278
|
-
server.register_service(handler);
|
|
279
|
-
|
|
280
|
-
let result = send_unary_request(
|
|
281
|
-
&server,
|
|
282
|
-
"test.OrderService",
|
|
283
|
-
"ProcessOrder",
|
|
284
|
-
Bytes::from("{}"),
|
|
285
|
-
create_test_metadata(),
|
|
286
|
-
)
|
|
287
|
-
.await;
|
|
288
|
-
|
|
289
|
-
assert!(result.is_err());
|
|
290
|
-
// Error verified
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
/// Test `ABORTED` status code
|
|
294
|
-
#[tokio::test]
|
|
295
|
-
async fn test_status_aborted() {
|
|
296
|
-
let server = GrpcTestServer::new();
|
|
297
|
-
|
|
298
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
299
|
-
"test.TransactionService",
|
|
300
|
-
Code::Aborted,
|
|
301
|
-
"Transaction was aborted due to concurrency conflict",
|
|
302
|
-
));
|
|
303
|
-
server.register_service(handler);
|
|
304
|
-
|
|
305
|
-
let result = send_unary_request(
|
|
306
|
-
&server,
|
|
307
|
-
"test.TransactionService",
|
|
308
|
-
"CommitTransaction",
|
|
309
|
-
Bytes::from("{}"),
|
|
310
|
-
create_test_metadata(),
|
|
311
|
-
)
|
|
312
|
-
.await;
|
|
313
|
-
|
|
314
|
-
assert!(result.is_err());
|
|
315
|
-
// Error verified
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/// Test `OUT_OF_RANGE` status code
|
|
319
|
-
#[tokio::test]
|
|
320
|
-
async fn test_status_out_of_range() {
|
|
321
|
-
let server = GrpcTestServer::new();
|
|
322
|
-
|
|
323
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
324
|
-
"test.PageService",
|
|
325
|
-
Code::OutOfRange,
|
|
326
|
-
"Requested page 999 is out of range. Only 10 pages available.",
|
|
327
|
-
));
|
|
328
|
-
server.register_service(handler);
|
|
329
|
-
|
|
330
|
-
let result = send_unary_request(
|
|
331
|
-
&server,
|
|
332
|
-
"test.PageService",
|
|
333
|
-
"GetPage",
|
|
334
|
-
Bytes::from("{}"),
|
|
335
|
-
create_test_metadata(),
|
|
336
|
-
)
|
|
337
|
-
.await;
|
|
338
|
-
|
|
339
|
-
assert!(result.is_err());
|
|
340
|
-
// Error verified
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/// Test `UNIMPLEMENTED` status code
|
|
344
|
-
#[tokio::test]
|
|
345
|
-
async fn test_status_unimplemented() {
|
|
346
|
-
let server = GrpcTestServer::new();
|
|
347
|
-
|
|
348
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
349
|
-
"test.ExperimentalService",
|
|
350
|
-
Code::Unimplemented,
|
|
351
|
-
"Method 'AdvancedFeature' is not yet implemented",
|
|
352
|
-
));
|
|
353
|
-
server.register_service(handler);
|
|
354
|
-
|
|
355
|
-
let result = send_unary_request(
|
|
356
|
-
&server,
|
|
357
|
-
"test.ExperimentalService",
|
|
358
|
-
"AdvancedFeature",
|
|
359
|
-
Bytes::from("{}"),
|
|
360
|
-
create_test_metadata(),
|
|
361
|
-
)
|
|
362
|
-
.await;
|
|
363
|
-
|
|
364
|
-
assert!(result.is_err());
|
|
365
|
-
// Error verified
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
/// Test `INTERNAL` status code
|
|
369
|
-
#[tokio::test]
|
|
370
|
-
async fn test_status_internal_error() {
|
|
371
|
-
let server = GrpcTestServer::new();
|
|
372
|
-
|
|
373
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
374
|
-
"test.DatabaseService",
|
|
375
|
-
Code::Internal,
|
|
376
|
-
"Internal server error: Database connection pool exhausted",
|
|
377
|
-
));
|
|
378
|
-
server.register_service(handler);
|
|
379
|
-
|
|
380
|
-
let result = send_unary_request(
|
|
381
|
-
&server,
|
|
382
|
-
"test.DatabaseService",
|
|
383
|
-
"QueryData",
|
|
384
|
-
Bytes::from("{}"),
|
|
385
|
-
create_test_metadata(),
|
|
386
|
-
)
|
|
387
|
-
.await;
|
|
388
|
-
|
|
389
|
-
assert!(result.is_err());
|
|
390
|
-
// Error verified
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
/// Test `UNAVAILABLE` status code
|
|
394
|
-
#[tokio::test]
|
|
395
|
-
async fn test_status_unavailable() {
|
|
396
|
-
let server = GrpcTestServer::new();
|
|
397
|
-
|
|
398
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
399
|
-
"test.ExternalService",
|
|
400
|
-
Code::Unavailable,
|
|
401
|
-
"Service is temporarily unavailable. Please retry later.",
|
|
402
|
-
));
|
|
403
|
-
server.register_service(handler);
|
|
404
|
-
|
|
405
|
-
let result = send_unary_request(
|
|
406
|
-
&server,
|
|
407
|
-
"test.ExternalService",
|
|
408
|
-
"CallExternal",
|
|
409
|
-
Bytes::from("{}"),
|
|
410
|
-
create_test_metadata(),
|
|
411
|
-
)
|
|
412
|
-
.await;
|
|
413
|
-
|
|
414
|
-
assert!(result.is_err());
|
|
415
|
-
// Error verified
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/// Test `DATA_LOSS` status code
|
|
419
|
-
#[tokio::test]
|
|
420
|
-
async fn test_status_data_loss() {
|
|
421
|
-
let server = GrpcTestServer::new();
|
|
422
|
-
|
|
423
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
424
|
-
"test.FileService",
|
|
425
|
-
Code::DataLoss,
|
|
426
|
-
"Data loss detected: corrupted database records",
|
|
427
|
-
));
|
|
428
|
-
server.register_service(handler);
|
|
429
|
-
|
|
430
|
-
let result = send_unary_request(
|
|
431
|
-
&server,
|
|
432
|
-
"test.FileService",
|
|
433
|
-
"RecoverData",
|
|
434
|
-
Bytes::from("{}"),
|
|
435
|
-
create_test_metadata(),
|
|
436
|
-
)
|
|
437
|
-
.await;
|
|
438
|
-
|
|
439
|
-
assert!(result.is_err());
|
|
440
|
-
// Error verified
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
/// Test `UNAUTHENTICATED` status code
|
|
444
|
-
#[tokio::test]
|
|
445
|
-
async fn test_status_unauthenticated() {
|
|
446
|
-
let server = GrpcTestServer::new();
|
|
447
|
-
|
|
448
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
449
|
-
"test.SecureService",
|
|
450
|
-
Code::Unauthenticated,
|
|
451
|
-
"Authentication required. Please provide valid credentials.",
|
|
452
|
-
));
|
|
453
|
-
server.register_service(handler);
|
|
454
|
-
|
|
455
|
-
let result = send_unary_request(
|
|
456
|
-
&server,
|
|
457
|
-
"test.SecureService",
|
|
458
|
-
"SecureOperation",
|
|
459
|
-
Bytes::from("{}"),
|
|
460
|
-
create_test_metadata(),
|
|
461
|
-
)
|
|
462
|
-
.await;
|
|
463
|
-
|
|
464
|
-
assert!(result.is_err());
|
|
465
|
-
// Error verified
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/// Test error message propagation
|
|
469
|
-
#[tokio::test]
|
|
470
|
-
async fn test_error_message_propagation() {
|
|
471
|
-
let server = GrpcTestServer::new();
|
|
472
|
-
|
|
473
|
-
let detailed_message = "Validation failed: Password must be at least 12 characters. \
|
|
474
|
-
Current length: 8. Special characters required.";
|
|
475
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
476
|
-
"test.DetailedErrorService",
|
|
477
|
-
Code::InvalidArgument,
|
|
478
|
-
detailed_message,
|
|
479
|
-
));
|
|
480
|
-
server.register_service(handler);
|
|
481
|
-
|
|
482
|
-
let result = send_unary_request(
|
|
483
|
-
&server,
|
|
484
|
-
"test.DetailedErrorService",
|
|
485
|
-
"Validate",
|
|
486
|
-
Bytes::from("{}"),
|
|
487
|
-
create_test_metadata(),
|
|
488
|
-
)
|
|
489
|
-
.await;
|
|
490
|
-
|
|
491
|
-
assert!(result.is_err());
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
/// Test multiple error responses in sequence
|
|
495
|
-
#[tokio::test]
|
|
496
|
-
async fn test_multiple_error_responses() {
|
|
497
|
-
let server = GrpcTestServer::new();
|
|
498
|
-
|
|
499
|
-
// Register service that returns INVALID_ARGUMENT
|
|
500
|
-
let handler1 = Arc::new(ErrorMockHandler::new(
|
|
501
|
-
"test.Service1",
|
|
502
|
-
Code::InvalidArgument,
|
|
503
|
-
"Invalid input",
|
|
504
|
-
));
|
|
505
|
-
server.register_service(handler1);
|
|
506
|
-
|
|
507
|
-
// Register service that returns NOT_FOUND
|
|
508
|
-
let handler2 = Arc::new(ErrorMockHandler::new(
|
|
509
|
-
"test.Service2",
|
|
510
|
-
Code::NotFound,
|
|
511
|
-
"Resource not found",
|
|
512
|
-
));
|
|
513
|
-
server.register_service(handler2);
|
|
514
|
-
|
|
515
|
-
// Register service that returns PERMISSION_DENIED
|
|
516
|
-
let handler3 = Arc::new(ErrorMockHandler::new(
|
|
517
|
-
"test.Service3",
|
|
518
|
-
Code::PermissionDenied,
|
|
519
|
-
"Access denied",
|
|
520
|
-
));
|
|
521
|
-
server.register_service(handler3);
|
|
522
|
-
|
|
523
|
-
// Test first error
|
|
524
|
-
let result1 = send_unary_request(
|
|
525
|
-
&server,
|
|
526
|
-
"test.Service1",
|
|
527
|
-
"Method",
|
|
528
|
-
Bytes::from("{}"),
|
|
529
|
-
create_test_metadata(),
|
|
530
|
-
)
|
|
531
|
-
.await;
|
|
532
|
-
assert!(result1.is_err());
|
|
533
|
-
|
|
534
|
-
// Test second error
|
|
535
|
-
let result2 = send_unary_request(
|
|
536
|
-
&server,
|
|
537
|
-
"test.Service2",
|
|
538
|
-
"Method",
|
|
539
|
-
Bytes::from("{}"),
|
|
540
|
-
create_test_metadata(),
|
|
541
|
-
)
|
|
542
|
-
.await;
|
|
543
|
-
assert!(result2.is_err());
|
|
544
|
-
|
|
545
|
-
// Test third error
|
|
546
|
-
let result3 = send_unary_request(
|
|
547
|
-
&server,
|
|
548
|
-
"test.Service3",
|
|
549
|
-
"Method",
|
|
550
|
-
Bytes::from("{}"),
|
|
551
|
-
create_test_metadata(),
|
|
552
|
-
)
|
|
553
|
-
.await;
|
|
554
|
-
assert!(result3.is_err());
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/// Test error with empty message
|
|
558
|
-
#[tokio::test]
|
|
559
|
-
async fn test_error_with_empty_message() {
|
|
560
|
-
let server = GrpcTestServer::new();
|
|
561
|
-
|
|
562
|
-
let handler = Arc::new(ErrorMockHandler::new("test.EmptyErrorService", Code::Internal, ""));
|
|
563
|
-
server.register_service(handler);
|
|
564
|
-
|
|
565
|
-
let result = send_unary_request(
|
|
566
|
-
&server,
|
|
567
|
-
"test.EmptyErrorService",
|
|
568
|
-
"Method",
|
|
569
|
-
Bytes::from("{}"),
|
|
570
|
-
create_test_metadata(),
|
|
571
|
-
)
|
|
572
|
-
.await;
|
|
573
|
-
|
|
574
|
-
assert!(result.is_err());
|
|
575
|
-
}
|
|
576
|
-
|
|
577
|
-
/// Test error with very long message
|
|
578
|
-
#[tokio::test]
|
|
579
|
-
async fn test_error_with_long_message() {
|
|
580
|
-
let server = GrpcTestServer::new();
|
|
581
|
-
|
|
582
|
-
let long_message =
|
|
583
|
-
"Error occurred during processing: ".to_string() + &"detailed reason ".repeat(50) + "Please contact support.";
|
|
584
|
-
|
|
585
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
586
|
-
"test.LongErrorService",
|
|
587
|
-
Code::Internal,
|
|
588
|
-
&long_message,
|
|
589
|
-
));
|
|
590
|
-
server.register_service(handler);
|
|
591
|
-
|
|
592
|
-
let result = send_unary_request(
|
|
593
|
-
&server,
|
|
594
|
-
"test.LongErrorService",
|
|
595
|
-
"Method",
|
|
596
|
-
Bytes::from("{}"),
|
|
597
|
-
create_test_metadata(),
|
|
598
|
-
)
|
|
599
|
-
.await;
|
|
600
|
-
|
|
601
|
-
assert!(result.is_err());
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
/// Test handler conversion of custom errors to gRPC status
|
|
605
|
-
#[tokio::test]
|
|
606
|
-
async fn test_handler_error_to_status_conversion() {
|
|
607
|
-
struct ValidationHandler;
|
|
608
|
-
impl spikard_http::grpc::GrpcHandler for ValidationHandler {
|
|
609
|
-
fn call(
|
|
610
|
-
&self,
|
|
611
|
-
request: spikard_http::grpc::GrpcRequestData,
|
|
612
|
-
) -> std::pin::Pin<Box<dyn std::future::Future<Output = spikard_http::grpc::GrpcHandlerResult> + Send>>
|
|
613
|
-
{
|
|
614
|
-
// Simulate validation logic
|
|
615
|
-
if request.payload.is_empty() {
|
|
616
|
-
Box::pin(async {
|
|
617
|
-
Err(tonic::Status::new(
|
|
618
|
-
Code::InvalidArgument,
|
|
619
|
-
"Request body cannot be empty",
|
|
620
|
-
))
|
|
621
|
-
})
|
|
622
|
-
} else {
|
|
623
|
-
Box::pin(async {
|
|
624
|
-
Ok(spikard_http::grpc::GrpcResponseData {
|
|
625
|
-
payload: Bytes::from(r#"{"status": "valid"}"#),
|
|
626
|
-
metadata: tonic::metadata::MetadataMap::new(),
|
|
627
|
-
})
|
|
628
|
-
})
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
fn service_name(&self) -> &'static str {
|
|
632
|
-
"test.ValidationService"
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
let server = GrpcTestServer::new();
|
|
637
|
-
|
|
638
|
-
server.register_service(Arc::new(ValidationHandler));
|
|
639
|
-
|
|
640
|
-
// Test with empty payload (should error)
|
|
641
|
-
let error_result = send_unary_request(
|
|
642
|
-
&server,
|
|
643
|
-
"test.ValidationService",
|
|
644
|
-
"Validate",
|
|
645
|
-
Bytes::new(),
|
|
646
|
-
create_test_metadata(),
|
|
647
|
-
)
|
|
648
|
-
.await;
|
|
649
|
-
|
|
650
|
-
assert!(error_result.is_err());
|
|
651
|
-
assert!(error_result.unwrap_err().to_string().contains("empty"));
|
|
652
|
-
}
|