Skip to content

Commit 93c37e5

Browse files
author
Alexander Furer
committed
closes #98
1 parent 38dcfbc commit 93c37e5

File tree

3 files changed

+161
-46
lines changed

3 files changed

+161
-46
lines changed

grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/DemoAppTest.java

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@
77
import io.grpc.examples.CalculatorOuterClass;
88
import io.grpc.examples.GreeterGrpc;
99
import io.grpc.examples.GreeterOuterClass;
10-
import io.grpc.reflection.v1alpha.ServerReflectionGrpc;
11-
import io.grpc.reflection.v1alpha.ServerReflectionRequest;
12-
import io.grpc.reflection.v1alpha.ServerReflectionResponse;
13-
import io.grpc.reflection.v1alpha.ServiceResponse;
14-
import io.grpc.stub.StreamObserver;
1510
import io.micrometer.prometheus.PrometheusConfig;
1611
import org.awaitility.Awaitility;
1712
import org.hamcrest.Matchers;
@@ -32,23 +27,18 @@
3227
import org.springframework.test.context.junit4.SpringRunner;
3328

3429
import java.time.Duration;
35-
import java.util.ArrayList;
36-
import java.util.List;
3730
import java.util.Optional;
3831
import java.util.Spliterator;
3932
import java.util.Spliterators;
4033
import java.util.concurrent.Callable;
41-
import java.util.concurrent.CountDownLatch;
4234
import java.util.concurrent.ExecutionException;
43-
import java.util.concurrent.TimeUnit;
4435
import java.util.stream.Stream;
4536
import java.util.stream.StreamSupport;
4637

4738
import static org.hamcrest.CoreMatchers.containsString;
4839
import static org.hamcrest.CoreMatchers.not;
4940
import static org.hamcrest.MatcherAssert.assertThat;
5041
import static org.junit.Assert.assertEquals;
51-
import static org.junit.Assert.assertFalse;
5242
import static org.junit.Assert.assertNotNull;
5343
import static org.junit.Assert.assertNull;
5444
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@@ -58,7 +48,7 @@
5848
*/
5949
@RunWith(SpringRunner.class)
6050
@SpringBootTest(classes = {DemoApp.class, TestConfig.class}, webEnvironment = RANDOM_PORT
61-
, properties = {"grpc.enableReflection=true",
51+
, properties = {
6252
"grpc.shutdownGrace=-1",
6353
"spring.main.web-application-type=servlet"
6454
})
@@ -124,34 +114,7 @@ public void testDefaultConfigurer() {
124114
GRpcServerBuilderConfigurer.class);
125115
}
126116

127-
@Test
128-
public void testReflection() throws InterruptedException {
129-
List<String> discoveredServiceNames = new ArrayList<>();
130-
ServerReflectionRequest request = ServerReflectionRequest.newBuilder().setListServices("services").setHost("localhost").build();
131-
CountDownLatch latch = new CountDownLatch(1);
132-
ServerReflectionGrpc.newStub(channel).serverReflectionInfo(new StreamObserver<ServerReflectionResponse>() {
133-
@Override
134-
public void onNext(ServerReflectionResponse value) {
135-
List<ServiceResponse> serviceList = value.getListServicesResponse().getServiceList();
136-
for (ServiceResponse serviceResponse : serviceList) {
137-
discoveredServiceNames.add(serviceResponse.getName());
138-
}
139-
}
140-
141-
@Override
142-
public void onError(Throwable t) {
143-
144-
}
145-
146-
@Override
147-
public void onCompleted() {
148-
latch.countDown();
149-
}
150-
}).onNext(request);
151-
152-
latch.await(3, TimeUnit.SECONDS);
153-
assertFalse(discoveredServiceNames.isEmpty());
154-
}
117+
155118

156119

157120

grpc-spring-boot-starter-demo/src/test/java/org/lognet/springboot/grpc/health/CustomManagedHealthStatusServiceTest.java

Lines changed: 141 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
import io.grpc.health.v1.HealthCheckRequest;
55
import io.grpc.health.v1.HealthCheckResponse;
66
import io.grpc.health.v1.HealthGrpc;
7+
import io.grpc.reflection.v1alpha.ServerReflectionGrpc;
8+
import io.grpc.reflection.v1alpha.ServerReflectionRequest;
9+
import io.grpc.reflection.v1alpha.ServerReflectionResponse;
10+
import io.grpc.reflection.v1alpha.ServiceResponse;
11+
import io.grpc.stub.StreamObserver;
12+
import lombok.Getter;
13+
import lombok.extern.slf4j.Slf4j;
14+
import org.hamcrest.Matchers;
15+
import org.junit.Rule;
716
import org.junit.Test;
817
import org.junit.runner.RunWith;
918
import org.lognet.springboot.grpc.GRpcService;
@@ -13,26 +22,64 @@
1322
import org.springframework.boot.test.context.SpringBootTest;
1423
import org.springframework.boot.test.context.TestConfiguration;
1524
import org.springframework.boot.test.mock.mockito.SpyBean;
25+
import org.springframework.cloud.commons.util.InetUtils;
26+
import org.springframework.cloud.commons.util.InetUtilsProperties;
1627
import org.springframework.test.annotation.DirtiesContext;
1728
import org.springframework.test.context.ActiveProfiles;
1829
import org.springframework.test.context.junit4.SpringRunner;
30+
import org.testcontainers.containers.Container;
1931

32+
import java.io.IOException;
33+
import java.util.ArrayList;
34+
import java.util.List;
35+
import java.util.concurrent.CountDownLatch;
2036
import java.util.concurrent.ExecutionException;
37+
import java.util.concurrent.TimeUnit;
2138

2239
import static org.hamcrest.MatcherAssert.assertThat;
40+
import static org.hamcrest.Matchers.containsInAnyOrder;
41+
import static org.hamcrest.Matchers.greaterThan;
42+
import static org.hamcrest.Matchers.hasSize;
2343
import static org.hamcrest.Matchers.is;
2444
import static org.hamcrest.Matchers.isA;
2545
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE;
2646

2747
@RunWith(SpringRunner.class)
28-
@SpringBootTest(classes = {DemoApp.class, CustomManagedHealthStatusServiceTest.Cfg.class}, webEnvironment = NONE)
48+
@SpringBootTest(classes = {DemoApp.class, CustomManagedHealthStatusServiceTest.Cfg.class}, webEnvironment = NONE,
49+
properties = "grpc.enableReflection=true")
2950
@ActiveProfiles("disable-security")
30-
51+
@Slf4j
3152
public class CustomManagedHealthStatusServiceTest extends GrpcServerTestBase {
53+
54+
@Rule
55+
public GrpcHealthProbeContainer grpcHealthProbe = new GrpcHealthProbeContainer();
56+
3257
@TestConfiguration
33-
static class Cfg{
58+
static class Cfg {
3459
@GRpcService
35-
static class MyCustomHealthStatusService extends DefaultHealthStatusService {}
60+
static class MyCustomHealthStatusService extends DefaultHealthStatusService {
61+
@Getter
62+
private final ArrayList<String> registeredServices = new ArrayList<>();
63+
64+
@Getter
65+
private final ArrayList<String> checkedServices = new ArrayList<>();
66+
67+
@Override
68+
public void setStatus(String service, HealthCheckResponse.ServingStatus status) {
69+
synchronized (registeredServices) {
70+
registeredServices.add(service);
71+
}
72+
super.setStatus(service, status);
73+
}
74+
75+
@Override
76+
public void check(HealthCheckRequest request, StreamObserver<HealthCheckResponse> responseObserver) {
77+
synchronized (checkedServices) {
78+
checkedServices.add(request.getService());
79+
}
80+
super.check(request, responseObserver);
81+
}
82+
}
3683

3784
}
3885

@@ -42,7 +89,52 @@ static class MyCustomHealthStatusService extends DefaultHealthStatusService {}
4289
@Test
4390
@DirtiesContext
4491
public void contextLoads() {
45-
assertThat(healthStatusManager,isA(Cfg.MyCustomHealthStatusService.class));
92+
assertThat(healthStatusManager, isA(Cfg.MyCustomHealthStatusService.class));
93+
}
94+
95+
@Test
96+
@DirtiesContext
97+
public void grpcHealthProbeTest() throws InterruptedException, IOException {
98+
99+
100+
Cfg.MyCustomHealthStatusService healthManager = (Cfg.MyCustomHealthStatusService) healthStatusManager;
101+
102+
assertThat(healthManager.getRegisteredServices(), hasSize(greaterThan(0)));
103+
final List<String> discovered = discoverServicesNames();
104+
105+
assertThat(discovered, containsInAnyOrder(healthManager.getRegisteredServices().toArray()));
106+
107+
String addressParameter = String.format("-addr=%s:%d",
108+
new InetUtils(new InetUtilsProperties()).findFirstNonLoopbackHostInfo().getIpAddress(),
109+
getPort());
110+
111+
112+
ArrayList<String> allServices = new ArrayList<>(discovered);
113+
allServices.add("");
114+
115+
for (String serviceName : allServices) {
116+
final Container.ExecResult execResult = grpcHealthProbe
117+
.execInContainer("/bin/grpc_health_probe",
118+
addressParameter,
119+
"-service=" + serviceName
120+
);
121+
122+
assertThat(execResult.getExitCode(), is(0));
123+
124+
}
125+
assertThat(healthManager.getCheckedServices(), containsInAnyOrder(allServices.toArray()));
126+
127+
128+
final Container.ExecResult execResult = grpcHealthProbe
129+
.execInContainer("/bin/grpc_health_probe",
130+
addressParameter,
131+
"-service=blah"
132+
);
133+
134+
assertThat(execResult.getExitCode(), Matchers.not(0));
135+
136+
137+
46138
}
47139

48140
@Test
@@ -54,7 +146,49 @@ public void testHealthCheck() throws ExecutionException, InterruptedException {
54146

55147
assertThat(servingStatus, is(HealthCheckResponse.ServingStatus.SERVING));
56148

57-
Mockito.verify(healthStatusManager,Mockito.atLeast(1))
58-
.setStatus(Mockito.any(String.class),Mockito.eq(HealthCheckResponse.ServingStatus.SERVING));
149+
Mockito.verify(healthStatusManager, Mockito.atLeast(1))
150+
.setStatus(Mockito.any(String.class), Mockito.eq(HealthCheckResponse.ServingStatus.SERVING));
151+
}
152+
153+
@Test
154+
public void testReflection() throws InterruptedException {
155+
156+
assertThat(discoverServicesNames(), Matchers.not(Matchers.empty()));
157+
}
158+
159+
private List<String> discoverServicesNames() throws InterruptedException {
160+
List<String> discoveredServiceNames = new ArrayList<>();
161+
ServerReflectionRequest request = ServerReflectionRequest.newBuilder().setListServices("services").setHost("localhost").build();
162+
CountDownLatch latch = new CountDownLatch(1);
163+
ServerReflectionGrpc.newStub(channel).serverReflectionInfo(new StreamObserver<ServerReflectionResponse>() {
164+
@Override
165+
public void onNext(ServerReflectionResponse value) {
166+
List<ServiceResponse> serviceList = value.getListServicesResponse().getServiceList();
167+
for (ServiceResponse serviceResponse : serviceList) {
168+
169+
final String serviceName = serviceResponse.getName();
170+
if (
171+
!serviceName.equals(ServerReflectionGrpc.getServiceDescriptor().getName()) &&
172+
!serviceName.equals(HealthGrpc.getServiceDescriptor().getName())
173+
) {
174+
175+
discoveredServiceNames.add(serviceName);
176+
}
177+
}
178+
}
179+
180+
@Override
181+
public void onError(Throwable t) {
182+
183+
}
184+
185+
@Override
186+
public void onCompleted() {
187+
latch.countDown();
188+
}
189+
}).onNext(request);
190+
191+
latch.await(3, TimeUnit.SECONDS);
192+
return discoveredServiceNames;
59193
}
60194
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.lognet.springboot.grpc.health;
2+
3+
import lombok.extern.slf4j.Slf4j;
4+
import org.testcontainers.containers.GenericContainer;
5+
6+
@Slf4j
7+
public class GrpcHealthProbeContainer extends GenericContainer<GrpcHealthProbeContainer> {
8+
public GrpcHealthProbeContainer() {
9+
super("slyncio/grpc-health-probe");
10+
withLogConsumer(f -> log.info(f.getUtf8String()))
11+
.withCreateContainerCmdModifier(cmd ->
12+
cmd.withStdinOpen(true)
13+
.withEntrypoint("sh")
14+
);
15+
}
16+
17+
18+
}

0 commit comments

Comments
 (0)