blob: e142a3f118865f84ff5247ac62eceedfa4dbae51 [file] [log] [blame]
package org.robolectric.shadows;
import junit.framework.Assert;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultRequestDirector;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.tester.org.apache.http.FakeHttpLayer;
import org.robolectric.tester.org.apache.http.RequestMatcher;
import org.robolectric.tester.org.apache.http.TestHttpResponse;
import org.robolectric.util.Strings;
import org.robolectric.util.TestRunnerWithManifest;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.*;
import static org.robolectric.fakehttp.Shadows.shadowOf;
@RunWith(TestRunnerWithManifest.class)
public class DefaultRequestDirectorTest {
private DefaultRequestDirector requestDirector;
private ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
@Before
public void setUp_EnsureStaticStateIsReset() {
FakeHttpLayer fakeHttpLayer = FakeHttp.getFakeHttpLayer();
assertFalse(fakeHttpLayer.hasPendingResponses());
assertFalse(fakeHttpLayer.hasRequestInfos());
assertFalse(fakeHttpLayer.hasResponseRules());
connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
@Override public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
return 0;
}
};
requestDirector = new DefaultRequestDirector(null, null, null, connectionKeepAliveStrategy, null, null, null, null, null, null, null, null);
}
@After
public void tearDown_EnsureStaticStateIsReset() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
}
@Test
public void shouldGetHttpResponseFromExecute() throws Exception {
FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a happy response body");
}
@Test
public void shouldPreferPendingResponses() throws Exception {
FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
FakeHttp.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
new TestHttpResponse(200, "a cheery response body"));
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a happy response body");
}
@Test
public void shouldReturnRequestsByRule() throws Exception {
FakeHttp.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
new TestHttpResponse(200, "a cheery response body"));
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a cheery response body");
}
@Test
public void shouldReturnRequestsByRule_MatchingMethod() throws Exception {
FakeHttp.setDefaultHttpResponse(404, "no such page");
FakeHttp.addHttpResponseRule(HttpPost.METHOD_NAME, "http://some.uri",
new TestHttpResponse(200, "a cheery response body"));
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(404);
}
@Test
public void shouldReturnRequestsByRule_AnyMethod() throws Exception {
FakeHttp.addHttpResponseRule("http://some.uri", new TestHttpResponse(200, "a cheery response body"));
HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(getResponse);
assertThat(getResponse.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(getResponse.getEntity().getContent())).isEqualTo("a cheery response body");
HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
assertNotNull(postResponse);
assertThat(postResponse.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(postResponse.getEntity().getContent())).isEqualTo("a cheery response body");
}
@Test
public void shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams() throws Exception {
TestHttpResponse testHttpResponse = new TestHttpResponse(200, "a cheery response body");
FakeHttp.addHttpResponseRule("http://some.uri", testHttpResponse);
assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isTrue();
HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
InputStream getResponseStream = getResponse.getEntity().getContent();
assertThat(Strings.fromStream(getResponseStream)).isEqualTo("a cheery response body");
assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse();
HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
InputStream postResponseStream = postResponse.getEntity().getContent();
assertThat(Strings.fromStream(postResponseStream)).isEqualTo("a cheery response body");
assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse();
getResponseStream.close();
assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse();
postResponseStream.close();
assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isTrue();
}
@Test
public void shouldReturnRequestsByRule_WithTextResponse() throws Exception {
FakeHttp.addHttpResponseRule("http://some.uri", "a cheery response body");
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a cheery response body");
}
@Test
public void clearHttpResponseRules_shouldRemoveAllRules() throws Exception {
FakeHttp.addHttpResponseRule("http://some.uri", "a cheery response body");
FakeHttp.clearHttpResponseRules();
FakeHttp.addHttpResponseRule("http://some.uri", "a gloomy response body");
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a gloomy response body");
}
@Test
public void clearPendingHttpResponses() throws Exception {
FakeHttp.addPendingHttpResponse(200, "earlier");
FakeHttp.clearPendingHttpResponses();
FakeHttp.addPendingHttpResponse(500, "later");
HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(500);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("later");
}
@Test
public void shouldReturnRequestsByRule_WithCustomRequestMatcher() throws Exception {
FakeHttp.setDefaultHttpResponse(404, "no such page");
FakeHttp.addHttpResponseRule(new RequestMatcher() {
@Override
public boolean matches(HttpRequest request) {
return request.getRequestLine().getUri().equals("http://matching.uri");
}
}, new TestHttpResponse(200, "a cheery response body"));
HttpResponse response = requestDirector.execute(null, new HttpGet("http://matching.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a cheery response body");
response = requestDirector.execute(null, new HttpGet("http://non-matching.uri"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(404);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("no such page");
}
@Test
public void shouldGetHttpResponseFromExecuteSimpleApi() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a happy response body");
}
@Test
public void shouldHandleMultipleInvocations() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
FakeHttp.addPendingHttpResponse(201, "another happy response body");
HttpResponse response1 = requestDirector.execute(null, new HttpGet("http://example.com"), null);
HttpResponse response2 = requestDirector.execute(null, new HttpGet("www.example.com"), null);
assertThat(response1.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response1.getEntity().getContent())).isEqualTo("a happy response body");
assertThat(response2.getStatusLine().getStatusCode()).isEqualTo(201);
assertThat(Strings.fromStream(response2.getEntity().getContent())).isEqualTo("another happy response body");
}
@Test
public void shouldHandleMultipleInvocationsOfExecute() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
FakeHttp.addPendingHttpResponse(201, "another happy response body");
requestDirector.execute(null, new HttpGet("http://example.com"), null);
requestDirector.execute(null, new HttpGet("www.example.com"), null);
HttpUriRequest request1 = (HttpUriRequest) FakeHttp.getSentHttpRequest(0);
assertThat(request1.getMethod()).isEqualTo(HttpGet.METHOD_NAME);
assertThat(request1.getURI()).isEqualTo(URI.create("http://example.com"));
HttpUriRequest request2 = (HttpUriRequest) FakeHttp.getSentHttpRequest(1);
assertThat(request2.getMethod()).isEqualTo(HttpGet.METHOD_NAME);
assertThat(request2.getURI()).isEqualTo(URI.create("www.example.com"));
}
@Test
public void shouldRejectUnexpectedCallsToExecute() throws Exception {
try {
requestDirector.execute(null, new HttpGet("http://example.com"), null);
fail();
} catch (RuntimeException expected) {
assertThat(expected.getMessage()).isEqualTo("Unexpected call to execute, no pending responses are available. See Robolectric.addPendingResponse(). Request was: GET http://example.com");
}
}
@Test
public void shouldRecordExtendedRequestData() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
HttpGet httpGet = new HttpGet("http://example.com");
requestDirector.execute(null, httpGet, null);
assertSame(FakeHttp.getSentHttpRequestInfo(0).getHttpRequest(), httpGet);
ConnectionKeepAliveStrategy strategy = shadowOf((DefaultRequestDirector) FakeHttp.getSentHttpRequestInfo(0).getRequestDirector()).getConnectionKeepAliveStrategy();
assertSame(strategy, connectionKeepAliveStrategy);
}
@Test
public void getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
HttpGet httpGet = new HttpGet("http://example.com");
requestDirector.execute(null, httpGet, null);
assertSame(FakeHttp.getNextSentHttpRequestInfo().getHttpRequest(), httpGet);
assertNull(FakeHttp.getNextSentHttpRequestInfo());
}
@Test
public void getNextSentHttpRequest_shouldRemoveHttpRequests() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
HttpGet httpGet = new HttpGet("http://example.com");
requestDirector.execute(null, httpGet, null);
assertSame(FakeHttp.getNextSentHttpRequest(), httpGet);
assertNull(FakeHttp.getNextSentHttpRequest());
}
@Test
public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception {
FakeHttp.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain"));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = client.execute(new HttpGet("http://www.nowhere.org"));
assertThat(((HttpUriRequest) FakeHttp.getSentHttpRequest(0)).getURI()).isEqualTo(URI.create("http://www.nowhere.org"));
Assert.assertNotNull(response);
String responseStr = new BasicResponseHandler().handleResponse(response);
Assert.assertEquals("OK", responseStr);
}
@Test
public void shouldFindLastRequestMade() throws Exception {
FakeHttp.addPendingHttpResponse(200, "a happy response body");
FakeHttp.addPendingHttpResponse(200, "a happy response body");
FakeHttp.addPendingHttpResponse(200, "a happy response body");
DefaultHttpClient client = new DefaultHttpClient();
client.execute(new HttpGet("http://www.first.org"));
client.execute(new HttpGet("http://www.second.org"));
client.execute(new HttpGet("http://www.third.org"));
assertThat(((HttpUriRequest) FakeHttp.getLatestSentHttpRequest()).getURI()).isEqualTo(URI.create("http://www.third.org"));
}
@Test
public void shouldSupportConnectionTimeoutWithExceptions() throws Exception {
FakeHttp.setDefaultHttpResponse(new TestHttpResponse() {
@Override
public HttpParams getParams() {
HttpParams httpParams = super.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, -1);
return httpParams;
}
});
DefaultHttpClient client = new DefaultHttpClient();
try {
client.execute(new HttpGet("http://www.nowhere.org"));
} catch (ConnectTimeoutException x) {
return;
}
fail("Exception should have been thrown");
}
@Test
public void shouldSupportSocketTimeoutWithExceptions() throws Exception {
FakeHttp.setDefaultHttpResponse(new TestHttpResponse() {
@Override
public HttpParams getParams() {
HttpParams httpParams = super.getParams();
HttpConnectionParams.setSoTimeout(httpParams, -1);
return httpParams;
}
});
DefaultHttpClient client = new DefaultHttpClient();
try {
client.execute(new HttpGet("http://www.nowhere.org"));
} catch (ConnectTimeoutException x) {
return;
}
fail("Exception should have been thrown");
}
@Test(expected = IOException.class)
public void shouldSupportRealHttpRequests() throws Exception {
FakeHttp.getFakeHttpLayer().interceptHttpRequests(false);
DefaultHttpClient client = new DefaultHttpClient();
client.execute(new HttpGet("http://www.this-host-should-not-exist-123456790.org:999"));
}
@Test
public void shouldSupportRealHttpRequestsAddingRequestInfo() throws Exception {
FakeHttp.getFakeHttpLayer().interceptHttpRequests(false);
DefaultHttpClient client = new DefaultHttpClient();
// it's really bad to depend on an external server in order to get a test pass,
// but this test is about making sure that we can intercept calls to external servers
// so, I think that in this specific case, it's appropriate...
client.execute(new HttpGet("http://google.com"));
assertNotNull(FakeHttp.getFakeHttpLayer().getLastSentHttpRequestInfo());
assertNotNull(FakeHttp.getFakeHttpLayer().getLastHttpResponse());
}
@Test
public void realHttpRequestsShouldMakeContentDataAvailable() throws Exception {
FakeHttp.getFakeHttpLayer().interceptHttpRequests(false);
FakeHttp.getFakeHttpLayer().interceptResponseContent(true);
DefaultHttpClient client = new DefaultHttpClient();
client.execute(new HttpGet("http://google.com"));
byte[] cachedContent = FakeHttp.getFakeHttpLayer().getHttpResposeContentList().get(0);
assertThat(cachedContent.length).isNotEqualTo(0);
InputStream content = FakeHttp.getFakeHttpLayer().getLastHttpResponse().getEntity().getContent();
BufferedReader contentReader = new BufferedReader(new InputStreamReader(content));
String firstLineOfContent = contentReader.readLine();
assertThat(firstLineOfContent).contains("Google");
BufferedReader cacheReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(cachedContent)));
String firstLineOfCachedContent = cacheReader.readLine();
assertThat(firstLineOfCachedContent).isEqualTo(firstLineOfContent);
}
@Test
public void shouldReturnResponseFromHttpResponseGenerator() throws Exception {
FakeHttp.addPendingHttpResponse(new HttpResponseGenerator() {
@Override
public HttpResponse getResponse(HttpRequest request) {
return new TestHttpResponse(200, "a happy response body");
}
});
HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
assertNotNull(response);
assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200);
assertThat(Strings.fromStream(response.getEntity().getContent())).isEqualTo("a happy response body");
}
}