diff --git a/instrumentation/apache-httpclient-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientInstrumentationTest.java b/instrumentation/apache-httpclient-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientInstrumentationTest.java index 2c13d71cd..e8f8dbd8a 100644 --- a/instrumentation/apache-httpclient-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientInstrumentationTest.java +++ b/instrumentation/apache-httpclient-4.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/apachehttpclient/v4_0/ApacheHttpClientInstrumentationTest.java @@ -16,204 +16,56 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.apachehttpclient.v4_0; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.sdk.trace.data.SpanData; -import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.net.URI; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeoutException; -import org.apache.http.HttpEntity; +import java.util.Map; import org.apache.http.HttpResponse; -import org.apache.http.NameValuePair; import org.apache.http.client.HttpClient; -import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.message.BasicNameValuePair; -import org.apache.http.protocol.HTTP; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.hypertrace.agent.testing.AbstractHttpClientTest; -public class ApacheHttpClientInstrumentationTest extends AbstractInstrumenterTest { - - private static final String JSON = "{\"id\":1,\"name\":\"John\"}"; - private static final TestHttpServer testHttpServer = new TestHttpServer(); +public class ApacheHttpClientInstrumentationTest extends AbstractHttpClientTest { private final HttpClient client = new DefaultHttpClient(); - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); - } - - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); + public ApacheHttpClientInstrumentationTest() { + super(true); } - @Test - public void getJson() throws IOException, TimeoutException, InterruptedException { - HttpGet getRequest = new HttpGet(); - getRequest.addHeader("foo", "bar"); - getRequest.setURI( - URI.create(String.format("http://localhost:%d/get_json", testHttpServer.port()))); - HttpResponse response = client.execute(getRequest); - Assertions.assertEquals(200, response.getStatusLine().getStatusCode()); - InputStream inputStream = response.getEntity().getContent(); - Assertions.assertEquals(GetJsonHandler.RESPONSE_BODY, readInputStream(inputStream)); - - Assertions.assertEquals(false, Span.current().isRecording()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(2, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - "bar", - clientSpan.getAttributes().get(HypertraceSemanticAttributes.httpRequestHeader("foo"))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - SpanData responseBodySpan = traces.get(0).get(1); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - responseBodySpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } - - @Test - public void postUrlEncoded() throws IOException, TimeoutException, InterruptedException { - List nvps = new ArrayList<>(); - nvps.add(new BasicNameValuePair("key1", "value1")); - nvps.add(new BasicNameValuePair("key2", "value2")); - - HttpPost postRequest = new HttpPost(); - postRequest.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8)); - postRequest.setURI( - URI.create(String.format("http://localhost:%d/post", testHttpServer.port()))); - HttpResponse response = client.execute(postRequest); - Assertions.assertEquals(204, response.getStatusLine().getStatusCode()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - "key1=value1&key2=value2", - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } - - @Test - public void postJson() throws IOException, TimeoutException, InterruptedException { - StringEntity entity = new StringEntity(JSON); - entity.setContentType("application/json"); - postJsonEntity(entity); - } + @Override + public Response doPostRequest( + String uri, Map headers, String body, String contentType) throws IOException { - @Test - public void postJsonNonRepeatableEntity() - throws IOException, TimeoutException, InterruptedException { - StringEntity entity = new NonRepeatableStringEntity(JSON); - entity.setContentType("application/json"); - postJsonEntity(entity); - } - - public void postJsonEntity(HttpEntity entity) - throws TimeoutException, InterruptedException, IOException { - HttpPost postRequest = new HttpPost(); - postRequest.setEntity(entity); - postRequest.setHeader("Content-type", "application/json"); - postRequest.setURI( - URI.create(String.format("http://localhost:%d/post", testHttpServer.port()))); - HttpResponse response = client.execute(postRequest); - Assertions.assertEquals(204, response.getStatusLine().getStatusCode()); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - readInputStream(entity.getContent()), - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } - - @Test - public void getContent_throws_exception() throws IOException { - HttpClient client = new DefaultHttpClient(); - HttpGet getRequest = new HttpGet(); - getRequest.setURI( - URI.create(String.format("http://localhost:%d/get_json", testHttpServer.port()))); - HttpResponse response = client.execute(getRequest); - HttpEntity entity = response.getEntity(); - Assertions.assertNotNull(entity.getContent()); - try { - entity.getContent(); - } catch (Exception ex) { - Assertions.assertEquals(IllegalStateException.class, ex.getClass()); - } - } - - private static String readInputStream(InputStream inputStream) throws IOException { - StringBuilder textBuilder = new StringBuilder(); - - try (BufferedReader reader = - new BufferedReader( - new InputStreamReader(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { - int c; - while ((c = reader.read()) != -1) { - textBuilder.append((char) c); - } + HttpPost request = new HttpPost(); + for (Map.Entry entry : headers.entrySet()) { + request.addHeader(entry.getKey(), entry.getValue()); } - return textBuilder.toString(); + request.setURI(URI.create(uri)); + StringEntity entity = new StringEntity(body); + entity.setContentType(contentType); + request.setEntity(entity); + request.addHeader("Content-type", contentType); + HttpResponse response = client.execute(request); + InputStream inputStream = response.getEntity().getContent(); + return new Response(readInputStream(inputStream), response.getStatusLine().getStatusCode()); } - class NonRepeatableStringEntity extends StringEntity { - - public NonRepeatableStringEntity(String s) throws UnsupportedEncodingException { - super(s); + @Override + public Response doGetRequest(String uri, Map headers) throws IOException { + HttpGet request = new HttpGet(); + for (Map.Entry entry : headers.entrySet()) { + request.addHeader(entry.getKey(), entry.getValue()); } - - @Override - public boolean isRepeatable() { - return false; + request.setURI(URI.create(uri)); + HttpResponse response = client.execute(request); + if (response.getEntity() == null || response.getEntity().getContentLength() <= 0) { + return new Response(null, response.getStatusLine().getStatusCode()); } + InputStream inputStream = response.getEntity().getContent(); + return new Response(readInputStream(inputStream), response.getStatusLine().getStatusCode()); } } diff --git a/instrumentation/okhttp/okhttp-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptorTest.java b/instrumentation/okhttp/okhttp-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptorTest.java index d1adb0bf2..7e0f13fd8 100644 --- a/instrumentation/okhttp/okhttp-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptorTest.java +++ b/instrumentation/okhttp/okhttp-3.0/src/test/java/io/opentelemetry/javaagent/instrumentation/hypertrace/okhttp/v3_0/OkHttpTracingInterceptorTest.java @@ -16,159 +16,61 @@ package io.opentelemetry.javaagent.instrumentation.hypertrace.okhttp.v3_0; -import io.opentelemetry.sdk.trace.data.SpanData; -import java.util.List; -import okhttp3.FormBody; +import java.io.IOException; +import java.util.Map; +import okhttp3.Headers; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; -import okhttp3.Request.Builder; import okhttp3.RequestBody; -import okhttp3.Response; -import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; -import org.hypertrace.agent.testing.AbstractInstrumenterTest; -import org.hypertrace.agent.testing.TestHttpServer; -import org.hypertrace.agent.testing.TestHttpServer.GetJsonHandler; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; +import org.hypertrace.agent.testing.AbstractHttpClientTest; -public class OkHttpTracingInterceptorTest extends AbstractInstrumenterTest { - - private static final TestHttpServer testHttpServer = new TestHttpServer(); +public class OkHttpTracingInterceptorTest extends AbstractHttpClientTest { private final OkHttpClient client = new OkHttpClient.Builder().followRedirects(true).build(); - @BeforeAll - public static void startServer() throws Exception { - testHttpServer.start(); + public OkHttpTracingInterceptorTest() { + super(false); } - @AfterAll - public static void closeServer() throws Exception { - testHttpServer.close(); - } + @Override + public Response doPostRequest( + String uri, Map headersMap, String body, String contentType) + throws IOException { - @Test - public void getNoContent() throws Exception { - Request request = - new Builder() - .url(String.format("http://localhost:%d/get_no_content", testHttpServer.port())) - .header("test-request-header", "test-value") - .get() - .build(); - - Response response = client.newCall(request).execute(); - response.close(); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpRequestHeader("test-request-header"))); - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } + Headers.Builder headers = new Headers.Builder(); + for (Map.Entry entry : headersMap.entrySet()) { + headers.add(entry.getKey(), entry.getValue()); + } - @Test - public void getJson() throws Exception { Request request = - new Builder() - .url(String.format("http://localhost:%d/get_json", testHttpServer.port())) - .get() + new Request.Builder() + .url(uri) + .post(RequestBody.create(body, MediaType.get(contentType))) + .headers(headers.build()) .build(); - Response response = client.newCall(request).execute(); - response.close(); + okhttp3.Response response = client.newCall(request).execute(); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertEquals( - GetJsonHandler.RESPONSE_BODY, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + String responseBody = response.body() != null ? response.body().string() : null; + return new Response(responseBody, response.code()); } - @Test - public void postUrlEncoded() throws Exception { - FormBody formBody = new FormBody.Builder().add("key1", "value1").add("key2", "value2").build(); - Request request = - new Builder() - .url(String.format("http://localhost:%d/post", testHttpServer.port())) - .post(formBody) - .build(); + @Override + public Response doGetRequest(String uri, Map headersMap) throws IOException { + Headers.Builder headers = new Headers.Builder(); + for (Map.Entry entry : headersMap.entrySet()) { + headers.add(entry.getKey(), entry.getValue()); + } - Response response = client.newCall(request).execute(); - response.close(); - - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - "key1=value1&key2=value2", - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); - } - - @Test - public void postRedirect() throws Exception { - String requestBodyStr = "{\"foo\": \"bar\"}"; - RequestBody requestBody = RequestBody.create(requestBodyStr, MediaType.get("application/json")); - Request request = - new Builder() - .url( - String.format( - "http://localhost:%d/post_redirect_to_get_no_content", testHttpServer.port())) - .post(requestBody) - .build(); + Request request = new Request.Builder().url(uri).headers(headers.build()).get().build(); - Response response = client.newCall(request).execute(); - response.close(); + okhttp3.Response response = client.newCall(request).execute(); - TEST_WRITER.waitForTraces(1); - List> traces = TEST_WRITER.getTraces(); - Assertions.assertEquals(1, traces.size()); - Assertions.assertEquals(1, traces.get(0).size()); - SpanData clientSpan = traces.get(0).get(0); - Assertions.assertEquals( - "test-value", - clientSpan - .getAttributes() - .get(HypertraceSemanticAttributes.httpResponseHeader("test-response-header"))); - Assertions.assertEquals( - requestBodyStr, - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); - Assertions.assertNull( - clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + String responseBody = + (response.body() != null && response.body().contentLength() > 0) + ? response.body().string() + : null; + return new Response(responseBody, response.code()); } } diff --git a/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java b/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java new file mode 100644 index 000000000..e6fb8c411 --- /dev/null +++ b/testing-common/src/main/java/org/hypertrace/agent/testing/AbstractHttpClientTest.java @@ -0,0 +1,290 @@ +/* + * Copyright The Hypertrace Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.hypertrace.agent.testing; + +import io.opentelemetry.sdk.trace.data.SpanData; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; +import org.hypertrace.agent.core.instrumentation.HypertraceSemanticAttributes; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +public abstract class AbstractHttpClientTest extends AbstractInstrumenterTest { + + private static final String ECHO_PATH_FORMAT = "http://localhost:%d/echo"; + private static final String GET_NO_CONTENT_PATH_FORMAT = "http://localhost:%d/get_no_content"; + private static final String GET_JSON_PATH_FORMAT = "http://localhost:%d/get_json"; + + private static final String HEADER_NAME = "headerName"; + private static final String HEADER_VALUE = "headerValue"; + private static final Map headers; + + protected static final TestHttpServer testHttpServer = new TestHttpServer(); + + static { + Map headersMap = new HashMap<>(); + headersMap.put(HEADER_NAME, HEADER_VALUE); + headers = Collections.unmodifiableMap(headersMap); + } + + private final boolean hasResponseBodySpan; + + public AbstractHttpClientTest(boolean hasResponseBodySpan) { + this.hasResponseBodySpan = hasResponseBodySpan; + } + + @BeforeAll + public static void startServer() throws Exception { + testHttpServer.start(); + } + + @AfterAll + public static void closeServer() throws Exception { + testHttpServer.close(); + } + + /** + * Make request using client and return response status code and body + * + * @param uri URI to send request to + * @param headers Request headers + * @param body Request body + * @param contentType Content-type of request body + * @return status code and body of response + */ + public abstract Response doPostRequest( + String uri, Map headers, String body, String contentType) + throws IOException, ExecutionException, InterruptedException, TimeoutException; + + /** + * Make request using client and return response status code and body + * + * @param uri URI to send request to + * @param headers Request headers + * @return status code and body of response + */ + public abstract Response doGetRequest(String uri, Map headers) + throws IOException, ExecutionException, InterruptedException, TimeoutException; + + @Test + public void postJson_echo() + throws TimeoutException, InterruptedException, IOException, ExecutionException { + String body = "{\"foo\": \"bar\"}"; + String uri = String.format(ECHO_PATH_FORMAT, testHttpServer.port()); + + Response response = doPostRequest(uri, headers, body, "application/json"); + + Assertions.assertEquals(200, response.statusCode); + Assertions.assertEquals(body, response.body); + + TEST_WRITER.waitForTraces(1); + if (hasResponseBodySpan) { + TEST_WRITER.waitForSpans(2); + } + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + SpanData clientSpan = traces.get(0).get(0); + + if (hasResponseBodySpan) { + Assertions.assertEquals(2, traces.get(0).size()); + SpanData responseBodySpan = traces.get(0).get(1); + assertBodies(clientSpan, responseBodySpan, body, body); + } else { + Assertions.assertEquals(1, traces.get(0).size()); + assertRequestAndResponseBody(clientSpan, body, body); + } + } + + @Test + public void postUrlEncoded_echo() + throws TimeoutException, InterruptedException, IOException, ExecutionException { + String body = "key1=value1&key2=value2"; + String uri = String.format(ECHO_PATH_FORMAT, testHttpServer.port()); + + Response response = doPostRequest(uri, headers, body, "application/x-www-form-urlencoded"); + + Assertions.assertEquals(200, response.statusCode); + Assertions.assertEquals(body, response.body); + + TEST_WRITER.waitForTraces(1); + if (hasResponseBodySpan) { + TEST_WRITER.waitForSpans(2); + } + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + SpanData clientSpan = traces.get(0).get(0); + + if (hasResponseBodySpan) { + Assertions.assertEquals(2, traces.get(0).size()); + SpanData responseBodySpan = traces.get(0).get(1); + assertBodies(clientSpan, responseBodySpan, body, body); + } else { + Assertions.assertEquals(1, traces.get(0).size()); + assertRequestAndResponseBody(clientSpan, body, body); + } + } + + @Test + public void postPlainText_echo() + throws TimeoutException, InterruptedException, IOException, ExecutionException { + String body = "foobar"; + String uri = String.format(ECHO_PATH_FORMAT, testHttpServer.port()); + + Response response = doPostRequest(uri, headers, body, "text/plain"); + + Assertions.assertEquals(200, response.statusCode); + Assertions.assertEquals(body, response.body); + + TEST_WRITER.waitForTraces(1); + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + Assertions.assertEquals(1, traces.get(0).size()); + SpanData clientSpan = traces.get(0).get(0); + + assertHeaders(clientSpan); + assertNoBodies(clientSpan); + } + + @Test + public void getNoContent() + throws IOException, TimeoutException, InterruptedException, ExecutionException { + String uri = String.format(GET_NO_CONTENT_PATH_FORMAT, testHttpServer.port()); + + Response response = doGetRequest(uri, headers); + + Assertions.assertEquals(204, response.statusCode); + Assertions.assertNull(response.body); + + TEST_WRITER.waitForTraces(1); + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + Assertions.assertEquals(1, traces.get(0).size()); + SpanData clientSpan = traces.get(0).get(0); + + assertHeaders(clientSpan); + assertNoBodies(clientSpan); + } + + @Test + public void getJson() + throws IOException, TimeoutException, InterruptedException, ExecutionException { + String uri = String.format(GET_JSON_PATH_FORMAT, testHttpServer.port()); + + Response response = doGetRequest(uri, headers); + + Assertions.assertEquals(200, response.statusCode); + Assertions.assertEquals(TestHttpServer.GetJsonHandler.RESPONSE_BODY, response.body); + + TEST_WRITER.waitForTraces(1); + if (hasResponseBodySpan) { + TEST_WRITER.waitForSpans(2); + } + List> traces = TEST_WRITER.getTraces(); + Assertions.assertEquals(1, traces.size()); + SpanData clientSpan = traces.get(0).get(0); + Assertions.assertNull( + clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + + if (hasResponseBodySpan) { + Assertions.assertEquals(2, traces.get(0).size()); + SpanData responseBodySpan = traces.get(0).get(1); + Assertions.assertEquals( + TestHttpServer.GetJsonHandler.RESPONSE_BODY, + responseBodySpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + } else { + Assertions.assertEquals(1, traces.get(0).size()); + Assertions.assertEquals( + TestHttpServer.GetJsonHandler.RESPONSE_BODY, + clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + } + } + + private void assertHeaders(SpanData spanData) { + Assertions.assertEquals( + TestHttpServer.RESPONSE_HEADER_VALUE, + spanData + .getAttributes() + .get( + HypertraceSemanticAttributes.httpResponseHeader( + TestHttpServer.RESPONSE_HEADER_NAME))); + Assertions.assertEquals( + HEADER_VALUE, + spanData.getAttributes().get(HypertraceSemanticAttributes.httpRequestHeader(HEADER_NAME))); + } + + private void assertRequestAndResponseBody( + SpanData spanData, String requestBody, String responseBody) { + Assertions.assertEquals( + requestBody, spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + Assertions.assertEquals( + responseBody, + spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + } + + private void assertBodies( + SpanData clientSpan, SpanData responseBodySpan, String requestBody, String responseBody) { + Assertions.assertEquals( + requestBody, + clientSpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + Assertions.assertEquals( + responseBody, + responseBodySpan.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + } + + private void assertNoBodies(SpanData spanData) { + Assertions.assertNull( + spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_RESPONSE_BODY)); + Assertions.assertNull( + spanData.getAttributes().get(HypertraceSemanticAttributes.HTTP_REQUEST_BODY)); + } + + public static String readInputStream(InputStream inputStream) throws IOException { + StringBuilder textBuilder = new StringBuilder(); + + try (BufferedReader reader = + new BufferedReader( + new InputStreamReader(inputStream, Charset.forName(StandardCharsets.UTF_8.name())))) { + int c; + while ((c = reader.read()) != -1) { + textBuilder.append((char) c); + } + } + return textBuilder.toString(); + } + + public static class Response { + String body; + int statusCode; + + public Response(String body, int statusCode) { + this.body = body; + this.statusCode = statusCode; + } + } +} diff --git a/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java b/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java index f254a72c2..2ebb0f70b 100644 --- a/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java +++ b/testing-common/src/main/java/org/hypertrace/agent/testing/TestHttpServer.java @@ -41,6 +41,7 @@ public void start() throws Exception { handlerList.addHandler(new GetJsonHandler()); handlerList.addHandler(new PostHandler()); handlerList.addHandler(new PostRedirect()); + handlerList.addHandler(new EchoHandler()); server.setHandler(handlerList); server.start(); } @@ -152,4 +153,30 @@ public void handle( } } } + + static class EchoHandler extends ResponseTestHeadersHandler { + @Override + public void handle( + String target, + Request baseRequest, + HttpServletRequest request, + HttpServletResponse response) + throws IOException { + super.handle(target, baseRequest, request, response); + + if (target.equals("/echo") && "post".equalsIgnoreCase(request.getMethod())) { + ServletInputStream inputStream = request.getInputStream(); + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + int nRead; + while ((nRead = inputStream.read()) != -1) { + buffer.write((byte) nRead); + } + + response.setStatus(200); + response.setContentType(request.getContentType()); + response.getWriter().print(buffer.toString()); + baseRequest.setHandled(true); + } + } + } }