spikard 0.8.1 → 0.8.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/ext/spikard_rb/Cargo.toml +1 -1
- data/lib/spikard/grpc.rb +5 -5
- data/lib/spikard/version.rb +1 -1
- data/vendor/crates/spikard-bindings-shared/Cargo.toml +1 -1
- data/vendor/crates/spikard-bindings-shared/src/grpc_metadata.rs +3 -3
- data/vendor/crates/spikard-core/Cargo.toml +1 -1
- data/vendor/crates/spikard-core/src/metadata.rs +3 -14
- data/vendor/crates/spikard-http/Cargo.toml +1 -1
- data/vendor/crates/spikard-http/src/grpc/mod.rs +1 -1
- data/vendor/crates/spikard-http/src/grpc/service.rs +11 -11
- data/vendor/crates/spikard-http/src/grpc/streaming.rs +5 -1
- data/vendor/crates/spikard-http/src/server/grpc_routing.rs +59 -20
- data/vendor/crates/spikard-http/src/server/routing_factory.rs +179 -201
- data/vendor/crates/spikard-http/tests/common/grpc_helpers.rs +49 -60
- data/vendor/crates/spikard-http/tests/common/handlers.rs +5 -5
- data/vendor/crates/spikard-http/tests/common/mod.rs +7 -8
- data/vendor/crates/spikard-http/tests/common/test_builders.rs +14 -19
- data/vendor/crates/spikard-http/tests/grpc_error_handling_test.rs +68 -69
- data/vendor/crates/spikard-http/tests/grpc_integration_test.rs +1 -3
- data/vendor/crates/spikard-http/tests/grpc_metadata_test.rs +98 -84
- data/vendor/crates/spikard-http/tests/grpc_server_integration.rs +76 -57
- data/vendor/crates/spikard-rb/Cargo.toml +1 -1
- data/vendor/crates/spikard-rb/src/grpc/handler.rs +30 -25
- data/vendor/crates/spikard-rb/src/lib.rs +1 -2
- data/vendor/crates/spikard-rb-macros/Cargo.toml +1 -1
- metadata +1 -1
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
//! Comprehensive gRPC error handling tests
|
|
2
2
|
//!
|
|
3
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)
|
|
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
21
|
|
|
22
22
|
use crate::common::grpc_helpers::*;
|
|
23
23
|
use bytes::Bytes;
|
|
@@ -29,12 +29,12 @@ mod common;
|
|
|
29
29
|
/// Test OK status (success case)
|
|
30
30
|
#[tokio::test]
|
|
31
31
|
async fn test_status_ok_success() {
|
|
32
|
-
let mut server = GrpcTestServer::new();
|
|
33
|
-
|
|
34
32
|
struct SuccessHandler;
|
|
35
33
|
impl spikard_http::grpc::GrpcHandler for SuccessHandler {
|
|
36
|
-
fn call(
|
|
37
|
-
|
|
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
38
|
{
|
|
39
39
|
Box::pin(async {
|
|
40
40
|
Ok(spikard_http::grpc::GrpcResponseData {
|
|
@@ -48,6 +48,8 @@ async fn test_status_ok_success() {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
let server = GrpcTestServer::new();
|
|
52
|
+
|
|
51
53
|
server.register_service(Arc::new(SuccessHandler));
|
|
52
54
|
|
|
53
55
|
let response = send_unary_request(
|
|
@@ -61,13 +63,13 @@ async fn test_status_ok_success() {
|
|
|
61
63
|
|
|
62
64
|
assert!(response.is_ok());
|
|
63
65
|
let resp = response.unwrap();
|
|
64
|
-
assert_grpc_response(resp, serde_json::json!({"result": "success"}));
|
|
66
|
+
assert_grpc_response(&resp, &serde_json::json!({"result": "success"}));
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
/// Test CANCELLED status code
|
|
68
70
|
#[tokio::test]
|
|
69
71
|
async fn test_status_cancelled() {
|
|
70
|
-
let
|
|
72
|
+
let server = GrpcTestServer::new();
|
|
71
73
|
|
|
72
74
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
73
75
|
"test.CancelledService",
|
|
@@ -92,7 +94,7 @@ async fn test_status_cancelled() {
|
|
|
92
94
|
/// Test UNKNOWN status code
|
|
93
95
|
#[tokio::test]
|
|
94
96
|
async fn test_status_unknown() {
|
|
95
|
-
let
|
|
97
|
+
let server = GrpcTestServer::new();
|
|
96
98
|
|
|
97
99
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
98
100
|
"test.UnknownService",
|
|
@@ -113,10 +115,10 @@ async fn test_status_unknown() {
|
|
|
113
115
|
assert!(result.is_err());
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
/// Test INVALID_ARGUMENT status code
|
|
118
|
+
/// Test `INVALID_ARGUMENT` status code
|
|
117
119
|
#[tokio::test]
|
|
118
120
|
async fn test_status_invalid_argument() {
|
|
119
|
-
let
|
|
121
|
+
let server = GrpcTestServer::new();
|
|
120
122
|
|
|
121
123
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
122
124
|
"test.ValidationService",
|
|
@@ -138,10 +140,10 @@ async fn test_status_invalid_argument() {
|
|
|
138
140
|
// Error verified
|
|
139
141
|
}
|
|
140
142
|
|
|
141
|
-
/// Test DEADLINE_EXCEEDED status code
|
|
143
|
+
/// Test `DEADLINE_EXCEEDED` status code
|
|
142
144
|
#[tokio::test]
|
|
143
145
|
async fn test_status_deadline_exceeded() {
|
|
144
|
-
let
|
|
146
|
+
let server = GrpcTestServer::new();
|
|
145
147
|
|
|
146
148
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
147
149
|
"test.TimeoutService",
|
|
@@ -163,10 +165,10 @@ async fn test_status_deadline_exceeded() {
|
|
|
163
165
|
// Error verified
|
|
164
166
|
}
|
|
165
167
|
|
|
166
|
-
/// Test NOT_FOUND status code
|
|
168
|
+
/// Test `NOT_FOUND` status code
|
|
167
169
|
#[tokio::test]
|
|
168
170
|
async fn test_status_not_found() {
|
|
169
|
-
let
|
|
171
|
+
let server = GrpcTestServer::new();
|
|
170
172
|
|
|
171
173
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
172
174
|
"test.NotFoundService",
|
|
@@ -188,10 +190,10 @@ async fn test_status_not_found() {
|
|
|
188
190
|
// Error verified
|
|
189
191
|
}
|
|
190
192
|
|
|
191
|
-
/// Test ALREADY_EXISTS status code
|
|
193
|
+
/// Test `ALREADY_EXISTS` status code
|
|
192
194
|
#[tokio::test]
|
|
193
195
|
async fn test_status_already_exists() {
|
|
194
|
-
let
|
|
196
|
+
let server = GrpcTestServer::new();
|
|
195
197
|
|
|
196
198
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
197
199
|
"test.CreateService",
|
|
@@ -213,10 +215,10 @@ async fn test_status_already_exists() {
|
|
|
213
215
|
// Error verified
|
|
214
216
|
}
|
|
215
217
|
|
|
216
|
-
/// Test PERMISSION_DENIED status code
|
|
218
|
+
/// Test `PERMISSION_DENIED` status code
|
|
217
219
|
#[tokio::test]
|
|
218
220
|
async fn test_status_permission_denied() {
|
|
219
|
-
let
|
|
221
|
+
let server = GrpcTestServer::new();
|
|
220
222
|
|
|
221
223
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
222
224
|
"test.AuthService",
|
|
@@ -238,10 +240,10 @@ async fn test_status_permission_denied() {
|
|
|
238
240
|
// Error verified
|
|
239
241
|
}
|
|
240
242
|
|
|
241
|
-
/// Test RESOURCE_EXHAUSTED status code
|
|
243
|
+
/// Test `RESOURCE_EXHAUSTED` status code
|
|
242
244
|
#[tokio::test]
|
|
243
245
|
async fn test_status_resource_exhausted() {
|
|
244
|
-
let
|
|
246
|
+
let server = GrpcTestServer::new();
|
|
245
247
|
|
|
246
248
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
247
249
|
"test.QuotaService",
|
|
@@ -263,10 +265,10 @@ async fn test_status_resource_exhausted() {
|
|
|
263
265
|
// Error verified
|
|
264
266
|
}
|
|
265
267
|
|
|
266
|
-
/// Test FAILED_PRECONDITION status code
|
|
268
|
+
/// Test `FAILED_PRECONDITION` status code
|
|
267
269
|
#[tokio::test]
|
|
268
270
|
async fn test_status_failed_precondition() {
|
|
269
|
-
let
|
|
271
|
+
let server = GrpcTestServer::new();
|
|
270
272
|
|
|
271
273
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
272
274
|
"test.OrderService",
|
|
@@ -288,10 +290,10 @@ async fn test_status_failed_precondition() {
|
|
|
288
290
|
// Error verified
|
|
289
291
|
}
|
|
290
292
|
|
|
291
|
-
/// Test ABORTED status code
|
|
293
|
+
/// Test `ABORTED` status code
|
|
292
294
|
#[tokio::test]
|
|
293
295
|
async fn test_status_aborted() {
|
|
294
|
-
let
|
|
296
|
+
let server = GrpcTestServer::new();
|
|
295
297
|
|
|
296
298
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
297
299
|
"test.TransactionService",
|
|
@@ -313,10 +315,10 @@ async fn test_status_aborted() {
|
|
|
313
315
|
// Error verified
|
|
314
316
|
}
|
|
315
317
|
|
|
316
|
-
/// Test OUT_OF_RANGE status code
|
|
318
|
+
/// Test `OUT_OF_RANGE` status code
|
|
317
319
|
#[tokio::test]
|
|
318
320
|
async fn test_status_out_of_range() {
|
|
319
|
-
let
|
|
321
|
+
let server = GrpcTestServer::new();
|
|
320
322
|
|
|
321
323
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
322
324
|
"test.PageService",
|
|
@@ -338,10 +340,10 @@ async fn test_status_out_of_range() {
|
|
|
338
340
|
// Error verified
|
|
339
341
|
}
|
|
340
342
|
|
|
341
|
-
/// Test UNIMPLEMENTED status code
|
|
343
|
+
/// Test `UNIMPLEMENTED` status code
|
|
342
344
|
#[tokio::test]
|
|
343
345
|
async fn test_status_unimplemented() {
|
|
344
|
-
let
|
|
346
|
+
let server = GrpcTestServer::new();
|
|
345
347
|
|
|
346
348
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
347
349
|
"test.ExperimentalService",
|
|
@@ -363,10 +365,10 @@ async fn test_status_unimplemented() {
|
|
|
363
365
|
// Error verified
|
|
364
366
|
}
|
|
365
367
|
|
|
366
|
-
/// Test INTERNAL status code
|
|
368
|
+
/// Test `INTERNAL` status code
|
|
367
369
|
#[tokio::test]
|
|
368
370
|
async fn test_status_internal_error() {
|
|
369
|
-
let
|
|
371
|
+
let server = GrpcTestServer::new();
|
|
370
372
|
|
|
371
373
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
372
374
|
"test.DatabaseService",
|
|
@@ -388,10 +390,10 @@ async fn test_status_internal_error() {
|
|
|
388
390
|
// Error verified
|
|
389
391
|
}
|
|
390
392
|
|
|
391
|
-
/// Test UNAVAILABLE status code
|
|
393
|
+
/// Test `UNAVAILABLE` status code
|
|
392
394
|
#[tokio::test]
|
|
393
395
|
async fn test_status_unavailable() {
|
|
394
|
-
let
|
|
396
|
+
let server = GrpcTestServer::new();
|
|
395
397
|
|
|
396
398
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
397
399
|
"test.ExternalService",
|
|
@@ -413,10 +415,10 @@ async fn test_status_unavailable() {
|
|
|
413
415
|
// Error verified
|
|
414
416
|
}
|
|
415
417
|
|
|
416
|
-
/// Test DATA_LOSS status code
|
|
418
|
+
/// Test `DATA_LOSS` status code
|
|
417
419
|
#[tokio::test]
|
|
418
420
|
async fn test_status_data_loss() {
|
|
419
|
-
let
|
|
421
|
+
let server = GrpcTestServer::new();
|
|
420
422
|
|
|
421
423
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
422
424
|
"test.FileService",
|
|
@@ -438,10 +440,10 @@ async fn test_status_data_loss() {
|
|
|
438
440
|
// Error verified
|
|
439
441
|
}
|
|
440
442
|
|
|
441
|
-
/// Test UNAUTHENTICATED status code
|
|
443
|
+
/// Test `UNAUTHENTICATED` status code
|
|
442
444
|
#[tokio::test]
|
|
443
445
|
async fn test_status_unauthenticated() {
|
|
444
|
-
let
|
|
446
|
+
let server = GrpcTestServer::new();
|
|
445
447
|
|
|
446
448
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
447
449
|
"test.SecureService",
|
|
@@ -466,7 +468,7 @@ async fn test_status_unauthenticated() {
|
|
|
466
468
|
/// Test error message propagation
|
|
467
469
|
#[tokio::test]
|
|
468
470
|
async fn test_error_message_propagation() {
|
|
469
|
-
let
|
|
471
|
+
let server = GrpcTestServer::new();
|
|
470
472
|
|
|
471
473
|
let detailed_message = "Validation failed: Password must be at least 12 characters. \
|
|
472
474
|
Current length: 8. Special characters required.";
|
|
@@ -492,7 +494,7 @@ async fn test_error_message_propagation() {
|
|
|
492
494
|
/// Test multiple error responses in sequence
|
|
493
495
|
#[tokio::test]
|
|
494
496
|
async fn test_multiple_error_responses() {
|
|
495
|
-
let
|
|
497
|
+
let server = GrpcTestServer::new();
|
|
496
498
|
|
|
497
499
|
// Register service that returns INVALID_ARGUMENT
|
|
498
500
|
let handler1 = Arc::new(ErrorMockHandler::new(
|
|
@@ -555,13 +557,9 @@ async fn test_multiple_error_responses() {
|
|
|
555
557
|
/// Test error with empty message
|
|
556
558
|
#[tokio::test]
|
|
557
559
|
async fn test_error_with_empty_message() {
|
|
558
|
-
let
|
|
560
|
+
let server = GrpcTestServer::new();
|
|
559
561
|
|
|
560
|
-
let handler = Arc::new(ErrorMockHandler::new(
|
|
561
|
-
"test.EmptyErrorService",
|
|
562
|
-
Code::Internal,
|
|
563
|
-
"",
|
|
564
|
-
));
|
|
562
|
+
let handler = Arc::new(ErrorMockHandler::new("test.EmptyErrorService", Code::Internal, ""));
|
|
565
563
|
server.register_service(handler);
|
|
566
564
|
|
|
567
565
|
let result = send_unary_request(
|
|
@@ -579,11 +577,10 @@ async fn test_error_with_empty_message() {
|
|
|
579
577
|
/// Test error with very long message
|
|
580
578
|
#[tokio::test]
|
|
581
579
|
async fn test_error_with_long_message() {
|
|
582
|
-
let
|
|
580
|
+
let server = GrpcTestServer::new();
|
|
583
581
|
|
|
584
|
-
let long_message =
|
|
585
|
-
+ &"detailed reason ".repeat(50)
|
|
586
|
-
+ "Please contact support.";
|
|
582
|
+
let long_message =
|
|
583
|
+
"Error occurred during processing: ".to_string() + &"detailed reason ".repeat(50) + "Please contact support.";
|
|
587
584
|
|
|
588
585
|
let handler = Arc::new(ErrorMockHandler::new(
|
|
589
586
|
"test.LongErrorService",
|
|
@@ -607,19 +604,19 @@ async fn test_error_with_long_message() {
|
|
|
607
604
|
/// Test handler conversion of custom errors to gRPC status
|
|
608
605
|
#[tokio::test]
|
|
609
606
|
async fn test_handler_error_to_status_conversion() {
|
|
610
|
-
let mut server = GrpcTestServer::new();
|
|
611
|
-
|
|
612
607
|
struct ValidationHandler;
|
|
613
608
|
impl spikard_http::grpc::GrpcHandler for ValidationHandler {
|
|
614
|
-
fn call(
|
|
615
|
-
|
|
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>>
|
|
616
613
|
{
|
|
617
614
|
// Simulate validation logic
|
|
618
615
|
if request.payload.is_empty() {
|
|
619
616
|
Box::pin(async {
|
|
620
617
|
Err(tonic::Status::new(
|
|
621
618
|
Code::InvalidArgument,
|
|
622
|
-
"Request body cannot be empty"
|
|
619
|
+
"Request body cannot be empty",
|
|
623
620
|
))
|
|
624
621
|
})
|
|
625
622
|
} else {
|
|
@@ -636,6 +633,8 @@ async fn test_handler_error_to_status_conversion() {
|
|
|
636
633
|
}
|
|
637
634
|
}
|
|
638
635
|
|
|
636
|
+
let server = GrpcTestServer::new();
|
|
637
|
+
|
|
639
638
|
server.register_service(Arc::new(ValidationHandler));
|
|
640
639
|
|
|
641
640
|
// Test with empty payload (should error)
|
|
@@ -280,9 +280,7 @@ fn test_handler_service_name() {
|
|
|
280
280
|
let echo_handler = EchoGrpcHandler;
|
|
281
281
|
assert_eq!(echo_handler.service_name(), "test.EchoService");
|
|
282
282
|
|
|
283
|
-
let fixed_handler = FixedResponseHandler {
|
|
284
|
-
response: Bytes::new(),
|
|
285
|
-
};
|
|
283
|
+
let fixed_handler = FixedResponseHandler { response: Bytes::new() };
|
|
286
284
|
assert_eq!(fixed_handler.service_name(), "test.FixedService");
|
|
287
285
|
|
|
288
286
|
let error_handler = ErrorGrpcHandler;
|