| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.libraries.entitlement.http; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.verify; |
| import static org.mockito.Mockito.when; |
| import static org.testng.Assert.expectThrows; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| |
| import android.net.Network; |
| |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import com.android.libraries.entitlement.ServiceEntitlementException; |
| import com.android.libraries.entitlement.http.HttpConstants.ContentType; |
| import com.android.libraries.entitlement.http.HttpConstants.RequestMethod; |
| import com.android.libraries.entitlement.testing.FakeURLStreamHandler; |
| import com.android.libraries.entitlement.testing.FakeURLStreamHandler.FakeHttpsURLConnection; |
| import com.android.libraries.entitlement.testing.FakeURLStreamHandler.FakeResponse; |
| |
| import com.google.common.collect.ImmutableMap; |
| |
| import org.json.JSONObject; |
| import org.junit.Before; |
| import org.junit.BeforeClass; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.net.HttpURLConnection; |
| import java.net.URL; |
| import java.util.Map; |
| |
| @RunWith(AndroidJUnit4.class) |
| public class HttpClientTest { |
| private static final String TEST_URL = "https://test.url"; |
| private static final String TEST_RESPONSE_BODY = "TEST_RESPONSE_BODY"; |
| private static final String CONTENT_TYPE_STRING_JSON = "application/json"; |
| private static final String RETRY_AFTER = "RETRY_AFTER"; |
| |
| private static FakeURLStreamHandler sFakeURLStreamHandler; |
| |
| private HttpClient mHttpClient; |
| |
| @BeforeClass |
| public static void setupURLStreamHandlerFactory() { |
| sFakeURLStreamHandler = new FakeURLStreamHandler(); |
| URL.setURLStreamHandlerFactory(sFakeURLStreamHandler); |
| } |
| |
| @Before |
| public void setUp() { |
| // Reset sFakeURLStreamHandler |
| sFakeURLStreamHandler.stubResponse(ImmutableMap.of()); |
| |
| mHttpClient = new HttpClient(); |
| } |
| |
| @Test |
| public void request_contentTypeXml_returnsXmlBody() throws Exception { |
| FakeResponse responseContent = |
| FakeResponse.builder() |
| .setResponseCode(HttpURLConnection.HTTP_OK) |
| .setResponseLocation(null) |
| .setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8)) |
| .setContentType(CONTENT_TYPE_STRING_JSON) |
| .build(); |
| Map<String, FakeResponse> response = ImmutableMap.of(TEST_URL, responseContent); |
| sFakeURLStreamHandler.stubResponse(response); |
| HttpRequest request = |
| HttpRequest.builder() |
| .setUrl(TEST_URL) |
| .setRequestMethod(RequestMethod.GET) |
| .setTimeoutInSec(70) |
| .build(); |
| |
| HttpResponse httpResponse = mHttpClient.request(request); |
| |
| // Verify that one HttpURLConnection was opened and its timeout is 70 seconds. |
| assertThat(sFakeURLStreamHandler.getConnections()).hasSize(1); |
| HttpURLConnection connection = sFakeURLStreamHandler.getConnections().get(0); |
| assertThat(connection.getConnectTimeout()).isEqualTo(70 * 1000); |
| assertThat(connection.getReadTimeout()).isEqualTo(70 * 1000); |
| // Verify the HttpResponse. |
| assertThat(httpResponse.contentType()).isEqualTo(ContentType.JSON); |
| assertThat(httpResponse.body()).isEqualTo(TEST_RESPONSE_BODY); |
| assertThat(httpResponse.responseCode()).isEqualTo(HttpURLConnection.HTTP_OK); |
| } |
| |
| @Test |
| public void request_httpGetResponseBadRequest_throwsException() { |
| FakeResponse responseContent = |
| FakeResponse.builder() |
| .setResponseCode(HttpURLConnection.HTTP_BAD_REQUEST) |
| .setResponseLocation(null) |
| .setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8)) |
| .setContentType(CONTENT_TYPE_STRING_JSON) |
| .setRetryAfter(RETRY_AFTER) |
| .build(); |
| HttpRequest request = |
| HttpRequest.builder().setUrl(TEST_URL).setRequestMethod(RequestMethod.GET).build(); |
| Map<String, FakeResponse> response = ImmutableMap.of(TEST_URL, responseContent); |
| sFakeURLStreamHandler.stubResponse(response); |
| |
| ServiceEntitlementException exception = |
| expectThrows(ServiceEntitlementException.class, () -> mHttpClient.request(request)); |
| |
| // Verify the ServiceEntitlementException. |
| assertThat(exception.getErrorCode()).isEqualTo( |
| ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS); |
| assertThat(exception.getHttpStatus()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST); |
| assertThat(exception).hasMessageThat().contains("Invalid connection response"); |
| assertThat(exception.getRetryAfter()).isEqualTo(RETRY_AFTER); |
| // Verify that one HttpURLConnection was opened and its timeout is 30 seconds. |
| assertThat(sFakeURLStreamHandler.getConnections()).hasSize(1); |
| HttpURLConnection connection = sFakeURLStreamHandler.getConnections().get(0); |
| assertThat(connection.getConnectTimeout()).isEqualTo(30 * 1000); |
| assertThat(connection.getReadTimeout()).isEqualTo(30 * 1000); |
| } |
| |
| @Test |
| public void request_contentTypeXml_returnsXmlBody_useSpecificNetwork() throws Exception { |
| FakeResponse responseContent = |
| FakeResponse.builder() |
| .setResponseCode(HttpURLConnection.HTTP_OK) |
| .setResponseLocation(null) |
| .setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8)) |
| .setContentType(CONTENT_TYPE_STRING_JSON) |
| .build(); |
| Network network = mock(Network.class); |
| URL url = new URL(TEST_URL); |
| FakeHttpsURLConnection connection = new FakeHttpsURLConnection(url, responseContent); |
| when(network.openConnection(url)).thenReturn(connection); |
| HttpRequest request = |
| HttpRequest.builder() |
| .setUrl(TEST_URL) |
| .setRequestMethod(RequestMethod.GET) |
| .setNetwork(network) |
| .setTimeoutInSec(70) |
| .build(); |
| |
| HttpResponse httpResponse = mHttpClient.request(request); |
| |
| // Verify that the HttpURLConnection associsted with Netwotk was opened |
| // and its timeout is 70 seconds. |
| verify(network).openConnection(url); |
| assertThat(connection.getConnectTimeout()).isEqualTo(70 * 1000); |
| assertThat(connection.getReadTimeout()).isEqualTo(70 * 1000); |
| // Verify the HttpResponse. |
| assertThat(httpResponse.contentType()).isEqualTo(ContentType.JSON); |
| assertThat(httpResponse.body()).isEqualTo(TEST_RESPONSE_BODY); |
| assertThat(httpResponse.responseCode()).isEqualTo(HttpURLConnection.HTTP_OK); |
| } |
| |
| @Test |
| public void request_postJson_doNotEscapeForwardSlash() throws Exception { |
| String postData = "{\"key\":\"base64/base64+b\"}"; |
| HttpRequest request = |
| HttpRequest.builder() |
| .setUrl(TEST_URL) |
| .setRequestMethod(RequestMethod.POST) |
| .setPostData(new JSONObject(postData)) |
| .build(); |
| FakeResponse responseContent = |
| FakeResponse.builder() |
| .setResponseCode(HttpURLConnection.HTTP_OK) |
| .setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8)) |
| .setContentType(CONTENT_TYPE_STRING_JSON) |
| .build(); |
| Map<String, FakeResponse> response = ImmutableMap.of(TEST_URL, responseContent); |
| sFakeURLStreamHandler.stubResponse(response); |
| |
| HttpResponse httpResponse = mHttpClient.request(request); |
| |
| FakeHttpsURLConnection connection = sFakeURLStreamHandler.getConnections().get(0); |
| assertThat(connection.getBytesWrittenToOutputStream()).isEqualTo(postData.getBytes(UTF_8)); |
| } |
| } |