Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ public void cancelled() {
writeFuture.get(writeTimeout, TimeUnit.MILLISECONDS);
}
} catch (TimeoutException e) {
throw new IOException("Write Timeout", e.getCause());
responseFuture.cancel(true);
throw new IOException("Write Timeout", e);
} catch (Exception e) {
throw new IOException("Exception in write", e.getCause());
}
Expand Down
189 changes: 42 additions & 147 deletions src/test/java/com/google/firebase/internal/ApacheHttp2TransportIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.LowLevelHttpResponse;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.util.GenericData;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.collect.ImmutableMap;
import com.google.firebase.ErrorCode;
Expand All @@ -49,7 +48,6 @@
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpRequestInterceptor;
import org.apache.hc.core5.http.protocol.HttpContext;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
Expand All @@ -58,15 +56,9 @@
public class ApacheHttp2TransportIT {
private static FirebaseApp app;
private static final GoogleCredentials MOCK_CREDENTIALS = new MockGoogleCredentials("test_token");
private static final ImmutableMap<String, Object> payload =
private static final ImmutableMap<String, Object> payload =
ImmutableMap.<String, Object>of("foo", "bar");

// Sets a 5 second delay before server response to simulate a slow network that
// results in a read timeout.
private static final String DELAY_URL = "https://nghttp2.org/httpbin/delay/5";
private static final String GET_URL = "https://nghttp2.org/httpbin/get";
private static final String POST_URL = "https://nghttp2.org/httpbin/post";

private static ServerSocket serverSocket;
private static Socket fillerSocket;
private static int port;
Expand Down Expand Up @@ -104,29 +96,13 @@ public void cleanup() {
System.clearProperty("https.proxyPort");
}

@Test(timeout = 10_000L)
public void testUnauthorizedGetRequest() throws FirebaseException {
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(false);
HttpRequestInfo request = HttpRequestInfo.buildGetRequest(GET_URL);
IncomingHttpResponse response = httpClient.send(request);
assertEquals(200, response.getStatusCode());
}

@Test(timeout = 10_000L)
public void testUnauthorizedPostRequest() throws FirebaseException {
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(false);
HttpRequestInfo request = HttpRequestInfo.buildJsonPostRequest(POST_URL, payload);
GenericData body = httpClient.sendAndParse(request, GenericData.class);
assertEquals("{\"foo\":\"bar\"}", body.get("data"));
}

@Test(timeout = 10_000L)
public void testConnectTimeoutAuthorizedGet() throws FirebaseException {
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.setConnectTimeout(100)
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(app);
HttpRequestInfo request = HttpRequestInfo.buildGetRequest("https://localhost:" + port);

try {
Expand All @@ -145,8 +121,9 @@ public void testConnectTimeoutAuthorizedPost() throws FirebaseException {
.setCredentials(MOCK_CREDENTIALS)
.setConnectTimeout(100)
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
HttpRequestInfo request = HttpRequestInfo.buildJsonPostRequest("https://localhost:" + port, payload);
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(app);
HttpRequestInfo request = HttpRequestInfo.buildJsonPostRequest(
"https://localhost:" + port, payload);

try {
httpClient.send(request);
Expand All @@ -158,102 +135,25 @@ public void testConnectTimeoutAuthorizedPost() throws FirebaseException {
}
}

@Test(timeout = 10_000L)
public void testReadTimeoutAuthorizedGet() throws FirebaseException {
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.setReadTimeout(100)
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
HttpRequestInfo request = HttpRequestInfo.buildGetRequest(DELAY_URL);

try {
httpClient.send(request);
fail("No exception thrown for HTTP error response");
} catch (FirebaseException e) {
assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
assertEquals("IO error: Stream exception in request", e.getMessage());
assertNull(e.getHttpResponse());
}
}

@Test(timeout = 10_000L)
public void testReadTimeoutAuthorizedPost() throws FirebaseException {
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.setReadTimeout(100)
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
HttpRequestInfo request = HttpRequestInfo.buildJsonPostRequest(DELAY_URL, payload);

try {
httpClient.send(request);
fail("No exception thrown for HTTP error response");
} catch (FirebaseException e) {
assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
assertEquals("IO error: Stream exception in request", e.getMessage());
assertNull(e.getHttpResponse());
}
}

@Test(timeout = 10_000L)
public void testWriteTimeoutAuthorizedGet() throws FirebaseException {
// Use a fresh transport so that writeTimeout triggers while waiting for the transport to
// be ready to receive data.
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.setWriteTimeout(100)
.setHttpTransport(new ApacheHttp2Transport())
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
HttpRequestInfo request = HttpRequestInfo.buildGetRequest(GET_URL);

try {
httpClient.send(request);
fail("No exception thrown for HTTP error response");
} catch (FirebaseException e) {
assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
assertEquals("IO error: Write Timeout", e.getMessage());
assertNull(e.getHttpResponse());
}
}

@Test(timeout = 10_000L)
public void testWriteTimeoutAuthorizedPost() throws FirebaseException {
// Use a fresh transport so that writeTimeout triggers while waiting for the transport to
// be ready to receive data.
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.setWriteTimeout(100)
.setHttpTransport(new ApacheHttp2Transport())
.build(), "test-app");
ErrorHandlingHttpClient<FirebaseException> httpClient = getHttpClient(true, app);
HttpRequestInfo request = HttpRequestInfo.buildJsonPostRequest(POST_URL, payload);

try {
httpClient.send(request);
fail("No exception thrown for HTTP error response");
} catch (FirebaseException e) {
assertEquals(ErrorCode.UNKNOWN, e.getErrorCode());
assertEquals("IO error: Write Timeout", e.getMessage());
assertNull(e.getHttpResponse());
}
}

@Test(timeout = 10_000L)
public void testRequestShouldNotFollowRedirects() throws IOException {
ApacheHttp2Transport transport = new ApacheHttp2Transport();
ApacheHttp2Request request = transport.buildRequest("GET",
"https://google.com");
LowLevelHttpResponse response = request.execute();

assertEquals(301, response.getStatusCode());
assert (response instanceof ApacheHttp2Response);
assertEquals("https://www.google.com/", ((ApacheHttp2Response) response).getHeaderValue("location"));
try {
ApacheHttp2Request request = transport.buildRequest("GET", "https://google.com");
LowLevelHttpResponse response = request.execute();

assertEquals(301, response.getStatusCode());
assertTrue(response instanceof ApacheHttp2Response);
assertEquals(
"https://www.google.com/",
((ApacheHttp2Response) response).getHeaderValue("location"));
} finally {
transport.shutdown();
}
}

@Test(timeout = 10_000L)
public void testRequestCanSetHeaders() {
public void testRequestCanSetHeaders() throws IOException {
final AtomicBoolean interceptorCalled = new AtomicBoolean(false);
CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.addRequestInterceptorFirst(
Expand All @@ -272,29 +172,37 @@ public void process(
.build();

ApacheHttp2Transport transport = new ApacheHttp2Transport(client);
ApacheHttp2Request request = transport.buildRequest("GET", "http://www.google.com");
request.addHeader("foo", "bar");
try {
request.execute();
fail("should not actually make the request");
} catch (IOException exception) {
assertEquals("Unknown exception in request", exception.getMessage());
ApacheHttp2Request request = transport.buildRequest("GET", "http://www.google.com");
request.addHeader("foo", "bar");
try {
request.execute();
fail("should not actually make the request");
} catch (IOException exception) {
assertEquals("Unknown exception in request", exception.getMessage());
}
assertTrue("Expected to have called our test interceptor", interceptorCalled.get());
} finally {
transport.shutdown();
}
assertTrue("Expected to have called our test interceptor", interceptorCalled.get());
}

@Test(timeout = 10_000L)
public void testVerifyProxyIsRespected() {
try {
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8080");
public void testVerifyProxyIsRespected() throws IOException {
System.setProperty("https.proxyHost", "localhost");
System.setProperty("https.proxyPort", "8080");

HttpTransport transport = new ApacheHttp2Transport();
transport.createRequestFactory().buildGetRequest(new GenericUrl(GET_URL)).execute();
HttpTransport transport = new ApacheHttp2Transport();
try {
transport.createRequestFactory()
.buildGetRequest(new GenericUrl("https://www.google.com"))
.execute();
fail("No exception thrown for HTTP error response");
} catch (IOException e) {
assertEquals("Connection exception in request", e.getMessage());
assertTrue(e.getCause().getMessage().contains("localhost:8080"));
} finally {
transport.shutdown();
}
}

Expand All @@ -303,7 +211,7 @@ public void testVerifyDefaultTransportReused() {
FirebaseOptions o1 = FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.build();

FirebaseOptions o2 = FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.build();
Expand All @@ -313,26 +221,13 @@ public void testVerifyDefaultTransportReused() {
assertEquals(t1, t2);
}

private static ErrorHandlingHttpClient<FirebaseException> getHttpClient(boolean authorized,
FirebaseApp app) {
HttpRequestFactory requestFactory;
if (authorized) {
requestFactory = ApiClientUtils.newAuthorizedRequestFactory(app);
} else {
requestFactory = ApiClientUtils.newUnauthorizedRequestFactory(app);
}
private static ErrorHandlingHttpClient<FirebaseException> getHttpClient(FirebaseApp app) {
HttpRequestFactory requestFactory = ApiClientUtils.newAuthorizedRequestFactory(app);
JsonFactory jsonFactory = ApiClientUtils.getDefaultJsonFactory();
TestHttpErrorHandler errorHandler = new TestHttpErrorHandler();
return new ErrorHandlingHttpClient<>(requestFactory, jsonFactory, errorHandler);
}

private static ErrorHandlingHttpClient<FirebaseException> getHttpClient(boolean authorized) {
app = FirebaseApp.initializeApp(FirebaseOptions.builder()
.setCredentials(MOCK_CREDENTIALS)
.build(), "test-app");
return getHttpClient(authorized, app);
}

private static class TestHttpErrorHandler implements HttpErrorHandler<FirebaseException> {
@Override
public FirebaseException handleIOException(IOException e) {
Expand Down
Loading
Loading