From 534849c017c1dd09a489b6e69ad1e968c94910d4 Mon Sep 17 00:00:00 2001 From: Kevin McGoldrick Date: Fri, 23 May 2025 15:52:29 -0700 Subject: [PATCH] Http Client Coverage --- .../tank/httpclient3/TankHttpClient3.java | 18 +- .../tank/httpclient3/TankHttpClient3Test.java | 179 +++++++++++++++++- .../resources/mappings/httpbin.org-stubs.json | 38 +++- .../tank/httpclient4/TankHttpClient4.java | 24 +-- .../tank/httpclient4/TankHttpClient4Test.java | 112 +++++++---- .../resources/mappings/httpbin.org-stubs.json | 38 +++- .../tank/httpclientjdk/TankHttpClientJDK.java | 24 ++- .../httpclientjdk/TankHttpClientJDKTest.java | 55 ++++++ .../resources/mappings/httpbin.org-stubs.json | 38 +++- 9 files changed, 446 insertions(+), 80 deletions(-) diff --git a/agent/http_client_3/src/main/java/com/intuit/tank/httpclient3/TankHttpClient3.java b/agent/http_client_3/src/main/java/com/intuit/tank/httpclient3/TankHttpClient3.java index 6d069ca96..486c3d829 100644 --- a/agent/http_client_3/src/main/java/com/intuit/tank/httpclient3/TankHttpClient3.java +++ b/agent/http_client_3/src/main/java/com/intuit/tank/httpclient3/TankHttpClient3.java @@ -79,6 +79,13 @@ public TankHttpClient3() { httpclient.setState(new HttpState()); } + /** + * constructor for test + */ + public TankHttpClient3(HttpClient httpclient) { + this.httpclient = httpclient; + } + public Object createHttpClient() { return null; } public void setHttpClient(Object httpClient) {} @@ -434,19 +441,14 @@ private void processResponse(byte[] bResponse, long waitTime, BaseRequest reques @SuppressWarnings("rawtypes") private void setHeaders(BaseRequest request, HttpMethod method, HashMap headerInformation) { try { - Set set = headerInformation.entrySet(); - - for (Object aSet : set) { - Map.Entry mapEntry = (Map.Entry) aSet; - method.setRequestHeader((String) mapEntry.getKey(), (String) mapEntry.getValue()); - } + headerInformation.entrySet().forEach(entry -> { + method.setRequestHeader((String) ((Map.Entry) entry).getKey(), (String) ((Map.Entry) entry).getValue()); + }); } catch (Exception ex) { LOG.warn(request.getLogUtil().getLogMessage("Unable to set header: " + ex.getMessage(), LogEventType.System)); } } - - private List buildParts(BaseRequest request) { List parts = new ArrayList(); for (PartHolder h : TankHttpUtil.getPartsFromBody(request)) { diff --git a/agent/http_client_3/src/test/java/com/intuit/tank/httpclient3/TankHttpClient3Test.java b/agent/http_client_3/src/test/java/com/intuit/tank/httpclient3/TankHttpClient3Test.java index dee127773..3320f177f 100644 --- a/agent/http_client_3/src/test/java/com/intuit/tank/httpclient3/TankHttpClient3Test.java +++ b/agent/http_client_3/src/test/java/com/intuit/tank/httpclient3/TankHttpClient3Test.java @@ -1,8 +1,9 @@ package com.intuit.tank.httpclient3; -import java.io.File; +import java.io.IOException; +import java.net.SocketException; import java.net.URL; -import java.util.List; +import java.net.UnknownHostException; import com.intuit.tank.http.AuthCredentials; import com.intuit.tank.http.AuthScheme; @@ -11,14 +12,19 @@ import com.intuit.tank.http.TankCookie; import com.intuit.tank.http.TankHttpClient; import com.intuit.tank.test.TestGroups; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; import org.apache.http.entity.ContentType; import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.mockito.Mockito.when; public class TankHttpClient3Test { @@ -109,6 +115,41 @@ public void doGet() { assertNotNull(response.getBody()); } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doGetException() throws IOException { + HttpClient mockHttpClient = Mockito.mock(HttpClient.class); + when(mockHttpClient + .executeMethod(ArgumentMatchers.any(HttpMethod.class))) + .thenThrow(new UnknownHostException("Mocked UnknownHost exception")); + BaseRequest request = getRequest(new TankHttpClient3(mockHttpClient), wireMockServer.baseUrl() + "/get"); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .executeMethod(ArgumentMatchers.any(HttpMethod.class))) + .thenThrow(new SocketException("Mocked Socket Exception")); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .executeMethod(ArgumentMatchers.any(HttpMethod.class))) + .thenThrow(new RuntimeException("Mocked Exception")); + assertThrows(RuntimeException.class, () -> request.doGet(null)); + } + + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doOptions() { + BaseRequest request = getRequest(new TankHttpClient3(), wireMockServer.baseUrl() + "/options"); + request.doOptions(null); + BaseResponse response = request.getResponse(); + verify(exactly(1), optionsRequestedFor(urlEqualTo("/options"))); + assertNotNull(response); + assertEquals(204, response.getHttpCode()); + assertNotNull(response.getBody()); + } + @Test @Tag(TestGroups.FUNCTIONAL) public void doPost() { @@ -233,6 +274,140 @@ public void testSSL() { } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doPostMultipartwithFile() throws IOException { + BaseRequest request = getRequest(new TankHttpClient3(), wireMockServer.baseUrl() + "/post"); + request.setContentType(BaseRequest.CONTENT_TYPE_MULTIPART); + request.setBody( + "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3" + + "U2NyaXB0Rm9ybSINCg0KY3JlYXRlTmV3U2NyaXB0Rm9ybQ0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRG" + + "lzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpqX2lkdDUxOnNhdmVCdG4iDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0t" + + "LS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpuYW1lVEYiDQo" + + "NClRlc3RNdWx0aVBhcnQNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdG" + + "E7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06cHJvZHVjdE5hbWVDQl9mb2N1cyINCg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzN" + + "DkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXdTY3JpcHRGb3JtOnByb2R1Y3ROYW1lQ0JfaW5wdXQiDQoNCkNB" + + "Uw0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXR" + + "lTmV3U2NyaXB0Rm9ybTpqX2lkdDg0Ig0KDQpVcGxvYWQgU2NyaXB0DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udG" + + "VudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXdTY3JpcHRGb3JtOmpfaWR0OTEiOyBmaWxlbmFtZT0ic2FtcGxlLnhtbCINCkNvbnRlb" + + "nQtVHlwZTogdGV4dC94bWwNCg0KPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzbnM6c2Vzc2lvbiB4bWxu" + + "czpzbnM9InVybjpwcm94eS9jb252ZXJzYXRpb24vdjEiIGZvbGxvd1JlZGlyZWN0cz0idHJ1ZSI+Cjx0cmFuc2FjdGlvbiB4bWxucz0idXJuOnByb3h5L2NvbnZ" + + "lcnNhdGlvbi92MSI+CiAgICA8cmVxdWVzdD4KICAgICAgICA8cHJvdG9jb2w+aHR0cDwvcHJvdG9jb2w+CiAgICAgICAgPGZpcnN0TGluZT5HRVQgL3Byb2plY3" + + "RzIEhUVFAvMS4xPC9maXJzdExpbmU+CiAgICAgICAgPGhlYWRlcnM+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5Pkhvc3Q8L2tle" + + "T4KICAgICAgICAgICAgICAgIDx2YWx1ZT5hVzUwWlhKdVlXd3RkR0Z1YXkxd2IyTXRNVEF4T1RneE56TTNPQzUxY3kxM1pYTjBMVEl1Wld4aUxtRnRZWHB2Ym1GM" + + "2N5NWpiMjA9PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PlVzZXItQWdlbnQ8" + + "L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5UVzk2YVd4c1lTODFMakFnS0ZkcGJtUnZkM01nVGxRZ05pNHhPeUJYVDFjMk5Ec2djblk2TkRFdU1Da2dSMlZ" + + "qYTI4dk1qQXhNREF4TURFZ1JtbHlaV1p2ZUM4ME1TNHc8L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgIC" + + "AgICAgICAgIDxrZXk+QWNjZXB0PC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+ZEdWNGRDOW9kRzFzTEdGd2NHeHBZMkYwYVc5dUwzaG9kRzFzSzNodGJDe" + + "GhjSEJzYVdOaGRHbHZiaTk0Yld3N2NUMHdMamtzS2k4cU8zRTlNQzQ0PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+" + + "CiAgICAgICAgICAgICAgICA8a2V5PkFjY2VwdC1MYW5ndWFnZTwva2V5PgogICAgICAgICAgICAgICAgPHZhbHVlPlpXNHRWVk1zWlc0N2NUMHdMalU9PC92YWx1" + + "ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PkFjY2VwdC1FbmNvZGluZzwva2V5PgogICAg" + + "ICAgICAgICAgICAgPHZhbHVlPlozcHBjQ3dnWkdWbWJHRjBaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiA" + + "gICAgICAgICAgICAgICA8a2V5PlJlZmVyZXI8L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5hSFIwY0RvdkwybHVkR1Z5Ym1Gc0xYUmhibXN0Y0c5akxURX" + + "dNVGs0TVRjek56Z3VkWE10ZDJWemRDMHlMbVZzWWk1aGJXRjZiMjVoZDNNdVkyOXRMM05qY21sd2RITXZZM0psWVhSbFRtVjNVMk55YVhCMExtcHpaajlqYVdRO" + + "U1RPT08L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgICAgICAgICAgIDxrZXk+Q29va2llPC9rZXk+CiA" + + "gICAgICAgICAgICAgICA8dmFsdWU+U2xORlUxTkpUMDVKUkQweU5VRXhNams1UVRBMU9EWkNSRVUwUkVNNFJrSTVNa1l5TVRCQlFqTkRRdz09PC92YWx1ZT4KIC" + + "AgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PkNvbm5lY3Rpb248L2tleT4KICAgICAgICAgICAgIC" + + "AgIDx2YWx1ZT5hMlZsY0MxaGJHbDJaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgIC" + + "A8a2V5PlgtUFJPWFktQVBQPC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+Y21Wa2FYSmxZM1JEYjJ4c1lYQnpaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9" + + "oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PlgtUmVkaXJlY3QtTG9jYXRpb248L2tleT4KICAgICAgICAgICAgICAgIDx2" + + "YWx1ZT5hSFIwY0RvdkwybHVkR1Z5Ym1Gc0xYUmhibXN0Y0c5akxURXdNVGs0TVRjek56Z3VkWE10ZDJWemRDMHlMbVZzWWk1aGJXRjZiMjVoZDNNdVkyOXRMM0J5Y" + + "jJwbFkzUnpMdz09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgPC9oZWFkZXJzPgogICAgPC9yZXF1ZXN0PgogICAgPHJlc3BvbnNlPgogIC" + + "AgICAgIDxmaXJzdExpbmU+SFRUUC8xLjEgMzA0IE5vdCBNb2RpZmllZDwvZmlyc3RMaW5lPgogICAgICAgIDxoZWFkZXJzPgogICAgICAgICAgICA8aGVhZGVyPgo" + + "gICAgICAgICAgICAgICAgPGtleT5EYXRlPC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+VjJWa0xDQXpNQ0JUWlhBZ01qQXhOU0F4T0Rvd09Ub3dNU0JIVFZRP" + + "TwvdmFsdWU+CiAgICAgICAgICAgIDwvaGVhZGVyPgogICAgICAgICAgICA8aGVhZGVyPgogICAgICAgICAgICAgICAgPGtleT5FVGFnPC9rZXk+CiAgICAgICAgICAg" + + "ICAgICA8dmFsdWU+Vnk4aU1qWXdMVEUwTkRNd01qa3dPRFl3TURBaTwvdmFsdWU+CiAgICAgICAgICAgIDwvaGVhZGVyPgogICAgICAgICAgICA8aGVhZGVyPgogICA" + + "gICAgICAgICAgICAgPGtleT5TZXJ2ZXI8L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5RWEJoWTJobExVTnZlVzkwWlM4eExqRT08L3ZhbHVlPgogICAgICAgIC" + + "AgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgICAgICAgICAgIDxrZXk+Q29ubmVjdGlvbjwva2V5PgogICAgICAgICAgICAgICAgPHZhbHVl" + + "PmEyVmxjQzFoYkdsMlpRPT08L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICA8L2hlYWRlcnM+CiAgICAgICAgPGJvZHk+PC9ib2R5PgogICAgPC9" + + "yZXNwb25zZT4KPC90cmFuc2FjdGlvbj4KPC9zbnM6c2Vzc2lvbj4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LU" + + "Rpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06Z3JvdXBUYWJsZTpmaWx0ZXJHcm91cE5hbWU6ZmlsdGVyIg0KDQoNCi0tLS0" + + "tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1Njcmlwd" + + "EZvcm06Z3JvdXBUYWJsZTpmaWx0ZXJHcm91cFByb2R1Y3Q6ZmlsdGVyIg0KDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQp" + + "Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06ZmlsdGVyVGFibGVJZDpmaWx0ZXJOYW1lOmZpbHRlciINCg0KD" + + "QotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXd" + + "TY3JpcHRGb3JtOmZpbHRlclRhYmxlSWQ6ZmlsdGVyUHJvZHVjdDpmaWx0ZXIiDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4M" + + "jYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpmaWx0ZXJUYWJsZUlkOjA6al9pZHQxMDJfaW5wdXQiDQo" + + "NCm9uDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhd" + + "GVOZXdTY3JpcHRGb3JtOmZpbHRlclRhYmxlSWQ6MTpqX2lkdDEwMl9pbnB1dCINCg0Kb24NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI" + + "5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06ZmlsdGVyVGFibGVJZF9zY3JvbGxTdGF0ZSINCg0KM" + + "CwwDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJqYXZheC5" + + "mYWNlcy5WaWV3U3RhdGUiDQoNCi0yMDU5ODE2MTg5MDc2NDYzMzg5Oi01NDAzNTEzNDYxNzE3MjAzMDUNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyN" + + "jExNTM0OTI5ODI2LS0NCg=="); + request.doPost(null); + BaseResponse response = request.getResponse(); + assertNotNull(response); + assertEquals(200, response.getHttpCode()); + assertNotNull(response.getBody()); + } + + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doPutMultipartwithFile() throws IOException { + BaseRequest request = getRequest(new TankHttpClient3(), wireMockServer.baseUrl() + "/put"); + request.setContentType(BaseRequest.CONTENT_TYPE_MULTIPART); + request.setBody( + "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3" + + "U2NyaXB0Rm9ybSINCg0KY3JlYXRlTmV3U2NyaXB0Rm9ybQ0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRG" + + "lzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpqX2lkdDUxOnNhdmVCdG4iDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0t" + + "LS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpuYW1lVEYiDQo" + + "NClRlc3RNdWx0aVBhcnQNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdG" + + "E7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06cHJvZHVjdE5hbWVDQl9mb2N1cyINCg0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzN" + + "DkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXdTY3JpcHRGb3JtOnByb2R1Y3ROYW1lQ0JfaW5wdXQiDQoNCkNB" + + "Uw0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXR" + + "lTmV3U2NyaXB0Rm9ybTpqX2lkdDg0Ig0KDQpVcGxvYWQgU2NyaXB0DQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udG" + + "VudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXdTY3JpcHRGb3JtOmpfaWR0OTEiOyBmaWxlbmFtZT0ic2FtcGxlLnhtbCINCkNvbnRlb" + + "nQtVHlwZTogdGV4dC94bWwNCg0KPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzbnM6c2Vzc2lvbiB4bWxu" + + "czpzbnM9InVybjpwcm94eS9jb252ZXJzYXRpb24vdjEiIGZvbGxvd1JlZGlyZWN0cz0idHJ1ZSI+Cjx0cmFuc2FjdGlvbiB4bWxucz0idXJuOnByb3h5L2NvbnZ" + + "lcnNhdGlvbi92MSI+CiAgICA8cmVxdWVzdD4KICAgICAgICA8cHJvdG9jb2w+aHR0cDwvcHJvdG9jb2w+CiAgICAgICAgPGZpcnN0TGluZT5HRVQgL3Byb2plY3" + + "RzIEhUVFAvMS4xPC9maXJzdExpbmU+CiAgICAgICAgPGhlYWRlcnM+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5Pkhvc3Q8L2tle" + + "T4KICAgICAgICAgICAgICAgIDx2YWx1ZT5hVzUwWlhKdVlXd3RkR0Z1YXkxd2IyTXRNVEF4T1RneE56TTNPQzUxY3kxM1pYTjBMVEl1Wld4aUxtRnRZWHB2Ym1GM" + + "2N5NWpiMjA9PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PlVzZXItQWdlbnQ8" + + "L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5UVzk2YVd4c1lTODFMakFnS0ZkcGJtUnZkM01nVGxRZ05pNHhPeUJYVDFjMk5Ec2djblk2TkRFdU1Da2dSMlZ" + + "qYTI4dk1qQXhNREF4TURFZ1JtbHlaV1p2ZUM4ME1TNHc8L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgIC" + + "AgICAgICAgIDxrZXk+QWNjZXB0PC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+ZEdWNGRDOW9kRzFzTEdGd2NHeHBZMkYwYVc5dUwzaG9kRzFzSzNodGJDe" + + "GhjSEJzYVdOaGRHbHZiaTk0Yld3N2NUMHdMamtzS2k4cU8zRTlNQzQ0PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+" + + "CiAgICAgICAgICAgICAgICA8a2V5PkFjY2VwdC1MYW5ndWFnZTwva2V5PgogICAgICAgICAgICAgICAgPHZhbHVlPlpXNHRWVk1zWlc0N2NUMHdMalU9PC92YWx1" + + "ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PkFjY2VwdC1FbmNvZGluZzwva2V5PgogICAg" + + "ICAgICAgICAgICAgPHZhbHVlPlozcHBjQ3dnWkdWbWJHRjBaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiA" + + "gICAgICAgICAgICAgICA8a2V5PlJlZmVyZXI8L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5hSFIwY0RvdkwybHVkR1Z5Ym1Gc0xYUmhibXN0Y0c5akxURX" + + "dNVGs0TVRjek56Z3VkWE10ZDJWemRDMHlMbVZzWWk1aGJXRjZiMjVoZDNNdVkyOXRMM05qY21sd2RITXZZM0psWVhSbFRtVjNVMk55YVhCMExtcHpaajlqYVdRO" + + "U1RPT08L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgICAgICAgICAgIDxrZXk+Q29va2llPC9rZXk+CiA" + + "gICAgICAgICAgICAgICA8dmFsdWU+U2xORlUxTkpUMDVKUkQweU5VRXhNams1UVRBMU9EWkNSRVUwUkVNNFJrSTVNa1l5TVRCQlFqTkRRdz09PC92YWx1ZT4KIC" + + "AgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PkNvbm5lY3Rpb248L2tleT4KICAgICAgICAgICAgIC" + + "AgIDx2YWx1ZT5hMlZsY0MxaGJHbDJaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgIC" + + "A8a2V5PlgtUFJPWFktQVBQPC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+Y21Wa2FYSmxZM1JEYjJ4c1lYQnpaUT09PC92YWx1ZT4KICAgICAgICAgICAgPC9" + + "oZWFkZXI+CiAgICAgICAgICAgIDxoZWFkZXI+CiAgICAgICAgICAgICAgICA8a2V5PlgtUmVkaXJlY3QtTG9jYXRpb248L2tleT4KICAgICAgICAgICAgICAgIDx2" + + "YWx1ZT5hSFIwY0RvdkwybHVkR1Z5Ym1Gc0xYUmhibXN0Y0c5akxURXdNVGs0TVRjek56Z3VkWE10ZDJWemRDMHlMbVZzWWk1aGJXRjZiMjVoZDNNdVkyOXRMM0J5Y" + + "jJwbFkzUnpMdz09PC92YWx1ZT4KICAgICAgICAgICAgPC9oZWFkZXI+CiAgICAgICAgPC9oZWFkZXJzPgogICAgPC9yZXF1ZXN0PgogICAgPHJlc3BvbnNlPgogIC" + + "AgICAgIDxmaXJzdExpbmU+SFRUUC8xLjEgMzA0IE5vdCBNb2RpZmllZDwvZmlyc3RMaW5lPgogICAgICAgIDxoZWFkZXJzPgogICAgICAgICAgICA8aGVhZGVyPgo" + + "gICAgICAgICAgICAgICAgPGtleT5EYXRlPC9rZXk+CiAgICAgICAgICAgICAgICA8dmFsdWU+VjJWa0xDQXpNQ0JUWlhBZ01qQXhOU0F4T0Rvd09Ub3dNU0JIVFZRP" + + "TwvdmFsdWU+CiAgICAgICAgICAgIDwvaGVhZGVyPgogICAgICAgICAgICA8aGVhZGVyPgogICAgICAgICAgICAgICAgPGtleT5FVGFnPC9rZXk+CiAgICAgICAgICAg" + + "ICAgICA8dmFsdWU+Vnk4aU1qWXdMVEUwTkRNd01qa3dPRFl3TURBaTwvdmFsdWU+CiAgICAgICAgICAgIDwvaGVhZGVyPgogICAgICAgICAgICA8aGVhZGVyPgogICA" + + "gICAgICAgICAgICAgPGtleT5TZXJ2ZXI8L2tleT4KICAgICAgICAgICAgICAgIDx2YWx1ZT5RWEJoWTJobExVTnZlVzkwWlM4eExqRT08L3ZhbHVlPgogICAgICAgIC" + + "AgICA8L2hlYWRlcj4KICAgICAgICAgICAgPGhlYWRlcj4KICAgICAgICAgICAgICAgIDxrZXk+Q29ubmVjdGlvbjwva2V5PgogICAgICAgICAgICAgICAgPHZhbHVl" + + "PmEyVmxjQzFoYkdsMlpRPT08L3ZhbHVlPgogICAgICAgICAgICA8L2hlYWRlcj4KICAgICAgICA8L2hlYWRlcnM+CiAgICAgICAgPGJvZHk+PC9ib2R5PgogICAgPC9" + + "yZXNwb25zZT4KPC90cmFuc2FjdGlvbj4KPC9zbnM6c2Vzc2lvbj4NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LU" + + "Rpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06Z3JvdXBUYWJsZTpmaWx0ZXJHcm91cE5hbWU6ZmlsdGVyIg0KDQoNCi0tLS0" + + "tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1Njcmlwd" + + "EZvcm06Z3JvdXBUYWJsZTpmaWx0ZXJHcm91cFByb2R1Y3Q6ZmlsdGVyIg0KDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI5ODI2DQp" + + "Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06ZmlsdGVyVGFibGVJZDpmaWx0ZXJOYW1lOmZpbHRlciINCg0KD" + + "QotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhdGVOZXd" + + "TY3JpcHRGb3JtOmZpbHRlclRhYmxlSWQ6ZmlsdGVyUHJvZHVjdDpmaWx0ZXIiDQoNCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4M" + + "jYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3U2NyaXB0Rm9ybTpmaWx0ZXJUYWJsZUlkOjA6al9pZHQxMDJfaW5wdXQiDQo" + + "NCm9uDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJjcmVhd" + + "GVOZXdTY3JpcHRGb3JtOmZpbHRlclRhYmxlSWQ6MTpqX2lkdDEwMl9pbnB1dCINCg0Kb24NCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyNjExNTM0OTI" + + "5ODI2DQpDb250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9ImNyZWF0ZU5ld1NjcmlwdEZvcm06ZmlsdGVyVGFibGVJZF9zY3JvbGxTdGF0ZSINCg0KM" + + "CwwDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLTE3MjYxMTUzNDkyOTgyNg0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJqYXZheC5" + + "mYWNlcy5WaWV3U3RhdGUiDQoNCi0yMDU5ODE2MTg5MDc2NDYzMzg5Oi01NDAzNTEzNDYxNzE3MjAzMDUNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tMTcyN" + + "jExNTM0OTI5ODI2LS0NCg=="); + request.doPut(null); + BaseResponse response = request.getResponse(); + assertNotNull(response); + assertEquals(200, response.getHttpCode()); + assertNotNull(response.getBody()); + } + private BaseRequest getRequest(TankHttpClient client, String url) { try { URL u = new URL(url); diff --git a/agent/http_client_3/src/test/resources/mappings/httpbin.org-stubs.json b/agent/http_client_3/src/test/resources/mappings/httpbin.org-stubs.json index ed61ded71..4f4433e7c 100644 --- a/agent/http_client_3/src/test/resources/mappings/httpbin.org-stubs.json +++ b/agent/http_client_3/src/test/resources/mappings/httpbin.org-stubs.json @@ -1164,7 +1164,12 @@ "method" : "POST" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{\n \"key\" : \"value\"\n}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "NumberFormatException" + } }, "uuid" : "62f1251b-62e1-453f-86ae-3568c80feaa6", "persistent" : true, @@ -1524,7 +1529,12 @@ "method" : "GET" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{ \"message\": \"The request's query parameters.\"}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "123456" + } }, "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e42", "persistent" : true, @@ -2664,5 +2674,29 @@ } }, "insertionIndex" : 109 + }, { + "id" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "name" : "The request's options. - 204", + "request" : { + "urlPath" : "/options", + "method" : "OPTIONS" + }, + "response" : { + "status" : 204 + }, + "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "persistent" : true, + "metadata" : { + "mocklab" : { + "created" : { + "at" : "2023-03-28T09:23:52.398583Z", + "via" : "OAS3_IMPORT" + }, + "oas" : { + "operationId" : "(none)" + } + } + }, + "insertionIndex" : 110 } ] } \ No newline at end of file diff --git a/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java b/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java index 0d4151786..51c8b7a8a 100644 --- a/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java +++ b/agent/http_client_4/src/main/java/com/intuit/tank/httpclient4/TankHttpClient4.java @@ -284,16 +284,10 @@ public void setCookie(TankCookie tankCookie) { @Override public void setProxy(String proxyhost, int proxyport) { - if (StringUtils.isNotBlank(proxyhost)) { - HttpHost proxy = new HttpHost(proxyhost, proxyport); - RequestConfig requestConfig = - context.getRequestConfig().custom().setProxy(proxy).build(); - context.setRequestConfig(requestConfig); - } else { - RequestConfig requestConfig = - context.getRequestConfig().custom().setProxy(null).build(); - context.setRequestConfig(requestConfig); - } + RequestConfig requestConfig = (StringUtils.isNotBlank(proxyhost)) + ? context.getRequestConfig().custom().setProxy(new HttpHost(proxyhost, proxyport)).build() + : context.getRequestConfig().custom().setProxy(null).build(); + context.setRequestConfig(requestConfig); } private void sendRequest(BaseRequest request, @Nonnull HttpRequestBase method, String requestBody) { @@ -453,18 +447,14 @@ private void processResponse(byte[] bResponse, long waitTime, BaseRequest reques @SuppressWarnings("rawtypes") private void setHeaders(BaseRequest request, HttpRequestBase method, HashMap headerInformation) { try { - Set set = headerInformation.entrySet(); - - for (Object aSet : set) { - Map.Entry mapEntry = (Map.Entry) aSet; - method.setHeader((String) mapEntry.getKey(), (String) mapEntry.getValue()); - } + headerInformation.entrySet().forEach(entry -> { + method.setHeader((String) ((Map.Entry) entry).getKey(), (String) ((Map.Entry) entry).getValue()); + }); } catch (Exception ex) { LOG.warn(request.getLogUtil().getLogMessage("Unable to set header: " + ex.getMessage(), LogEventType.System)); } } - private HttpEntity buildParts(BaseRequest request) { MultipartEntityBuilder builder = MultipartEntityBuilder.create(); String contentType = request.getContentType(); diff --git a/agent/http_client_4/src/test/java/com/intuit/tank/httpclient4/TankHttpClient4Test.java b/agent/http_client_4/src/test/java/com/intuit/tank/httpclient4/TankHttpClient4Test.java index e8537bf75..e07cc9a47 100644 --- a/agent/http_client_4/src/test/java/com/intuit/tank/httpclient4/TankHttpClient4Test.java +++ b/agent/http_client_4/src/test/java/com/intuit/tank/httpclient4/TankHttpClient4Test.java @@ -1,12 +1,15 @@ package com.intuit.tank.httpclient4; import java.io.IOException; +import java.net.SocketException; import java.net.URL; -import java.nio.charset.StandardCharsets; +import java.net.UnknownHostException; import java.util.Base64; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.http.HttpEntity; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; @@ -17,13 +20,17 @@ import com.intuit.tank.http.TankCookie; import com.intuit.tank.http.TankHttpClient; import com.intuit.tank.test.TestGroups; +import org.apache.http.impl.client.CloseableHttpClient; import org.junit.jupiter.api.*; import static org.junit.jupiter.api.Assertions.*; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.mockito.Mockito.when; public class TankHttpClient4Test { @@ -46,7 +53,7 @@ public void teardown() { @Test @Tag(TestGroups.FUNCTIONAL) public void testBasicAuth() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/basic-auth/test/test_pass"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/basic-auth/test/test_pass"); request.getHttpclient().addAuth(AuthCredentials.builder().withUserName("test").withPassword("test_pass").withRealm("bogus").withScheme(AuthScheme.Basic).build()); request.addHeader("X-Test-Mode", "Fail"); @@ -55,7 +62,7 @@ public void testBasicAuth() { assertNotNull(response); assertEquals(401, response.getHttpCode()); - request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/basic-auth/test/test_pass"); + request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/basic-auth/test/test_pass"); request.getHttpclient().addAuth(AuthCredentials.builder().withUserName("test").withPassword("test_pass").withHost("localhost").withRealm("Fake Realm").withScheme(AuthScheme.Basic).build()); request.addHeader("X-Test-Mode", "Pass"); @@ -70,7 +77,7 @@ public void testBasicAuth() { @Test @Tag(TestGroups.FUNCTIONAL) public void testDigestAuth() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/digest-auth/auth/test/test_pass"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/digest-auth/auth/test/test_pass"); request.getHttpclient().addAuth(AuthCredentials.builder().withUserName("test").withPassword("test_pass").withRealm("bogus").withScheme(AuthScheme.Digest).build()); request.addHeader("X-Test-Mode", "Fail"); @@ -79,7 +86,7 @@ public void testDigestAuth() { assertNotNull(response); assertEquals(401, response.getHttpCode()); - request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/digest-auth/auth/test/test_pass"); + request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/digest-auth/auth/test/test_pass"); request.getHttpclient().addAuth(AuthCredentials.builder().withUserName("test").withPassword("test_pass").withHost("httpbin.org").withScheme(AuthScheme.Digest).build()); request.addHeader("X-Test-Mode", "Pass"); @@ -95,7 +102,8 @@ public void testDigestAuth() { @Test @Tag(TestGroups.FUNCTIONAL) public void doDelete() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/delete"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/delete"); + request.getLogUtil().getAgentConfig().getLogPostResponse(); request.doDelete(null); BaseResponse response = request.getResponse(); verify(exactly(1), deleteRequestedFor(urlEqualTo("/delete"))); @@ -106,7 +114,7 @@ public void doDelete() { @Test @Tag(TestGroups.FUNCTIONAL) public void doGet() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/get"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/get"); request.doGet(null); BaseResponse response = request.getResponse(); verify(exactly(1), getRequestedFor(urlEqualTo("/get"))); @@ -115,10 +123,45 @@ public void doGet() { assertNotNull(response.getBody()); } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doGetException() throws IOException { + CloseableHttpClient mockHttpClient = Mockito.mock(CloseableHttpClient.class); + when(mockHttpClient + .execute(ArgumentMatchers.any(HttpRequestBase.class), ArgumentMatchers.any(HttpClientContext.class))) + .thenThrow(new UnknownHostException("Mocked UnknownHost exception")); + BaseRequest request = getRequest(new TankHttpClient4(), mockHttpClient, wireMockServer.baseUrl() + "/get"); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .execute(ArgumentMatchers.any(HttpRequestBase.class), ArgumentMatchers.any(HttpClientContext.class))) + .thenThrow(new SocketException("Mocked Socket Exception")); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .execute(ArgumentMatchers.any(HttpRequestBase.class), ArgumentMatchers.any(HttpClientContext.class))) + .thenThrow(new RuntimeException("Mocked Exception")); + assertThrows(RuntimeException.class, () -> request.doGet(null)); + } + + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doOptions() { + BaseRequest request = getRequest(new TankHttpClient4(), null,wireMockServer.baseUrl() + "/options"); + request.doOptions(null); + BaseResponse response = request.getResponse(); + verify(exactly(1), optionsRequestedFor(urlEqualTo("/options"))); + assertNotNull(response); + assertEquals(204, response.getHttpCode()); + assertNotNull(response.getBody()); + } + @Test @Tag(TestGroups.FUNCTIONAL) public void doPost() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/post"); + BaseRequest request = getRequest(new TankHttpClient4(), null,wireMockServer.baseUrl() + "/post"); request.setBody("{\"title\":\"Direct deposit with Credit Karma Money™ checking account¹\"}"); request.setContentType(ContentType.APPLICATION_JSON.getMimeType()); request.doPost(null); @@ -131,10 +174,22 @@ public void doPost() { assertNotNull(response.getBody()); } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doPatch() { + BaseRequest request = getRequest(new TankHttpClient4(), null,wireMockServer.baseUrl() + "/patch"); + request.doPatch(null); + BaseResponse response = request.getResponse(); + verify(exactly(1), patchRequestedFor(urlEqualTo("/patch"))); + assertNotNull(response); + assertEquals(200, response.getHttpCode()); + assertNotNull(response.getBody()); + } + @Test @Tag(TestGroups.FUNCTIONAL) public void doPut() { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/put"); + BaseRequest request = getRequest(new TankHttpClient4(), null,wireMockServer.baseUrl() + "/put"); request.setBody("{\"title\":\"Direct deposit with Credit Karma Money™ checking account¹\"}"); request.setContentType(ContentType.APPLICATION_JSON.getMimeType()); request.doPut(null); @@ -165,7 +220,7 @@ public void clearSession() { .atPriority(2) ); - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/cookies"); + BaseRequest request = getRequest(new TankHttpClient4(),null, wireMockServer.baseUrl() + "/cookies"); request.getHttpclient().setCookie(TankCookie.builder().withName("test-cookie").withValue("test-value").withDomain("localhost").withPath("/").build()); request.doGet(null); BaseResponse response = request.getResponse(); @@ -192,7 +247,7 @@ public void setCookie() { .atPriority(1) ); - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/cookies"); + BaseRequest request = getRequest(new TankHttpClient4(), null,wireMockServer.baseUrl() + "/cookies"); request.getHttpclient().setCookie(TankCookie.builder().withName("test-cookie").withValue("test-value").withDomain("localhost").withPath("/").build()); request.doGet(null); BaseResponse response = request.getResponse(); @@ -205,8 +260,7 @@ public void setCookie() { @Disabled @Tag(TestGroups.FUNCTIONAL) public void setProxy() { - BaseRequest request = getRequest(new TankHttpClient4(), - "http://httpbin.org/ip"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/get"); request.getHttpclient().setProxy("168.9.128.152", 8080); request.doGet(null); BaseResponse response = request.getResponse(); @@ -232,7 +286,7 @@ public void setProxy() { @Test @Tag(TestGroups.MANUAL) public void testSSL() { - BaseRequest request = getRequest(new TankHttpClient4(), "https://turbotax.intuit.com/"); + BaseRequest request = getRequest(new TankHttpClient4(), null,"https://turbotax.intuit.com/"); request.doGet(null); BaseResponse response = request.getResponse(); assertNotNull(response); @@ -243,7 +297,7 @@ public void testSSL() { @Disabled @Tag(TestGroups.FUNCTIONAL) public void doPostMultipart() throws IOException { - BaseRequest request = getRequest(new TankHttpClient4(), "http://httpbin.org/post"); + BaseRequest request = getRequest(new TankHttpClient4(), null, "http://httpbin.org/post"); request.setContentType(BaseRequest.CONTENT_TYPE_MULTIPART); request.setBody(createMultiPartBody()); request.doPost(null); @@ -256,7 +310,7 @@ public void doPostMultipart() throws IOException { @Test @Tag(TestGroups.FUNCTIONAL) public void doPostMultipartwithFile() throws IOException { - BaseRequest request = getRequest(new TankHttpClient4(), wireMockServer.baseUrl() + "/post"); + BaseRequest request = getRequest(new TankHttpClient4(), null, wireMockServer.baseUrl() + "/post"); request.setContentType(BaseRequest.CONTENT_TYPE_MULTIPART); request.setBody( "LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0xNzI2MTE1MzQ5Mjk4MjYNCkNvbnRlbnQtRGlzcG9zaXRpb246IGZvcm0tZGF0YTsgbmFtZT0iY3JlYXRlTmV3" @@ -324,18 +378,13 @@ private String createMultiPartBody() throws IOException { HttpEntity entity = MultipartEntityBuilder.create().addTextBody("textPart", "here is sample xml", ContentType.APPLICATION_XML).build(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); entity.writeTo(byteArrayOutputStream); - String ret = new String(byteArrayOutputStream.toByteArray()); - - System.out.println(ret); - ret = toBase64(byteArrayOutputStream.toByteArray()); - System.out.println(ret); - return ret; + return Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray()).trim(); } - private BaseRequest getRequest(TankHttpClient client, String url) { + private BaseRequest getRequest(TankHttpClient client, CloseableHttpClient httpclient, String url) { try { URL u = new URL(url); - client.setHttpClient(null); + client.setHttpClient(httpclient); BaseRequest request = new MockBaseRequest(client); request.setHost(u.getHost()); request.setPath(u.getPath()); @@ -347,19 +396,4 @@ private BaseRequest getRequest(TankHttpClient client, String url) { throw new RuntimeException(e); } } - - /** - * Returns a string's base64 encoding - * - * @param bytes - * @return base64 string - */ - public String toBase64(byte[] bytes) { - try { - return Base64.getEncoder().encodeToString(bytes).trim(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } diff --git a/agent/http_client_4/src/test/resources/mappings/httpbin.org-stubs.json b/agent/http_client_4/src/test/resources/mappings/httpbin.org-stubs.json index ed61ded71..4f4433e7c 100644 --- a/agent/http_client_4/src/test/resources/mappings/httpbin.org-stubs.json +++ b/agent/http_client_4/src/test/resources/mappings/httpbin.org-stubs.json @@ -1164,7 +1164,12 @@ "method" : "POST" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{\n \"key\" : \"value\"\n}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "NumberFormatException" + } }, "uuid" : "62f1251b-62e1-453f-86ae-3568c80feaa6", "persistent" : true, @@ -1524,7 +1529,12 @@ "method" : "GET" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{ \"message\": \"The request's query parameters.\"}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "123456" + } }, "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e42", "persistent" : true, @@ -2664,5 +2674,29 @@ } }, "insertionIndex" : 109 + }, { + "id" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "name" : "The request's options. - 204", + "request" : { + "urlPath" : "/options", + "method" : "OPTIONS" + }, + "response" : { + "status" : 204 + }, + "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "persistent" : true, + "metadata" : { + "mocklab" : { + "created" : { + "at" : "2023-03-28T09:23:52.398583Z", + "via" : "OAS3_IMPORT" + }, + "oas" : { + "operationId" : "(none)" + } + } + }, + "insertionIndex" : 110 } ] } \ No newline at end of file diff --git a/agent/http_client_jdk/src/main/java/com/intuit/tank/httpclientjdk/TankHttpClientJDK.java b/agent/http_client_jdk/src/main/java/com/intuit/tank/httpclientjdk/TankHttpClientJDK.java index 13cedf28f..22b6c12ac 100644 --- a/agent/http_client_jdk/src/main/java/com/intuit/tank/httpclientjdk/TankHttpClientJDK.java +++ b/agent/http_client_jdk/src/main/java/com/intuit/tank/httpclientjdk/TankHttpClientJDK.java @@ -67,6 +67,14 @@ public TankHttpClientJDK() { httpclient = httpclientBuilder.build(); } + /** + * constructor for test + */ + public TankHttpClientJDK(HttpClient mockHttpClient) { + this.httpclient = mockHttpClient; + this.httpclientBuilder = HttpClient.newBuilder(); + } + public Object createHttpClient() { return null; } public void setHttpClient(Object httpClient) {} @@ -80,7 +88,7 @@ public void setConnectionTimeout(long connectionTimeout) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doGet(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doGet(com.intuit.tank.http. * BaseRequest) */ @Override @@ -94,7 +102,7 @@ public void doGet(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doPut(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doPut(com.intuit.tank.http. * BaseRequest) */ @Override @@ -117,7 +125,7 @@ public void doPut(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doDelete(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doDelete(com.intuit.tank.http. * BaseRequest) */ @Override @@ -131,7 +139,7 @@ public void doDelete(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doOptions(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doOptions(com.intuit.tank.http. * BaseRequest) */ @Override @@ -146,7 +154,7 @@ public void doOptions(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doPost(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doPost(com.intuit.tank.http. * BaseRequest) */ @Override @@ -169,7 +177,7 @@ public void doPost(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#doPatch(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#doPatch(com.intuit.tank.http. * BaseRequest) */ @Override @@ -192,7 +200,7 @@ public void doPatch(BaseRequest request) { * (non-Javadoc) * * @see - * com.intuit.tank.httpclient3.TankHttpClient#addAuth(com.intuit.tank.http. + * com.intuit.tank.httpclientjdk.TankHttpClient#addAuth(com.intuit.tank.http. * AuthCredentials) */ @Override @@ -213,7 +221,7 @@ public void setCookie(TankCookie cookie) { /* * (non-Javadoc) * - * @see com.intuit.tank.httpclient3.TankHttpClient#clearSession() + * @see com.intuit.tank.httpclientjdk.TankHttpClient#clearSession() */ @Override public void clearSession() { diff --git a/agent/http_client_jdk/src/test/java/com/intuit/tank/httpclientjdk/TankHttpClientJDKTest.java b/agent/http_client_jdk/src/test/java/com/intuit/tank/httpclientjdk/TankHttpClientJDKTest.java index 0d027b776..d69e08de9 100644 --- a/agent/http_client_jdk/src/test/java/com/intuit/tank/httpclientjdk/TankHttpClientJDKTest.java +++ b/agent/http_client_jdk/src/test/java/com/intuit/tank/httpclientjdk/TankHttpClientJDKTest.java @@ -1,8 +1,12 @@ package com.intuit.tank.httpclientjdk; import java.io.IOException; +import java.net.SocketException; import java.net.URL; +import java.net.UnknownHostException; import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; import com.intuit.tank.http.AuthCredentials; import com.intuit.tank.http.AuthScheme; @@ -16,8 +20,12 @@ import static org.junit.jupiter.api.Assertions.*; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.core.WireMockConfiguration; +import org.mockito.ArgumentMatchers; +import org.mockito.Mockito; import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; public class TankHttpClientJDKTest { @@ -107,6 +115,41 @@ public void doGet() { assertNotNull(response.getBody()); } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doGetException() throws IOException, InterruptedException { + HttpClient mockHttpClient = Mockito.mock(HttpClient.class); + when(mockHttpClient + .send(ArgumentMatchers.any(HttpRequest.class), eq(HttpResponse.BodyHandlers.ofInputStream()))) + .thenThrow(new UnknownHostException("Mocked UnknownHost exception")); + BaseRequest request = getRequest(new TankHttpClientJDK(mockHttpClient), wireMockServer.baseUrl() + "/get"); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .send(ArgumentMatchers.any(HttpRequest.class), eq(HttpResponse.BodyHandlers.ofInputStream()))) + .thenThrow(new SocketException("Mocked Socket Exception")); + request.doGet(null); + assertNull(request.getResponse()); + + when(mockHttpClient + .send(ArgumentMatchers.any(HttpRequest.class), eq(HttpResponse.BodyHandlers.ofInputStream()))) + .thenThrow(new RuntimeException("Mocked Exception")); + assertThrows(RuntimeException.class, () -> request.doGet(null)); + } + + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doOptions() { + BaseRequest request = getRequest(new TankHttpClientJDK(), wireMockServer.baseUrl() + "/options"); + request.doOptions(null); + BaseResponse response = request.getResponse(); + verify(exactly(1), optionsRequestedFor(urlEqualTo("/options"))); + assertNotNull(response); + assertEquals(204, response.getHttpCode()); + assertNotNull(response.getBody()); + } + @Test @Tag(TestGroups.FUNCTIONAL) public void doPost() { @@ -123,6 +166,18 @@ public void doPost() { assertNotNull(response.getBody()); } + @Test + @Tag(TestGroups.FUNCTIONAL) + public void doPatch() { + BaseRequest request = getRequest(new TankHttpClientJDK(), wireMockServer.baseUrl() + "/patch"); + request.doPatch(null); + BaseResponse response = request.getResponse(); + verify(exactly(1), patchRequestedFor(urlEqualTo("/patch"))); + assertNotNull(response); + assertEquals(200, response.getHttpCode()); + assertNotNull(response.getBody()); + } + @Test @Tag(TestGroups.FUNCTIONAL) public void doPut() { diff --git a/agent/http_client_jdk/src/test/resources/mappings/httpbin.org-stubs.json b/agent/http_client_jdk/src/test/resources/mappings/httpbin.org-stubs.json index ed61ded71..4f4433e7c 100644 --- a/agent/http_client_jdk/src/test/resources/mappings/httpbin.org-stubs.json +++ b/agent/http_client_jdk/src/test/resources/mappings/httpbin.org-stubs.json @@ -1164,7 +1164,12 @@ "method" : "POST" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{\n \"key\" : \"value\"\n}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "NumberFormatException" + } }, "uuid" : "62f1251b-62e1-453f-86ae-3568c80feaa6", "persistent" : true, @@ -1524,7 +1529,12 @@ "method" : "GET" }, "response" : { - "status" : 200 + "status" : 200, + "body" : "{ \"message\": \"The request's query parameters.\"}", + "headers": { + "Content-Type": "application/json", + "x-envoy-upstream-service-time": "123456" + } }, "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e42", "persistent" : true, @@ -2664,5 +2674,29 @@ } }, "insertionIndex" : 109 + }, { + "id" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "name" : "The request's options. - 204", + "request" : { + "urlPath" : "/options", + "method" : "OPTIONS" + }, + "response" : { + "status" : 204 + }, + "uuid" : "eb4cd338-b7d5-411b-9c59-56d8a53b8e43", + "persistent" : true, + "metadata" : { + "mocklab" : { + "created" : { + "at" : "2023-03-28T09:23:52.398583Z", + "via" : "OAS3_IMPORT" + }, + "oas" : { + "operationId" : "(none)" + } + } + }, + "insertionIndex" : 110 } ] } \ No newline at end of file