5
5
package kotlinx.rpc.grpc.test.proto
6
6
7
7
import kotlinx.coroutines.flow.Flow
8
+ import kotlinx.coroutines.flow.map
8
9
import kotlinx.rpc.RpcServer
9
10
import kotlinx.rpc.grpc.GrpcClient
10
11
import kotlinx.rpc.grpc.GrpcTrailers
11
12
import kotlinx.rpc.grpc.ServerCallScope
12
13
import kotlinx.rpc.grpc.ServerInterceptor
14
+ import kotlinx.rpc.grpc.Status
15
+ import kotlinx.rpc.grpc.StatusCode
16
+ import kotlinx.rpc.grpc.StatusException
17
+ import kotlinx.rpc.grpc.statusCode
13
18
import kotlinx.rpc.grpc.test.EchoRequest
14
19
import kotlinx.rpc.grpc.test.EchoService
15
20
import kotlinx.rpc.grpc.test.EchoServiceImpl
16
21
import kotlinx.rpc.grpc.test.invoke
17
22
import kotlinx.rpc.registerService
18
23
import kotlinx.rpc.withService
19
24
import kotlin.test.Test
25
+ import kotlin.test.assertContains
20
26
import kotlin.test.assertEquals
21
27
import kotlin.test.assertFailsWith
28
+ import kotlin.test.assertIs
22
29
23
30
class ServerInterceptorTest : GrpcProtoTest () {
24
31
@@ -27,18 +34,82 @@ class ServerInterceptorTest : GrpcProtoTest() {
27
34
}
28
35
29
36
@Test
30
- fun `throw during intercept - should fail with thrown exception` () {
31
- val error = assertFailsWith<IllegalStateException > {
32
- val interceptor = interceptor { scope, headers, request ->
33
- scope.proceed(request)
37
+ fun `throw during intercept - should fail with unknown status on client` () {
38
+ var cause: Throwable ? = null
39
+ val error = assertFailsWith<StatusException > {
40
+ val interceptor = interceptor {
41
+ onClose { status, _ -> cause = status.getCause() }
42
+ // this exception is not propagated to the client (only as UNKNOWN status code)
43
+ throw IllegalStateException (" Failing in interceptor" )
34
44
}
35
45
runGrpcTest(serverInterceptors = interceptor, test = ::unaryCall)
36
46
}
37
47
38
- assertEquals(error.message, " Failing in interceptor" )
48
+ assertEquals(StatusCode .UNKNOWN , error.getStatus().statusCode)
49
+ assertIs<IllegalStateException >(cause)
50
+ assertEquals(" Failing in interceptor" , cause?.message)
39
51
}
40
52
41
53
54
+ @Test
55
+ fun `close during intercept - should fail with correct status on client` () {
56
+ val error = assertFailsWith<StatusException > {
57
+ val interceptor = interceptor {
58
+ close(Status (StatusCode .UNAUTHENTICATED , " Close in interceptor" ), GrpcTrailers ())
59
+ }
60
+ runGrpcTest(serverInterceptors = interceptor, test = ::unaryCall)
61
+ }
62
+
63
+ assertEquals(StatusCode .UNAUTHENTICATED , error.getStatus().statusCode)
64
+ assertContains(error.message!! , " Close in interceptor" )
65
+ }
66
+
67
+ @Test
68
+ fun `close during request flow - should fail with correct status on client` () {
69
+ val error = assertFailsWith<StatusException > {
70
+ val interceptor = interceptor {
71
+ proceed(
72
+ it.map {
73
+ close(Status (StatusCode .UNAUTHENTICATED , " Close in request flow" ), GrpcTrailers ())
74
+ }
75
+ )
76
+ }
77
+ runGrpcTest(serverInterceptors = interceptor, test = ::unaryCall)
78
+ }
79
+
80
+ assertEquals(StatusCode .UNAUTHENTICATED , error.getStatus().statusCode)
81
+ assertContains(error.message!! , " Close in request flow" )
82
+ }
83
+
84
+ @Test
85
+ fun `close during response flow - should fail with correct status on client` () {
86
+ val error = assertFailsWith<StatusException > {
87
+ val interceptor = interceptor {
88
+ proceed(it).map {
89
+ close(Status (StatusCode .UNAUTHENTICATED , " Close in response flow" ), GrpcTrailers ())
90
+ }
91
+ }
92
+ runGrpcTest(serverInterceptors = interceptor, test = ::unaryCall)
93
+ }
94
+
95
+ assertEquals(StatusCode .UNAUTHENTICATED , error.getStatus().statusCode)
96
+ assertContains(error.message!! , " Close in response flow" )
97
+ }
98
+
99
+ @Test
100
+ fun `close during onClose - should fail with correct status on client` () {
101
+ val error = assertFailsWith<StatusException > {
102
+ val interceptor = interceptor {
103
+ onClose { _, _ -> close(Status (StatusCode .UNAUTHENTICATED , " Close in onClose" ), GrpcTrailers ()) }
104
+ proceed(it)
105
+ }
106
+ runGrpcTest(serverInterceptors = interceptor, test = ::unaryCall)
107
+ }
108
+
109
+ assertEquals(StatusCode .UNAUTHENTICATED , error.getStatus().statusCode)
110
+ assertContains(error.message!! , " Close in onClose" )
111
+ }
112
+
42
113
private suspend fun unaryCall (grpcClient : GrpcClient ) {
43
114
val service = grpcClient.withService<EchoService >()
44
115
val response = service.UnaryEcho (EchoRequest { message = " Hello" })
@@ -48,16 +119,16 @@ class ServerInterceptorTest : GrpcProtoTest() {
48
119
49
120
50
121
private fun interceptor (
51
- block : ( ServerCallScope <Any , Any >, GrpcTrailers , Flow <Any >) -> Flow <Any >,
122
+ block : ServerCallScope <Any , Any >.( Flow <Any >) -> Flow <Any >,
52
123
): List <ServerInterceptor > {
53
124
return listOf (object : ServerInterceptor {
54
125
@Suppress(" UNCHECKED_CAST" )
55
- override fun <Req , Resp > intercept (
56
- scope : ServerCallScope <Req , Resp >,
57
- requestHeaders : GrpcTrailers ,
126
+ override fun <Req , Resp > ServerCallScope <Req , Resp >.intercept (
58
127
request : Flow <Req >,
59
128
): Flow <Resp > {
60
- return block(scope as ServerCallScope <Any , Any >, requestHeaders, request as Flow <Any >) as Flow <Resp >
129
+ with (this as ServerCallScope <Any , Any >) {
130
+ return block(request as Flow <Any >) as Flow <Resp >
131
+ }
61
132
}
62
133
})
63
134
}
0 commit comments