1 package org.robolectric.shadows.httpclient; 2 3 import static com.google.common.truth.Truth.assertThat; 4 import static java.nio.charset.StandardCharsets.UTF_8; 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertNotNull; 7 import static org.junit.Assert.assertNull; 8 import static org.junit.Assert.assertSame; 9 import static org.junit.Assert.fail; 10 import static org.robolectric.shadows.httpclient.Shadows.shadowOf; 11 12 import com.google.common.io.CharStreams; 13 import java.io.BufferedReader; 14 import java.io.ByteArrayInputStream; 15 import java.io.IOException; 16 import java.io.InputStream; 17 import java.io.InputStreamReader; 18 import java.net.URI; 19 import org.apache.http.HttpRequest; 20 import org.apache.http.HttpResponse; 21 import org.apache.http.client.methods.HttpGet; 22 import org.apache.http.client.methods.HttpPost; 23 import org.apache.http.client.methods.HttpUriRequest; 24 import org.apache.http.conn.ConnectTimeoutException; 25 import org.apache.http.conn.ConnectionKeepAliveStrategy; 26 import org.apache.http.impl.client.BasicResponseHandler; 27 import org.apache.http.impl.client.DefaultHttpClient; 28 import org.apache.http.impl.client.DefaultRequestDirector; 29 import org.apache.http.message.BasicHeader; 30 import org.apache.http.params.HttpConnectionParams; 31 import org.apache.http.params.HttpParams; 32 import org.apache.http.protocol.HttpContext; 33 import org.junit.After; 34 import org.junit.Assert; 35 import org.junit.Before; 36 import org.junit.Test; 37 import org.junit.runner.RunWith; 38 import org.robolectric.util.TestRunnerWithManifest; 39 40 @RunWith(TestRunnerWithManifest.class) 41 public class ShadowDefaultRequestDirectorTest { 42 43 private DefaultRequestDirector requestDirector; 44 private ConnectionKeepAliveStrategy connectionKeepAliveStrategy; 45 46 @Before setUp_EnsureStaticStateIsReset()47 public void setUp_EnsureStaticStateIsReset() { 48 FakeHttpLayer fakeHttpLayer = FakeHttp.getFakeHttpLayer(); 49 assertFalse(fakeHttpLayer.hasPendingResponses()); 50 assertFalse(fakeHttpLayer.hasRequestInfos()); 51 assertFalse(fakeHttpLayer.hasResponseRules()); 52 53 connectionKeepAliveStrategy = 54 new ConnectionKeepAliveStrategy() { 55 @Override 56 public long getKeepAliveDuration(HttpResponse httpResponse, HttpContext httpContext) { 57 return 0; 58 } 59 }; 60 requestDirector = 61 new DefaultRequestDirector( 62 null, 63 null, 64 null, 65 connectionKeepAliveStrategy, 66 null, 67 null, 68 null, 69 null, 70 null, 71 null, 72 null, 73 null); 74 } 75 76 @After tearDown_EnsureStaticStateIsReset()77 public void tearDown_EnsureStaticStateIsReset() throws Exception { 78 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 79 } 80 81 @Test shouldGetHttpResponseFromExecute()82 public void shouldGetHttpResponseFromExecute() throws Exception { 83 FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body")); 84 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 85 86 assertNotNull(response); 87 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 88 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 89 } 90 91 @Test shouldPreferPendingResponses()92 public void shouldPreferPendingResponses() throws Exception { 93 FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body")); 94 95 FakeHttp.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri", 96 new TestHttpResponse(200, "a cheery response body")); 97 98 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 99 100 assertNotNull(response); 101 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 102 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 103 } 104 105 @Test shouldReturnRequestsByRule()106 public void shouldReturnRequestsByRule() throws Exception { 107 FakeHttp.addHttpResponseRule(HttpGet.METHOD_NAME, "http://some.uri", 108 new TestHttpResponse(200, "a cheery response body")); 109 110 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 111 112 assertNotNull(response); 113 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 114 assertThat(getStringContent(response)).isEqualTo("a cheery response body"); 115 } 116 117 @Test shouldReturnRequestsByRule_MatchingMethod()118 public void shouldReturnRequestsByRule_MatchingMethod() throws Exception { 119 FakeHttp.setDefaultHttpResponse(404, "no such page"); 120 FakeHttp.addHttpResponseRule(HttpPost.METHOD_NAME, "http://some.uri", 121 new TestHttpResponse(200, "a cheery response body")); 122 123 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 124 125 assertNotNull(response); 126 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(404); 127 } 128 129 @Test shouldReturnRequestsByRule_AnyMethod()130 public void shouldReturnRequestsByRule_AnyMethod() throws Exception { 131 FakeHttp.addHttpResponseRule( 132 "http://some.uri", new TestHttpResponse(200, "a cheery response body")); 133 134 HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 135 assertNotNull(getResponse); 136 assertThat(getResponse.getStatusLine().getStatusCode()).isEqualTo(200); 137 assertThat(getStringContent(getResponse)).isEqualTo("a cheery response body"); 138 139 HttpResponse postResponse = 140 requestDirector.execute(null, new HttpPost("http://some.uri"), null); 141 assertNotNull(postResponse); 142 assertThat(postResponse.getStatusLine().getStatusCode()).isEqualTo(200); 143 assertThat(getStringContent(postResponse)).isEqualTo("a cheery response body"); 144 } 145 146 @Test shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams()147 public void shouldReturnRequestsByRule_KeepsTrackOfOpenContentStreams() throws Exception { 148 TestHttpResponse testHttpResponse = new TestHttpResponse(200, "a cheery response body"); 149 FakeHttp.addHttpResponseRule("http://some.uri", testHttpResponse); 150 151 assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isTrue(); 152 153 HttpResponse getResponse = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 154 InputStream getResponseStream = getResponse.getEntity().getContent(); 155 assertThat(CharStreams.toString(new InputStreamReader(getResponseStream, UTF_8))) 156 .isEqualTo("a cheery response body"); 157 assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse(); 158 159 HttpResponse postResponse = 160 requestDirector.execute(null, new HttpPost("http://some.uri"), null); 161 InputStream postResponseStream = postResponse.getEntity().getContent(); 162 assertThat(CharStreams.toString(new InputStreamReader(postResponseStream, UTF_8))) 163 .isEqualTo("a cheery response body"); 164 assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse(); 165 166 getResponseStream.close(); 167 assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isFalse(); 168 169 postResponseStream.close(); 170 assertThat(testHttpResponse.entityContentStreamsHaveBeenClosed()).isTrue(); 171 } 172 173 @Test shouldReturnRequestsByRule_WithTextResponse()174 public void shouldReturnRequestsByRule_WithTextResponse() throws Exception { 175 FakeHttp.addHttpResponseRule("http://some.uri", "a cheery response body"); 176 177 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 178 179 assertNotNull(response); 180 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 181 assertThat(getStringContent(response)).isEqualTo("a cheery response body"); 182 } 183 184 @Test clearHttpResponseRules_shouldRemoveAllRules()185 public void clearHttpResponseRules_shouldRemoveAllRules() throws Exception { 186 FakeHttp.addHttpResponseRule("http://some.uri", "a cheery response body"); 187 FakeHttp.clearHttpResponseRules(); 188 FakeHttp.addHttpResponseRule("http://some.uri", "a gloomy response body"); 189 190 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 191 192 assertNotNull(response); 193 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 194 assertThat(getStringContent(response)).isEqualTo("a gloomy response body"); 195 } 196 197 @Test clearPendingHttpResponses()198 public void clearPendingHttpResponses() throws Exception { 199 FakeHttp.addPendingHttpResponse(200, "earlier"); 200 FakeHttp.clearPendingHttpResponses(); 201 FakeHttp.addPendingHttpResponse(500, "later"); 202 203 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 204 205 assertNotNull(response); 206 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(500); 207 assertThat(getStringContent(response)).isEqualTo("later"); 208 } 209 210 @Test shouldReturnRequestsByRule_WithCustomRequestMatcher()211 public void shouldReturnRequestsByRule_WithCustomRequestMatcher() throws Exception { 212 FakeHttp.setDefaultHttpResponse(404, "no such page"); 213 214 FakeHttp.addHttpResponseRule(new RequestMatcher() { 215 @Override 216 public boolean matches(HttpRequest request) { 217 return request.getRequestLine().getUri().equals("http://matching.uri"); 218 } 219 }, new TestHttpResponse(200, "a cheery response body")); 220 221 HttpResponse response = requestDirector.execute(null, new HttpGet("http://matching.uri"), null); 222 assertNotNull(response); 223 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 224 assertThat(getStringContent(response)).isEqualTo("a cheery response body"); 225 226 response = requestDirector.execute(null, new HttpGet("http://non-matching.uri"), null); 227 assertNotNull(response); 228 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(404); 229 assertThat(getStringContent(response)).isEqualTo("no such page"); 230 } 231 232 @Test shouldGetHttpResponseFromExecuteSimpleApi()233 public void shouldGetHttpResponseFromExecuteSimpleApi() throws Exception { 234 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 235 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 236 237 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 238 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 239 } 240 241 @Test shouldHandleMultipleInvocations()242 public void shouldHandleMultipleInvocations() throws Exception { 243 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 244 FakeHttp.addPendingHttpResponse(201, "another happy response body"); 245 246 HttpResponse response1 = requestDirector.execute(null, new HttpGet("http://example.com"), null); 247 HttpResponse response2 = requestDirector.execute(null, new HttpGet("www.example.com"), null); 248 249 assertThat(response1.getStatusLine().getStatusCode()).isEqualTo(200); 250 assertThat(getStringContent(response1)).isEqualTo("a happy response body"); 251 252 assertThat(response2.getStatusLine().getStatusCode()).isEqualTo(201); 253 assertThat(getStringContent(response2)).isEqualTo("another happy response body"); 254 } 255 256 @Test shouldHandleMultipleInvocationsOfExecute()257 public void shouldHandleMultipleInvocationsOfExecute() throws Exception { 258 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 259 FakeHttp.addPendingHttpResponse(201, "another happy response body"); 260 261 requestDirector.execute(null, new HttpGet("http://example.com"), null); 262 requestDirector.execute(null, new HttpGet("www.example.com"), null); 263 264 HttpUriRequest request1 = (HttpUriRequest) FakeHttp.getSentHttpRequest(0); 265 assertThat(request1.getMethod()).isEqualTo(HttpGet.METHOD_NAME); 266 assertThat(request1.getURI()).isEqualTo(URI.create("http://example.com")); 267 268 HttpUriRequest request2 = (HttpUriRequest) FakeHttp.getSentHttpRequest(1); 269 assertThat(request2.getMethod()).isEqualTo(HttpGet.METHOD_NAME); 270 assertThat(request2.getURI()).isEqualTo(URI.create("www.example.com")); 271 } 272 273 @Test shouldRejectUnexpectedCallsToExecute()274 public void shouldRejectUnexpectedCallsToExecute() throws Exception { 275 try { 276 requestDirector.execute(null, new HttpGet("http://example.com"), null); 277 fail(); 278 } catch (RuntimeException expected) { 279 assertThat(expected.getMessage()) 280 .isEqualTo( 281 "Unexpected call to execute, no pending responses are available. " 282 + "See Robolectric.addPendingResponse(). Request was: GET http://example.com"); 283 } 284 } 285 286 @Test shouldRecordExtendedRequestData()287 public void shouldRecordExtendedRequestData() throws Exception { 288 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 289 HttpGet httpGet = new HttpGet("http://example.com"); 290 requestDirector.execute(null, httpGet, null); 291 292 assertSame(FakeHttp.getSentHttpRequestInfo(0).getHttpRequest(), httpGet); 293 ConnectionKeepAliveStrategy strategy = 294 shadowOf((DefaultRequestDirector) FakeHttp.getSentHttpRequestInfo(0).getRequestDirector()) 295 .getConnectionKeepAliveStrategy(); 296 assertSame(strategy, connectionKeepAliveStrategy); 297 } 298 299 @Test getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos()300 public void getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos() throws Exception { 301 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 302 HttpGet httpGet = new HttpGet("http://example.com"); 303 requestDirector.execute(null, httpGet, null); 304 305 assertSame(FakeHttp.getNextSentHttpRequestInfo().getHttpRequest(), httpGet); 306 assertNull(FakeHttp.getNextSentHttpRequestInfo()); 307 } 308 309 @Test getNextSentHttpRequest_shouldRemoveHttpRequests()310 public void getNextSentHttpRequest_shouldRemoveHttpRequests() throws Exception { 311 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 312 HttpGet httpGet = new HttpGet("http://example.com"); 313 requestDirector.execute(null, httpGet, null); 314 315 assertSame(FakeHttp.getNextSentHttpRequest(), httpGet); 316 assertNull(FakeHttp.getNextSentHttpRequest()); 317 } 318 319 @Test shouldSupportBasicResponseHandlerHandleResponse()320 public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception { 321 FakeHttp.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain")); 322 323 DefaultHttpClient client = new DefaultHttpClient(); 324 HttpResponse response = client.execute(new HttpGet("http://www.nowhere.org")); 325 326 assertThat(((HttpUriRequest) FakeHttp.getSentHttpRequest(0)).getURI()) 327 .isEqualTo(URI.create("http://www.nowhere.org")); 328 329 Assert.assertNotNull(response); 330 String responseStr = new BasicResponseHandler().handleResponse(response); 331 Assert.assertEquals("OK", responseStr); 332 } 333 334 @Test shouldFindLastRequestMade()335 public void shouldFindLastRequestMade() throws Exception { 336 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 337 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 338 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 339 340 DefaultHttpClient client = new DefaultHttpClient(); 341 client.execute(new HttpGet("http://www.first.org")); 342 client.execute(new HttpGet("http://www.second.org")); 343 client.execute(new HttpGet("http://www.third.org")); 344 345 assertThat(((HttpUriRequest) FakeHttp.getLatestSentHttpRequest()).getURI()) 346 .isEqualTo(URI.create("http://www.third.org")); 347 } 348 349 350 @Test shouldSupportConnectionTimeoutWithExceptions()351 public void shouldSupportConnectionTimeoutWithExceptions() throws Exception { 352 FakeHttp.setDefaultHttpResponse(new TestHttpResponse() { 353 @Override 354 public HttpParams getParams() { 355 HttpParams httpParams = super.getParams(); 356 HttpConnectionParams.setConnectionTimeout(httpParams, -1); 357 return httpParams; 358 } 359 }); 360 361 DefaultHttpClient client = new DefaultHttpClient(); 362 try { 363 client.execute(new HttpGet("http://www.nowhere.org")); 364 } catch (ConnectTimeoutException x) { 365 return; 366 } 367 368 fail("Exception should have been thrown"); 369 } 370 371 @Test shouldSupportSocketTimeoutWithExceptions()372 public void shouldSupportSocketTimeoutWithExceptions() throws Exception { 373 FakeHttp.setDefaultHttpResponse(new TestHttpResponse() { 374 @Override 375 public HttpParams getParams() { 376 HttpParams httpParams = super.getParams(); 377 HttpConnectionParams.setSoTimeout(httpParams, -1); 378 return httpParams; 379 } 380 }); 381 382 DefaultHttpClient client = new DefaultHttpClient(); 383 try { 384 client.execute(new HttpGet("http://www.nowhere.org")); 385 } catch (ConnectTimeoutException x) { 386 return; 387 } 388 389 fail("Exception should have been thrown"); 390 } 391 392 @Test(expected = IOException.class) shouldSupportRealHttpRequests()393 public void shouldSupportRealHttpRequests() throws Exception { 394 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 395 DefaultHttpClient client = new DefaultHttpClient(); 396 client.execute(new HttpGet("http://www.this-host-should-not-exist-123456790.org:999")); 397 } 398 399 @Test shouldSupportRealHttpRequestsAddingRequestInfo()400 public void shouldSupportRealHttpRequestsAddingRequestInfo() throws Exception { 401 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 402 DefaultHttpClient client = new DefaultHttpClient(); 403 404 // it's really bad to depend on an external server in order to get a test pass, 405 // but this test is about making sure that we can intercept calls to external servers 406 // so, I think that in this specific case, it's appropriate... 407 client.execute(new HttpGet("http://google.com")); 408 409 assertNotNull(FakeHttp.getFakeHttpLayer().getLastSentHttpRequestInfo()); 410 assertNotNull(FakeHttp.getFakeHttpLayer().getLastHttpResponse()); 411 } 412 413 @Test realHttpRequestsShouldMakeContentDataAvailable()414 public void realHttpRequestsShouldMakeContentDataAvailable() throws Exception { 415 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 416 FakeHttp.getFakeHttpLayer().interceptResponseContent(true); 417 DefaultHttpClient client = new DefaultHttpClient(); 418 419 client.execute(new HttpGet("http://google.com")); 420 421 byte[] cachedContent = FakeHttp.getFakeHttpLayer().getHttpResposeContentList().get(0); 422 assertThat(cachedContent.length).isNotEqualTo(0); 423 424 InputStream content = 425 FakeHttp.getFakeHttpLayer().getLastHttpResponse().getEntity().getContent(); 426 BufferedReader contentReader = new BufferedReader(new InputStreamReader(content, UTF_8)); 427 String firstLineOfContent = contentReader.readLine(); 428 assertThat(firstLineOfContent).contains("Google"); 429 430 BufferedReader cacheReader = 431 new BufferedReader(new InputStreamReader(new ByteArrayInputStream(cachedContent), UTF_8)); 432 String firstLineOfCachedContent = cacheReader.readLine(); 433 assertThat(firstLineOfCachedContent).isEqualTo(firstLineOfContent); 434 } 435 436 @Test shouldReturnResponseFromHttpResponseGenerator()437 public void shouldReturnResponseFromHttpResponseGenerator() throws Exception { 438 FakeHttp.addPendingHttpResponse(new HttpResponseGenerator() { 439 @Override 440 public HttpResponse getResponse(HttpRequest request) { 441 return new TestHttpResponse(200, "a happy response body"); 442 } 443 }); 444 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 445 446 assertNotNull(response); 447 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 448 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 449 } 450 getStringContent(HttpResponse response)451 private static String getStringContent(HttpResponse response) throws IOException { 452 return CharStreams.toString(new InputStreamReader(response.getEntity().getContent(), UTF_8)); 453 } 454 455 }