@@ -1168,4 +1168,56 @@ class ServerCallsTest : AbstractCallsTest() {
11681168 assertThat(statusCause!! .stackTraceToString()).contains(" internalServerCall" )
11691169 }
11701170
1171+ @Test
1172+ fun testPropagateStackTraceForNonStatusExceptionWithStatusExceptionCause () = runBlocking {
1173+ val thrownStatusCause = CompletableDeferred <Throwable ?>()
1174+
1175+ val serverImpl = object : GreeterCoroutineImplBase () {
1176+ override suspend fun sayHello (request : HelloRequest ): HelloReply {
1177+ internalServerCall()
1178+ }
1179+
1180+ private fun internalServerCall (): Nothing {
1181+ val exception = Exception (" causal exception" , Status .INTERNAL .asException())
1182+ thrownStatusCause.complete(exception)
1183+ throw exception
1184+ }
1185+ }
1186+
1187+ val receivedStatusCause = CompletableDeferred <Throwable ?>()
1188+
1189+ val interceptor = object : ServerInterceptor {
1190+ override fun <ReqT , RespT > interceptCall (
1191+ call : ServerCall <ReqT , RespT >,
1192+ requestHeaders : Metadata ,
1193+ next : ServerCallHandler <ReqT , RespT >
1194+ ): ServerCall .Listener <ReqT > =
1195+ next.startCall(
1196+ object : ForwardingServerCall .SimpleForwardingServerCall <ReqT , RespT >(call) {
1197+ override fun close (status : Status , trailers : Metadata ) {
1198+ receivedStatusCause.complete(status.cause)
1199+ super .close(status, trailers)
1200+ }
1201+ },
1202+ requestHeaders
1203+ )
1204+ }
1205+
1206+ val channel = makeChannel(serverImpl, interceptor)
1207+
1208+ val stub = GreeterGrpc .newBlockingStub(channel)
1209+ val clientException = assertThrows<StatusRuntimeException > {
1210+ stub.sayHello(helloRequest(" " ))
1211+ }
1212+
1213+ // the exception should not propagate to the client
1214+ assertThat(clientException.cause).isNull()
1215+
1216+ assertThat(clientException.status.code).isEqualTo(Status .Code .INTERNAL )
1217+ val statusCause = receivedStatusCause.await()
1218+ // but the exception should propagate to server interceptors, with stack trace intact
1219+ assertThat(statusCause).isEqualTo(thrownStatusCause.await())
1220+ assertThat(statusCause!! .stackTraceToString()).contains(" internalServerCall" )
1221+ }
1222+
11711223}
0 commit comments