From 825828955036fcda2ed7e9a382576d832107aa59 Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Fri, 22 Jan 2016 13:24:42 +0100 Subject: [PATCH] [#128] Added an integration test --- .../sample/SampleMessagingApplication.java | 5 ++++ .../src/main/java/sample/SampleService.java | 14 ++++++++- .../MessagingApplicationTests.java | 29 +++++++++++++++++-- .../java/tools/AbstractIntegrationTest.java | 19 +++++++++++- .../java/tools/RequestSendingRunnable.java | 14 ++++++--- .../java/integration/ZipkinStreamTests.java | 28 +++++++++++------- 6 files changed, 90 insertions(+), 19 deletions(-) diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java index 081068f44..dd8251d65 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleMessagingApplication.java @@ -60,6 +60,11 @@ public class SampleMessagingApplication { return msg; } + @RequestMapping("/foo") + public String foo() { + return "foo"; + } + @RequestMapping("/xform") public String xform() { String msg = "Hello"; diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java index 724f9e055..265567de8 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/main/java/sample/SampleService.java @@ -18,9 +18,13 @@ package sample; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.embedded.EmbeddedServletContainerInitializedEvent; +import org.springframework.context.ApplicationListener; import org.springframework.integration.annotation.MessageEndpoint; import org.springframework.integration.annotation.ServiceActivator; import org.springframework.messaging.Message; +import org.springframework.web.client.RestTemplate; /** * @author Dave Syer @@ -28,11 +32,19 @@ import org.springframework.messaging.Message; */ @MessageEndpoint @Slf4j -public class SampleService { +public class SampleService implements + ApplicationListener { + @Autowired private RestTemplate restTemplate; + private int port; @ServiceActivator(inputChannel="messages") public void log(Message message) { log.info("Received: " + message); + this.restTemplate.getForObject("http://localhost:" + this.port + "/foo", String.class); } + @Override public void onApplicationEvent( + EmbeddedServletContainerInitializedEvent event) { + this.port = event.getEmbeddedServletContainer().getPort(); + } } diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java index a2a325cb7..b0d16d0a3 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-messaging/src/test/java/integration/MessagingApplicationTests.java @@ -29,8 +29,10 @@ import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import sample.SampleMessagingApplication; import tools.AbstractIntegrationTest; +import zipkin.Span; import java.util.Collection; +import java.util.Optional; import java.util.Random; import static org.assertj.core.api.BDDAssertions.then; @@ -51,7 +53,7 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { } @Test - public void should_propagate_spans_for_messaging() { + public void should_have_passed_trace_id_when_message_is_about_to_be_sent() { long traceId = new Random().nextLong(); await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId)); @@ -62,7 +64,20 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { } @Test - public void should_propagate_spans_for_messaging_with_async() { + public void should_have_passed_trace_id_and_generate_new_span_id_when_message_is_about_to_be_sent() { + long traceId = new Random().nextLong(); + long spanId = new Random().nextLong(); + + await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/", traceId, spanId)); + + await().until(() -> { + thenAllSpansHaveTraceIdEqualTo(traceId); + thenTheLastSpansParentHasIdEqualToFirstSpansId(); + }); + } + + @Test + public void should_have_passed_trace_id_with_annotations_in_async_thread_when_message_is_about_to_be_sent() { long traceId = new Random().nextLong(); await().until(httpMessageWithTraceIdInHeadersIsSuccessfullySent(sampleAppUrl + "/xform", traceId)); @@ -84,6 +99,16 @@ public class MessagingApplicationTests extends AbstractIntegrationTest { then(this.integrationTestSpanCollector.hashedSpans.stream().allMatch(span -> span.traceId == traceId)).isTrue(); } + private void thenTheLastSpansParentHasIdEqualToFirstSpansId() { + Optional firstSpan = this.integrationTestSpanCollector.hashedSpans.stream() + .filter(span -> "http/".equals(span.name) && span.parentId != null).findFirst(); + Optional lastSpan = this.integrationTestSpanCollector.hashedSpans.stream() + .filter(span -> "http/foo".equals(span.name)).findFirst(); + then(firstSpan.isPresent()).isTrue(); + then(lastSpan.isPresent()).isTrue(); + then(lastSpan.get().parentId).isEqualTo(firstSpan.get().id); + } + @Configuration public static class IntegrationSpanCollectorConfig { @Bean diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java index c639ed697..5a68fafb3 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/AbstractIntegrationTest.java @@ -18,6 +18,9 @@ package tools; import com.jayway.awaitility.Awaitility; import com.jayway.awaitility.core.ConditionFactory; import lombok.extern.slf4j.Slf4j; +import org.junit.After; +import org.junit.Before; +import org.springframework.cloud.sleuth.trace.SpanContextHolder; import org.springframework.http.*; import org.springframework.web.client.RestTemplate; import zipkin.Codec; @@ -40,6 +43,16 @@ public abstract class AbstractIntegrationTest { protected static int timeout = 20; protected RestTemplate restTemplate = new AssertingRestTemplate(); + @Before + public void clearSpanBefore() { + SpanContextHolder.removeCurrentSpan(); + } + + @After + public void clearSpanAfter() { + SpanContextHolder.removeCurrentSpan(); + } + public static ConditionFactory await() { return Awaitility.await().pollInterval(pollInterval, SECONDS).atMost(timeout, SECONDS); } @@ -102,7 +115,11 @@ public abstract class AbstractIntegrationTest { } protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId) { - return new RequestSendingRunnable(this.restTemplate, endpoint, traceId); + return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, null); + } + + protected Runnable httpMessageWithTraceIdInHeadersIsSuccessfullySent(String endpoint, long traceId, Long spanId) { + return new RequestSendingRunnable(this.restTemplate, endpoint, traceId, spanId); } protected Runnable allSpansWereRegisteredInZipkinWithTraceIdEqualTo(long traceId) { diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java index 2c9871c8b..677522e37 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-test-core/src/main/java/tools/RequestSendingRunnable.java @@ -25,6 +25,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import java.net.URI; +import java.util.Random; import static org.assertj.core.api.BDDAssertions.then; @@ -39,25 +40,30 @@ public class RequestSendingRunnable implements Runnable { private final RestTemplate restTemplate; private final String url; private final long traceId; + private final Random random = new Random(); + private final long spanId; - public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId) { + public RequestSendingRunnable(RestTemplate restTemplate, String url, long traceId, + Long spanId) { this.restTemplate = restTemplate; this.url = url; this.traceId = traceId; + this.spanId = spanId != null ? spanId : this.random.nextLong(); } @Override public void run() { log.info("Sending the request to url [{}] with trace id in headers [{}]", this.url, this.traceId); ResponseEntity responseEntity = - this.restTemplate.exchange(requestWithTraceId(this.traceId), String.class); + this.restTemplate.exchange(requestWithTraceId(), String.class); then(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); log.info("Received the following response [{}]", responseEntity); } - private RequestEntity requestWithTraceId(long traceId) { + private RequestEntity requestWithTraceId() { HttpHeaders headers = new HttpHeaders(); - headers.add(Span.TRACE_ID_NAME, Span.toHex(traceId)); + headers.add(Span.TRACE_ID_NAME, Span.toHex(this.traceId)); + headers.add(Span.SPAN_ID_NAME, Span.toHex(this.spanId)); URI uri = URI.create(this.url); RequestEntity requestEntity = new RequestEntity<>(headers, HttpMethod.GET, uri); log.info("Request [" + requestEntity + "] is ready"); diff --git a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java index b83abba32..4381584bc 100644 --- a/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java +++ b/spring-cloud-sleuth-samples/spring-cloud-sleuth-sample-zipkin-stream/src/test/java/integration/ZipkinStreamTests.java @@ -16,7 +16,7 @@ package integration; import example.ZipkinStreamServerApplication; -import lombok.SneakyThrows; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -30,6 +30,7 @@ import org.springframework.cloud.sleuth.stream.SleuthSink; import org.springframework.cloud.sleuth.stream.Spans; import org.springframework.cloud.stream.test.binder.TestSupportBinderAutoConfiguration; import org.springframework.integration.support.MessageBuilder; +import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -47,29 +48,34 @@ public class ZipkinStreamTests extends AbstractIntegrationTest { @Value("${local.server.port}") private int zipkinServerPort = 9411; + long traceId = new Random().nextLong(); + long spanId = new Random().nextLong(); @Autowired @Qualifier(SleuthSink.INPUT) private MessageChannel input; - @Test - @SneakyThrows - public void should_propagate_spans_to_zipkin() { - + @Before + public void setup() { await().until(zipkinServerIsUp()); + } - long traceId = new Random().nextLong(); - Span span = Span.builder().traceId(traceId).spanId(traceId).name("test") - .build(); + @Test + public void should_propagate_spans_to_zipkin() { + Span span = Span.builder().traceId(traceId).spanId(spanId).name("test").build(); span.tag(getRequiredBinaryAnnotationName(), "10131"); - this.input.send(MessageBuilder.withPayload( - new Spans(new Host(getAppName(), "127.0.0.1", 8080), Collections.singletonList(span))) - .build()); + this.input.send(messageWithSpan(span)); await().until(allSpansWereRegisteredInZipkinWithTraceIdEqualTo(traceId)); } + private Message messageWithSpan(Span span) { + return MessageBuilder.withPayload( + new Spans(new Host(getAppName(), "127.0.0.1", 8080), Collections.singletonList(span))) + .build(); + } + @Override protected int getZipkinServerPort() { return this.zipkinServerPort;