convert http url connection test from groovy to java
related to
DELETE
instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionResponseCodeOnlyTest.groovy
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import io.opentelemetry.instrumentation.test.AgentTestTrait
-import io.opentelemetry.instrumentation.test.base.HttpClientTest
-
-class HttpUrlConnectionResponseCodeOnlyTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
-
- @Override
- HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
- return uri.toURL().openConnection() as HttpURLConnection
- }
-
- @Override
- int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
- try {
- connection.setRequestMethod(method)
- connection.connectTimeout = CONNECT_TIMEOUT_MS
- if (uri.toString().contains("/read-timeout")) {
- connection.readTimeout = READ_TIMEOUT_MS
- }
- headers.each { connection.setRequestProperty(it.key, it.value) }
- connection.setRequestProperty("Connection", "close")
- return connection.getResponseCode()
- } finally {
- connection.disconnect()
- }
- }
-
- @Override
- int maxRedirects() {
- 20
- }
-
- @Override
- Integer responseCodeOnRedirectError() {
- return 302
- }
-
- @Override
- boolean testReusedRequest() {
- // HttpURLConnection can't be reused
- return false
- }
-
- @Override
- boolean testCallback() {
- return false
- }
-
- @Override
- boolean testReadTimeout() {
- true
- }
-}

DELETE
instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionTest.groovy
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.instrumentation.test.AgentTestTrait
-import io.opentelemetry.instrumentation.test.base.HttpClientTest
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
-import spock.lang.Unroll
-
-import static io.opentelemetry.api.trace.SpanKind.CLIENT
-import static io.opentelemetry.api.trace.SpanKind.SERVER
-import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
-
-class HttpUrlConnectionTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
-
- static final RESPONSE = "Hello."
- static final STATUS = 200
-
- @Override
- HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
- return uri.toURL().openConnection() as HttpURLConnection
- }
-
- @Override
- int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
- if (uri.toString().contains("/read-timeout")) {
- connection.readTimeout = READ_TIMEOUT_MS
- }
- try {
- connection.setRequestMethod(method)
- headers.each { connection.setRequestProperty(it.key, it.value) }
- connection.setRequestProperty("Connection", "close")
- connection.useCaches = true
- connection.connectTimeout = CONNECT_TIMEOUT_MS
- def parentSpan = Span.current()
- def stream = connection.inputStream
- assert Span.current() == parentSpan
- stream.readLines()
- stream.close()
- return connection.getResponseCode()
- } finally {
- connection.disconnect()
- }
- }
-
- @Override
- int maxRedirects() {
- 20
- }
-
- @Override
- Integer responseCodeOnRedirectError() {
- return 302
- }
-
- @Override
- boolean testReusedRequest() {
- // HttpURLConnection can't be reused
- return false
- }
-
- @Override
- boolean testCallback() {
- return false
- }
-
- @Override
- boolean testReadTimeout() {
- true
- }
-
- @Unroll
- def "trace request (useCaches: #useCaches)"() {
- setup:
- def url = resolveAddress("/success").toURL()
- runWithSpan("someTrace") {
- HttpURLConnection connection = url.openConnection()
- connection.useCaches = useCaches
- assert Span.current().getSpanContext().isValid()
- def stream = connection.inputStream
- def lines = stream.readLines()
- stream.close()
- assert connection.getResponseCode() == STATUS
- assert lines == [RESPONSE]
-
- // call again to ensure the cycling is ok
- connection = url.openConnection()
- connection.useCaches = useCaches
- assert Span.current().getSpanContext().isValid()
- // call before input stream to test alternate behavior
- assert connection.getResponseCode() == STATUS
- connection.inputStream
- stream = connection.inputStream // one more to ensure state is working
- lines = stream.readLines()
- stream.close()
- assert lines == [RESPONSE]
- }
-
- expect:
- assertTraces(1) {
- trace(0, 5) {
- span(0) {
- name "someTrace"
- hasNoParent()
- attributes {
- }
- }
- span(1) {
- name "HTTP GET"
- kind CLIENT
- childOf span(0)
- attributes {
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" server.httpPort()
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "GET"
- "$SemanticAttributes.HTTP_STATUS_CODE" STATUS
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
- }
- }
- span(2) {
- name "test-http-server"
- kind SERVER
- childOf span(1)
- attributes {
- }
- }
- span(3) {
- name "HTTP GET"
- kind CLIENT
- childOf span(0)
- attributes {
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" server.httpPort()
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "GET"
- "$SemanticAttributes.HTTP_STATUS_CODE" STATUS
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
- }
- }
- span(4) {
- name "test-http-server"
- kind SERVER
- childOf span(3)
- attributes {
- }
- }
- }
- }
-
- where:
- useCaches << [false, true]
- }
-
- def "test broken API usage (#iteration)"() {
- setup:
- def url = resolveAddress("/success").toURL()
- HttpURLConnection connection = runWithSpan("someTrace") {
- HttpURLConnection con = url.openConnection()
- con.setRequestProperty("Connection", "close")
- assert Span.current().getSpanContext().isValid()
- assert con.getResponseCode() == STATUS
- return con
- }
-
- expect:
- assertTraces(1) {
- trace(0, 3) {
- span(0) {
- name "someTrace"
- hasNoParent()
- attributes {
- }
- }
- span(1) {
- name "HTTP GET"
- kind CLIENT
- childOf span(0)
- attributes {
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" server.httpPort()
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "GET"
- "$SemanticAttributes.HTTP_STATUS_CODE" STATUS
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
- }
- }
- serverSpan(it, 2, span(1))
- }
- }
-
- cleanup:
- connection.disconnect()
-
- where:
- iteration << (1..10)
- }
-
- def "test post request"() {
- setup:
- def url = resolveAddress("/success").toURL()
- runWithSpan("someTrace") {
- HttpURLConnection connection = url.openConnection()
- connection.setRequestMethod("POST")
-
- String urlParameters = "q=ASDF&w=&e=&r=12345&t="
-
- // Send post request
- connection.setDoOutput(true)
- DataOutputStream wr = new DataOutputStream(connection.getOutputStream())
- wr.writeBytes(urlParameters)
- wr.flush()
- wr.close()
-
- assert connection.getResponseCode() == STATUS
-
- def stream = connection.inputStream
- def lines = stream.readLines()
- stream.close()
- assert lines == [RESPONSE]
- }
-
- expect:
- assertTraces(1) {
- trace(0, 3) {
- span(0) {
- name "someTrace"
- hasNoParent()
- attributes {
- }
- }
- span(1) {
- name "HTTP POST"
- kind CLIENT
- childOf span(0)
- attributes {
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" server.httpPort()
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "POST"
- "$SemanticAttributes.HTTP_STATUS_CODE" STATUS
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
- "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
- }
- }
- span(2) {
- name "test-http-server"
- kind SERVER
- childOf span(1)
- attributes {
- }
- }
- }
- }
- }
-
- def "sun.net.www.protocol.http.HttpURLConnection.getOutputStream should transform GET into POST"() {
- setup:
- def url = resolveAddress("/success").toURL()
- runWithSpan("someTrace") {
-
- HttpURLConnection connection = url.openConnection()
-
- def connectionClassName = connection.getClass().getName()
-
- assert "sun.net.www.protocol.http.HttpURLConnection".equals(connectionClassName)
-
- connection.setRequestMethod("GET")
-
- String urlParameters = "q=ASDF&w=&e=&r=12345&t="
-
- // Send POST request
- connection.setDoOutput(true)
- DataOutputStream wr = new DataOutputStream(connection.getOutputStream())
- wr.writeBytes(urlParameters)
- wr.flush()
- wr.close()
-
- assert connection.getResponseCode() == STATUS
-
- def stream = connection.inputStream
- def lines = stream.readLines()
- stream.close()
- assert lines == [RESPONSE]
- }
-
- expect:
- assertTraces(1) {
- trace(0, 3) {
- span(0) {
- name "someTrace"
- hasNoParent()
- attributes {
- }
- }
- span(1) {
- name "HTTP POST"
- kind CLIENT
- childOf span(0)
- attributes {
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" server.httpPort()
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "POST"
- "$SemanticAttributes.HTTP_STATUS_CODE" STATUS
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- "$SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH" Long
- "$SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH" Long
- }
- }
- span(2) {
- name "test-http-server"
- kind SERVER
- childOf span(1)
- attributes {
- }
- }
- }
- }
- }
-
-}

DELETE
instrumentation/http-url-connection/javaagent/src/test/groovy/HttpUrlConnectionUseCachesFalseTest.groovy
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.instrumentation.test.AgentTestTrait
-import io.opentelemetry.instrumentation.test.base.HttpClientTest
-
-class HttpUrlConnectionUseCachesFalseTest extends HttpClientTest<HttpURLConnection> implements AgentTestTrait {
-
- @Override
- HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers) {
- return uri.toURL().openConnection() as HttpURLConnection
- }
-
- @Override
- int sendRequest(HttpURLConnection connection, String method, URI uri, Map<String, String> headers) {
- try {
- connection.setRequestMethod(method)
- headers.each { connection.setRequestProperty(it.key, it.value) }
- connection.setRequestProperty("Connection", "close")
- connection.useCaches = false
- connection.connectTimeout = CONNECT_TIMEOUT_MS
- if (uri.toString().contains("/read-timeout")) {
- connection.readTimeout = READ_TIMEOUT_MS
- }
- def parentSpan = Span.current()
- def stream = connection.inputStream
- assert Span.current() == parentSpan
- stream.readLines()
- stream.close()
- return connection.getResponseCode()
- } finally {
- connection.disconnect()
- }
- }
-
- @Override
- int maxRedirects() {
- 20
- }
-
- @Override
- Integer responseCodeOnRedirectError() {
- return 302
- }
-
- @Override
- boolean testReusedRequest() {
- // HttpURLConnection can't be reused
- return false
- }
-
- @Override
- boolean testCallback() {
- return false
- }
-
- @Override
- boolean testReadTimeout() {
- true
- }
-}

DELETE
instrumentation/http-url-connection/javaagent/src/test/groovy/UrlConnectionTest.groovy
-/*
- * Copyright The OpenTelemetry Authors
- * SPDX-License-Identifier: Apache-2.0
- */
-
-import io.opentelemetry.api.trace.Span
-import io.opentelemetry.instrumentation.test.AgentInstrumentationSpecification
-import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
-
-import static io.opentelemetry.api.trace.SpanKind.CLIENT
-import static io.opentelemetry.api.trace.StatusCode.ERROR
-import static io.opentelemetry.instrumentation.test.utils.PortUtils.UNUSABLE_PORT
-import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP
-
-class UrlConnectionTest extends AgentInstrumentationSpecification {
-
- def "trace request with connection failure #scheme"() {
- when:
- runWithSpan("someTrace") {
- URLConnection connection = url.openConnection()
- connection.setConnectTimeout(10000)
- connection.setReadTimeout(10000)
- assert Span.current() != null
- connection.inputStream
- }
-
- then:
- thrown ConnectException
-
- expect:
- assertTraces(1) {
- trace(0, 2) {
- span(0) {
- name "someTrace"
- hasNoParent()
- status ERROR
- errorEvent ConnectException, String
- }
- span(1) {
- name "HTTP GET"
- kind CLIENT
- childOf span(0)
- status ERROR
- errorEvent ConnectException, String
- attributes {
- "$SemanticAttributes.NET_TRANSPORT" IP_TCP
- "$SemanticAttributes.NET_PEER_NAME" "localhost"
- "$SemanticAttributes.NET_PEER_PORT" UNUSABLE_PORT
- "$SemanticAttributes.HTTP_URL" "$url"
- "$SemanticAttributes.HTTP_METHOD" "GET"
- "$SemanticAttributes.HTTP_FLAVOR" "1.1"
- }
- }
- }
- }
-
- where:
- scheme << ["http", "https"]
-
- url = new URI("$scheme://localhost:$UNUSABLE_PORT").toURL()
- }
-}

ADD
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionResponseCodeOnlyTest.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
+
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
+import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.util.Map;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class HttpUrlConnectionResponseCodeOnlyTest extends AbstractHttpClientTest<HttpURLConnection> {
+ @RegisterExtension
+ static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
+
+ @Override
+ public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ return (HttpURLConnection) uri.toURL().openConnection();
+ }
+
+ @Override
+ public int sendRequest(
+ HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ try {
+ connection.setRequestMethod(method);
+ connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
+ if (uri.toString().contains("/read-timeout")) {
+ connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
+ }
+
+ headers.forEach(connection::setRequestProperty);
+ connection.setRequestProperty("Connection", "close");
+ return connection.getResponseCode();
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+ @Override
+ public int maxRedirects() {
+ return 20;
+ }
+
+ @Override
+ public Integer responseCodeOnRedirectError() {
+ return 302;
+ }
+
+ @Override
+ public boolean testReusedRequest() {
+ // HttpURLConnection can't be reused
+ return false;
+ }
+
+ @Override
+ public boolean testCallback() {
+ return false;
+ }
+
+ @Override
+ public boolean testReadTimeout() {
+ return true;
+ }
+}

ADD
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionTest.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
+
+import static io.opentelemetry.api.trace.SpanKind.CLIENT;
+import static io.opentelemetry.api.trace.SpanKind.SERVER;
+import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.StreamUtils.readLines;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.satisfies;
+import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
+import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.assertj.core.api.AbstractLongAssert;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class HttpUrlConnectionTest extends AbstractHttpClientTest<HttpURLConnection> {
+
+ @RegisterExtension
+ static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
+
+ static final List<String> RESPONSE = Collections.singletonList("Hello.");
+ static final int STATUS = 200;
+
+ @Override
+ public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ return (HttpURLConnection) uri.toURL().openConnection();
+ }
+
+ @Override
+ public int sendRequest(
+ HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ if (uri.toString().contains("/read-timeout")) {
+ connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
+ }
+ try {
+ connection.setRequestMethod(method);
+ headers.forEach(connection::setRequestProperty);
+ connection.setRequestProperty("Connection", "close");
+ connection.setUseCaches(true);
+ connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
+ Span parentSpan = Span.current();
+ InputStream stream = connection.getInputStream();
+ assertThat(Span.current()).isEqualTo(parentSpan);
+ stream.close();
+ return connection.getResponseCode();
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+ @Override
+ public int maxRedirects() {
+ return 20;
+ }
+
+ @Override
+ public Integer responseCodeOnRedirectError() {
+ return 302;
+ }
+
+ @Override
+ public boolean testReusedRequest() {
+ // HttpURLConnection can't be reused
+ return false;
+ }
+
+ @Override
+ public boolean testCallback() {
+ return false;
+ }
+
+ @Override
+ public boolean testReadTimeout() {
+ return true;
+ }
+
+ @ParameterizedTest
+ @ValueSource(booleans = {false, true})
+ public void traceRequest(boolean useCache) throws IOException {
+ URL url = resolveAddress("/success").toURL();
+
+ testing.runWithSpan(
+ "someTrace",
+ () -> {
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setUseCaches(useCache);
+ assertThat(Span.current().getSpanContext().isValid()).isTrue();
+ InputStream stream = connection.getInputStream();
+ List<String> lines = readLines(stream);
+ stream.close();
+ assertThat(connection.getResponseCode()).isEqualTo(STATUS);
+ assertThat(lines).isEqualTo(RESPONSE);
+
+ // call again to ensure the cycling is ok
+ connection = (HttpURLConnection) url.openConnection();
+ connection.setUseCaches(useCache);
+ assertThat(Span.current().getSpanContext().isValid()).isTrue();
+ // call before input stream to test alternate behavior
+ assertThat(connection.getResponseCode()).isEqualTo(STATUS);
+ connection.getInputStream();
+ stream = connection.getInputStream(); // one more to ensure state is working
+ lines = readLines(stream);
+ stream.close();
+ assertThat(lines).isEqualTo(RESPONSE);
+ });
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span -> span.hasName("someTrace").hasNoParent(),
+ span ->
+ span.hasName("HTTP GET")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
+ equalTo(SemanticAttributes.HTTP_URL, url.toString()),
+ equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
+ equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
+ satisfies(
+ SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative)),
+ span ->
+ span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1)),
+ span ->
+ span.hasName("HTTP GET")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
+ equalTo(SemanticAttributes.HTTP_URL, url.toString()),
+ equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
+ equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
+ satisfies(
+ SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative)),
+ span ->
+ span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(3))));
+ }
+
+ @ParameterizedTest
+ @ValueSource(ints = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
+ public void testBrokenApiUsage() throws IOException {
+ URL url = resolveAddress("/success").toURL();
+ HttpURLConnection connection =
+ testing.runWithSpan(
+ "someTrace",
+ () -> {
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestProperty("Connection", "close");
+ assertThat(Span.current().getSpanContext().isValid()).isTrue();
+ assertThat(con.getResponseCode()).isEqualTo(STATUS);
+ return con;
+ });
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span -> span.hasName("someTrace").hasNoParent(),
+ span ->
+ span.hasName("HTTP GET")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
+ equalTo(SemanticAttributes.HTTP_URL, url.toString()),
+ equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
+ equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
+ satisfies(
+ SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative)),
+ span ->
+ span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
+
+ connection.disconnect();
+ }
+
+ @Test
+ public void testPostRequest() throws IOException {
+ URL url = resolveAddress("/success").toURL();
+ testing.runWithSpan(
+ "someTrace",
+ () -> {
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestMethod("POST");
+
+ String urlParameters = "q=ASDF&w=&e=&r=12345&t=";
+
+ // Send post request
+ connection.setDoOutput(true);
+ DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
+ wr.writeBytes(urlParameters);
+ wr.flush();
+ wr.close();
+
+ assertThat(connection.getResponseCode()).isEqualTo(STATUS);
+
+ InputStream stream = connection.getInputStream();
+ List<String> lines = readLines(stream);
+ stream.close();
+ assertThat(lines).isEqualTo(RESPONSE);
+ });
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span -> span.hasName("someTrace").hasNoParent(),
+ span ->
+ span.hasName("HTTP POST")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
+ equalTo(SemanticAttributes.HTTP_URL, url.toString()),
+ equalTo(SemanticAttributes.HTTP_METHOD, "POST"),
+ equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
+ satisfies(
+ SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative),
+ satisfies(
+ SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative)),
+ span ->
+ span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
+ }
+
+ @Test
+ public void getOutputStreamShouldTransformGetIntoPost() throws IOException {
+ URL url = resolveAddress("/success").toURL();
+ testing.runWithSpan(
+ "someTrace",
+ () -> {
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+
+ assertThat(connection.getClass().getName())
+ .isEqualTo("sun.net.www.protocol.http.HttpURLConnection");
+
+ connection.setRequestMethod("GET");
+
+ String urlParameters = "q=ASDF&w=&e=&r=12345&t=";
+
+ // Send POST request
+ connection.setDoOutput(true);
+ DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
+ wr.writeBytes(urlParameters);
+ wr.flush();
+ wr.close();
+
+ assertThat(connection.getResponseCode()).isEqualTo(STATUS);
+
+ InputStream stream = connection.getInputStream();
+ List<String> lines = readLines(stream);
+ stream.close();
+ assertThat(lines).isEqualTo(RESPONSE);
+ });
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span -> span.hasName("someTrace").hasNoParent(),
+ span ->
+ span.hasName("HTTP POST")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, url.getPort()),
+ equalTo(SemanticAttributes.HTTP_URL, url.toString()),
+ equalTo(SemanticAttributes.HTTP_METHOD, "POST"),
+ equalTo(SemanticAttributes.HTTP_STATUS_CODE, STATUS),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"),
+ satisfies(
+ SemanticAttributes.HTTP_REQUEST_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative),
+ satisfies(
+ SemanticAttributes.HTTP_RESPONSE_CONTENT_LENGTH,
+ AbstractLongAssert::isNotNegative)),
+ span ->
+ span.hasName("test-http-server").hasKind(SERVER).hasParent(trace.getSpan(1))));
+ }
+}

ADD
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/HttpUrlConnectionUseCachesFalseTest.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
+
+import static io.opentelemetry.javaagent.instrumentation.httpurlconnection.StreamUtils.readLines;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
+import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.util.Map;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class HttpUrlConnectionUseCachesFalseTest extends AbstractHttpClientTest<HttpURLConnection> {
+ @RegisterExtension
+ static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
+
+ @Override
+ public HttpURLConnection buildRequest(String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ return (HttpURLConnection) uri.toURL().openConnection();
+ }
+
+ @Override
+ public int sendRequest(
+ HttpURLConnection connection, String method, URI uri, Map<String, String> headers)
+ throws Exception {
+ try {
+ connection.setRequestMethod(method);
+ headers.forEach(connection::setRequestProperty);
+ connection.setRequestProperty("Connection", "close");
+ connection.setUseCaches(false);
+ connection.setConnectTimeout((int) CONNECTION_TIMEOUT.toMillis());
+ if (uri.toString().contains("/read-timeout")) {
+ connection.setReadTimeout((int) READ_TIMEOUT.toMillis());
+ }
+ Span parentSpan = Span.current();
+ InputStream stream = connection.getInputStream();
+ assertThat(Span.current()).isEqualTo(parentSpan);
+ readLines(stream);
+ stream.close();
+ return connection.getResponseCode();
+ } finally {
+ connection.disconnect();
+ }
+ }
+
+ @Override
+ public int maxRedirects() {
+ return 20;
+ }
+
+ @Override
+ public Integer responseCodeOnRedirectError() {
+ return 302;
+ }
+
+ @Override
+ public boolean testReusedRequest() {
+ // HttpURLConnection can't be reused
+ return false;
+ }
+
+ @Override
+ public boolean testCallback() {
+ return false;
+ }
+
+ @Override
+ public boolean testReadTimeout() {
+ return true;
+ }
+}

ADD
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/StreamUtils.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Strings;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+final class StreamUtils {
+ static List<String> readLines(InputStream stream) throws IOException {
+ List<String> lines = new ArrayList<>();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(stream, UTF_8));
+ while (reader.ready()) {
+ String line = reader.readLine();
+ if (!Strings.isNullOrEmpty(line)) {
+ lines.add(line);
+ }
+ }
+
+ return lines;
+ }
+
+ private StreamUtils() {}
+}

ADD
instrumentation/http-url-connection/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/httpurlconnection/UrlConnectionTest.java
+/*
+ * Copyright The OpenTelemetry Authors
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package io.opentelemetry.javaagent.instrumentation.httpurlconnection;
+
+import static io.opentelemetry.api.trace.SpanKind.CLIENT;
+import static io.opentelemetry.api.trace.SpanKind.INTERNAL;
+import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
+import static io.opentelemetry.semconv.trace.attributes.SemanticAttributes.NetTransportValues.IP_TCP;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.catchThrowable;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.instrumentation.test.utils.PortUtils;
+import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
+import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
+import io.opentelemetry.sdk.trace.data.StatusData;
+import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+class UrlConnectionTest {
+ @RegisterExtension
+ static final InstrumentationExtension testing = AgentInstrumentationExtension.create();
+
+ @ParameterizedTest
+ @ValueSource(strings = {"http", "https"})
+ public void traceRequestWithConnectionFailure(String scheme) {
+ String uri = scheme + "://localhost:" + PortUtils.UNUSABLE_PORT;
+
+ Throwable thrown =
+ catchThrowable(
+ () ->
+ testing.runWithSpan(
+ "someTrace",
+ () -> {
+ URL url = new URI(uri).toURL();
+ URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(10000);
+ connection.setReadTimeout(10000);
+ assertThat(Span.current().getSpanContext().isValid()).isTrue();
+ connection.getInputStream();
+ }));
+
+ testing.waitAndAssertTraces(
+ trace ->
+ trace.hasSpansSatisfyingExactly(
+ span ->
+ span.hasName("someTrace")
+ .hasKind(INTERNAL)
+ .hasNoParent()
+ .hasStatus(StatusData.error())
+ .hasException(thrown),
+ span ->
+ span.hasName("HTTP GET")
+ .hasKind(CLIENT)
+ .hasParent(trace.getSpan(0))
+ .hasStatus(StatusData.error())
+ .hasException(thrown)
+ .hasAttributesSatisfyingExactly(
+ equalTo(SemanticAttributes.NET_TRANSPORT, IP_TCP),
+ equalTo(SemanticAttributes.NET_PEER_NAME, "localhost"),
+ equalTo(SemanticAttributes.NET_PEER_PORT, PortUtils.UNUSABLE_PORT),
+ equalTo(SemanticAttributes.HTTP_URL, uri),
+ equalTo(SemanticAttributes.HTTP_METHOD, "GET"),
+ equalTo(SemanticAttributes.HTTP_FLAVOR, "1.1"))));
+ }
+}

convert http url connection test from groovy to java (#7676)

related to #7195