diff --git a/okhttp-modules/pom.xml b/okhttp-modules/pom.xml index 53943f24c..11939042a 100644 --- a/okhttp-modules/pom.xml +++ b/okhttp-modules/pom.xml @@ -43,11 +43,6 @@ logging-interceptor 4.12.0 - - org.apache.httpcomponents.client5 - httpclient5 - 5.0.3 - io.split.client java-client diff --git a/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpClientImpl.java b/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpClientImpl.java index fe1ad1dc0..d642cabe9 100644 --- a/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpClientImpl.java +++ b/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpClientImpl.java @@ -7,7 +7,7 @@ import io.split.service.SplitHttpClient; import okhttp3.*; -import okhttp3.OkHttpClient.Builder; +import okhttp3.OkHttpClient.*; import okhttp3.Request.*; import okhttp3.logging.HttpLoggingInterceptor; import org.slf4j.Logger; @@ -31,7 +31,7 @@ import java.util.concurrent.TimeUnit; public class OkHttpClientImpl implements SplitHttpClient { - public final OkHttpClient httpClient; + protected OkHttpClient httpClient; private static final Logger _log = LoggerFactory.getLogger(OkHttpClientImpl.class); private static final String HEADER_CACHE_CONTROL_NAME = "Cache-Control"; private static final String HEADER_CACHE_CONTROL_VALUE = "no-cache"; @@ -42,7 +42,7 @@ public class OkHttpClientImpl implements SplitHttpClient { private static final String HEADER_CLIENT_VERSION = "SplitSDKVersion"; private RequestDecorator _requestDecorator; private String _apikey; - private SDKMetadata _metadata; + protected SDKMetadata _metadata; public OkHttpClientImpl(String apiToken, SDKMetadata sdkMetadata, RequestDecorator requestDecorator, Proxy proxy, String proxyAuthKerberosPrincipalName, boolean debugEnabled, @@ -50,7 +50,18 @@ public OkHttpClientImpl(String apiToken, SDKMetadata sdkMetadata, RequestDecorat _apikey = apiToken; _metadata = sdkMetadata; _requestDecorator = requestDecorator; + setHttpClient(proxy, proxyAuthKerberosPrincipalName, debugEnabled, + readTimeout, connectionTimeout); + } + + protected void setHttpClient(Proxy proxy, String proxyAuthKerberosPrincipalName, boolean debugEnabled, + int readTimeout, int connectionTimeout) throws IOException { + httpClient = initializeClient(proxy, proxyAuthKerberosPrincipalName, debugEnabled, + readTimeout, connectionTimeout); + } + protected OkHttpClient initializeClient(Proxy proxy, String proxyAuthKerberosPrincipalName, boolean debugEnabled, + int readTimeout, int connectionTimeout) throws IOException { HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); if (debugEnabled) { logging.setLevel(HttpLoggingInterceptor.Level.HEADERS); @@ -66,7 +77,7 @@ public OkHttpClientImpl(String apiToken, SDKMetadata sdkMetadata, RequestDecorat Authenticator proxyAuthenticator = getProxyAuthenticator(proxyAuthKerberosPrincipalName, kerberosOptions); - httpClient = new okhttp3.OkHttpClient.Builder() + return new okhttp3.OkHttpClient.Builder() .proxy(proxy) .readTimeout(readTimeout, TimeUnit.MILLISECONDS) .connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS) @@ -83,7 +94,7 @@ public HTTPKerberosAuthInterceptor getProxyAuthenticator(String proxyKerberosPri @Override public SplitHttpResponse get(URI uri, FetchOptions options, Map> additionalHeaders) { try { - okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + okhttp3.Request.Builder requestBuilder = getRequestBuilder(); requestBuilder.url(uri.toString()); setBasicHeaders(requestBuilder); setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); @@ -135,7 +146,8 @@ public SplitHttpResponse post(URI url, HttpEntity entity, RequestBody postBody = RequestBody.create(post.getBytes()); requestBuilder.post(postBody); - Request request = getRequest(requestBuilder); + Request request = requestBuilder.build(); + System.out.println(request); _log.debug(String.format("Request Headers: %s", request.headers())); Response response = httpClient.newCall(request).execute(); diff --git a/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpModule.java b/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpModule.java index 7480f1014..77fe1d971 100644 --- a/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpModule.java +++ b/okhttp-modules/src/main/java/io/split/httpmodules/okhttp/OkHttpModule.java @@ -12,11 +12,11 @@ import org.slf4j.LoggerFactory; public class OkHttpModule implements CustomHttpModule { - private static final int DEFAULT_CONNECTION_TIMEOUT = 10000; - private static final int DEFAULT_READ_TIMEOUT = 10000; - private final boolean _debugEnabled; - private final int _connectionTimeout; - private final int _readTimeout; + private static final int DEFAULT_CONNECTION_TIMEOUT = 15000; + private static final int DEFAULT_READ_TIMEOUT = 15000; + private final Boolean _debugEnabled; + private final Integer _connectionTimeout; + private final Integer _readTimeout; private final Proxy _proxy; private final ProxyAuthScheme _proxyAuthScheme; private final String _proxyAuthKerberosPrincipalName; @@ -29,9 +29,9 @@ public static Builder builder() { private OkHttpModule(ProxyAuthScheme proxyAuthScheme, String proxyAuthKerberosPrincipalName, Proxy proxy, - int connectionTimeout, - int readTimeout, - boolean debugEnabled) { + Integer connectionTimeout, + Integer readTimeout, + Boolean debugEnabled) { _proxyAuthScheme = proxyAuthScheme; _proxyAuthKerberosPrincipalName = proxyAuthKerberosPrincipalName; _proxy = proxy; @@ -54,24 +54,24 @@ public ProxyAuthScheme proxyAuthScheme() { return _proxyAuthScheme; } public String proxyKerberosPrincipalName() { return _proxyAuthKerberosPrincipalName; } - public int connectionTimeout() { + public Integer connectionTimeout() { return _connectionTimeout; } - public boolean debugEnabled() { + public Boolean debugEnabled() { return _debugEnabled; } - public int readTimeout() { + public Integer readTimeout() { return _readTimeout; } public static final class Builder { - private int _connectionTimeout = 15000; - private int _readTimeout = 15000; + private Integer _connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; + private Integer _readTimeout = DEFAULT_READ_TIMEOUT; private String _proxyHost = "localhost"; private int _proxyPort = -1; private ProxyAuthScheme _proxyAuthScheme = null; private String _proxyAuthKerberosPrincipalName = null; - private boolean _debugEnabled = false; + private Boolean _debugEnabled = false; public Builder() { } @@ -133,6 +133,28 @@ public Builder proxyAuthKerberosPrincipalName(String proxyAuthKerberosPrincipalN return this; } + /** + * HTTP Connection Timeout + * + * @param connectionTimeout + * @return this builder + */ + public Builder connectionTimeout(int connectionTimeout) { + _connectionTimeout = connectionTimeout; + return this; + } + + /** + * HTTP Read Timeout + * + * @param readTimeout + * @return this builder + */ + public Builder readTimeout(int readTimeout) { + _readTimeout = readTimeout; + return this; + } + private void verifyAuthScheme() { if (_proxyAuthScheme == ProxyAuthScheme.KERBEROS) { if (proxy() == null) { @@ -145,10 +167,10 @@ private void verifyAuthScheme() { } private void verifyTimeouts() { - if (_connectionTimeout <= 0 || _connectionTimeout > DEFAULT_CONNECTION_TIMEOUT) { + if (_connectionTimeout <= 0) { _connectionTimeout = DEFAULT_CONNECTION_TIMEOUT; } - if (_readTimeout <= 0 || _readTimeout > DEFAULT_READ_TIMEOUT) { + if (_readTimeout <= 0) { _readTimeout = DEFAULT_READ_TIMEOUT; } } diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HTTPKerberosAuthIntercepterTest.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HTTPKerberosAuthIntercepterTest.java index b56c7bff0..94fcb85a7 100644 --- a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HTTPKerberosAuthIntercepterTest.java +++ b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HTTPKerberosAuthIntercepterTest.java @@ -1,6 +1,5 @@ package io.split.httpmodules.okhttp; -import io.split.httpmodules.okhttp.HTTPKerberosAuthInterceptor; import org.junit.Test; import org.junit.runner.RunWith; import org.powermock.api.mockito.PowerMockito; @@ -29,7 +28,6 @@ @RunWith(PowerMockRunner.class) @PrepareForTest(HTTPKerberosAuthInterceptor.class) public class HTTPKerberosAuthIntercepterTest { -/* @Test public void testBasicFlow() throws Exception { System.setProperty("java.security.krb5.conf", "src/test/resources/krb5.conf"); @@ -64,7 +62,7 @@ public void testBasicFlow() throws Exception { okhttp3.Request request = kerberosAuthInterceptor.authenticate(null, response); assertThat(request.headers("Proxy-authorization"), is(equalTo(Arrays.asList("Negotiate secured-token")))); } - +/* @Test public void testKerberosLoginConfiguration() { Map kerberosOptions = new HashMap(); @@ -84,7 +82,7 @@ public void testKerberosLoginConfigurationException() { HTTPKerberosAuthInterceptor.KerberosLoginConfiguration kerberosConfig = new HTTPKerberosAuthInterceptor.KerberosLoginConfiguration(); AppConfigurationEntry[] appConfig = kerberosConfig.getAppConfigurationEntry(""); } - +*/ @Test public void testBuildAuthorizationHeader() throws LoginException, PrivilegedActionException { System.setProperty("java.security.krb5.conf", "src/test/resources/krb5.conf"); @@ -110,6 +108,4 @@ public void testBuildAuthorizationHeader() throws LoginException, PrivilegedActi assertThat("secret-token", is(equalTo(kerberosAuthInterceptor.buildAuthorizationHeader("bilal")))); } - - */ } diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HttpSplitClientKerberosTest.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HttpSplitClientKerberosTest.java deleted file mode 100644 index 75aed5a82..000000000 --- a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/HttpSplitClientKerberosTest.java +++ /dev/null @@ -1,316 +0,0 @@ -package io.split.httpmodules.okhttp; - -import com.google.common.base.Charsets; -import com.google.common.io.Files; - -import io.split.client.CustomHeaderDecorator; -import io.split.client.RequestDecorator; -import io.split.client.dtos.*; -import io.split.client.impressions.Impression; -import io.split.client.utils.Json; -import io.split.client.utils.SDKMetadata; -import io.split.client.utils.Utils; -import io.split.engine.common.FetchOptions; - -import okhttp3.OkHttpClient; -//import okhttp3.OkHttpClient.Builder; -import okhttp3.HttpUrl; -import okhttp3.Headers; - -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import split.org.apache.hc.core5.http.*; -import split.org.apache.hc.core5.http.io.entity.EntityUtils; -import org.junit.Assert; -import org.junit.Test; - -import java.io.*; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.HttpURLConnection; -import java.net.Proxy; -import java.net.InetSocketAddress; -import java.util.List; -import java.util.Arrays; -import java.util.Collections; -import java.util.Map; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.hamcrest.core.IsEqual.equalTo; - -public class HttpSplitClientKerberosTest { -/* - @Test - public void testGetWithSpecialCharacters() throws IOException, InterruptedException { - MockWebServer server = new MockWebServer(); - BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json")); - String body; - try { - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - - while (line != null) { - sb.append(line); - sb.append(System.lineSeparator()); - line = br.readLine(); - } - body = sb.toString(); - } finally { - br.close(); - } - - server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); - server.start(); - HttpUrl baseUrl = server.url("/v1/"); - URI rootTarget = baseUrl.uri(); - RequestDecorator decorator = new RequestDecorator(null); - OkHttpClient client = new Builder().build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", - Collections.singletonList("add")); - - SplitHttpResponse splitHttpResponse = okHttpModuleImpl.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); - - - RecordedRequest request = server.takeRequest(); - server.shutdown(); - Headers requestHeaders = request.getHeaders(); - - assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_OK))); - Assert.assertEquals("/v1/", request.getPath()); - assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ; - assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty"))); - assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3"))); - assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4"))); - assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP"))); - assertThat(requestHeaders.get("AdditionalHeader"), is(equalTo("add"))); - - SplitChange change = Json.fromJson(splitHttpResponse.body(), SplitChange.class); - Header[] headers = splitHttpResponse.responseHeaders(); - assertThat(headers[1].getName(), is(equalTo("via"))); - assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]"))); - assertThat(splitHttpResponse.statusCode(), is(equalTo(200))); - Assert.assertNotNull(change); - Assert.assertEquals(1, change.splits.size()); - Assert.assertNotNull(change.splits.get(0)); - - Split split = change.splits.get(0); - Map configs = split.configurations; - Assert.assertEquals(2, configs.size()); - Assert.assertEquals("{\"test\": \"blue\",\"grüne Straße\": 13}", configs.get("on")); - Assert.assertEquals("{\"test\": \"blue\",\"size\": 15}", configs.get("off")); - Assert.assertEquals(2, split.sets.size()); - okHttpModuleImpl.close(); - } - - @Test - public void testGetErrors() throws IOException, InterruptedException { - MockWebServer server = new MockWebServer(); - server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR)); - server.start(); - HttpUrl baseUrl = server.url("/v1/"); - URI rootTarget = baseUrl.uri(); - RequestDecorator decorator = new RequestDecorator(null); - - OkHttpClient client = new Builder().build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", - Collections.singletonList("add")); - - SplitHttpResponse splitHttpResponse = okHttpModuleImpl.get(rootTarget, - new FetchOptions.Builder().cacheControlHeaders(true).build(), additionalHeaders); - - - RecordedRequest request = server.takeRequest(); - server.shutdown(); - assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR))); - okHttpModuleImpl.close(); - } - - @Test - public void testGetParameters() throws IOException, InterruptedException { - class MyCustomHeaders implements CustomHeaderDecorator { - public MyCustomHeaders() {} - @Override - public Map> getHeaderOverrides(RequestContext context) { - Map> additionalHeaders = context.headers(); - additionalHeaders.put("first", Arrays.asList("1")); - additionalHeaders.put("second", Arrays.asList("2.1", "2.2")); - additionalHeaders.put("third", Arrays.asList("3")); - return additionalHeaders; - } - } - - MockWebServer server = new MockWebServer(); - BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json")); - String body; - try { - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - - while (line != null) { - sb.append(line); - sb.append(System.lineSeparator()); - line = br.readLine(); - } - body = sb.toString(); - } finally { - br.close(); - } - - server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); - server.start(); - HttpUrl baseUrl = server.url("/splitChanges?since=1234567"); - URI rootTarget = baseUrl.uri(); - RequestDecorator decorator = new RequestDecorator(new MyCustomHeaders()); - OkHttpClient client = new Builder().build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - - FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build(); - SplitHttpResponse splitHttpResponse = okHttpModuleImpl.get(rootTarget, options, null); - - RecordedRequest request = server.takeRequest(); - server.shutdown(); - Headers requestHeaders = request.getHeaders(); - - assertThat(requestHeaders.get("Cache-Control"), is(equalTo("no-cache"))); - assertThat(requestHeaders.get("first"), is(equalTo("1"))); - assertThat(requestHeaders.values("second"), is(equalTo(Arrays.asList("2.1","2.2")))); - assertThat(requestHeaders.get("third"), is(equalTo("3"))); - Assert.assertEquals("/splitChanges?since=1234567", request.getPath()); - assertThat(request.getMethod(), is(equalTo("GET"))); - } - - @Test(expected = IllegalStateException.class) - public void testException() throws URISyntaxException, IOException { - URI uri = new URI("https://api.split.io/splitChanges?since=1234567"); - RequestDecorator decorator = null; - - ByteArrayInputStream stubInputStream = new ByteArrayInputStream(Files.asCharSource( - new File("src/test/resources/split-change-special-characters.json"), Charsets.UTF_8).read().getBytes(Charsets.UTF_8)); - - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("1.0.0.127", 8080)); - OkHttpClient client = new OkHttpClient.Builder() - .proxy(proxy) - .build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - SplitHttpResponse splitHttpResponse = splitHtpClientKerberos.get(uri, - new FetchOptions.Builder().cacheControlHeaders(true).build(), null); - } - - @Test - public void testPost() throws IOException, ParseException, InterruptedException { - MockWebServer server = new MockWebServer(); - - server.enqueue(new MockResponse().addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); - server.start(); - HttpUrl baseUrl = server.url("/impressions"); - URI rootTarget = baseUrl.uri(); - RequestDecorator decorator = new RequestDecorator(null); - OkHttpClient client = new Builder().build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - - FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build(); - // Send impressions - List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( - KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)))), - new TestImpressions("t2", Arrays.asList( - KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), - KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); - - Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode", - Collections.singletonList("OPTIMIZED")); - - SplitHttpResponse splitHttpResponse = okHttpModuleImpl.post(rootTarget, Utils.toJsonEntity(toSend), - additionalHeaders); - - RecordedRequest request = server.takeRequest(); - server.shutdown(); - Headers requestHeaders = request.getHeaders(); - String postBody = EntityUtils.toString(Utils.toJsonEntity(toSend)); - - Assert.assertEquals("POST /impressions HTTP/1.1", request.getRequestLine()); - Assert.assertEquals(postBody, request.getBody().readUtf8()); - assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ; - assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty"))); - assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3"))); - assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4"))); - assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP"))); - assertThat(requestHeaders.get("SplitSDKImpressionsMode"), is(equalTo("OPTIMIZED"))); - - Header[] headers = splitHttpResponse.responseHeaders(); - assertThat(headers[1].getName(), is(equalTo("via"))); - assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]"))); - assertThat(splitHttpResponse.statusCode(), is(equalTo(200))); - } - - @Test - public void testPostErrors() throws IOException, InterruptedException { - MockWebServer server = new MockWebServer(); - server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR)); - server.start(); - HttpUrl baseUrl = server.url("/v1/"); - URI rootTarget = baseUrl.uri(); - RequestDecorator decorator = new RequestDecorator(null); - OkHttpClient client = new Builder().build(); - - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - - Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", - Collections.singletonList("add")); - - SplitHttpResponse splitHttpResponse = okHttpModuleImpl.post(rootTarget, - Utils.toJsonEntity("<>"), additionalHeaders); - - - RecordedRequest request = server.takeRequest(); - server.shutdown(); - assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR))); - okHttpModuleImpl.close(); - } - - @Test(expected = IllegalStateException.class) - public void testPosttException() throws URISyntaxException { - RequestDecorator decorator = null; - URI uri = new URI("https://kubernetesturl.com/split/api/testImpressions/bulk"); - - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("1.0.0.127", 8080)); - OkHttpClient client = new OkHttpClient.Builder() - .proxy(proxy) - .build(); - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - okHttpModuleImpl.setMetaData(metadata()); - okHttpModuleImpl.setRequestDecorator(decorator); - SplitHttpResponse splitHttpResponse = splitHtpClientKerberos.post(uri, - Utils.toJsonEntity(Arrays.asList(new String[] { "A", "B", "C", "D" })), null); - } -*/ - private SDKMetadata metadata() { - return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); - } -} diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpClientImplTest.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpClientImplTest.java new file mode 100644 index 000000000..30b2813f1 --- /dev/null +++ b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpClientImplTest.java @@ -0,0 +1,420 @@ +package io.split.httpmodules.okhttp; + +import org.powermock.api.mockito.PowerMockito; +import org.powermock.reflect.Whitebox; +import split.com.google.common.base.Charsets; +import split.com.google.common.io.Files; + +import io.split.client.CustomHeaderDecorator; +import io.split.client.RequestDecorator; +import io.split.client.dtos.*; +import io.split.client.impressions.Impression; +import io.split.client.utils.Json; +import io.split.client.utils.SDKMetadata; +import io.split.client.utils.Utils; +import io.split.engine.common.FetchOptions; + +import okhttp3.OkHttpClient; +import okhttp3.OkHttpClient.*; +import okhttp3.HttpUrl; +import okhttp3.Headers; + +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; +import split.org.apache.hc.core5.http.*; +import split.org.apache.hc.core5.http.io.entity.EntityUtils; +import split.org.apache.hc.core5.http.HttpEntity; +import org.junit.Assert; +import org.junit.Test; + +import java.io.*; + +import java.net.URI; +import java.net.URISyntaxException; +import java.net.HttpURLConnection; +import java.util.*; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Matchers.any; +import static org.powermock.api.mockito.PowerMockito.mock; + +public class OkHttpClientImplTest { + + @Test + public void testGetWithSpecialCharacters() throws IOException, InterruptedException { + MockWebServer server = new MockWebServer(); + BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json")); + String body; + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + body = sb.toString(); + } finally { + br.close(); + } + + server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); + server.start(); + HttpUrl baseUrl = server.url("/v1/"); + URI rootTarget = baseUrl.uri(); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", + Collections.singletonList("add")); + FetchOptions fetchOptions = new FetchOptions.Builder().cacheControlHeaders(true).build(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).get(rootTarget, fetchOptions, additionalHeaders); + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); + RequestDecorator requestDecorator = new RequestDecorator(null); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + PowerMockito.doReturn(requestBuilder.build()).when(okHttpClientImpl).getRequest(requestBuilder); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getRequest(requestBuilder); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.get(rootTarget, fetchOptions, additionalHeaders); + + RecordedRequest request = server.takeRequest(); + server.shutdown(); + Headers requestHeaders = request.getHeaders(); + + assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_OK))); + Assert.assertEquals("/v1/", request.getPath()); + assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ; + assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty"))); + assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3"))); + assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4"))); + assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP"))); + assertThat(requestHeaders.get("AdditionalHeader"), is(equalTo("add"))); + + SplitChange change = Json.fromJson(splitHttpResponse.body(), SplitChange.class); + + Header[] headers = splitHttpResponse.responseHeaders(); + assertThat(headers[1].getName(), is(equalTo("via"))); + assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]"))); + assertThat(splitHttpResponse.statusCode(), is(equalTo(200))); + Assert.assertNotNull(change); + Assert.assertEquals(1, change.splits.size()); + Assert.assertNotNull(change.splits.get(0)); + + Split split = change.splits.get(0); + Map configs = split.configurations; + Assert.assertEquals(2, configs.size()); + Assert.assertEquals("{\"test\": \"blue\",\"grüne Straße\": 13}", configs.get("on")); + Assert.assertEquals("{\"test\": \"blue\",\"size\": 15}", configs.get("off")); + Assert.assertEquals(2, split.sets.size()); + okHttpClientImpl.close(); + } + + @Test + public void testGetErrors() throws IOException, InterruptedException { + MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR)); + server.start(); + HttpUrl baseUrl = server.url("/v1/"); + URI rootTarget = baseUrl.uri(); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + + Map> additionalHeaders = Collections.singletonMap("AdditionalHeader", + Collections.singletonList("add")); + FetchOptions fetchOptions = new FetchOptions.Builder().cacheControlHeaders(true).build(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).get(rootTarget, fetchOptions, additionalHeaders); + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); + RequestDecorator requestDecorator = new RequestDecorator(null); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.get(rootTarget, + fetchOptions, additionalHeaders); + + RecordedRequest request = server.takeRequest(); + server.shutdown(); + assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR))); + okHttpClientImpl.close(); + } + + @Test + public void testGetParameters() throws IOException, InterruptedException { + class MyCustomHeaders implements CustomHeaderDecorator { + public MyCustomHeaders() {} + @Override + public Map> getHeaderOverrides(RequestContext context) { + Map> additionalHeaders = context.headers(); + additionalHeaders.put("first", Arrays.asList("1")); + additionalHeaders.put("second", Arrays.asList("2.1", "2.2")); + additionalHeaders.put("third", Arrays.asList("3")); + return additionalHeaders; + } + } + MockWebServer server = new MockWebServer(); + BufferedReader br = new BufferedReader(new FileReader("src/test/resources/split-change-special-characters.json")); + String body; + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + + while (line != null) { + sb.append(line); + sb.append(System.lineSeparator()); + line = br.readLine(); + } + body = sb.toString(); + } finally { + br.close(); + } + + server.enqueue(new MockResponse().setBody(body).addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); + server.start(); + HttpUrl baseUrl = server.url("/splitChanges?since=1234567"); + URI rootTarget = baseUrl.uri(); + RequestDecorator requestDecorator = new RequestDecorator(new MyCustomHeaders()); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + + FetchOptions fetchOptions = new FetchOptions.Builder().cacheControlHeaders(true).build(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).get(rootTarget, fetchOptions, null); + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, null); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build(); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.get(rootTarget, options, null); + + RecordedRequest request = server.takeRequest(); + server.shutdown(); + Headers requestHeaders = request.getHeaders(); + + assertThat(requestHeaders.get("Cache-Control"), is(equalTo("no-cache"))); + assertThat(requestHeaders.get("first"), is(equalTo("1"))); + assertThat(requestHeaders.values("second"), is(equalTo(Arrays.asList("2.1","2.2")))); + assertThat(requestHeaders.get("third"), is(equalTo("3"))); + Assert.assertEquals("/splitChanges?since=1234567", request.getPath()); + assertThat(request.getMethod(), is(equalTo("GET"))); + } + + @Test(expected = IllegalStateException.class) + public void testException() throws URISyntaxException, IOException { + URI rootTarget = new URI("https://api.split.io/splitChanges?since=1234567"); + RequestDecorator requestDecorator = null; + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + + FetchOptions fetchOptions = new FetchOptions.Builder().cacheControlHeaders(true).build(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).get(rootTarget, fetchOptions, null); + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, null); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + FetchOptions options = new FetchOptions.Builder().cacheControlHeaders(true).build(); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.get(rootTarget, + new FetchOptions.Builder().cacheControlHeaders(true).build(), null); + } + + @Test + public void testPost() throws IOException, ParseException, InterruptedException { + MockWebServer server = new MockWebServer(); + + server.enqueue(new MockResponse().addHeader(HttpHeaders.VIA, "HTTP/1.1 s_proxy_rio1")); + server.start(); + HttpUrl baseUrl = server.url("/impressions"); + URI rootTarget = baseUrl.uri(); + RequestDecorator requestDecorator = new RequestDecorator(null); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode", + Collections.singletonList("OPTIMIZED")); + + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + // Send impressions + List toSend = Arrays.asList(new TestImpressions("t1", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t1", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t1", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t1", "on", 123L, "r1", 456L, null)))), + new TestImpressions("t2", Arrays.asList( + KeyImpression.fromImpression(new Impression("k1", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k2", null, "t2", "on", 123L, "r1", 456L, null)), + KeyImpression.fromImpression(new Impression("k3", null, "t2", "on", 123L, "r1", 456L, null))))); + HttpEntity data = Utils.toJsonEntity(toSend); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).post(rootTarget, data, + additionalHeaders); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.post(rootTarget, data, + additionalHeaders); + + RecordedRequest request = server.takeRequest(); + server.shutdown(); + Headers requestHeaders = request.getHeaders(); + String postBody = EntityUtils.toString(Utils.toJsonEntity(toSend)); + + Assert.assertEquals("POST /impressions HTTP/1.1", request.getRequestLine()); + Assert.assertEquals(postBody, request.getBody().readUtf8()); + assertThat(requestHeaders.get("Authorization"), is(equalTo("Bearer qwerty"))) ; + assertThat(requestHeaders.get("SplitSDKClientKey"), is(equalTo("erty"))); + assertThat(requestHeaders.get("SplitSDKVersion"), is(equalTo("java-1.2.3"))); + assertThat(requestHeaders.get("SplitSDKMachineIP"), is(equalTo("1.2.3.4"))); + assertThat(requestHeaders.get("SplitSDKMachineName"), is(equalTo("someIP"))); + assertThat(requestHeaders.get("SplitSDKImpressionsMode"), is(equalTo("OPTIMIZED"))); + + Header[] headers = splitHttpResponse.responseHeaders(); + assertThat(headers[1].getName(), is(equalTo("via"))); + assertThat(headers[1].getValue(), is(equalTo("[HTTP/1.1 s_proxy_rio1]"))); + assertThat(splitHttpResponse.statusCode(), is(equalTo(200))); + } + + @Test + public void testPostErrors() throws IOException, InterruptedException { + MockWebServer server = new MockWebServer(); + server.enqueue(new MockResponse().setBody("").setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR)); + server.start(); + HttpUrl baseUrl = server.url("/v1/"); + URI rootTarget = baseUrl.uri(); + RequestDecorator requestDecorator = new RequestDecorator(null); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode", + Collections.singletonList("OPTIMIZED")); + + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + + HttpEntity data = Utils.toJsonEntity("<>"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).post(rootTarget, data, + additionalHeaders); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.post(rootTarget, data, + additionalHeaders); + + RecordedRequest request = server.takeRequest(); + server.shutdown(); + assertThat(splitHttpResponse.statusCode(), is(equalTo(HttpURLConnection.HTTP_INTERNAL_ERROR))); + okHttpClientImpl.close(); + } + + @Test(expected = IllegalStateException.class) + public void testPosttException() throws URISyntaxException, IOException { + RequestDecorator requestDecorator = null; + URI rootTarget = new URI("https://kubernetesturl.com/split/api/testImpressions/bulk"); + + OkHttpClientImpl okHttpClientImpl = mock(OkHttpClientImpl.class); + OkHttpClient client = new OkHttpClient.Builder().build(); + PowerMockito.doReturn(client).when(okHttpClientImpl).initializeClient(null, "bilal", false, + 0, 0); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setHttpClient(null, "bilal", false, + 0, 0); + okHttpClientImpl.setHttpClient(null, "bilal", false, + 0, 0); + Map> additionalHeaders = Collections.singletonMap("SplitSDKImpressionsMode", + Collections.singletonList("OPTIMIZED")); + + okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder(); + requestBuilder.url(rootTarget.toString()); + PowerMockito.doReturn(requestBuilder).when(okHttpClientImpl).getRequestBuilder(); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setBasicHeaders(requestBuilder); + Whitebox.setInternalState(okHttpClientImpl, "_metadata", metadata()); + Whitebox.setInternalState(okHttpClientImpl, "_apikey", "qwerty"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).setAdditionalAndDecoratedHeaders(requestBuilder, additionalHeaders); + Whitebox.setInternalState(okHttpClientImpl, "_requestDecorator", requestDecorator); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).getResponseHeaders(any()); + + HttpEntity data = Utils.toJsonEntity("<>"); + PowerMockito.doCallRealMethod().when(okHttpClientImpl).post(rootTarget, data, + additionalHeaders); + + SplitHttpResponse splitHttpResponse = okHttpClientImpl.post(rootTarget, data, + additionalHeaders); + } + + private SDKMetadata metadata() { + return new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); + } +} diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpModuleTests.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpModuleTests.java new file mode 100644 index 000000000..e647fb0e5 --- /dev/null +++ b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/OkHttpModuleTests.java @@ -0,0 +1,111 @@ +package io.split.httpmodules.okhttp; + +import io.split.client.RequestDecorator; +import io.split.client.utils.SDKMetadata; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.mockito.stubbing.Answer; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.mockito.Mockito.verify; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.whenNew; + +@RunWith(PowerMockRunner.class) +@PrepareForTest(OkHttpModule.class) +public class OkHttpModuleTests { + @Test + public void checkProxySettings() { + OkHttpModule module = OkHttpModule.builder() + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyAuthKerberosPrincipalName("bilal@bilal") + .proxyHost("some-proxy") + .proxyPort(3128) + .build(); + Assert.assertEquals(ProxyAuthScheme.KERBEROS, module.proxyAuthScheme()); + Assert.assertEquals("bilal@bilal", module.proxyKerberosPrincipalName()); + Assert.assertEquals("HTTP @ some-proxy:3128", module.proxy().toString()); + } + + @Test + public void checkDebugLog() { + OkHttpModule module = OkHttpModule.builder() + .debugEnabled() + .build(); + Assert.assertEquals(true, module.debugEnabled()); + + module = OkHttpModule.builder() + .build(); + Assert.assertEquals(false, module.debugEnabled()); + } + + @Test + public void checkTimeouts() { + OkHttpModule module = OkHttpModule.builder() + .build(); + Assert.assertEquals(15000, (int) module.connectionTimeout()); + Assert.assertEquals(15000, (int) module.readTimeout()); + + module = OkHttpModule.builder() + .connectionTimeout(13000) + .readTimeout(14000) + .build(); + Assert.assertEquals(13000, (int) module.connectionTimeout()); + Assert.assertEquals(14000, (int) module.readTimeout()); + + module = OkHttpModule.builder() + .connectionTimeout(-1) + .readTimeout(-10) + .build(); + Assert.assertEquals(15000, (int) module.connectionTimeout()); + Assert.assertEquals(15000, (int) module.readTimeout()); + } + + @Test + public void testCreateClient() throws Exception { + OkHttpClientImpl mockclient = mock(OkHttpClientImpl.class); + AtomicBoolean argsCaptured = new AtomicBoolean(false); + + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("some-proxy", 3128)); + String apiToken = "qwerty"; + SDKMetadata sdkMetadata = new SDKMetadata("1.1.1", "ip", "name"); + RequestDecorator requestDecorator = new RequestDecorator(null); + + whenNew(OkHttpClientImpl.class).withAnyArguments() + .then((Answer) invocationOnMock -> { + assertThat("qwerty", is(equalTo((String) invocationOnMock.getArguments()[0]))); + assertThat(sdkMetadata, is(equalTo((SDKMetadata) invocationOnMock.getArguments()[1]))); + assertThat(requestDecorator, is(equalTo((RequestDecorator) invocationOnMock.getArguments()[2]))); + assertThat(proxy, is(equalTo((Proxy) invocationOnMock.getArguments()[3]))); + assertThat("bilal@bilal", is(equalTo((String) invocationOnMock.getArguments()[4]))); + assertThat(false, is(equalTo((Boolean) invocationOnMock.getArguments()[5]))); + assertThat(11000, is(equalTo((Integer) invocationOnMock.getArguments()[6]))); + assertThat(12000, is(equalTo((Integer) invocationOnMock.getArguments()[7]))); + argsCaptured.set(true); + return mockclient; + } + ); + + OkHttpModule module = OkHttpModule.builder() + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyAuthKerberosPrincipalName("bilal@bilal") + .proxyHost("some-proxy") + .proxyPort(3128) + .connectionTimeout(12000) + .readTimeout(11000) + .build(); + + module.createClient(apiToken, sdkMetadata, requestDecorator); + assertThat(true, is(equalTo(argsCaptured.get()))); + } +} diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitConfigTests.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitConfigTests.java index 3dca97d28..d4093464d 100644 --- a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitConfigTests.java +++ b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitConfigTests.java @@ -1,48 +1,31 @@ package io.split.httpmodules.okhttp; -import okhttp3.OkHttpClient; -//import okhttp3.OkHttpClient.Builder; +import io.split.client.SplitClientConfig; +import org.junit.Assert; +import org.junit.Test; public class SplitConfigTests { - /* + @Test public void checkExpectedAuthScheme() { - OkHttpClient client = new Builder().build(); - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - SplitClientConfig cfg = SplitClientConfig.builder() - .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosPrincipalName("bilal@bilal") - .proxyKerberosClient(okHttpModuleImpl) + .alternativeHTTPModule(OkHttpModule.builder() + .proxyAuthScheme(ProxyAuthScheme.KERBEROS) + .proxyAuthKerberosPrincipalName("bilal@bilal") + .proxyHost("some-proxy") + .proxyPort(3128) + .debugEnabled() + .build() + ) .build(); - Assert.assertEquals(ProxyAuthScheme.KERBEROS, cfg.proxyAuthScheme()); - Assert.assertEquals("bilal@bilal", cfg.proxyKerberosPrincipalName()); - Assert.assertEquals(okHttpModuleImpl, cfg.proxyKerberosClient()); + OkHttpModule module = (OkHttpModule) cfg.alternativeHTTPModule(); + Assert.assertEquals(ProxyAuthScheme.KERBEROS, module.proxyAuthScheme()); + Assert.assertEquals("bilal@bilal", module.proxyKerberosPrincipalName()); + Assert.assertEquals("HTTP @ some-proxy:3128", module.proxy().toString()); cfg = SplitClientConfig.builder() .build(); - Assert.assertEquals(null, cfg.proxyAuthScheme()); - } - - @Test(expected = IllegalStateException.class) - public void testAuthSchemeWithoutClient() { - SplitClientConfig.builder() - .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosPrincipalName("bilal") - .build(); + Assert.assertEquals(null, cfg.alternativeHTTPModule()); } - @Test(expected = IllegalStateException.class) - public void testAuthSchemeWithoutPrincipalName() { - OkHttpClient client = new Builder().build(); - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - - SplitClientConfig.builder() - .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosClient(okHttpModuleImpl) - .build(); - } - - */ - } diff --git a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitFactoryTests.java b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitFactoryTests.java index 0b623368c..f5dba8b7f 100644 --- a/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitFactoryTests.java +++ b/okhttp-modules/src/test/java/io/split/httpmodules/okhttp/SplitFactoryTests.java @@ -1,107 +1,67 @@ package io.split.httpmodules.okhttp; -import io.split.client.SplitFactoryImpl; +import io.split.client.*; +import io.split.client.utils.SDKMetadata; +import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.stubbing.Answer; +import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; -import okhttp3.OkHttpClient; -import okhttp3.OkHttpClient.*; -import okhttp3.HttpUrl; -import okhttp3.Headers; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.powermock.api.mockito.PowerMockito.mock; +import static org.powermock.api.mockito.PowerMockito.whenNew; @RunWith(PowerMockRunner.class) -@PrepareForTest(SplitFactoryImpl.class) +@PrepareForTest(OkHttpModule.class) public class SplitFactoryTests { - /* - public static final String ENDPOINT = "https://sdk.split-stage.io"; - @Test - public void testBuildKerberosClientParams() throws URISyntaxException, IOException { - PowerMockito.mockStatic(SplitFactoryImpl.class); - PowerMockito.mockStatic(OkHttpModule.class); - - ArgumentCaptor proxyCaptor = ArgumentCaptor.forClass(Proxy.class); - ArgumentCaptor configCaptor = ArgumentCaptor.forClass(SplitClientConfig.class); - ArgumentCaptor< HttpLoggingInterceptor> logCaptor = ArgumentCaptor.forClass( HttpLoggingInterceptor.class); - ArgumentCaptor authCaptor = ArgumentCaptor.forClass(Authenticator.class); - - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ENDPOINT, 6060)); - OkHttpClient client = OkHttpModule.buildOkHttpClient(proxy, "bilal@localhost", true, 0, 0) - OkHttpModuleImpl okHttpModuleImpl = new OkHttpModuleImpl(client, "qwerty"); - - SplitClientConfig splitClientConfig = SplitClientConfig.builder() - .setBlockUntilReadyTimeout(10000) + public void testFactoryCreatingClient() throws Exception { + OkHttpClientImpl mockclient = mock(OkHttpClientImpl.class); + AtomicBoolean argsCaptured = new AtomicBoolean(false); + + Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("some-proxy", 3128)); + String apiToken = "qwerty"; + + whenNew(OkHttpClientImpl.class).withAnyArguments() + .then((Answer) invocationOnMock -> { + assertThat("qwerty", is(equalTo((String) invocationOnMock.getArguments()[0]))); + assertThat((SDKMetadata) invocationOnMock.getArguments()[1], instanceOf(SDKMetadata.class)); + assertThat((RequestDecorator) invocationOnMock.getArguments()[2], instanceOf(RequestDecorator.class)); + assertThat(proxy, is(equalTo((Proxy) invocationOnMock.getArguments()[3]))); + assertThat("bilal@bilal", is(equalTo((String) invocationOnMock.getArguments()[4]))); + assertThat(false, is(equalTo((Boolean) invocationOnMock.getArguments()[5]))); + assertThat(11000, is(equalTo((Integer) invocationOnMock.getArguments()[6]))); + assertThat(12000, is(equalTo((Integer) invocationOnMock.getArguments()[7]))); + argsCaptured.set(true); + return mockclient; + } + ); + + OkHttpModule module = OkHttpModule.builder() .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosPrincipalName("bilal@localhost") - .proxyKerberosClient(okHttpModuleImpl) + .proxyAuthKerberosPrincipalName("bilal@bilal") + .proxyHost("some-proxy") + .proxyPort(3128) + .connectionTimeout(12000) + .readTimeout(11000) .build(); - Map kerberosOptions = new HashMap(); - kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required"); - kerberosOptions.put("refreshKrb5Config", "false"); - kerberosOptions.put("doNotPrompt", "false"); - kerberosOptions.put("useTicketCache", "true"); - BDDMockito.given(OkHttpModule.getProxyAuthenticator("bilal@localhost", kerberosOptions)) - .willReturn(null); - - RequestDecorator requestDecorator = new RequestDecorator(null); - SDKMetadata sdkmeta = new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); - - PowerMockito.verifyStatic(); - SplitFactoryImpl.buildOkHttpClient(proxyCaptor.capture(), configCaptor.capture(),logCaptor.capture(), authCaptor.capture()); - - Assert.assertEquals("HTTP @ https://sdk.split-stage.io:6060", proxyCaptor.getValue().toString()); - Assert.assertTrue(logCaptor.getValue() instanceof okhttp3.logging.HttpLoggingInterceptor); - } - - @Test - public void testFactoryKerberosInstance() throws URISyntaxException, IOException { - OkHttpClient okHttpClient = new OkHttpClient.Builder().build(); - PowerMockito.stub(PowerMockito.method(OkHttpModule.class, "buildOkHttpClient")).toReturn(okHttpClient); - PowerMockito.stub(PowerMockito.method(OkHttpModule.class, "getProxyAuthenticator")).toReturn(null); - - SplitClientConfig splitClientConfig = SplitClientConfig.builder() - .setBlockUntilReadyTimeout(10000) - .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosPrincipalName("bilal@localhost") - .proxyPort(6060) - .proxyHost(ENDPOINT) + SplitClientConfig cfg = SplitClientConfig.builder() + .alternativeHTTPModule(module) .build(); - Map kerberosOptions = new HashMap(); - kerberosOptions.put("com.sun.security.auth.module.Krb5LoginModule", "required"); - kerberosOptions.put("refreshKrb5Config", "false"); - kerberosOptions.put("doNotPrompt", "false"); - kerberosOptions.put("useTicketCache", "true"); - - RequestDecorator requestDecorator = new RequestDecorator(null); - SDKMetadata sdkmeta = new SDKMetadata("java-1.2.3", "1.2.3.4", "someIP"); - SplitHttpClient splitHttpClient = SplitFactoryImpl.buildSplitHttpClient("qwer", - splitClientConfig, - sdkmeta, - requestDecorator); - Assert.assertTrue(splitHttpClient instanceof OkHttpModuleImpl); - } + SplitFactoryImpl factory = (SplitFactoryImpl) SplitFactoryBuilder.build(apiToken, cfg); - @Test - public void testBuildOkHttpClient() { - SplitClientConfig splitClientConfig = SplitClientConfig.builder() - .setBlockUntilReadyTimeout(10000) - .proxyAuthScheme(ProxyAuthScheme.KERBEROS) - .proxyKerberosPrincipalName("bilal@localhost") - .proxyPort(6060) - .proxyHost(ENDPOINT) - .build(); - HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); - Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("host", 8080)); - OkHttpClient okHttpClient = SplitFactoryImpl.buildOkHttpClient(proxy, - splitClientConfig, loggingInterceptor, Authenticator.NONE); - assertEquals(Authenticator.NONE, okHttpClient.authenticator()); - assertEquals(proxy, okHttpClient.proxy()); - assertEquals(loggingInterceptor, okHttpClient.interceptors().get(0)); +// module.createClient(apiToken, sdkMetadata, requestDecorator); + assertThat(true, is(equalTo(argsCaptured.get()))); } - - */ - } diff --git a/okhttp-modules/src/test/resources/split-change-special-characters.json b/okhttp-modules/src/test/resources/split-change-special-characters.json new file mode 100644 index 000000000..9fd55904e --- /dev/null +++ b/okhttp-modules/src/test/resources/split-change-special-characters.json @@ -0,0 +1,56 @@ +{ + "splits": [ + { + "trafficTypeName": "user", + "name": "DEMO_MURMUR2", + "trafficAllocation": 100, + "trafficAllocationSeed": 1314112417, + "seed": -2059033614, + "status": "ACTIVE", + "killed": false, + "defaultTreatment": "of", + "changeNumber": 1491244291288, + "sets": [ "set1", "set2" ], + "algo": 2, + "configurations": { + "on": "{\"test\": \"blue\",\"grüne Straße\": 13}", + "off": "{\"test\": \"blue\",\"size\": 15}" + }, + "conditions": [ + { + "conditionType": "ROLLOUT", + "matcherGroup": { + "combiner": "AND", + "matchers": [ + { + "keySelector": { + "trafficType": "user", + "attribute": null + }, + "matcherType": "ALL_KEYS", + "negate": false, + "userDefinedSegmentMatcherData": null, + "whitelistMatcherData": null, + "unaryNumericMatcherData": null, + "betweenMatcherData": null + } + ] + }, + "partitions": [ + { + "treatment": "on", + "size": 0 + }, + { + "treatment": "of", + "size": 100 + } + ], + "label": "in segment all" + } + ] + } + ], + "since": 1491244291288, + "till": 1491244291288 +} diff --git a/pom.xml b/pom.xml index 5afc4f3f7..a7c51ff30 100644 --- a/pom.xml +++ b/pom.xml @@ -84,8 +84,8 @@ pluggable-storage redis-wrapper testing - client okhttp-modules + client