From 8f4383a2a583ea1b65f17d577f0ed47280e41777 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 8 Sep 2020 16:04:05 -0400 Subject: [PATCH 01/17] - removes defaulthttpprovider --- .../ChunkedUploadResponseHandler.java | 10 +- .../graph/http/CoreHttpProvider.java | 20 +- .../graph/http/DefaultHttpProvider.java | 533 ------------------ .../graph/http/GraphServiceException.java | 4 +- .../graph/functional/OutlookTests.java | 2 +- .../graph/http/BaseStreamRequestTests.java | 168 +++--- .../graph/http/CoreHttpProviderTests.java | 10 +- .../graph/http/DefaultHttpProviderTests.java | 384 ------------- 8 files changed, 111 insertions(+), 1020 deletions(-) delete mode 100644 src/main/java/com/microsoft/graph/http/DefaultHttpProvider.java delete mode 100644 src/test/java/com/microsoft/graph/http/DefaultHttpProviderTests.java diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java index 381331a6f21..adac7f27bdb 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java @@ -26,7 +26,7 @@ import java.io.IOException; import java.io.InputStream; -import com.microsoft.graph.http.DefaultHttpProvider; +import com.microsoft.graph.http.CoreHttpProvider; import com.microsoft.graph.http.GraphServiceException; import com.microsoft.graph.http.HttpResponseCode; import com.microsoft.graph.http.IConnection; @@ -103,7 +103,7 @@ public ChunkedUploadResult generateResult( logger.logDebug("Chunk bytes has been accepted by the server."); in = new BufferedInputStream(connection.getInputStream()); final UploadSession session = serializer.deserializeObject( - DefaultHttpProvider.streamToString(in), UploadSession.class); + CoreHttpProvider.streamToString(in), UploadSession.class); return new ChunkedUploadResult(session); @@ -111,7 +111,7 @@ public ChunkedUploadResult generateResult( || connection.getResponseCode() == HttpResponseCode.HTTP_OK) { logger.logDebug("Upload session is completed, uploaded item returned."); in = new BufferedInputStream(connection.getInputStream()); - String rawJson = DefaultHttpProvider.streamToString(in); + String rawJson = CoreHttpProvider.streamToString(in); UploadType uploadedItem = serializer.deserializeObject(rawJson, this.deserializeTypeClass); @@ -158,7 +158,7 @@ public ChunkedUploadResult generateResult( logger.logDebug("Chunk bytes has been accepted by the server."); in = new BufferedInputStream(response.body().byteStream()); final UploadSession session = serializer.deserializeObject( - DefaultHttpProvider.streamToString(in), UploadSession.class); + CoreHttpProvider.streamToString(in), UploadSession.class); return new ChunkedUploadResult(session); @@ -166,7 +166,7 @@ public ChunkedUploadResult generateResult( || response.code() == HttpResponseCode.HTTP_OK) { logger.logDebug("Upload session is completed, uploaded item returned."); in = new BufferedInputStream(response.body().byteStream()); - String rawJson = DefaultHttpProvider.streamToString(in); + String rawJson = CoreHttpProvider.streamToString(in); UploadType uploadedItem = serializer.deserializeObject(rawJson, this.deserializeTypeClass); diff --git a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java index 708294d4892..80eac525a5c 100644 --- a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java +++ b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java @@ -99,7 +99,7 @@ public class CoreHttpProvider implements IHttpProvider { private OkHttpClient corehttpClient; /** - * Creates the DefaultHttpProvider + * Creates the CoreHttpProvider * * @param serializer the serializer * @param authenticationProvider the authentication provider @@ -110,10 +110,28 @@ public CoreHttpProvider(final ISerializer serializer, final IAuthenticationProvider authenticationProvider, final IExecutors executors, final ILogger logger) { + this(serializer, authenticationProvider, executors, logger, null); + } + + /** + * Creates the CoreHttpProvider + * + * @param serializer the serializer + * @param authenticationProvider the authentication provider + * @param executors the executors + * @param logger the logger for diagnostic information + * @param httpClient the client to send http requests with + */ + public CoreHttpProvider(final ISerializer serializer, + final IAuthenticationProvider authenticationProvider, + final IExecutors executors, + final ILogger logger, + final OkHttpClient httpClient) { this.serializer = serializer; this.authenticationProvider = authenticationProvider; this.executors = executors; this.logger = logger; + this.corehttpClient = httpClient; } /** diff --git a/src/main/java/com/microsoft/graph/http/DefaultHttpProvider.java b/src/main/java/com/microsoft/graph/http/DefaultHttpProvider.java deleted file mode 100644 index 969dcb8e18a..00000000000 --- a/src/main/java/com/microsoft/graph/http/DefaultHttpProvider.java +++ /dev/null @@ -1,533 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2017 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import com.google.common.annotations.VisibleForTesting; -import com.microsoft.graph.authentication.IAuthenticationProvider; -import com.microsoft.graph.concurrency.ICallback; -import com.microsoft.graph.concurrency.IExecutors; -import com.microsoft.graph.concurrency.IProgressCallback; -import com.microsoft.graph.core.ClientException; -import com.microsoft.graph.core.DefaultConnectionConfig; -import com.microsoft.graph.core.IConnectionConfig; -import com.microsoft.graph.logger.ILogger; -import com.microsoft.graph.logger.LoggerLevel; -import com.microsoft.graph.options.HeaderOption; -import com.microsoft.graph.serializer.ISerializer; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.net.URL; -import java.util.List; -import java.util.Map; -import java.util.Scanner; - -/** - * HTTP provider based off of URLConnection - */ -public class DefaultHttpProvider implements IHttpProvider { - - /** - * The content type header - */ - static final String CONTENT_TYPE_HEADER_NAME = "Content-Type"; - - /** - * The content type for JSON responses - */ - static final String JSON_CONTENT_TYPE = "application/json"; - - /** - * The encoding type for getBytes - */ - static final String JSON_ENCODING = "UTF-8"; - - /** - * The serializer - */ - private final ISerializer serializer; - - /** - * The authentication provider - */ - private final IAuthenticationProvider authenticationProvider; - - /** - * The executors - */ - private final IExecutors executors; - - /** - * The logger - */ - private final ILogger logger; - - /** - * The connection factory - */ - private IConnectionFactory connectionFactory; - - /** - * The connection config - */ - private IConnectionConfig connectionConfig; - - /** - * Creates the DefaultHttpProvider using a DefaultConnectionFactory. - * - * @param serializer the serializer - * @param authenticationProvider the authentication provider - * @param executors the executors - * @param logger the logger for diagnostic information - */ - public DefaultHttpProvider(final ISerializer serializer, - final IAuthenticationProvider authenticationProvider, - final IExecutors executors, - final ILogger logger) { - this(serializer, authenticationProvider, executors, logger, new DefaultConnectionFactory()); - } - - /** - * Creates the DefaultHttpProvider - * - * @param serializer the serializer - * @param authenticationProvider the authentication provider - * @param executors the executors - * @param logger the logger for diagnostic information - * @param connectionFactory an IConnectionFactory to create outgoing connections - */ - public DefaultHttpProvider(final ISerializer serializer, - final IAuthenticationProvider authenticationProvider, - final IExecutors executors, - final ILogger logger, - final IConnectionFactory connectionFactory) { - this.serializer = serializer; - this.authenticationProvider = authenticationProvider; - this.executors = executors; - this.logger = logger; - this.connectionFactory = connectionFactory; - } - - /** - * Gets the serializer for this HTTP provider - * - * @return the serializer for this provider - */ - @Override - public ISerializer getSerializer() { - return serializer; - } - - /** - * Sends the HTTP request asynchronously - * - * @param request the request description - * @param callback the callback to be called after success or failure - * @param resultClass the class of the response from the service - * @param serializable the object to send to the service in the body of the request - * @param the type of the response object - * @param the type of the object to send to the service in the body of the request - */ - @Override - public void send(final IHttpRequest request, - final ICallback callback, - final Class resultClass, - final Body serializable) { - final IProgressCallback progressCallback; - if (callback instanceof IProgressCallback) { - progressCallback = (IProgressCallback) callback; - } else { - progressCallback = null; - } - - executors.performOnBackground(new Runnable() { - @Override - public void run() { - try { - executors.performOnForeground(sendRequestInternal(request, - resultClass, - serializable, - progressCallback, - null), - callback); - } catch (final ClientException e) { - executors.performOnForeground(e, callback); - } - } - }); - } - - /** - * Sends the HTTP request - * - * @param request the request description - * @param resultClass the class of the response from the service - * @param serializable the object to send to the service in the body of the request - * @param the type of the response object - * @param the type of the object to send to the service in the body of the request - * @return the result from the request - * @throws ClientException an exception occurs if the request was unable to complete for any reason - */ - @Override - public Result send(final IHttpRequest request, - final Class resultClass, - final Body serializable) - throws ClientException { - return send(request, resultClass, serializable, null); - } - - /** - * Sends the HTTP request - * - * @param request the request description - * @param resultClass the class of the response from the service - * @param serializable the object to send to the service in the body of the request - * @param handler the handler for stateful response - * @param the type of the response object - * @param the type of the object to send to the service in the body of the request - * @param the response handler for stateful response - * @return the result from the request - * @throws ClientException this exception occurs if the request was unable to complete for any reason - */ - public Result send(final IHttpRequest request, - final Class resultClass, - final Body serializable, - final IStatefulResponseHandler handler) throws ClientException { - return sendRequestInternal(request, resultClass, serializable, null, handler); - } - - /** - * Sends the HTTP request - * - * @param request the request description - * @param resultClass the class of the response from the service - * @param serializable the object to send to the service in the body of the request - * @param progress the progress callback for the request - * @param handler the handler for stateful response - * @param the type of the response object - * @param the type of the object to send to the service in the body of the request - * @param the response handler for stateful response - * @return the result from the request - * @throws ClientException an exception occurs if the request was unable to complete for any reason - */ - @SuppressWarnings("unchecked") - private Result sendRequestInternal(final IHttpRequest request, - final Class resultClass, - final Body serializable, - final IProgressCallback progress, - final IStatefulResponseHandler handler) - throws ClientException { - final int defaultBufferSize = 4096; - final String binaryContentType = "application/octet-stream"; - - try { - if (authenticationProvider != null) { - authenticationProvider.authenticateRequest(request); - } - - OutputStream out = null; - InputStream in = null; - boolean isBinaryStreamInput = false; - final URL requestUrl = request.getRequestUrl(); - logger.logDebug("Starting to send request, URL " + requestUrl.toString()); - final IConnection connection = connectionFactory.createFromRequest(request); - if(this.connectionConfig == null) { - this.connectionConfig = new DefaultConnectionConfig(); - } - connection.setConnectTimeout(connectionConfig.getConnectTimeout()); - connection.setReadTimeout(connectionConfig.getReadTimeout()); - - try { - logger.logDebug("Request Method " + request.getHttpMethod().toString()); - List requestHeaders = request.getHeaders(); - - final byte[] bytesToWrite; - connection.addRequestHeader("Accept", "*/*"); - if (serializable == null) { - // Send an empty body through with a POST request - // This ensures that the Content-Length header is properly set - if (request.getHttpMethod() == HttpMethod.POST) { - bytesToWrite = new byte[0]; - } - else { - bytesToWrite = null; - } - } else if (serializable instanceof byte[]) { - logger.logDebug("Sending byte[] as request body"); - bytesToWrite = (byte[]) serializable; - - // If the user hasn't specified a Content-Type for the request - if (!hasHeader(requestHeaders, CONTENT_TYPE_HEADER_NAME)) { - connection.addRequestHeader(CONTENT_TYPE_HEADER_NAME, binaryContentType); - } - connection.setContentLength(bytesToWrite.length); - } else { - logger.logDebug("Sending " + serializable.getClass().getName() + " as request body"); - final String serializeObject = serializer.serializeObject(serializable); - bytesToWrite = serializeObject.getBytes(JSON_ENCODING); - - // If the user hasn't specified a Content-Type for the request - if (!hasHeader(requestHeaders, CONTENT_TYPE_HEADER_NAME)) { - connection.addRequestHeader(CONTENT_TYPE_HEADER_NAME, JSON_CONTENT_TYPE); - } - connection.setContentLength(bytesToWrite.length); - } - - // Handle cases where we've got a body to process. - if (bytesToWrite != null) { - out = connection.getOutputStream(); - - int writtenSoFar = 0; - BufferedOutputStream bos = new BufferedOutputStream(out); - - int toWrite; - do { - toWrite = Math.min(defaultBufferSize, bytesToWrite.length - writtenSoFar); - bos.write(bytesToWrite, writtenSoFar, toWrite); - writtenSoFar = writtenSoFar + toWrite; - if (progress != null) { - executors.performOnForeground(writtenSoFar, bytesToWrite.length, - progress); - } - } while (toWrite > 0); - bos.close(); - } - - if (handler != null) { - handler.configConnection(connection); - } - - logger.logDebug(String.format("Response code %d, %s", - connection.getResponseCode(), - connection.getResponseMessage())); - - if (handler != null) { - logger.logDebug("StatefulResponse is handling the HTTP response."); - return handler.generateResult( - request, connection, this.getSerializer(), this.logger); - } - - if (connection.getResponseCode() >= HttpResponseCode.HTTP_CLIENT_ERROR) { - logger.logDebug("Handling error response"); - in = connection.getInputStream(); - handleErrorResponse(request, serializable, connection); - } - - if (connection.getResponseCode() == HttpResponseCode.HTTP_NOBODY - || connection.getResponseCode() == HttpResponseCode.HTTP_NOT_MODIFIED) { - logger.logDebug("Handling response with no body"); - return handleEmptyResponse(connection.getResponseHeaders(), resultClass); - } - - if (connection.getResponseCode() == HttpResponseCode.HTTP_ACCEPTED) { - logger.logDebug("Handling accepted response"); - return handleEmptyResponse(connection.getResponseHeaders(), resultClass); - } - - in = new BufferedInputStream(connection.getInputStream()); - - final Map headers = connection.getHeaders(); - - final String contentType = headers.get(CONTENT_TYPE_HEADER_NAME); - if (contentType.contains(JSON_CONTENT_TYPE)) { - logger.logDebug("Response json"); - return handleJsonResponse(in, connection.getResponseHeaders(), resultClass); - } else { - logger.logDebug("Response binary"); - isBinaryStreamInput = true; - //no inspection unchecked - return (Result) handleBinaryStream(in); - } - } finally { - if (out != null) { - out.close(); - } - if (!isBinaryStreamInput && in != null) { - in.close(); - connection.close(); - } - } - } catch (final GraphServiceException ex) { - final boolean shouldLogVerbosely = logger.getLoggingLevel() == LoggerLevel.DEBUG; - logger.logError("Graph service exception " + ex.getMessage(shouldLogVerbosely), ex); - throw ex; - } catch (final UnsupportedEncodingException ex) { - final ClientException clientException = new ClientException("Unsupported encoding problem: ", - ex); - logger.logError("Unsupported encoding problem: " + ex.getMessage(), ex); - throw clientException; - } catch (final Exception ex) { - final ClientException clientException = new ClientException("Error during http request", - ex); - logger.logError("Error during http request", clientException); - throw clientException; - } - } - - /** - * Handles the event of an error response - * - * @param request the request that caused the failed response - * @param serializable the body of the request - * @param connection the URL connection - * @param the type of the request body - * @throws IOException an exception occurs if there were any problems interacting with the connection object - */ - private void handleErrorResponse(final IHttpRequest request, - final Body serializable, - final IConnection connection) - throws IOException { - throw GraphServiceException.createFromConnection(request, serializable, serializer, - connection, logger); - } - - /** - * Handles the cause where the response is a binary stream - * - * @param in the input stream from the response - * @return the input stream to return to the caller - */ - private InputStream handleBinaryStream(final InputStream in) { - return in; - } - - /** - * Handles the cause where the response is a JSON object - * - * @param in the input stream from the response - * @param responseHeaders the response header - * @param clazz the class of the response object - * @param the type of the response object - * @return the JSON object - */ - private Result handleJsonResponse(final InputStream in, Map> responseHeaders, final Class clazz) { - if (clazz == null) { - return null; - } - - final String rawJson = streamToString(in); - return getSerializer().deserializeObject(rawJson, clazz, responseHeaders); - } - - /** - * Handles the case where the response body is empty - * - * @param responseHeaders the response headers - * @param clazz the type of the response object - * @return the JSON object - */ - private Result handleEmptyResponse(Map> responseHeaders, final Class clazz) - throws UnsupportedEncodingException{ - //Create an empty object to attach the response headers to - InputStream in = new ByteArrayInputStream("{}".getBytes(JSON_ENCODING)); - return handleJsonResponse(in, responseHeaders, clazz); - } - - /** - * Sets the connection factory for this provider - * - * @param factory the new factory - */ - void setConnectionFactory(final IConnectionFactory factory) { - connectionFactory = factory; - } - - /** - * Reads in a stream and converts it into a string - * - * @param input the response body stream - * @return the string result - */ - public static String streamToString(final InputStream input) { - final String httpStreamEncoding = "UTF-8"; - final String endOfFile = "\\A"; - final Scanner scanner = new Scanner(input, httpStreamEncoding); - String scannerString = ""; - try { - scanner.useDelimiter(endOfFile); - scannerString = scanner.next(); - } finally { - scanner.close(); - } - return scannerString; - } - - /** - * Searches for the given header in a list of HeaderOptions - * - * @param headers the list of headers to search through - * @param header the header name to search for (case insensitive) - * @return true if the header has already been set - */ - @VisibleForTesting - static boolean hasHeader(List headers, String header) { - for (HeaderOption option : headers) { - if (option.getName().equalsIgnoreCase(header)) { - return true; - } - } - return false; - } - - @VisibleForTesting - public ILogger getLogger() { - return logger; - } - - @VisibleForTesting - public IExecutors getExecutors() { - return executors; - } - - @VisibleForTesting - public IAuthenticationProvider getAuthenticationProvider() { - return authenticationProvider; - } - - - /** - * Get connection config for read and connect timeout in requests - * - * @return Connection configuration to be used for timeout values - */ - public IConnectionConfig getConnectionConfig() { - if(this.connectionConfig == null) { - this.connectionConfig = new DefaultConnectionConfig(); - } - return connectionConfig; - } - - /** - * Set connection config for read and connect timeout in requests - * - * @param connectionConfig Connection configuration to be used for timeout values - */ - public void setConnectionConfig(IConnectionConfig connectionConfig) { - this.connectionConfig = connectionConfig; - } -} diff --git a/src/main/java/com/microsoft/graph/http/GraphServiceException.java b/src/main/java/com/microsoft/graph/http/GraphServiceException.java index cff5865b224..24a1cee1e53 100644 --- a/src/main/java/com/microsoft/graph/http/GraphServiceException.java +++ b/src/main/java/com/microsoft/graph/http/GraphServiceException.java @@ -325,7 +325,7 @@ public static GraphServiceException createFromConnection(final IHttpRequest final String responseMessage = connection.getResponseMessage(); String rawOutput = "{}"; if(connection.getInputStream() != null) { - rawOutput = DefaultHttpProvider.streamToString(connection.getInputStream()); + rawOutput = CoreHttpProvider.streamToString(connection.getInputStream()); } GraphErrorResponse error; try { @@ -429,7 +429,7 @@ public static GraphServiceException createFromConnection(final IHttpRequest InputStream is = response.body().byteStream(); try { - rawOutput = DefaultHttpProvider.streamToString(is); + rawOutput = CoreHttpProvider.streamToString(is); } finally { closeQuietly(is); } diff --git a/src/test/java/com/microsoft/graph/functional/OutlookTests.java b/src/test/java/com/microsoft/graph/functional/OutlookTests.java index 2a3f673ff4b..3eb56f86a18 100644 --- a/src/test/java/com/microsoft/graph/functional/OutlookTests.java +++ b/src/test/java/com/microsoft/graph/functional/OutlookTests.java @@ -234,7 +234,7 @@ private Event getEvent() { return event; } - public byte[] getByteArray(InputStream in) { + public static byte[] getByteArray(InputStream in) { try { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; diff --git a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java index fac30074ef2..69f4d5dca87 100644 --- a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -13,6 +14,16 @@ import org.junit.Before; import org.junit.Test; +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + +import static org.mockito.Mockito.*; + import com.microsoft.graph.authentication.MockAuthenticationProvider; import com.microsoft.graph.concurrency.ICallback; import com.microsoft.graph.concurrency.MockExecutors; @@ -36,30 +47,23 @@ public void setUp() throws Exception { } @Test - public void testSend() { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/octet-stream"); - return map; - } - }; - DefaultHttpProvider mProvider = new DefaultHttpProvider(new MockSerializer(null, ""), + public void testSend() throws IOException { + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/octet-stream"), + "{ \"id\": \"zzz\" }" + )) + .build(); + + final OkHttpClient mockClient = getMockClient(response); + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(null, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); final BaseStreamRequest request = new BaseStreamRequest("https://a.b.c", mBaseClient,null, null){}; request.send(); @@ -67,30 +71,23 @@ public Map getHeaders() { } @Test - public void testSendWithCallback() { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - DefaultHttpProvider mProvider = new DefaultHttpProvider(new MockSerializer(null, ""), + public void testSendWithCallback() throws IOException { + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{ \"id\": \"zzz\" }" + )) + .build(); + + final OkHttpClient mockClient = getMockClient(response); + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(null, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); final AtomicBoolean success = new AtomicBoolean(false); final AtomicBoolean failure = new AtomicBoolean(false); @@ -113,30 +110,23 @@ public void failure(ClientException ex) { } @Test - public void testSendWithContentAndCallback() { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - DefaultHttpProvider mProvider = new DefaultHttpProvider(new MockSerializer(null, ""), + public void testSendWithContentAndCallback() throws IOException { + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{ \"id\": \"zzz\" }" + )) + .build(); + + final OkHttpClient mockClient = getMockClient(response); + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(null, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); final AtomicBoolean success = new AtomicBoolean(false); final AtomicBoolean failure = new AtomicBoolean(false); @@ -159,30 +149,24 @@ public void failure(ClientException ex) { } @Test - public void testSendWithContent() { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - DefaultHttpProvider mProvider = new DefaultHttpProvider(new MockSerializer(null, ""), + public void testSendWithContent() throws IOException { + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{ \"id\": \"zzz\" }" + )) + .build(); + + final OkHttpClient mockClient = getMockClient(response); + + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(null, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); final BaseStreamRequest request = new BaseStreamRequest("https://a.b.c", mBaseClient,null, InputStream.class){}; request.send(new byte[]{1, 2, 3, 4}); @@ -198,5 +182,11 @@ public void testBaseMethod() { assertNull(request.getHttpMethod()); assertEquals(2, request.getOptions().size()); } - + private OkHttpClient getMockClient(final Response response) throws IOException { + final OkHttpClient mockClient = mock(OkHttpClient.class); + final Call remoteCall = mock(Call.class); + when(remoteCall.execute()).thenReturn(response); + when(mockClient.newCall(any())).thenReturn(remoteCall); + return mockClient; + } } diff --git a/src/test/java/com/microsoft/graph/http/CoreHttpProviderTests.java b/src/test/java/com/microsoft/graph/http/CoreHttpProviderTests.java index dea29b50140..46b94d341b6 100644 --- a/src/test/java/com/microsoft/graph/http/CoreHttpProviderTests.java +++ b/src/test/java/com/microsoft/graph/http/CoreHttpProviderTests.java @@ -39,7 +39,7 @@ public void testErrorResponse() throws Exception { toSerialize.error.message = expectedMessage; toSerialize.error.innererror = null; - setDefaultHttpProvider(toSerialize); + setCoreHttpProvider(toSerialize); try { mProvider.send(new MockHttpRequest(), DriveItem.class, null); fail("Expected exception in previous statement"); @@ -82,19 +82,19 @@ public void testVerboseErrorResponse() throws Exception { @Test public void testHasHeaderReturnsTrue() { HeaderOption h = new HeaderOption("name", "value"); - assertTrue(DefaultHttpProvider.hasHeader(Arrays.asList(h), "name")); + assertTrue(CoreHttpProvider.hasHeader(Arrays.asList(h), "name")); } @Test public void testHasHeaderReturnsTrueWhenDifferentCase() { HeaderOption h = new HeaderOption("name", "value"); - assertTrue(DefaultHttpProvider.hasHeader(Arrays.asList(h), "NAME")); + assertTrue(CoreHttpProvider.hasHeader(Arrays.asList(h), "NAME")); } @Test public void testHasHeaderReturnsFalse() { HeaderOption h = new HeaderOption("name", "value"); - assertFalse(DefaultHttpProvider.hasHeader(Arrays.asList(h), "blah")); + assertFalse(CoreHttpProvider.hasHeader(Arrays.asList(h), "blah")); } @@ -102,7 +102,7 @@ public void testHasHeaderReturnsFalse() { * Configures the http provider for test cases * @param toSerialize The object to serialize */ - private void setDefaultHttpProvider(final Object toSerialize) { + private void setCoreHttpProvider(final Object toSerialize) { mProvider = new CoreHttpProvider(new MockSerializer(toSerialize, ""), mAuthenticationProvider = new MockAuthenticationProvider(), new MockExecutors(), diff --git a/src/test/java/com/microsoft/graph/http/DefaultHttpProviderTests.java b/src/test/java/com/microsoft/graph/http/DefaultHttpProviderTests.java deleted file mode 100644 index ae4c671a276..00000000000 --- a/src/test/java/com/microsoft/graph/http/DefaultHttpProviderTests.java +++ /dev/null @@ -1,384 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2015 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.junit.Test; - -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.microsoft.graph.authentication.MockAuthenticationProvider; -import com.microsoft.graph.concurrency.IProgressCallback; -import com.microsoft.graph.concurrency.MockExecutors; -import com.microsoft.graph.core.ClientException; -import com.microsoft.graph.core.GraphErrorCodes; -import com.microsoft.graph.logger.LoggerLevel; -import com.microsoft.graph.logger.MockLogger; -import com.microsoft.graph.models.extensions.Drive; -import com.microsoft.graph.models.extensions.DriveItem; -import com.microsoft.graph.options.HeaderOption; -import com.microsoft.graph.serializer.MockSerializer; - -/** - * Test cases for {@see DefaultHttpProvider} - */ -public class DefaultHttpProviderTests { - - private MockAuthenticationProvider mAuthenticationProvider; - private DefaultHttpProvider mProvider; - - @Test - public void testNoContentType() throws Exception { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; - setDefaultHttpProvider(null); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - try { - mProvider.send(new MockHttpRequest(), Drive.class, null); - fail("Expected exception"); - } catch (final ClientException ce) { - if (!(ce.getCause() instanceof NullPointerException)) { - fail("Wrong inner exception!"); - } - } - assertEquals(1, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testDriveResponse() throws Exception { - final String driveId = "driveId"; - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - final Drive expectedDrive = new Drive(); - expectedDrive.id = driveId; - setDefaultHttpProvider(expectedDrive); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - final Drive drive = mProvider.send(new MockHttpRequest(), Drive.class, null); - - assertEquals(driveId, drive.id); - assertEquals(1, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testBinaryResponse() throws Exception { - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/octet-stream"); - return map; - } - }; - setDefaultHttpProvider(null); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - mProvider.send(new MockHttpRequest(), InputStream.class, null); - assertEquals(1, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testPostItem() throws Exception { - final String itemId = "itemId"; - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - - final DriveItem expectedItem = new DriveItem(); - expectedItem.id = itemId; - setDefaultHttpProvider(expectedItem); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - final DriveItem item = mProvider.send(new MockHttpRequest(), DriveItem.class, new DriveItem()); - - assertEquals(itemId, item.id); - assertEquals(1, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testPostByte() throws Exception { - final String itemId = "itemId"; - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - final DriveItem expectedItem = new DriveItem(); - expectedItem.id = itemId; - setDefaultHttpProvider(expectedItem); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - final AtomicBoolean progress = new AtomicBoolean(false); - final AtomicBoolean success = new AtomicBoolean(false); - final AtomicBoolean failure = new AtomicBoolean(false); - final IProgressCallback progressCallback = new IProgressCallback() { - @Override - public void progress(final long current, final long max) { - progress.set(true); - } - - @Override - public void success(final DriveItem item) { - success.set(true); - } - - @Override - public void failure(final ClientException ex) { - failure.set(true); - } - }; - - mProvider.send(new MockHttpRequest(), progressCallback, DriveItem.class, new byte[]{1, 2, 3, 4}); - - assertTrue(progress.get()); - assertTrue(success.get()); - assertEquals(1, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testErrorResponse() throws Exception { - final GraphErrorCodes expectedErrorCode = GraphErrorCodes.INVALID_REQUEST; - final String expectedMessage = "Test error!"; - final GraphErrorResponse toSerialize = new GraphErrorResponse(); - toSerialize.error = new GraphError(); - toSerialize.error.code = expectedErrorCode.toString(); - toSerialize.error.message = expectedMessage; - toSerialize.error.innererror = null; - - setDefaultHttpProvider(toSerialize); - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 415; - } - - @Override - public String getJsonResponse() { - return "{}"; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - try { - mProvider.send(new MockHttpRequest(), DriveItem.class, null); - fail("Expected exception in previous statement"); - } catch (final GraphServiceException e) { - assertTrue(e.getMessage().indexOf("truncated") > 0); - assertEquals(expectedMessage, e.getServiceError().message); - } - } - - @Test - public void testVerboseErrorResponse() throws Exception { - final GraphErrorCodes expectedErrorCode = GraphErrorCodes.INVALID_REQUEST; - final String expectedMessage = "Test error!"; - final GraphErrorResponse toSerialize = new GraphErrorResponse(); - toSerialize.error = new GraphError(); - toSerialize.error.code = expectedErrorCode.toString(); - toSerialize.error.message = expectedMessage; - toSerialize.error.innererror = null; - JsonObject raw = new JsonObject(); - raw.add("response", new JsonPrimitive("The raw request was invalid")); - toSerialize.rawObject = raw; - - MockLogger logger = new MockLogger(); - logger.setLoggingLevel(LoggerLevel.DEBUG); - - mProvider = new DefaultHttpProvider(new MockSerializer(toSerialize, ""), - mAuthenticationProvider = new MockAuthenticationProvider(), - new MockExecutors(), - logger); - - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 415; - } - - @Override - public String getJsonResponse() { - return "{}"; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - try { - mProvider.send(new MockHttpRequest(), DriveItem.class, null); - fail("Expected exception in previous statement"); - } catch (final GraphServiceException e) { - assertFalse(e.getMessage().indexOf("truncated") > 0); - assertTrue(e.getMessage().indexOf("The raw request was invalid") > 0); - } - } - - @Test - public void testBodyLessResponse() throws Exception { - final int[] codes = new int[] {204, 304 }; - final AtomicInteger currentCode = new AtomicInteger(0); - setDefaultHttpProvider(null); - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return codes[currentCode.get()]; - } - - @Override - public String getJsonResponse() { - return null; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); - - for (@SuppressWarnings("unused") final int ignored : codes) { - DriveItem result = mProvider.send(new MockHttpRequest(), DriveItem.class, null); - currentCode.incrementAndGet(); - assertNull(result); - } - assertEquals(codes.length, mAuthenticationProvider.getInterceptionCount()); - } - - @Test - public void testHasHeaderReturnsTrue() { - HeaderOption h = new HeaderOption("name", "value"); - assertTrue(DefaultHttpProvider.hasHeader(Arrays.asList(h), "name")); - } - - @Test - public void testHasHeaderReturnsTrueWhenDifferentCase() { - HeaderOption h = new HeaderOption("name", "value"); - assertTrue(DefaultHttpProvider.hasHeader(Arrays.asList(h), "NAME")); - } - - @Test - public void testHasHeaderReturnsFalse() { - HeaderOption h = new HeaderOption("name", "value"); - assertFalse(DefaultHttpProvider.hasHeader(Arrays.asList(h), "blah")); - } - - - /** - * Configures the http provider for test cases - * @param toSerialize The object to serialize - */ - private void setDefaultHttpProvider(final Object toSerialize) { - mProvider = new DefaultHttpProvider(new MockSerializer(toSerialize, ""), - mAuthenticationProvider = new MockAuthenticationProvider(), - new MockExecutors(), - new MockLogger()); - } -} From 2f89eb2f0dcda84c4c9e5812f7ece71144bdc017 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 8 Sep 2020 16:04:24 -0400 Subject: [PATCH 02/17] - adds mockito --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index b796f62999f..70581e95fcf 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,7 @@ dependencies { // Use JUnit test framework testImplementation 'junit:junit:4.13' + testImplementation 'org.mockito:mockito-inline:+' implementation 'com.google.code.gson:gson:2.8.6' From 8a1978def5802333ea68c362cff15d785a6a8b62 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 9 Sep 2020 09:10:30 -0400 Subject: [PATCH 03/17] - removes useless mock objects --- .../ChunkedUploadResponseHandler.java | 70 +------ .../graph/http/CoreHttpProvider.java | 2 +- .../graph/http/DefaultConnectionFactory.java | 43 ---- .../graph/http/GraphServiceException.java | 104 +--------- .../graph/http/IConnectionFactory.java | 40 ---- .../graph/http/IStatefulResponseHandler.java | 22 -- .../microsoft/graph/http/UrlConnection.java | 189 ------------------ .../microsoft/graph/core/BaseClientTests.java | 7 +- .../http/BaseCollectionRequestTests.java | 76 ++++--- .../graph/http/BaseRequestTests.java | 58 +++--- .../graph/http/BaseStreamRequestTests.java | 2 +- .../http/DefaultConnectionFactoryTests.java | 31 --- .../http/GraphServiceExceptionTests.java | 78 ++------ .../microsoft/graph/http/MockConnection.java | 102 ---------- .../graph/http/MockConnectionFactory.java | 20 -- .../graph/http/MockHttpProvider.java | 126 ------------ .../com/microsoft/graph/http/MockRequest.java | 124 ------------ .../http/MockSingleConnectionFactory.java | 49 ----- .../graph/http/UrlConnectionTests.java | 38 ---- .../serializer/DefaultSerializerTests.java | 20 +- 20 files changed, 117 insertions(+), 1084 deletions(-) delete mode 100644 src/main/java/com/microsoft/graph/http/DefaultConnectionFactory.java delete mode 100644 src/main/java/com/microsoft/graph/http/IConnectionFactory.java delete mode 100644 src/main/java/com/microsoft/graph/http/UrlConnection.java delete mode 100644 src/test/java/com/microsoft/graph/http/DefaultConnectionFactoryTests.java delete mode 100644 src/test/java/com/microsoft/graph/http/MockConnection.java delete mode 100644 src/test/java/com/microsoft/graph/http/MockConnectionFactory.java delete mode 100644 src/test/java/com/microsoft/graph/http/MockHttpProvider.java delete mode 100644 src/test/java/com/microsoft/graph/http/MockRequest.java delete mode 100644 src/test/java/com/microsoft/graph/http/MockSingleConnectionFactory.java delete mode 100644 src/test/java/com/microsoft/graph/http/UrlConnectionTests.java diff --git a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java index adac7f27bdb..911bfabd45e 100644 --- a/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java +++ b/src/main/java/com/microsoft/graph/concurrency/ChunkedUploadResponseHandler.java @@ -29,7 +29,6 @@ import com.microsoft.graph.http.CoreHttpProvider; import com.microsoft.graph.http.GraphServiceException; import com.microsoft.graph.http.HttpResponseCode; -import com.microsoft.graph.http.IConnection; import com.microsoft.graph.http.IHttpRequest; import com.microsoft.graph.http.IStatefulResponseHandler; import com.microsoft.graph.logger.ILogger; @@ -59,16 +58,6 @@ public class ChunkedUploadResponseHandler public ChunkedUploadResponseHandler(final Class uploadType) { this.deserializeTypeClass = uploadType; } - - /** - * Do nothing before getting the response - * - * @param connection the connection - */ - @Override - public void configConnection(final IConnection connection) { - return; - } /** * Do nothing before getting the response @@ -79,63 +68,6 @@ public void configConnection(final IConnection connection) { public void configConnection(final Response response) { return; } - - /** - * Generate the chunked upload response result - * - * @param request the HTTP request - * @param connection the HTTP connection - * @param serializer the serializer - * @param logger the system logger - * @return the chunked upload result, which could be either an uploaded item or error - * @throws Exception an exception occurs if the request was unable to complete for any reason - */ - @Override - public ChunkedUploadResult generateResult( - final IHttpRequest request, - final IConnection connection, - final ISerializer serializer, - final ILogger logger) throws Exception { - InputStream in = null; - - try { - if (connection.getResponseCode() == HttpResponseCode.HTTP_ACCEPTED) { - logger.logDebug("Chunk bytes has been accepted by the server."); - in = new BufferedInputStream(connection.getInputStream()); - final UploadSession session = serializer.deserializeObject( - CoreHttpProvider.streamToString(in), UploadSession.class); - - return new ChunkedUploadResult(session); - - } else if (connection.getResponseCode() == HttpResponseCode.HTTP_CREATED - || connection.getResponseCode() == HttpResponseCode.HTTP_OK) { - logger.logDebug("Upload session is completed, uploaded item returned."); - in = new BufferedInputStream(connection.getInputStream()); - String rawJson = CoreHttpProvider.streamToString(in); - UploadType uploadedItem = serializer.deserializeObject(rawJson, - this.deserializeTypeClass); - - return new ChunkedUploadResult(uploadedItem); - } else if (connection.getResponseCode() >= HttpResponseCode.HTTP_CLIENT_ERROR) { - logger.logDebug("Receiving error during upload, see detail on result error"); - - return new ChunkedUploadResult( - GraphServiceException.createFromConnection(request, null, serializer, - connection, logger)); - } - } finally { - if (in != null) { - try{ - in.close(); - } catch(IOException e) { - logger.logError(e.getMessage(), e); - } - } - } - - return null; - } - /** * Generate the chunked upload response result * @@ -175,7 +107,7 @@ public ChunkedUploadResult generateResult( logger.logDebug("Receiving error during upload, see detail on result error"); return new ChunkedUploadResult( - GraphServiceException.createFromConnection(request, null, serializer, + GraphServiceException.createFromResponse(request, null, serializer, response, logger)); } } finally { diff --git a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java index 80eac525a5c..53e03e80f6c 100644 --- a/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java +++ b/src/main/java/com/microsoft/graph/http/CoreHttpProvider.java @@ -502,7 +502,7 @@ private void handleErrorResponse(final IHttpRequest request, final Body serializable, final Response response) throws IOException { - throw GraphServiceException.createFromConnection(request, serializable, serializer, + throw GraphServiceException.createFromResponse(request, serializable, serializer, response, logger); } diff --git a/src/main/java/com/microsoft/graph/http/DefaultConnectionFactory.java b/src/main/java/com/microsoft/graph/http/DefaultConnectionFactory.java deleted file mode 100644 index 6bf32523db5..00000000000 --- a/src/main/java/com/microsoft/graph/http/DefaultConnectionFactory.java +++ /dev/null @@ -1,43 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2017 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import java.io.IOException; - -/** - * Creates connections to remove servers - */ -public class DefaultConnectionFactory implements IConnectionFactory { - - /** - * Creates a connection from an IHttpRequest - * - * @param request the request to make the connection from - * @return the connection object - * @throws IOException an exception occurs if there was a network issue creating the connection - */ - @Override - public IConnection createFromRequest(final IHttpRequest request) throws IOException { - return new UrlConnection(request); - } -} diff --git a/src/main/java/com/microsoft/graph/http/GraphServiceException.java b/src/main/java/com/microsoft/graph/http/GraphServiceException.java index 24a1cee1e53..570a7fb88e3 100644 --- a/src/main/java/com/microsoft/graph/http/GraphServiceException.java +++ b/src/main/java/com/microsoft/graph/http/GraphServiceException.java @@ -260,108 +260,6 @@ public GraphError getServiceError() { return error.error; } - /** - * Creates a Graph service exception from a given failed HTTP request - * - * @param request the request that resulted in this failure - * @param serializable the serialized object that was sent with this request - * @param serializer the serializer to re-create the option in its over the wire state - * @param connection the connection that was used to extract the response information from - * @param logger the logger to log exception information to - * @param the type of the serializable object - * @return the new GraphServiceException instance - * @throws IOException an exception occurs if there were any problems processing the connection - */ - public static GraphServiceException createFromConnection(final IHttpRequest request, - final T serializable, - final ISerializer serializer, - final IConnection connection, - final ILogger logger) - throws IOException { - final String method = connection.getRequestMethod(); - final String url = request.getRequestUrl().toString(); - final List requestHeaders = new LinkedList<>(); - for (final HeaderOption option : request.getHeaders()) { - requestHeaders.add(option.getName() + " : " + option.getValue()); - } - boolean isVerbose = logger.getLoggingLevel() == LoggerLevel.DEBUG; - final String requestBody; - if (serializable instanceof byte[]) { - final byte[] bytes = (byte[]) serializable; - StringBuilder sb = new StringBuilder(); - sb.append("byte[").append(bytes.length).append("]"); - - sb.append(" {"); - if (isVerbose) { - sb.append(bytes); - } else { - for (int i = 0; i < MAX_BYTE_COUNT_BEFORE_TRUNCATION && i < bytes.length; i++) { - sb.append(bytes[i]).append(", "); - } - if (bytes.length > MAX_BYTE_COUNT_BEFORE_TRUNCATION) { - sb.append(TRUNCATION_MARKER).append("}"); - } - } - requestBody = sb.toString(); - } else if (serializable != null) { - requestBody = serializer.serializeObject(serializable); - } else { - requestBody = null; - } - - final int responseCode = connection.getResponseCode(); - final List responseHeaders = new LinkedList<>(); - final Map headers = connection.getHeaders(); - for (final String key : headers.keySet()) { - final String fieldPrefix; - if (key == null) { - fieldPrefix = ""; - } else { - fieldPrefix = key + " : "; - } - responseHeaders.add(fieldPrefix + headers.get(key)); - } - - final String responseMessage = connection.getResponseMessage(); - String rawOutput = "{}"; - if(connection.getInputStream() != null) { - rawOutput = CoreHttpProvider.streamToString(connection.getInputStream()); - } - GraphErrorResponse error; - try { - error = serializer.deserializeObject(rawOutput, GraphErrorResponse.class, connection.getResponseHeaders()); - } catch (final Exception ex) { - error = new GraphErrorResponse(); - error.error = new GraphError(); - error.error.code = "Unable to parse error response message"; - error.error.message = "Raw error: " + rawOutput; - error.error.innererror = new GraphInnerError(); - error.error.innererror.code = ex.getMessage(); - } - - if (responseCode >= INTERNAL_SERVER_ERROR) { - return new GraphFatalServiceException(method, - url, - requestHeaders, - requestBody, - responseCode, - responseMessage, - responseHeaders, - error, - isVerbose); - } - - return new GraphServiceException(method, - url, - requestHeaders, - requestBody, - responseCode, - responseMessage, - responseHeaders, - error, - isVerbose); - } - /** * Creates a Graph service exception from a given failed HTTP request * @@ -374,7 +272,7 @@ public static GraphServiceException createFromConnection(final IHttpRequest * @return the new GraphServiceException instance * @throws IOException an exception occurs if there were any problems processing the connection */ - public static GraphServiceException createFromConnection(final IHttpRequest request, + public static GraphServiceException createFromResponse(final IHttpRequest request, final T serializable, final ISerializer serializer, final Response response, diff --git a/src/main/java/com/microsoft/graph/http/IConnectionFactory.java b/src/main/java/com/microsoft/graph/http/IConnectionFactory.java deleted file mode 100644 index f0ce28433c2..00000000000 --- a/src/main/java/com/microsoft/graph/http/IConnectionFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2017 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import java.io.IOException; - -/** - * Creates connections to remove servers - */ -public interface IConnectionFactory { - - /** - * Create a connection from an IHttpRequest - * - * @param request the request to make the connection from - * @return the connection object - * @throws IOException an exception occurs if there was a network issue while creating the connection - */ - IConnection createFromRequest(IHttpRequest request) throws IOException; -} diff --git a/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java b/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java index cf90df6823b..be7fa8fdd73 100644 --- a/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java +++ b/src/main/java/com/microsoft/graph/http/IStatefulResponseHandler.java @@ -37,34 +37,12 @@ * @param the deserialize type for serializer */ public interface IStatefulResponseHandler { - /** - * Configure the connection before get response - * - * @param connection the HTTP connection - */ - void configConnection(final IConnection connection); - /** * Configure the response * * @param response the HTTP response */ void configConnection(final Response response); - - /** - * Generate result after receiving response - * - * @param request the HTTP request - * @param connection the HTTP connection - * @param serializer the serializer for parsing response - * @param logger the logger - * @return the result generated by this handler - * @throws Exception an exception occurs if the request was unable to complete for any reason - */ - ResultType generateResult(final IHttpRequest request, - final IConnection connection, - final ISerializer serializer, - final ILogger logger) throws Exception; /** * Generate result after receiving response diff --git a/src/main/java/com/microsoft/graph/http/UrlConnection.java b/src/main/java/com/microsoft/graph/http/UrlConnection.java deleted file mode 100644 index 0f9439c022e..00000000000 --- a/src/main/java/com/microsoft/graph/http/UrlConnection.java +++ /dev/null @@ -1,189 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2017 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sub-license, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import com.microsoft.graph.options.HeaderOption; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.ProtocolException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Wrapper around HttpUrlConnection for testability - */ -public class UrlConnection implements IConnection { - - /** - * The backing HTTP URL connection instance - */ - private final HttpURLConnection connection; - - /** - * The response header cache - */ - private HashMap headers; - - /** - * Creates a new UrlConnection - * - * @param request the IHttpRequest to create the connection from - * @throws IOException an exception occurs if there was a problem creating the connection - */ - public UrlConnection(final IHttpRequest request) throws IOException { - connection = (HttpURLConnection) request.getRequestUrl().openConnection(); - - for (final HeaderOption header : request.getHeaders()) { - connection.addRequestProperty(header.getName(), header.getValue().toString()); - } - - connection.setUseCaches(request.getUseCaches()); - - try { - connection.setRequestMethod(request.getHttpMethod().toString()); - } catch (final ProtocolException ignored) { - // Some HTTP verbs are not supported by older HTTP implementations, use method override as an alternative - connection.setRequestMethod(HttpMethod.POST.toString()); - connection.addRequestProperty("X-HTTP-Method-Override", request.getHttpMethod().toString()); - connection.addRequestProperty("X-HTTP-Method", request.getHttpMethod().toString()); - } - } - - @Override - public void setFollowRedirects(final boolean followRedirects) { - connection.setInstanceFollowRedirects(followRedirects); - } - - @Override - public void addRequestHeader(final String headerName, final String headerValue) { - connection.addRequestProperty(headerName, headerValue); - } - - @Override - public OutputStream getOutputStream() throws IOException { - connection.setDoOutput(true); - return connection.getOutputStream(); - } - - @Override - public InputStream getInputStream() throws IOException { - final int httpClientErrorResponseCode = 400; - if (connection.getResponseCode() >= httpClientErrorResponseCode) { - return connection.getErrorStream(); - } else { - return connection.getInputStream(); - } - } - - @Override - public int getContentLength() { - return connection.getContentLength(); - } - - @Override - public int getResponseCode() throws IOException { - return connection.getResponseCode(); - } - - public Map> getResponseHeaders() { - // Copy unmodifiable map to hashmap - HashMap> headerFields = new HashMap<>(); - headerFields.putAll(connection.getHeaderFields()); - - // Add the response code - List list = new ArrayList<>(); - try { - list.add(String.format("%d", connection.getResponseCode())); - } catch (IOException e) { - throw new IllegalArgumentException("Invalid connection response code: could not connect to server", e); - } - - headerFields.put("responseCode", list); - return headerFields; - } - - @Override - public String getResponseMessage() throws IOException { - return connection.getResponseMessage(); - } - - @Override - public void close() { - connection.disconnect(); - } - - @Override - public Map getHeaders() { - if (headers == null) { - headers = getResponseHeaders(connection); - } - return headers; - } - - @Override - public String getRequestMethod() { - return connection.getRequestMethod(); - } - - @Override - public void setContentLength(final int length) { - connection.setFixedLengthStreamingMode(length); - } - - @Override - public void setReadTimeout(final int readTimeoutMilliseconds) { - connection.setReadTimeout(readTimeoutMilliseconds); - } - - @Override - public void setConnectTimeout(final int connectTimeoutMilliseconds) { - connection.setConnectTimeout(connectTimeoutMilliseconds); - } - - /** - * Gets the response headers from an HTTP URL connection - * - * @param connection the HTTP connection - * @return the set of headers names and value - */ - private static HashMap getResponseHeaders(final HttpURLConnection connection) { - final HashMap headers = new HashMap<>(); - int index = 0; - while (true) { - final String headerName = connection.getHeaderFieldKey(index); - final String headerValue = connection.getHeaderField(index); - if (headerName == null && headerValue == null) { - break; - } - headers.put(headerName, headerValue); - index++; - } - - return headers; - } -} diff --git a/src/test/java/com/microsoft/graph/core/BaseClientTests.java b/src/test/java/com/microsoft/graph/core/BaseClientTests.java index fa52d53f622..520f077acde 100644 --- a/src/test/java/com/microsoft/graph/core/BaseClientTests.java +++ b/src/test/java/com/microsoft/graph/core/BaseClientTests.java @@ -13,7 +13,7 @@ import com.microsoft.graph.concurrency.IExecutors; import com.microsoft.graph.concurrency.MockExecutors; import com.microsoft.graph.http.IHttpProvider; -import com.microsoft.graph.http.MockHttpProvider; +import com.microsoft.graph.http.CoreHttpProvider; import com.microsoft.graph.logger.ILogger; import com.microsoft.graph.logger.MockLogger; import com.microsoft.graph.serializer.ISerializer; @@ -47,9 +47,12 @@ public void setServiceRoot(String value) { }; mAuthenticationProvider = new MockAuthenticationProvider(); mExecutors = new MockExecutors(); - mHttpProvider = new MockHttpProvider(); mLogger = new MockLogger(); mSerializer = new MockSerializer(null, ""); + mHttpProvider = new CoreHttpProvider(mSerializer, + mAuthenticationProvider, + mExecutors, + mLogger); } @Test diff --git a/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java index ba6afeccd87..741e80a6cdc 100644 --- a/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseCollectionRequestTests.java @@ -3,6 +3,10 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.HashMap; @@ -10,8 +14,18 @@ import org.junit.Before; import org.junit.Test; +import org.mockito.Mockito; + +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; import com.microsoft.graph.authentication.MockAuthenticationProvider; import com.microsoft.graph.concurrency.MockExecutors; import com.microsoft.graph.core.MockBaseClient; @@ -28,50 +42,44 @@ public class BaseCollectionRequestTests { private MockAuthenticationProvider mAuthenticationProvider; private MockBaseClient mBaseClient; - private BaseCollectionRequest request; + private BaseCollectionRequest mRequest; @Before public void setUp() throws Exception { mAuthenticationProvider = new MockAuthenticationProvider(); mBaseClient = new MockBaseClient(); - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - - MockHttpProvider mProvider = new MockHttpProvider(new MockSerializer(null, ""), + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{ \"id\": \"zzz\" }" + )) + .addHeader("Content-Type", "application/json") + .build(); + final OkHttpClient mockClient = BaseStreamRequestTests.getMockClient(response); + final JsonObject result = new JsonObject(); + result.add("id", new JsonPrimitive("zzz")); + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(result, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); - request = new BaseCollectionRequest("https://a.b.c", mBaseClient, null, JsonObject.class,null){}; + mRequest = new BaseCollectionRequest("https://a.b.c", mBaseClient, null, JsonObject.class,null){}; } @Test public void testSend() { - JsonObject result = (JsonObject)request.send(); + JsonObject result = (JsonObject)mRequest.send(); assertNotNull(result); assertEquals("zzz", result.get("id").getAsString()); } @Test public void testPost() { - JsonObject result = (JsonObject)request.post(null); + JsonObject result = (JsonObject)mRequest.post(null); assertNotNull(result); assertEquals("zzz", result.get("id").getAsString()); } @@ -110,12 +118,16 @@ public void testFunctionAndQueryParameters() { } @Test - public void testHttpMethod() { - assertNull(request.getHttpMethod()); - request.send(); - assertEquals(HttpMethod.GET, request.getHttpMethod()); - request.post(null); - assertEquals(HttpMethod.POST, request.getHttpMethod()); + public void testGetMethod() { + assertNull(mRequest.getHttpMethod()); + mRequest.send(); + assertEquals(HttpMethod.GET, mRequest.getHttpMethod()); + } + @Test + public void testPostMethod() { + assertNull(mRequest.getHttpMethod()); + mRequest.post(null); + assertEquals(HttpMethod.POST, mRequest.getHttpMethod()); } @Test diff --git a/src/test/java/com/microsoft/graph/http/BaseRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseRequestTests.java index 2ed4e9eb7eb..14d15662788 100644 --- a/src/test/java/com/microsoft/graph/http/BaseRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseRequestTests.java @@ -14,7 +14,16 @@ import org.junit.Before; import org.junit.Test; +import okhttp3.Call; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; //import com.microsoft.graph.BuildConfig; import com.microsoft.graph.authentication.MockAuthenticationProvider; import com.microsoft.graph.concurrency.ICallback; @@ -33,43 +42,38 @@ public class BaseRequestTests { private MockAuthenticationProvider mAuthenticationProvider; private MockBaseClient mBaseClient; - private BaseRequest request; + private BaseRequest mRequest; private JsonObject callbackJsonObject; @Before public void setUp() throws Exception { mAuthenticationProvider = new MockAuthenticationProvider(); mBaseClient = new MockBaseClient(); - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 200; - } - - @Override - public String getJsonResponse() { - return "{ \"id\": \"zzz\" }"; - } - - @Override - public Map getHeaders() { - final HashMap map = new HashMap<>(); - map.put("Content-Type", "application/json"); - return map; - } - }; - MockHttpProvider mProvider = new MockHttpProvider(new MockSerializer(null, ""), + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(200).message("OK").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{ \"id\": \"zzz\" }" + )) + .addHeader("Content-Type", "application/json") + .build(); + final OkHttpClient mockClient = BaseStreamRequestTests.getMockClient(response); + final JsonObject result = new JsonObject(); + result.add("id", new JsonPrimitive("zzz")); + CoreHttpProvider mProvider = new CoreHttpProvider(new MockSerializer(result, ""), mAuthenticationProvider, new MockExecutors(), - new MockLogger()); - mProvider.setConnectionFactory(new MockConnectionFactory(new MockConnection(data))); + new MockLogger(), + mockClient); mBaseClient.setHttpProvider(mProvider); - request = new BaseRequest("https://a.b.c", mBaseClient, null,null){}; + mRequest = new BaseRequest("https://a.b.c", mBaseClient, null, JsonObject.class){}; } @Test public void testSend() { - JsonObject result = request.send(HttpMethod.GET, null); + JsonObject result = mRequest.send(HttpMethod.GET, null); assertNotNull(result); assertEquals("zzz", result.get("id").getAsString()); } @@ -91,7 +95,7 @@ public void failure(ClientException ex) { failure.set(true); } }; - request.send(HttpMethod.GET, callback,null); + mRequest.send(HttpMethod.GET, callback,null); assertTrue(success.get()); assertFalse(failure.get()); assertNotNull(callbackJsonObject); @@ -153,8 +157,8 @@ public void testHeader() { @Test public void testProtectedProperties() { - assertEquals(0, request.functionOptions.size()); - assertEquals(0, request.queryOptions.size()); + assertEquals(0, mRequest.functionOptions.size()); + assertEquals(0, mRequest.queryOptions.size()); final Option q1 = new QueryOption("q1","option1 "); final Option f1 = new FunctionOption("f1","option2"); final BaseRequest request = new BaseRequest("https://a.b.c", null, Arrays.asList(q1,f1), null){}; diff --git a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java index 69f4d5dca87..e0010aeff0e 100644 --- a/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java +++ b/src/test/java/com/microsoft/graph/http/BaseStreamRequestTests.java @@ -182,7 +182,7 @@ public void testBaseMethod() { assertNull(request.getHttpMethod()); assertEquals(2, request.getOptions().size()); } - private OkHttpClient getMockClient(final Response response) throws IOException { + public static OkHttpClient getMockClient(final Response response) throws IOException { final OkHttpClient mockClient = mock(OkHttpClient.class); final Call remoteCall = mock(Call.class); when(remoteCall.execute()).thenReturn(response); diff --git a/src/test/java/com/microsoft/graph/http/DefaultConnectionFactoryTests.java b/src/test/java/com/microsoft/graph/http/DefaultConnectionFactoryTests.java deleted file mode 100644 index 338d3faf910..00000000000 --- a/src/test/java/com/microsoft/graph/http/DefaultConnectionFactoryTests.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.microsoft.graph.http; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import org.junit.Before; -import org.junit.Test; - -/** - * Test cases for {@see DefaultConnectionFactory} - */ -public class DefaultConnectionFactoryTests { - - private IConnection mConnection; - - @Before - public void setUp() throws Exception { - mConnection = new DefaultConnectionFactory().createFromRequest(new MockHttpRequest()); - } - - @Test - public void testNotNull() { - assertNotNull(mConnection); - } - - @Test - public void testDefaultRequestMethod() { - assertEquals("GET", mConnection.getRequestMethod()); - } - -} diff --git a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java index 58485bb246b..2343c97a5c2 100644 --- a/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java +++ b/src/test/java/com/microsoft/graph/http/GraphServiceExceptionTests.java @@ -13,6 +13,12 @@ import org.junit.Test; +import okhttp3.MediaType; +import okhttp3.Protocol; +import okhttp3.Request; +import okhttp3.Response; +import okhttp3.ResponseBody; + import com.microsoft.graph.core.GraphErrorCodes; import com.microsoft.graph.logger.DefaultLogger; @@ -47,29 +53,22 @@ public void testVerboseError() { } @Test - public void testCreateFromConnection() { + public void testcreateFromResponse() { DefaultLogger logger = new DefaultLogger(); GraphServiceException exception = null; Boolean success = false; Boolean failure = false; - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 401; - } - - @Override - public String getJsonResponse() { - return "{}"; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; + final Response response = new Response.Builder() + .request(new Request.Builder().url("https://a.b.c").build()) + .protocol(Protocol.HTTP_1_1) + .code(401).message("Unauthorized").body( + ResponseBody.create( + MediaType.parse("application/json"), + "{}" + )) + .build(); try{ - exception = GraphServiceException.createFromConnection(new MockHttpRequest(),null,null,new MockConnection(data){},logger); + exception = GraphServiceException.createFromResponse(new MockHttpRequest(),null,null,response,logger); success = true; }catch (IOException ex){ failure = true; @@ -82,47 +81,4 @@ public Map getHeaders() { assertTrue(message.indexOf("Error code: Unable to parse error response message") == 0); assertTrue(message.indexOf("http://localhost") > 0); } - - @Test - public void testNullConnection() { - DefaultLogger logger = new DefaultLogger(); - GraphServiceException exception = null; - Boolean success = false; - Boolean failure = false; - final ITestConnectionData data = new ITestConnectionData() { - @Override - public int getRequestCode() { - return 401; - } - - @Override - public String getJsonResponse() { - return "{}"; - } - - @Override - public Map getHeaders() { - return new HashMap<>(); - } - }; - try{ - exception = GraphServiceException.createFromConnection(new MockHttpRequest(),null,null,new MockConnection(data) { - @Override - public InputStream getInputStream() throws IOException { - return null; - } - },logger); - success = true; - }catch (IOException ex){ - failure = true; - } - - assertTrue(success); - assertFalse(failure); - - String message = exception.getMessage(); - assertTrue(message.indexOf("Error code: Unable to parse error response message") == 0); - assertTrue(message.indexOf("http://localhost") > 0); - } - } diff --git a/src/test/java/com/microsoft/graph/http/MockConnection.java b/src/test/java/com/microsoft/graph/http/MockConnection.java deleted file mode 100644 index 7478260a467..00000000000 --- a/src/test/java/com/microsoft/graph/http/MockConnection.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.microsoft.graph.http; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Mock for {@see IConnection} - */ -public class MockConnection implements IConnection { - - private final ITestConnectionData mData; - private HashMap mHeaders = new HashMap<>(); - private Boolean mFollowRedirects; - private final String JSON_ENCODING = "UTF-8"; - - public MockConnection(ITestConnectionData data) { - mData = data; - } - - @Override - public void setFollowRedirects(boolean followRedirects) { - mFollowRedirects = followRedirects; - } - - @Override - public void addRequestHeader(String headerName, String headerValue) { - mHeaders.put(headerName, headerValue); - } - - @Override - public OutputStream getOutputStream() throws IOException { - return new ByteArrayOutputStream(); - } - - @Override - public InputStream getInputStream() throws IOException { - return new ByteArrayInputStream(mData.getJsonResponse().getBytes(JSON_ENCODING)); - } - - @Override - public int getResponseCode() throws IOException { - return mData.getRequestCode(); - } - - @Override - public String getResponseMessage() throws IOException { - return mData.getJsonResponse(); - } - - @Override - public void close() { - - } - - @Override - public Map getHeaders() { - return mData.getHeaders(); - } - - @Override - public String getRequestMethod() { - return "GET"; - } - - @Override - public int getContentLength() { - return mData.getJsonResponse().length(); - } - - @Override - public void setContentLength(int length) { - // noop - } - - @Override - public void setConnectTimeout(int connectionTimeoutMilliseconds) { - // noop - } - - @Override - public void setReadTimeout(int readTimeoutMilliseconds) { - // noop - } - - @Override - public Map> getResponseHeaders() { - Map> headers = new HashMap>(); - ArrayList headerValues = new ArrayList(); - headerValues.add("value1"); - headers.put("header1", headerValues); - - return headers; - } - -} diff --git a/src/test/java/com/microsoft/graph/http/MockConnectionFactory.java b/src/test/java/com/microsoft/graph/http/MockConnectionFactory.java deleted file mode 100644 index 5badfa22669..00000000000 --- a/src/test/java/com/microsoft/graph/http/MockConnectionFactory.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.microsoft.graph.http; - -import java.io.IOException; - -/** - * Mock for {@see IConnectionFactory} - */ -public class MockConnectionFactory implements IConnectionFactory { - - private final IConnection mConnection; - - public MockConnectionFactory(IConnection connection) { - mConnection = connection; - } - - @Override - public IConnection createFromRequest(IHttpRequest request) throws IOException { - return mConnection; - } -} diff --git a/src/test/java/com/microsoft/graph/http/MockHttpProvider.java b/src/test/java/com/microsoft/graph/http/MockHttpProvider.java deleted file mode 100644 index df6e3d8b2b5..00000000000 --- a/src/test/java/com/microsoft/graph/http/MockHttpProvider.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.microsoft.graph.http; - -import java.io.BufferedInputStream; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.microsoft.graph.authentication.IAuthenticationProvider; -import com.microsoft.graph.authentication.MockAuthenticationProvider; -import com.microsoft.graph.concurrency.ICallback; -import com.microsoft.graph.concurrency.IExecutors; -import com.microsoft.graph.concurrency.MockExecutors; -import com.microsoft.graph.core.ClientException; -import com.microsoft.graph.core.DefaultConnectionConfig; -import com.microsoft.graph.core.IConnectionConfig; -import com.microsoft.graph.logger.ILogger; -import com.microsoft.graph.logger.MockLogger; -import com.microsoft.graph.serializer.ISerializer; -import com.microsoft.graph.serializer.MockSerializer; - -/** - * Mock for {@see IHttpProvider} - */ -public class MockHttpProvider implements IHttpProvider { - - private final ISerializer mSerializer; - private final IAuthenticationProvider mAuthenticationProvider; - private final IExecutors mExecutors; - private final ILogger mLogger; - private IConnectionFactory mConnectionFactory; - private IConnectionConfig connectionConfig; - - @Override - public ISerializer getSerializer() { - return null; - } - - public MockHttpProvider() { - mLogger = new MockLogger(); - mSerializer = new MockSerializer(null,""); - mAuthenticationProvider = new MockAuthenticationProvider(); - mExecutors = new MockExecutors(); - mConnectionFactory = new DefaultConnectionFactory(); - } - - public MockHttpProvider(final ISerializer serializer, - final IAuthenticationProvider authenticationProvider, - final IExecutors executors, - final ILogger logger) { - mSerializer = serializer; - mAuthenticationProvider = authenticationProvider; - mExecutors = executors; - mLogger = logger; - mConnectionFactory = new DefaultConnectionFactory(); - } - - - @Override - public void send(IHttpRequest request, - ICallback callback, - Class resultClass, - BodyType serializable) { - Result result = null; - try{ - IConnection connection = mConnectionFactory.createFromRequest(request); - if(connection.getResponseCode() == 200) { - if(connection.getHeaders().containsKey("Content-Type")) { - if (connection.getHeaders().get("Content-Type").equals("application/json")){ - JsonObject jsonObject = JsonParser.parseString(connection.getResponseMessage()).getAsJsonObject(); - result = (Result) jsonObject; - }else if (connection.getHeaders().get("Content-Type").equals("application/octet-stream")) { - result = (Result) new BufferedInputStream(connection.getInputStream()); - } - } - } - } catch (Exception ex){ - final ClientException clientException = new ClientException("Error during http request", - ex); - callback.failure(clientException); - } - callback.success(result); - } - - @Override - public Result send(IHttpRequest request, - Class resultClass, - BodyType serializable) throws ClientException { - try{ - IConnection connection = mConnectionFactory.createFromRequest(request); - if(connection.getResponseCode() == 200) { - if(connection.getHeaders().containsKey("Content-Type")) { - if (connection.getHeaders().get("Content-Type").equals("application/json")){ - JsonObject jsonObject = JsonParser.parseString(connection.getResponseMessage()).getAsJsonObject(); - return (Result) jsonObject; - }else if (connection.getHeaders().get("Content-Type").equals("application/octet-stream")) { - return (Result) new BufferedInputStream(connection.getInputStream()); - } - } - } - } catch (Exception ex){ - final ClientException clientException = new ClientException("Error during http request", - ex); - throw clientException; - } - return null; - } - - @Override - public Result send(IHttpRequest request, Class resultClass, BodyType serializable, IStatefulResponseHandler handler) throws ClientException { - return null; - } - - void setConnectionFactory(final IConnectionFactory factory) { - mConnectionFactory = factory; - } - - public IConnectionConfig getConnectionConfig() { - if(this.connectionConfig == null) { - this.connectionConfig = new DefaultConnectionConfig(); - } - return this.connectionConfig; - } - - public void setConnectionConfig(IConnectionConfig connectionConfig) { - this.connectionConfig = connectionConfig; - } -} diff --git a/src/test/java/com/microsoft/graph/http/MockRequest.java b/src/test/java/com/microsoft/graph/http/MockRequest.java deleted file mode 100644 index af4cea087d2..00000000000 --- a/src/test/java/com/microsoft/graph/http/MockRequest.java +++ /dev/null @@ -1,124 +0,0 @@ -// ------------------------------------------------------------------------------ -// Copyright (c) 2015 Microsoft Corporation -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// ------------------------------------------------------------------------------ - -package com.microsoft.graph.http; - -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.List; - -import com.microsoft.graph.httpcore.middlewareoption.IShouldRedirect; -import com.microsoft.graph.httpcore.middlewareoption.IShouldRetry; -import com.microsoft.graph.httpcore.middlewareoption.RedirectOptions; -import com.microsoft.graph.httpcore.middlewareoption.RetryOptions; -import com.microsoft.graph.options.HeaderOption; -import com.microsoft.graph.options.Option; - -/** - * Mock request for {@see IHttpRequest} - */ -class MockRequest implements IHttpRequest { - - @Override - public URL getRequestUrl() { - try { - return new URL("http://localhost"); - } catch (final MalformedURLException ignored) { - } - return null; - } - - @Override - public HttpMethod getHttpMethod() { - return HttpMethod.GET; - } - - @Override - public List getHeaders() { - return new ArrayList<>(); - } - - @Override - public List