From 4c0ecbaa38ca5da23f4f7e1370ca7f3a37e09035 Mon Sep 17 00:00:00 2001 From: sullis Date: Tue, 21 Apr 2026 10:17:34 -0700 Subject: [PATCH] Add gzip compression tests --- .../grpc/GrpcGzipCompressionTest.java | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/GrpcGzipCompressionTest.java diff --git a/grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/GrpcGzipCompressionTest.java b/grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/GrpcGzipCompressionTest.java new file mode 100644 index 00000000..6bd9c233 --- /dev/null +++ b/grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/GrpcGzipCompressionTest.java @@ -0,0 +1,125 @@ +package org.lognet.springboot.grpc; + +import io.grpc.CallOptions; +import io.grpc.Channel; +import io.grpc.ClientCall; +import io.grpc.ClientInterceptor; +import io.grpc.ForwardingClientCall; +import io.grpc.ForwardingClientCallListener; +import io.grpc.Metadata; +import io.grpc.MethodDescriptor; +import io.grpc.ServerCall; +import io.grpc.ServerCallHandler; +import io.grpc.ServerInterceptor; +import io.grpc.examples.GreeterGrpc; +import io.grpc.examples.GreeterOuterClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.lognet.springboot.grpc.demo.DemoApp; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {DemoApp.class, TestConfig.class, GrpcGzipCompressionTest.CompressionTestConfig.class}, + webEnvironment = RANDOM_PORT, + properties = { + "grpc.shutdownGrace=-1", + "spring.main.web-application-type=servlet" + }) +@ActiveProfiles("disable-security") +public class GrpcGzipCompressionTest extends GrpcServerTestBase { + + private static final Metadata.Key GRPC_ENCODING_KEY = + Metadata.Key.of("grpc-encoding", Metadata.ASCII_STRING_MARSHALLER); + + private static final AtomicReference serverReceivedEncoding = new AtomicReference<>(); + private static final AtomicReference clientReceivedEncoding = new AtomicReference<>(); + + @TestConfiguration + public static class CompressionTestConfig { + + @Bean + @GRpcGlobalInterceptor + public ServerInterceptor compressionCapturingInterceptor() { + return new ServerInterceptor() { + @Override + public ServerCall.Listener interceptCall( + ServerCall call, Metadata headers, ServerCallHandler next) { + serverReceivedEncoding.set(headers.get(GRPC_ENCODING_KEY)); + call.setCompression("gzip"); + return next.startCall(call, headers); + } + }; + } + } + + @Test + public void gzipCompressedRequestShouldSucceed() throws Exception { + serverReceivedEncoding.set(null); + clientReceivedEncoding.set(null); + + GreeterGrpc.GreeterFutureStub stub = GreeterGrpc.newFutureStub(selectedChanel) + .withCompression("gzip"); + + GreeterOuterClass.HelloRequest request = GreeterOuterClass.HelloRequest.newBuilder() + .setName(name) + .build(); + + String reply = stub.sayHello(request).get().getMessage(); + + assertNotNull("Reply should not be null", reply); + assertTrue("Reply should contain the name", reply.contains(name)); + assertEquals("Server should receive gzip encoding header", "gzip", serverReceivedEncoding.get()); + } + + @Test + public void gzipCompressedResponseShouldBeDecodable() throws Exception { + clientReceivedEncoding.set(null); + + ClientInterceptor encodingCaptureInterceptor = new ClientInterceptor() { + @Override + public ClientCall interceptCall( + MethodDescriptor method, CallOptions callOptions, Channel next) { + return new ForwardingClientCall.SimpleForwardingClientCall( + next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener( + responseListener) { + @Override + public void onHeaders(Metadata headers) { + clientReceivedEncoding.set(headers.get(GRPC_ENCODING_KEY)); + super.onHeaders(headers); + } + }, headers); + } + }; + } + }; + + Channel interceptedChannel = io.grpc.ClientInterceptors.intercept(selectedChanel, encodingCaptureInterceptor); + + GreeterGrpc.GreeterFutureStub stub = GreeterGrpc.newFutureStub(interceptedChannel) + .withCompression("gzip"); + + GreeterOuterClass.HelloRequest request = GreeterOuterClass.HelloRequest.newBuilder() + .setName(name) + .build(); + + String reply = stub.sayHello(request).get().getMessage(); + + assertNotNull("Reply should not be null", reply); + assertTrue("Reply should contain the name", reply.contains(name)); + assertEquals("Response should be gzip-encoded", "gzip", clientReceivedEncoding.get()); + } +}