diff --git a/stub/src/test/java/io/grpc/kotlin/ServerCallsTest.kt b/stub/src/test/java/io/grpc/kotlin/ServerCallsTest.kt index d47a4587..9ed61a66 100644 --- a/stub/src/test/java/io/grpc/kotlin/ServerCallsTest.kt +++ b/stub/src/test/java/io/grpc/kotlin/ServerCallsTest.kt @@ -1168,4 +1168,56 @@ class ServerCallsTest : AbstractCallsTest() { assertThat(statusCause!!.stackTraceToString()).contains("internalServerCall") } + @Test + fun testPropagateStackTraceForNonStatusExceptionWithStatusExceptionCause() = runBlocking { + val thrownStatusCause = CompletableDeferred() + + val serverImpl = object : GreeterCoroutineImplBase() { + override suspend fun sayHello(request: HelloRequest): HelloReply { + internalServerCall() + } + + private fun internalServerCall(): Nothing { + val exception = Exception("causal exception", Status.INTERNAL.asException()) + thrownStatusCause.complete(exception) + throw exception + } + } + + val receivedStatusCause = CompletableDeferred() + + val interceptor = object : ServerInterceptor { + override fun interceptCall( + call: ServerCall, + requestHeaders: Metadata, + next: ServerCallHandler + ): ServerCall.Listener = + next.startCall( + object : ForwardingServerCall.SimpleForwardingServerCall(call) { + override fun close(status: Status, trailers: Metadata) { + receivedStatusCause.complete(status.cause) + super.close(status, trailers) + } + }, + requestHeaders + ) + } + + val channel = makeChannel(serverImpl, interceptor) + + val stub = GreeterGrpc.newBlockingStub(channel) + val clientException = assertThrows { + stub.sayHello(helloRequest("")) + } + + // the exception should not propagate to the client + assertThat(clientException.cause).isNull() + + assertThat(clientException.status.code).isEqualTo(Status.Code.INTERNAL) + val statusCause = receivedStatusCause.await() + // but the exception should propagate to server interceptors, with stack trace intact + assertThat(statusCause).isEqualTo(thrownStatusCause.await()) + assertThat(statusCause!!.stackTraceToString()).contains("internalServerCall") + } + }