1 package com.xtremelabs.robolectric.shadows;
2 
3 import com.xtremelabs.robolectric.Robolectric;
4 import com.xtremelabs.robolectric.WithTestDefaultsRunner;
5 import com.xtremelabs.robolectric.tester.org.apache.http.FakeHttpLayer;
6 import com.xtremelabs.robolectric.tester.org.apache.http.RequestMatcher;
7 import com.xtremelabs.robolectric.tester.org.apache.http.TestHttpResponse;
8 import com.xtremelabs.robolectric.util.Strings;
9 import junit.framework.Assert;
10 import org.apache.http.HttpRequest;
11 import org.apache.http.HttpResponse;
12 import org.apache.http.client.methods.HttpGet;
13 import org.apache.http.client.methods.HttpPost;
14 import org.apache.http.client.methods.HttpUriRequest;
15 import org.apache.http.conn.ConnectTimeoutException;
16 import org.apache.http.conn.ConnectionKeepAliveStrategy;
17 import org.apache.http.impl.client.BasicResponseHandler;
18 import org.apache.http.impl.client.DefaultHttpClient;
19 import org.apache.http.impl.client.DefaultRequestDirector;
20 import org.apache.http.message.BasicHeader;
21 import org.apache.http.params.HttpConnectionParams;
22 import org.apache.http.params.HttpParams;
23 import org.apache.http.protocol.HttpContext;
24 import org.junit.After;
25 import org.junit.Before;
26 import org.junit.Test;
27 import org.junit.runner.RunWith;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.net.URI;
32 
33 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
34 import static org.hamcrest.core.IsEqual.equalTo;
35 import static org.junit.Assert.*;
36 
37 @RunWith(WithTestDefaultsRunner.class)
38 public class DefaultRequestDirectorTest {
39     private DefaultRequestDirector requestDirector;
40     private ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
41 
42     @Before
setUp_EnsureStaticStateIsReset()43     public void setUp_EnsureStaticStateIsReset() {
44         FakeHttpLayer fakeHttpLayer = Robolectric.getFakeHttpLayer();
45         assertFalse(fakeHttpLayer.hasPendingResponses());
46         assertFalse(fakeHttpLayer.hasRequestInfos());
47         assertFalse(fakeHttpLayer.hasResponseRules());
48         assertNull(fakeHttpLayer.getDefaultResponse());
49 
50         connectionKeepAliveStrategy = new ConnectionKeepAliveStrategy() {
51             @Override public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) {
52                 return 0;
53             }
54         };
55         requestDirector = new DefaultRequestDirector(null, null, null, connectionKeepAliveStrategy, null, null, null, null, null, null, null, null);
56     }
57 
58     @After
tearDown_EnsureStaticStateIsReset()59     public void tearDown_EnsureStaticStateIsReset() throws Exception {
60         Robolectric.addPendingHttpResponse(200, "a happy response body");
61     }
62 
63     @Test
shouldGetHttpResponseFromExecute()64     public void shouldGetHttpResponseFromExecute() throws Exception {
65         Robolectric.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
66         HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
67 
68         assertNotNull(response);
69         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
70         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
71     }
72 
73     @Test
shouldPreferPendingResponses()74     public void shouldPreferPendingResponses() throws Exception {
75         Robolectric.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body"));
76 
77         Robolectric.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
78                 new TestHttpResponse(200, "a cheery response body"));
79 
80         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
81 
82         assertNotNull(response);
83         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
84         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
85     }
86 
87     @Test
shouldReturnRequestsByRule()88     public void shouldReturnRequestsByRule() throws Exception {
89         Robolectric.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri",
90                 new TestHttpResponse(200, "a cheery response body"));
91 
92         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
93 
94         assertNotNull(response);
95         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
96         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
97     }
98 
99     @Test
shouldReturnRequestsByRule_MatchingMethod()100     public void shouldReturnRequestsByRule_MatchingMethod() throws Exception {
101         Robolectric.setDefaultHttpResponse(404, "no such page");
102         Robolectric.addHttpResponseRule(HttpPost.METHOD_NAME, "http://some.uri",
103                 new TestHttpResponse(200, "a cheery response body"));
104 
105         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
106 
107         assertNotNull(response);
108         assertThat(response.getStatusLine().getStatusCode(), equalTo(404));
109     }
110 
111     @Test
shouldReturnRequestsByRule_AnyMethod()112     public void shouldReturnRequestsByRule_AnyMethod() throws Exception {
113         Robolectric.addHttpResponseRule("http://some.uri", new TestHttpResponse(200, "a cheery response body"));
114 
115         HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
116         assertNotNull(getResponse);
117         assertThat(getResponse.getStatusLine().getStatusCode(), equalTo(200));
118         assertThat(Strings.fromStream(getResponse.getEntity().getContent()), equalTo("a cheery response body"));
119 
120         HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
121         assertNotNull(postResponse);
122         assertThat(postResponse.getStatusLine().getStatusCode(), equalTo(200));
123         assertThat(Strings.fromStream(postResponse.getEntity().getContent()), equalTo("a cheery response body"));
124     }
125 
126     @Test
shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams()127     public void shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams() throws Exception {
128         TestHttpResponse testHttpResponse = new TestHttpResponse(200, "a cheery response body");
129         Robolectric.addHttpResponseRule("http://some.uri", testHttpResponse);
130 
131         assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(true));
132 
133         HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
134         InputStream getResponseStream = getResponse.getEntity().getContent();
135         assertThat(Strings.fromStream(getResponseStream), equalTo("a cheery response body"));
136         assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
137 
138         HttpResponse postResponse = requestDirector.execute(null, new HttpPost("http://some.uri"), null);
139         InputStream postResponseStream = postResponse.getEntity().getContent();
140         assertThat(Strings.fromStream(postResponseStream), equalTo("a cheery response body"));
141         assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
142 
143         getResponseStream.close();
144         assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(false));
145 
146         postResponseStream.close();
147         assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed(), equalTo(true));
148     }
149 
150     @Test
shouldReturnRequestsByRule_WithTextResponse()151     public void shouldReturnRequestsByRule_WithTextResponse() throws Exception {
152         Robolectric.addHttpResponseRule("http://some.uri", "a cheery response body");
153 
154         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
155 
156         assertNotNull(response);
157         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
158         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
159     }
160 
161     @Test
clearHttpResponseRules_shouldRemoveAllRules()162     public void clearHttpResponseRules_shouldRemoveAllRules() throws Exception {
163         Robolectric.addHttpResponseRule("http://some.uri", "a cheery response body");
164         Robolectric.clearHttpResponseRules();
165         Robolectric.addHttpResponseRule("http://some.uri", "a gloomy response body");
166 
167         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
168 
169         assertNotNull(response);
170         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
171         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a gloomy response body"));
172     }
173 
174     @Test
clearPendingHttpResponses()175     public void clearPendingHttpResponses() throws Exception {
176         Robolectric.addPendingHttpResponse(200, "earlier");
177         Robolectric.clearPendingHttpResponses();
178         Robolectric.addPendingHttpResponse(500, "later");
179 
180         HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null);
181 
182         assertNotNull(response);
183         assertThat(response.getStatusLine().getStatusCode(), equalTo(500));
184         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("later"));
185     }
186 
187     @Test
shouldReturnRequestsByRule_WithCustomRequestMatcher()188     public void shouldReturnRequestsByRule_WithCustomRequestMatcher() throws Exception {
189         Robolectric.setDefaultHttpResponse(404, "no such page");
190 
191         Robolectric.addHttpResponseRule(new RequestMatcher() {
192             @Override public boolean matches(HttpRequest request) {
193                 return request.getRequestLine().getUri().equals("http://matching.uri");
194             }
195         }, new TestHttpResponse(200, "a cheery response body"));
196 
197         HttpResponse response = requestDirector.execute(null, new HttpGet("http://matching.uri"), null);
198         assertNotNull(response);
199         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
200         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a cheery response body"));
201 
202         response = requestDirector.execute(null, new HttpGet("http://non-matching.uri"), null);
203         assertNotNull(response);
204         assertThat(response.getStatusLine().getStatusCode(), equalTo(404));
205         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("no such page"));
206     }
207 
208     @Test
shouldGetHttpResponseFromExecuteSimpleApi()209     public void shouldGetHttpResponseFromExecuteSimpleApi() throws Exception {
210         Robolectric.addPendingHttpResponse(200, "a happy response body");
211         HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
212 
213         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
214         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
215     }
216 
217     @Test
shouldHandleMultipleInvocations()218     public void shouldHandleMultipleInvocations() throws Exception {
219         Robolectric.addPendingHttpResponse(200, "a happy response body");
220         Robolectric.addPendingHttpResponse(201, "another happy response body");
221 
222         HttpResponse response1 = requestDirector.execute(null, new HttpGet("http://example.com"), null);
223         HttpResponse response2 = requestDirector.execute(null, new HttpGet("www.example.com"), null);
224 
225         assertThat(response1.getStatusLine().getStatusCode(), equalTo(200));
226         assertThat(Strings.fromStream(response1.getEntity().getContent()), equalTo("a happy response body"));
227 
228         assertThat(response2.getStatusLine().getStatusCode(), equalTo(201));
229         assertThat(Strings.fromStream(response2.getEntity().getContent()), equalTo("another happy response body"));
230     }
231 
232     @Test
shouldHandleMultipleInvocationsOfExecute()233     public void shouldHandleMultipleInvocationsOfExecute() throws Exception {
234         Robolectric.addPendingHttpResponse(200, "a happy response body");
235         Robolectric.addPendingHttpResponse(201, "another happy response body");
236 
237         requestDirector.execute(null, new HttpGet("http://example.com"), null);
238         requestDirector.execute(null, new HttpGet("www.example.com"), null);
239 
240         HttpUriRequest request1 = (HttpUriRequest) Robolectric.getSentHttpRequest(0);
241         assertThat(request1.getMethod(), equalTo(HttpGet.METHOD_NAME));
242         assertThat(request1.getURI(), equalTo(URI.create("http://example.com")));
243 
244         HttpUriRequest request2 = (HttpUriRequest) Robolectric.getSentHttpRequest(1);
245         assertThat(request2.getMethod(), equalTo(HttpGet.METHOD_NAME));
246         assertThat(request2.getURI(), equalTo(URI.create("www.example.com")));
247     }
248 
249     @Test
shouldRejectUnexpectedCallsToExecute()250     public void shouldRejectUnexpectedCallsToExecute() throws Exception {
251         try {
252             requestDirector.execute(null, new HttpGet("http://example.com"), null);
253             fail();
254         } catch (RuntimeException expected) {
255             assertThat(expected.getMessage(), equalTo("Unexpected call to execute, no pending responses are available. See Robolectric.addPendingResponse(). Request was: GET http://example.com"));
256         }
257     }
258 
259     @Test
shouldRecordExtendedRequestData()260     public void shouldRecordExtendedRequestData() throws Exception {
261         Robolectric.addPendingHttpResponse(200, "a happy response body");
262         HttpGet httpGet = new HttpGet("http://example.com");
263         requestDirector.execute(null, httpGet, null);
264 
265         assertSame(Robolectric.getSentHttpRequestInfo(0).getHttpRequest(), httpGet);
266         ConnectionKeepAliveStrategy strategy = shadowOf((DefaultRequestDirector) Robolectric.getSentHttpRequestInfo(0).getRequestDirector()).getConnectionKeepAliveStrategy();
267         assertSame(strategy, connectionKeepAliveStrategy);
268     }
269 
270     @Test
shouldSupportBasicResponseHandlerHandleResponse()271     public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception {
272         Robolectric.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain"));
273 
274         DefaultHttpClient client = new DefaultHttpClient();
275         HttpResponse response = client.execute(new HttpGet("http://www.nowhere.org"));
276 
277         assertThat(((HttpUriRequest) Robolectric.getSentHttpRequest(0)).getURI(),
278                 equalTo(URI.create("http://www.nowhere.org")));
279 
280         Assert.assertNotNull(response);
281         String responseStr = new BasicResponseHandler().handleResponse(response);
282         Assert.assertEquals("OK", responseStr);
283     }
284 
285     @Test
shouldFindLastRequestMade()286     public void shouldFindLastRequestMade() throws Exception {
287         Robolectric.addPendingHttpResponse(200, "a happy response body");
288         Robolectric.addPendingHttpResponse(200, "a happy response body");
289         Robolectric.addPendingHttpResponse(200, "a happy response body");
290 
291         DefaultHttpClient client = new DefaultHttpClient();
292         client.execute(new HttpGet("http://www.first.org"));
293         client.execute(new HttpGet("http://www.second.org"));
294         client.execute(new HttpGet("http://www.third.org"));
295 
296         assertThat(((HttpUriRequest) Robolectric.getLatestSentHttpRequest()).getURI(),
297                 equalTo(URI.create("http://www.third.org")));
298     }
299 
300 
301     @Test
shouldSupportConnectionTimeoutWithExceptions()302     public void shouldSupportConnectionTimeoutWithExceptions() throws Exception {
303         Robolectric.setDefaultHttpResponse(new TestHttpResponse() {
304             @Override
305             public HttpParams getParams() {
306                 HttpParams httpParams = super.getParams();
307                 HttpConnectionParams.setConnectionTimeout(httpParams, -1);
308                 return httpParams;
309             }
310         });
311 
312         DefaultHttpClient client = new DefaultHttpClient();
313         try {
314             client.execute(new HttpGet("http://www.nowhere.org"));
315         } catch (ConnectTimeoutException x) {
316             return;
317         }
318 
319         fail("Exception should have been thrown");
320     }
321 
322     @Test
shouldSupportSocketTimeoutWithExceptions()323     public void shouldSupportSocketTimeoutWithExceptions() throws Exception {
324         Robolectric.setDefaultHttpResponse(new TestHttpResponse() {
325             @Override
326             public HttpParams getParams() {
327                 HttpParams httpParams = super.getParams();
328                 HttpConnectionParams.setSoTimeout(httpParams, -1);
329                 return httpParams;
330             }
331         });
332 
333         DefaultHttpClient client = new DefaultHttpClient();
334         try {
335             client.execute(new HttpGet("http://www.nowhere.org"));
336         } catch (ConnectTimeoutException x) {
337             return;
338         }
339 
340         fail("Exception should have been thrown");
341     }
342 
343     @Test(expected = IOException.class)
shouldSupportRealHttpRequests()344     public void shouldSupportRealHttpRequests() throws Exception {
345         Robolectric.getFakeHttpLayer().interceptHttpRequests(false);
346         DefaultHttpClient client = new DefaultHttpClient();
347         client.execute(new HttpGet("http://www.this-host-should-not-exist-123456790.org:999"));
348     }
349 
350     @Test
shouldReturnResponseFromHttpResponseGenerator()351     public void shouldReturnResponseFromHttpResponseGenerator() throws Exception {
352         Robolectric.addPendingHttpResponse(new HttpResponseGenerator() {
353             @Override
354             public HttpResponse getResponse(HttpRequest request) {
355                 return new TestHttpResponse(200, "a happy response body");
356             }
357         });
358         HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null);
359 
360         assertNotNull(response);
361         assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
362         assertThat(Strings.fromStream(response.getEntity().getContent()), equalTo("a happy response body"));
363     }
364 
365 }
366