Skip to content

Commit b4208ed

Browse files
committed
Attempt to fix flaky Zipkin test
Update `ZipkinHttpClientSenderTests` to use one mock server per test rather than a shared static. For some reason the mock server sometimes seems to get itself in a deadlock state which causes the client to fail with a `HttpTimeoutException`.
1 parent 91d150c commit b4208ed

File tree

1 file changed

+23
-55
lines changed
  • spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin

1 file changed

+23
-55
lines changed

spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/tracing/zipkin/ZipkinHttpClientSenderTests.java

+23-55
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@
2828

2929
import okhttp3.mockwebserver.MockResponse;
3030
import okhttp3.mockwebserver.MockWebServer;
31-
import okhttp3.mockwebserver.QueueDispatcher;
3231
import okhttp3.mockwebserver.RecordedRequest;
33-
import org.junit.jupiter.api.AfterAll;
34-
import org.junit.jupiter.api.BeforeAll;
3532
import org.junit.jupiter.api.BeforeEach;
3633
import org.junit.jupiter.api.Test;
3734
import zipkin2.reporter.BytesMessageSender;
@@ -52,32 +49,23 @@
5249
*/
5350
class ZipkinHttpClientSenderTests extends ZipkinHttpSenderTests {
5451

55-
private static ClearableDispatcher dispatcher;
52+
private MockWebServer mockBackEnd;
5653

57-
private static MockWebServer mockBackEnd;
58-
59-
static String zipkinUrl;
60-
61-
@BeforeAll
62-
static void beforeAll() throws IOException {
63-
dispatcher = new ClearableDispatcher();
64-
mockBackEnd = new MockWebServer();
65-
mockBackEnd.setDispatcher(dispatcher);
66-
mockBackEnd.start();
67-
zipkinUrl = mockBackEnd.url("/api/v2/spans").toString();
68-
}
69-
70-
@AfterAll
71-
static void afterAll() throws IOException {
72-
mockBackEnd.shutdown();
73-
}
54+
private String zipkinUrl;
7455

7556
@Override
7657
@BeforeEach
7758
void beforeEach() throws Exception {
59+
this.mockBackEnd = new MockWebServer();
60+
this.mockBackEnd.start();
61+
this.zipkinUrl = this.mockBackEnd.url("/api/v2/spans").toString();
7862
super.beforeEach();
79-
clearResponses();
80-
clearRequests();
63+
}
64+
65+
@Override
66+
void afterEach() throws IOException {
67+
super.afterEach();
68+
this.mockBackEnd.shutdown();
8169
}
8270

8371
@Override
@@ -92,12 +80,12 @@ ZipkinHttpClientSender createSender(Encoding encoding, Duration timeout) {
9280
ZipkinHttpClientSender createSender(HttpEndpointSupplier.Factory endpointSupplierFactory, Encoding encoding,
9381
Duration timeout) {
9482
HttpClient httpClient = HttpClient.newBuilder().connectTimeout(timeout).build();
95-
return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, zipkinUrl, httpClient, timeout);
83+
return new ZipkinHttpClientSender(encoding, endpointSupplierFactory, this.zipkinUrl, httpClient, timeout);
9684
}
9785

9886
@Test
9987
void sendShouldSendSpansToZipkin() throws IOException, InterruptedException {
100-
mockBackEnd.enqueue(new MockResponse());
88+
this.mockBackEnd.enqueue(new MockResponse());
10189
List<byte[]> encodedSpans = List.of(toByteArray("span1"), toByteArray("span2"));
10290
this.sender.send(encodedSpans);
10391
requestAssertions((request) -> {
@@ -109,7 +97,7 @@ void sendShouldSendSpansToZipkin() throws IOException, InterruptedException {
10997

11098
@Test
11199
void sendShouldSendSpansToZipkinInProto3() throws IOException, InterruptedException {
112-
mockBackEnd.enqueue(new MockResponse());
100+
this.mockBackEnd.enqueue(new MockResponse());
113101
List<byte[]> encodedSpans = List.of(toByteArray("span1"), toByteArray("span2"));
114102
try (BytesMessageSender sender = createSender(Encoding.PROTO3, Duration.ofSeconds(10))) {
115103
sender.send(encodedSpans);
@@ -127,22 +115,22 @@ void sendShouldSendSpansToZipkinInProto3() throws IOException, InterruptedExcept
127115
*/
128116
@Test
129117
void sendUsesDynamicEndpoint() throws Exception {
130-
mockBackEnd.enqueue(new MockResponse());
131-
mockBackEnd.enqueue(new MockResponse());
132-
try (TestHttpEndpointSupplier httpEndpointSupplier = new TestHttpEndpointSupplier(zipkinUrl)) {
118+
this.mockBackEnd.enqueue(new MockResponse());
119+
this.mockBackEnd.enqueue(new MockResponse());
120+
try (TestHttpEndpointSupplier httpEndpointSupplier = new TestHttpEndpointSupplier(this.zipkinUrl)) {
133121
try (BytesMessageSender sender = createSender((endpoint) -> httpEndpointSupplier, Encoding.JSON,
134122
Duration.ofSeconds(10))) {
135123
sender.send(Collections.emptyList());
136124
sender.send(Collections.emptyList());
137125
}
138-
assertThat(mockBackEnd.takeRequest().getPath()).endsWith("/1");
139-
assertThat(mockBackEnd.takeRequest().getPath()).endsWith("/2");
126+
assertThat(this.mockBackEnd.takeRequest().getPath()).endsWith("/1");
127+
assertThat(this.mockBackEnd.takeRequest().getPath()).endsWith("/2");
140128
}
141129
}
142130

143131
@Test
144132
void sendShouldHandleHttpFailures() throws InterruptedException {
145-
mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
133+
this.mockBackEnd.enqueue(new MockResponse().setResponseCode(500));
146134
assertThatException().isThrownBy(() -> this.sender.send(Collections.emptyList()))
147135
.withMessageContaining("Expected HTTP status 2xx, got 500");
148136
requestAssertions((request) -> assertThat(request.getMethod()).isEqualTo("POST"));
@@ -154,7 +142,7 @@ void sendShouldCompressData() throws IOException, InterruptedException {
154142
// This is gzip compressed 10000 times 'a'
155143
byte[] compressed = Base64.getDecoder()
156144
.decode("H4sIAAAAAAAA/+3BMQ0AAAwDIKFLj/k3UR8NcA8AAAAAAAAAAAADUsAZfeASJwAA");
157-
mockBackEnd.enqueue(new MockResponse());
145+
this.mockBackEnd.enqueue(new MockResponse());
158146
this.sender.send(List.of(toByteArray(uncompressed)));
159147
requestAssertions((request) -> {
160148
assertThat(request.getMethod()).isEqualTo("POST");
@@ -168,35 +156,15 @@ void sendShouldCompressData() throws IOException, InterruptedException {
168156
void shouldTimeout() throws IOException {
169157
try (BytesMessageSender sender = createSender(Encoding.JSON, Duration.ofMillis(1))) {
170158
MockResponse response = new MockResponse().setResponseCode(200).setHeadersDelay(100, TimeUnit.MILLISECONDS);
171-
mockBackEnd.enqueue(response);
159+
this.mockBackEnd.enqueue(response);
172160
assertThatIOException().isThrownBy(() -> sender.send(Collections.emptyList()))
173161
.withMessageContaining("timed out");
174162
}
175163
}
176164

177165
private void requestAssertions(Consumer<RecordedRequest> assertions) throws InterruptedException {
178-
RecordedRequest request = mockBackEnd.takeRequest();
166+
RecordedRequest request = this.mockBackEnd.takeRequest();
179167
assertThat(request).satisfies(assertions);
180168
}
181169

182-
private static void clearRequests() throws InterruptedException {
183-
RecordedRequest request;
184-
do {
185-
request = mockBackEnd.takeRequest(0, TimeUnit.SECONDS);
186-
}
187-
while (request != null);
188-
}
189-
190-
private static void clearResponses() {
191-
dispatcher.clear();
192-
}
193-
194-
private static final class ClearableDispatcher extends QueueDispatcher {
195-
196-
void clear() {
197-
getResponseQueue().clear();
198-
}
199-
200-
}
201-
202170
}

0 commit comments

Comments
 (0)