Skip to content

Commit 0f13e48

Browse files
author
Alexander Furer
committed
closes #258, closes #259
1 parent 2c4364b commit 0f13e48

File tree

7 files changed

+321
-72
lines changed

7 files changed

+321
-72
lines changed
Lines changed: 5 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
11
package org.lognet.springboot.grpc;
22

3-
import com.fasterxml.jackson.databind.JsonNode;
4-
import com.fasterxml.jackson.databind.node.ObjectNode;
53
import io.grpc.ServerInterceptor;
64
import io.grpc.examples.CalculatorGrpc;
75
import io.grpc.examples.CalculatorOuterClass;
86
import io.grpc.examples.GreeterGrpc;
97
import io.grpc.examples.GreeterOuterClass;
10-
import io.micrometer.prometheus.PrometheusConfig;
11-
import org.awaitility.Awaitility;
12-
import org.hamcrest.Matchers;
13-
import org.junit.Assert;
148
import org.junit.Rule;
159
import org.junit.Test;
1610
import org.junit.runner.RunWith;
@@ -20,25 +14,15 @@
2014
import org.springframework.beans.factory.annotation.Qualifier;
2115
import org.springframework.boot.test.context.SpringBootTest;
2216
import org.springframework.boot.test.system.OutputCaptureRule;
23-
import org.springframework.boot.test.web.client.TestRestTemplate;
24-
import org.springframework.http.HttpStatus;
25-
import org.springframework.http.ResponseEntity;
2617
import org.springframework.test.context.ActiveProfiles;
2718
import org.springframework.test.context.junit4.SpringRunner;
2819

29-
import java.time.Duration;
30-
import java.util.Optional;
31-
import java.util.Spliterator;
32-
import java.util.Spliterators;
33-
import java.util.concurrent.Callable;
3420
import java.util.concurrent.ExecutionException;
35-
import java.util.stream.Stream;
36-
import java.util.stream.StreamSupport;
3721

3822
import static org.hamcrest.CoreMatchers.containsString;
23+
import static org.hamcrest.CoreMatchers.isA;
3924
import static org.hamcrest.CoreMatchers.not;
4025
import static org.hamcrest.MatcherAssert.assertThat;
41-
import static org.junit.Assert.assertEquals;
4226
import static org.junit.Assert.assertNotNull;
4327
import static org.junit.Assert.assertNull;
4428
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@@ -52,15 +36,12 @@
5236
"grpc.shutdownGrace=-1",
5337
"spring.main.web-application-type=servlet"
5438
})
55-
@ActiveProfiles({"disable-security", "measure"})
39+
@ActiveProfiles({"disable-security"})
5640

5741
public class DemoAppTest extends GrpcServerTestBase {
5842

59-
@Autowired
60-
private PrometheusConfig prometheusConfig;
6143

62-
@Autowired
63-
private TestRestTemplate restTemplate;
44+
6445

6546
@Rule
6647
public OutputCaptureRule outputCapture = new OutputCaptureRule();
@@ -72,7 +53,7 @@ public class DemoAppTest extends GrpcServerTestBase {
7253

7354

7455
@Test
75-
public void disabledServerTest() throws Throwable {
56+
public void disabledServerTest() {
7657
assertNotNull(grpcServerRunner);
7758
assertNull(grpcInprocessServerRunner);
7859
}
@@ -100,51 +81,16 @@ public void interceptorsTest() throws ExecutionException, InterruptedException {
10081
outputCapture.expect(containsString("I'm not Spring bean interceptor and still being invoked..."));
10182
}
10283

103-
@Test
104-
public void actuatorTest() throws ExecutionException, InterruptedException {
105-
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/env", String.class);
106-
assertEquals(HttpStatus.OK, response.getStatusCode());
107-
}
108-
10984

11085
@Test
11186
public void testDefaultConfigurer() {
112-
Assert.assertEquals("Default configurer should be picked up",
113-
context.getBean(GRpcServerBuilderConfigurer.class).getClass(),
114-
GRpcServerBuilderConfigurer.class);
87+
assertThat(context.getBean(GRpcServerBuilderConfigurer.class),isA(GRpcServerBuilderConfigurer.class));
11588
}
11689

11790

11891

11992

12093

12194

122-
@Override
123-
protected void afterGreeting() throws Exception {
12495

125-
126-
ResponseEntity<ObjectNode> metricsResponse = restTemplate.getForEntity("/actuator/metrics", ObjectNode.class);
127-
assertEquals(HttpStatus.OK, metricsResponse.getStatusCode());
128-
final String metricName = "grpc.server.calls";
129-
final Optional<String> containsGrpcServerCallsMetric = StreamSupport.stream(Spliterators.spliteratorUnknownSize(metricsResponse.getBody().withArray("names")
130-
.elements(), Spliterator.NONNULL), false)
131-
.map(JsonNode::asText)
132-
.filter(metricName::equals)
133-
.findFirst();
134-
assertThat("Should contain " + metricName,containsGrpcServerCallsMetric.isPresent());
135-
136-
137-
Callable<Long> getPrometheusMetrics = () -> {
138-
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/prometheus", String.class);
139-
assertEquals(HttpStatus.OK, response.getStatusCode());
140-
return Stream.of(response.getBody().split(System.lineSeparator()))
141-
.filter(s -> s.contains(metricName.replace('.','_')))
142-
.count();
143-
};
144-
145-
Awaitility
146-
.waitAtMost(Duration.ofMillis(prometheusConfig.step().toMillis() * 2))
147-
.until(getPrometheusMetrics,Matchers.greaterThan(0L));
148-
149-
}
15096
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package org.lognet.springboot.grpc.actuator;
2+
3+
import com.fasterxml.jackson.databind.JsonNode;
4+
import com.fasterxml.jackson.databind.node.ObjectNode;
5+
import com.jayway.jsonpath.Configuration;
6+
import com.jayway.jsonpath.DocumentContext;
7+
import com.jayway.jsonpath.JsonPath;
8+
import com.jayway.jsonpath.TypeRef;
9+
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
10+
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
11+
import io.micrometer.prometheus.PrometheusConfig;
12+
import org.awaitility.Awaitility;
13+
import org.hamcrest.Matchers;
14+
import org.junit.Test;
15+
import org.junit.runner.RunWith;
16+
import org.lognet.springboot.grpc.GrpcServerTestBase;
17+
import org.lognet.springboot.grpc.TestConfig;
18+
import org.lognet.springboot.grpc.demo.DemoApp;
19+
import org.springframework.beans.factory.annotation.Autowired;
20+
import org.springframework.boot.actuate.health.Status;
21+
import org.springframework.boot.test.context.SpringBootTest;
22+
import org.springframework.boot.test.web.client.TestRestTemplate;
23+
import org.springframework.http.HttpStatus;
24+
import org.springframework.http.ResponseEntity;
25+
import org.springframework.test.context.ActiveProfiles;
26+
import org.springframework.test.context.junit4.SpringRunner;
27+
28+
import java.time.Duration;
29+
import java.util.Optional;
30+
import java.util.Spliterator;
31+
import java.util.Spliterators;
32+
import java.util.concurrent.Callable;
33+
import java.util.concurrent.ExecutionException;
34+
import java.util.stream.Stream;
35+
import java.util.stream.StreamSupport;
36+
37+
import static org.hamcrest.CoreMatchers.is;
38+
import static org.hamcrest.MatcherAssert.assertThat;
39+
import static org.junit.Assert.assertEquals;
40+
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
41+
42+
/**
43+
* Created by alexf on 28-Jan-16.
44+
*/
45+
@RunWith(SpringRunner.class)
46+
@SpringBootTest(classes = {DemoApp.class, TestConfig.class}, webEnvironment = RANDOM_PORT
47+
, properties = {
48+
49+
"management.endpoint.health.show-details=always"
50+
, "management.endpoint.health.show-components=always"
51+
, "spring.main.web-application-type=servlet"
52+
})
53+
@ActiveProfiles({"disable-security", "measure"})
54+
public class ActuatorTest extends GrpcServerTestBase {
55+
56+
@Autowired
57+
private PrometheusConfig prometheusConfig;
58+
59+
@Autowired
60+
private TestRestTemplate restTemplate;
61+
62+
63+
@Test
64+
public void actuatorEnvTest() throws ExecutionException, InterruptedException {
65+
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/env", String.class);
66+
assertEquals(HttpStatus.OK, response.getStatusCode());
67+
}
68+
69+
@Test
70+
public void actuatorGrpcTest() throws ExecutionException, InterruptedException {
71+
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/grpc", String.class);
72+
assertEquals(HttpStatus.OK, response.getStatusCode());
73+
final DocumentContext json = JsonPath.parse(response.getBody(), Configuration.builder()
74+
.mappingProvider(new JacksonMappingProvider())
75+
.jsonProvider(new JacksonJsonProvider())
76+
.build());
77+
final String[] statuses = json.read("services.*name", new TypeRef<String[]>() {});
78+
assertThat(statuses,Matchers.arrayWithSize(Matchers.greaterThan(0)));
79+
for(String s:statuses) {
80+
assertThat(s, Matchers.not(Matchers.blankOrNullString()));
81+
}
82+
83+
final Integer port = json.read("port", Integer.class);
84+
assertThat(port,Matchers.greaterThan(0));
85+
}
86+
87+
@Test
88+
public void actuatorHealthTest() throws ExecutionException, InterruptedException {
89+
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/health", String.class);
90+
assertEquals(HttpStatus.OK, response.getStatusCode());
91+
92+
final DocumentContext json = JsonPath.parse(response.getBody(), Configuration.builder()
93+
.mappingProvider(new JacksonMappingProvider())
94+
.jsonProvider(new JacksonJsonProvider())
95+
.build());
96+
final String[] statuses = json.read("components.grpc.components.*status", new TypeRef<String[]>() {
97+
});
98+
assertThat(statuses,Matchers.arrayWithSize(Matchers.greaterThan(0)));
99+
for(String s:statuses) {
100+
assertThat(s, is(Status.UP.getCode()));
101+
}
102+
103+
}
104+
105+
@Override
106+
protected void afterGreeting() throws Exception {
107+
108+
109+
ResponseEntity<ObjectNode> metricsResponse = restTemplate.getForEntity("/actuator/metrics", ObjectNode.class);
110+
assertEquals(HttpStatus.OK, metricsResponse.getStatusCode());
111+
final String metricName = "grpc.server.calls";
112+
final Optional<String> containsGrpcServerCallsMetric = StreamSupport.stream(Spliterators.spliteratorUnknownSize(metricsResponse.getBody().withArray("names")
113+
.elements(), Spliterator.NONNULL), false)
114+
.map(JsonNode::asText)
115+
.filter(metricName::equals)
116+
.findFirst();
117+
assertThat("Should contain " + metricName, containsGrpcServerCallsMetric.isPresent());
118+
119+
120+
Callable<Long> getPrometheusMetrics = () -> {
121+
ResponseEntity<String> response = restTemplate.getForEntity("/actuator/prometheus", String.class);
122+
assertEquals(HttpStatus.OK, response.getStatusCode());
123+
return Stream.of(response.getBody().split(System.lineSeparator()))
124+
.filter(s -> s.contains(metricName.replace('.', '_')))
125+
.count();
126+
};
127+
128+
Awaitility
129+
.waitAtMost(Duration.ofMillis(prometheusConfig.step().toMillis() * 2))
130+
.until(getPrometheusMetrics, Matchers.greaterThan(0L));
131+
132+
}
133+
134+
135+
}

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import java.io.IOException;
3333
import java.util.ArrayList;
3434
import java.util.List;
35+
import java.util.Set;
3536
import java.util.concurrent.CountDownLatch;
3637
import java.util.concurrent.ExecutionException;
3738
import java.util.concurrent.TimeUnit;
@@ -58,19 +59,11 @@ public class CustomManagedHealthStatusServiceTest extends GrpcServerTestBase {
5859
static class Cfg {
5960
@GRpcService
6061
static class MyCustomHealthStatusService extends DefaultHealthStatusService {
61-
@Getter
62-
private final ArrayList<String> registeredServices = new ArrayList<>();
62+
6363

6464
@Getter
6565
private final ArrayList<String> checkedServices = new ArrayList<>();
6666

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-
}
7467

7568
@Override
7669
public void check(HealthCheckRequest request, StreamObserver<HealthCheckResponse> responseObserver) {
@@ -99,10 +92,11 @@ public void grpcHealthProbeTest() throws InterruptedException, IOException {
9992

10093
Cfg.MyCustomHealthStatusService healthManager = (Cfg.MyCustomHealthStatusService) healthStatusManager;
10194

102-
assertThat(healthManager.getRegisteredServices(), hasSize(greaterThan(0)));
95+
final Set<String> registeredServices = healthManager.statuses().keySet();
96+
assertThat(registeredServices , hasSize(greaterThan(0)));
10397
final List<String> discovered = discoverServicesNames();
10498

105-
assertThat(discovered, containsInAnyOrder(healthManager.getRegisteredServices().toArray()));
99+
assertThat(discovered, containsInAnyOrder(registeredServices.toArray()));
106100

107101
String addressParameter = String.format("-addr=%s:%d",
108102
new InetUtils(new InetUtilsProperties()).findFirstNonLoopbackHostInfo().getIpAddress(),

0 commit comments

Comments
 (0)