Refactor OkHttp tests to Java (#6484)

* Refactor OkHttp tests to Java

* throws Exception
This commit is contained in:
Mateusz Rzeszutek 2022-08-24 18:18:15 +02:00 committed by GitHub
parent 55a8308b85
commit a83e6ca652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 316 additions and 300 deletions

View File

@ -20,8 +20,6 @@ import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumenta
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions;
import io.opentelemetry.sdk.trace.data.StatusData;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.util.Collections;
import java.util.Locale;
@ -43,15 +41,11 @@ public abstract class AbstractGoogleHttpClientTest extends AbstractHttpClientTes
}
@Override
protected final HttpRequest buildRequest(String method, URI uri, Map<String, String> headers) {
protected final HttpRequest buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception {
GenericUrl genericUrl = new GenericUrl(uri);
HttpRequest request;
try {
request = requestFactory.buildRequest(method, genericUrl, null);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
HttpRequest request = requestFactory.buildRequest(method, genericUrl, null);
request.setConnectTimeout((int) connectTimeout().toMillis());
if (uri.toString().contains("/read-timeout")) {
request.setReadTimeout((int) readTimeout().toMillis());

View File

@ -1,16 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
class HeadersUtil {
static headersToArray(Map<String, String> headers) {
String[] headersArr = new String[headers.size() * 2]
headers.eachWithIndex { k, v, i ->
headersArr[i] = k
headersArr[i + 1] = v
}
headersArr
}
}

View File

@ -1,99 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
import com.squareup.okhttp.Callback
import com.squareup.okhttp.MediaType
import com.squareup.okhttp.OkHttpClient
import com.squareup.okhttp.Request
import com.squareup.okhttp.RequestBody
import com.squareup.okhttp.Response
import com.squareup.okhttp.internal.http.HttpMethod
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.AgentTestTrait
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import spock.lang.Shared
import java.util.concurrent.TimeUnit
class OkHttp2Test extends HttpClientTest<Request> implements AgentTestTrait {
@Shared
def client = new OkHttpClient()
@Shared
def clientWithReadTimeout = new OkHttpClient()
def setupSpec() {
client.setConnectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
clientWithReadTimeout.setConnectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
clientWithReadTimeout.setReadTimeout(READ_TIMEOUT_MS, TimeUnit.MILLISECONDS)
}
@Override
Request buildRequest(String method, URI uri, Map<String, String> headers) {
def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null
def request = new Request.Builder()
.url(uri.toURL())
.method(method, body)
headers.forEach({ key, value -> request.header(key, value) })
return request.build()
}
@Override
int sendRequest(Request request, String method, URI uri, Map<String, String> headers) {
return getClient(uri).newCall(request).execute().code()
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
getClient(uri).newCall(request).enqueue(new Callback() {
@Override
void onFailure(Request req, IOException e) {
requestResult.complete(e)
}
@Override
void onResponse(Response response) throws IOException {
requestResult.complete(response.code())
}
})
}
OkHttpClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return clientWithReadTimeout
}
return client
}
@Override
Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = [
SemanticAttributes.HTTP_HOST,
SemanticAttributes.HTTP_SCHEME
]
def attributes = super.httpAttributes(uri) + extra
// flavor is extracted from the response, and those URLs cause exceptions (= null response)
switch (uri.toString()) {
case "http://localhost:61/":
case "https://192.0.2.1/":
case resolveAddress("/read-timeout").toString():
attributes.remove(SemanticAttributes.HTTP_FLAVOR)
}
attributes
}
@Override
boolean testRedirects() {
false
}
@Override
boolean testReadTimeout() {
true
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.okhttp.v2_2;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.MediaType;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.RequestBody;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.internal.http.HttpMethod;
import io.opentelemetry.api.common.AttributeKey;
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.instrumentation.testing.junit.http.HttpClientTestOptions;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.io.IOException;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.extension.RegisterExtension;
public class OkHttp2Test extends AbstractHttpClientTest<Request> {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
private static final OkHttpClient client = new OkHttpClient();
private static final OkHttpClient clientWithReadTimeout = new OkHttpClient();
@BeforeAll
void setupSpec() {
client.setConnectTimeout(CONNECTION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
clientWithReadTimeout.setConnectTimeout(CONNECTION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
clientWithReadTimeout.setReadTimeout(READ_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
}
@Override
public Request buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception {
RequestBody body =
HttpMethod.requiresRequestBody(method)
? RequestBody.create(MediaType.parse("text/plain"), "")
: null;
Request.Builder request = new Request.Builder().url(uri.toURL()).method(method, body);
headers.forEach(request::header);
return request.build();
}
@Override
public int sendRequest(Request request, String method, URI uri, Map<String, String> headers)
throws Exception {
return getClient(uri).newCall(request).execute().code();
}
@Override
public void sendRequestWithCallback(
Request request,
String method,
URI uri,
Map<String, String> headers,
AbstractHttpClientTest.RequestResult requestResult) {
getClient(uri)
.newCall(request)
.enqueue(
new Callback() {
@Override
public void onFailure(Request req, IOException e) {
requestResult.complete(e);
}
@Override
public void onResponse(Response response) {
requestResult.complete(response.code());
}
});
}
private static OkHttpClient getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return clientWithReadTimeout;
}
return client;
}
@Override
protected void configure(HttpClientTestOptions options) {
options.disableTestCircularRedirects();
options.enableTestReadTimeout();
options.setHttpAttributes(
uri -> {
Set<AttributeKey<?>> attributes =
new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES);
// flavor is extracted from the response, and those URLs cause exceptions (= null
// response)
if ("http://localhost:61/".equals(uri.toString())
|| "https://192.0.2.1/".equals(uri.toString())
|| resolveAddress("/read-timeout").toString().equals(uri.toString())) {
attributes.remove(SemanticAttributes.HTTP_FLAVOR);
}
return attributes;
});
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0
import io.opentelemetry.instrumentation.okhttp.v3_0.AbstractOkHttp3Test
import io.opentelemetry.instrumentation.test.AgentTestTrait
import okhttp3.Call
import okhttp3.OkHttpClient
import java.util.concurrent.TimeUnit
class OkHttp3Test extends AbstractOkHttp3Test implements AgentTestTrait {
@Override
Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder) {
return clientBuilder.build()
}
def "reused builder has one interceptor"() {
def builder = new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(false)
when:
def newClient = builder.build().newBuilder().build()
then:
newClient.interceptors().size() == 1
}
def "builder created from client has one interceptor"() {
when:
def newClient = ((OkHttpClient) client).newBuilder().build()
then:
newClient.interceptors().size() == 1
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.javaagent.instrumentation.okhttp.v3_0;
import static org.assertj.core.api.Assertions.assertThat;
import io.opentelemetry.instrumentation.okhttp.v3_0.AbstractOkHttp3Test;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
public class OkHttp3Test extends AbstractOkHttp3Test {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forAgent();
@Override
public Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder) {
return clientBuilder.build();
}
@Test
void reusedBuilderHasOneInterceptor() {
OkHttpClient.Builder builder =
new OkHttpClient.Builder()
.connectTimeout(CONNECTION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)
.retryOnConnectionFailure(false);
OkHttpClient newClient = builder.build().newBuilder().build();
assertThat(newClient.interceptors()).hasSize(1);
}
@Test
void builderCreatedFromClientHasOneInterceptor() {
OkHttpClient newClient = ((OkHttpClient) client).newBuilder().build();
assertThat(newClient.interceptors()).hasSize(1);
}
}

View File

@ -1,19 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.okhttp.v3_0
import io.opentelemetry.instrumentation.test.LibraryTestTrait
import okhttp3.Call
import okhttp3.OkHttpClient
class OkHttp3Test extends AbstractOkHttp3Test implements LibraryTestTrait {
@Override
Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder) {
return OkHttpTelemetry.create(getOpenTelemetry()).newCallFactory(clientBuilder.build())
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.okhttp.v3_0;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientInstrumentationExtension;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import org.junit.jupiter.api.extension.RegisterExtension;
public class OkHttp3Test extends AbstractOkHttp3Test {
@RegisterExtension
static final InstrumentationExtension testing = HttpClientInstrumentationExtension.forLibrary();
@Override
public Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder) {
return OkHttpTelemetry.create(testing.getOpenTelemetry()).newCallFactory(clientBuilder.build());
}
}

View File

@ -1,115 +0,0 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.okhttp.v3_0
import io.opentelemetry.api.common.AttributeKey
import io.opentelemetry.instrumentation.test.base.HttpClientTest
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Headers
import okhttp3.MediaType
import okhttp3.OkHttpClient
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.RequestBody
import okhttp3.Response
import okhttp3.internal.http.HttpMethod
import spock.lang.Shared
import java.util.concurrent.TimeUnit
abstract class AbstractOkHttp3Test extends HttpClientTest<Request> {
abstract Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder)
@Shared
Call.Factory client = createCallFactory(getClientBuilder(false))
@Shared
Call.Factory clientWithReadTimeout = createCallFactory(getClientBuilder(true))
OkHttpClient.Builder getClientBuilder(boolean withReadTimeout) {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(CONNECT_TIMEOUT_MS, TimeUnit.MILLISECONDS)
.protocols(Arrays.asList(Protocol.HTTP_1_1))
.retryOnConnectionFailure(false)
if (withReadTimeout) {
builder.readTimeout(READ_TIMEOUT_MS, TimeUnit.MILLISECONDS)
}
return builder
}
@Override
Request buildRequest(String method, URI uri, Map<String, String> headers) {
def body = HttpMethod.requiresRequestBody(method) ? RequestBody.create(MediaType.parse("text/plain"), "") : null
return new Request.Builder()
.url(uri.toURL())
.method(method, body)
.headers(Headers.of(headers)).build()
}
@Override
int sendRequest(Request request, String method, URI uri, Map<String, String> headers) {
def response = getClient(uri).newCall(request).execute()
response.body().withCloseable {
return response.code()
}
}
@Override
void sendRequestWithCallback(Request request, String method, URI uri, Map<String, String> headers, AbstractHttpClientTest.RequestResult requestResult) {
getClient(uri).newCall(request).enqueue(new Callback() {
@Override
void onFailure(Call call, IOException e) {
requestResult.complete(e)
}
@Override
void onResponse(Call call, Response response) throws IOException {
response.body().withCloseable {
requestResult.complete(response.code())
}
}
})
}
Call.Factory getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return clientWithReadTimeout
}
return client
}
@Override
boolean testCircularRedirects() {
false
}
@Override
boolean testReadTimeout() {
true
}
@Override
Set<AttributeKey<?>> httpAttributes(URI uri) {
Set<AttributeKey<?>> extra = [
SemanticAttributes.HTTP_HOST,
SemanticAttributes.HTTP_SCHEME
]
def attributes = super.httpAttributes(uri) + extra
// flavor is extracted from the response, and those URLs cause exceptions (= null response)
switch (uri.toString()) {
case "http://localhost:61/":
case "https://192.0.2.1/":
case resolveAddress("/read-timeout").toString():
attributes.remove(SemanticAttributes.HTTP_FLAVOR)
}
attributes
}
}

View File

@ -0,0 +1,127 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/
package io.opentelemetry.instrumentation.okhttp.v3_0;
import static java.util.Collections.singletonList;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.testing.junit.http.AbstractHttpClientTest;
import io.opentelemetry.instrumentation.testing.junit.http.HttpClientTestOptions;
import io.opentelemetry.semconv.trace.attributes.SemanticAttributes;
import java.io.IOException;
import java.net.URI;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpMethod;
public abstract class AbstractOkHttp3Test extends AbstractHttpClientTest<Request> {
protected abstract Call.Factory createCallFactory(OkHttpClient.Builder clientBuilder);
protected final Call.Factory client = createCallFactory(getClientBuilder(false));
private final Call.Factory clientWithReadTimeout = createCallFactory(getClientBuilder(true));
OkHttpClient.Builder getClientBuilder(boolean withReadTimeout) {
OkHttpClient.Builder builder =
new OkHttpClient.Builder()
.connectTimeout(CONNECTION_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)
.protocols(singletonList(Protocol.HTTP_1_1))
.retryOnConnectionFailure(false);
if (withReadTimeout) {
builder.readTimeout(READ_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS);
}
return builder;
}
@Override
protected Request buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception {
RequestBody body =
HttpMethod.requiresRequestBody(method)
? RequestBody.create(MediaType.parse("text/plain"), "")
: null;
return new Request.Builder()
.url(uri.toURL())
.method(method, body)
.headers(Headers.of(headers))
.build();
}
@Override
protected int sendRequest(Request request, String method, URI uri, Map<String, String> headers)
throws Exception {
Response response = getClient(uri).newCall(request).execute();
try (ResponseBody ignored = response.body()) {
return response.code();
}
}
@Override
protected void sendRequestWithCallback(
Request request,
String method,
URI uri,
Map<String, String> headers,
AbstractHttpClientTest.RequestResult requestResult) {
getClient(uri)
.newCall(request)
.enqueue(
new Callback() {
@Override
public void onFailure(Call call, IOException e) {
requestResult.complete(e);
}
@Override
public void onResponse(Call call, Response response) {
try (ResponseBody ignored = response.body()) {
requestResult.complete(response.code());
}
}
});
}
private Call.Factory getClient(URI uri) {
if (uri.toString().contains("/read-timeout")) {
return clientWithReadTimeout;
}
return client;
}
@Override
protected void configure(HttpClientTestOptions options) {
options.disableTestCircularRedirects();
options.enableTestReadTimeout();
options.setHttpAttributes(
uri -> {
Set<AttributeKey<?>> attributes =
new HashSet<>(HttpClientTestOptions.DEFAULT_HTTP_ATTRIBUTES);
// flavor is extracted from the response, and those URLs cause exceptions (= null
// response)
if ("http://localhost:61/".equals(uri.toString())
|| "https://192.0.2.1/".equals(uri.toString())
|| resolveAddress("/read-timeout").toString().equals(uri.toString())) {
attributes.remove(SemanticAttributes.HTTP_FLAVOR);
}
return attributes;
});
}
}

View File

@ -63,7 +63,8 @@ public abstract class AbstractHttpClientTest<REQUEST> {
* request a second time to verify that the traceparent header is not added multiple times to the
* request, and that the last one wins. Tests will fail if the header shows multiple times.
*/
protected abstract REQUEST buildRequest(String method, URI uri, Map<String, String> headers);
protected abstract REQUEST buildRequest(String method, URI uri, Map<String, String> headers)
throws Exception;
/**
* Helper class for capturing result of asynchronous request and running a callback when result is