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.assertThrows; 10 import static org.junit.Assert.fail; 11 import static org.robolectric.shadows.httpclient.Shadows.shadowOf; 12 13 import androidx.test.ext.junit.runners.AndroidJUnit4; 14 import com.google.common.io.CharStreams; 15 import java.io.BufferedReader; 16 import java.io.ByteArrayInputStream; 17 import java.io.IOException; 18 import java.io.InputStream; 19 import java.io.InputStreamReader; 20 import java.net.URI; 21 import org.apache.http.HttpResponse; 22 import org.apache.http.client.methods.HttpGet; 23 import org.apache.http.client.methods.HttpPost; 24 import org.apache.http.client.methods.HttpUriRequest; 25 import org.apache.http.conn.ConnectTimeoutException; 26 import org.apache.http.conn.ConnectionKeepAliveStrategy; 27 import org.apache.http.impl.client.BasicResponseHandler; 28 import org.apache.http.impl.client.DefaultHttpClient; 29 import org.apache.http.impl.client.DefaultRequestDirector; 30 import org.apache.http.message.BasicHeader; 31 import org.apache.http.params.HttpConnectionParams; 32 import org.apache.http.params.HttpParams; 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 39 /** Tests for {@link DefaultRequestDirector} */ 40 @RunWith(AndroidJUnit4.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 = (httpResponse, httpContext) -> 0; 54 requestDirector = 55 new DefaultRequestDirector( 56 null, 57 null, 58 null, 59 connectionKeepAliveStrategy, 60 null, 61 null, 62 null, 63 null, 64 null, 65 null, 66 null, 67 null); 68 } 69 70 @After tearDown_EnsureStaticStateIsReset()71 public void tearDown_EnsureStaticStateIsReset() { 72 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 73 } 74 75 @Test shouldGetHttpResponseFromExecute()76 public void shouldGetHttpResponseFromExecute() throws Exception { 77 FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body")); 78 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 79 80 assertNotNull(response); 81 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 82 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 83 } 84 85 @Test shouldPreferPendingResponses()86 public void shouldPreferPendingResponses() throws Exception { 87 FakeHttp.addPendingHttpResponse(new TestHttpResponse(200, "a happy response body")); 88 89 FakeHttp.addHttpResponseRule( 90 HttpGet.METHOD_NAME, 91 "http://some.uri", 92 new TestHttpResponse(200, "a cheery response body")); 93 94 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 95 96 assertNotNull(response); 97 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 98 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 99 } 100 101 @Test shouldReturnRequestsByRule()102 public void shouldReturnRequestsByRule() throws Exception { 103 FakeHttp.addHttpResponseRule( 104 HttpGet.METHOD_NAME, 105 "http://some.uri", 106 new TestHttpResponse(200, "a cheery response body")); 107 108 HttpResponse response = requestDirector.execute(null, new HttpGet("http://some.uri"), null); 109 110 assertNotNull(response); 111 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 112 assertThat(getStringContent(response)).isEqualTo("a cheery response body"); 113 } 114 115 @Test shouldReturnRequestsByRule_MatchingMethod()116 public void shouldReturnRequestsByRule_MatchingMethod() throws Exception { 117 FakeHttp.setDefaultHttpResponse(404, "no such page"); 118 FakeHttp.addHttpResponseRule( 119 HttpPost.METHOD_NAME, 120 "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( 215 request -> request.getRequestLine().getUri().equals("http://matching.uri"), 216 new TestHttpResponse(200, "a cheery response body")); 217 218 HttpResponse response = requestDirector.execute(null, new HttpGet("http://matching.uri"), null); 219 assertNotNull(response); 220 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 221 assertThat(getStringContent(response)).isEqualTo("a cheery response body"); 222 223 response = requestDirector.execute(null, new HttpGet("http://non-matching.uri"), null); 224 assertNotNull(response); 225 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(404); 226 assertThat(getStringContent(response)).isEqualTo("no such page"); 227 } 228 229 @Test shouldGetHttpResponseFromExecuteSimpleApi()230 public void shouldGetHttpResponseFromExecuteSimpleApi() throws Exception { 231 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 232 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 233 234 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 235 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 236 } 237 238 @Test shouldHandleMultipleInvocations()239 public void shouldHandleMultipleInvocations() throws Exception { 240 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 241 FakeHttp.addPendingHttpResponse(201, "another happy response body"); 242 243 HttpResponse response1 = requestDirector.execute(null, new HttpGet("http://example.com"), null); 244 HttpResponse response2 = requestDirector.execute(null, new HttpGet("www.example.com"), null); 245 246 assertThat(response1.getStatusLine().getStatusCode()).isEqualTo(200); 247 assertThat(getStringContent(response1)).isEqualTo("a happy response body"); 248 249 assertThat(response2.getStatusLine().getStatusCode()).isEqualTo(201); 250 assertThat(getStringContent(response2)).isEqualTo("another happy response body"); 251 } 252 253 @Test shouldHandleMultipleInvocationsOfExecute()254 public void shouldHandleMultipleInvocationsOfExecute() throws Exception { 255 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 256 FakeHttp.addPendingHttpResponse(201, "another happy response body"); 257 258 requestDirector.execute(null, new HttpGet("http://example.com"), null); 259 requestDirector.execute(null, new HttpGet("www.example.com"), null); 260 261 HttpUriRequest request1 = (HttpUriRequest) FakeHttp.getSentHttpRequest(0); 262 assertThat(request1.getMethod()).isEqualTo(HttpGet.METHOD_NAME); 263 assertThat(request1.getURI()).isEqualTo(URI.create("http://example.com")); 264 265 HttpUriRequest request2 = (HttpUriRequest) FakeHttp.getSentHttpRequest(1); 266 assertThat(request2.getMethod()).isEqualTo(HttpGet.METHOD_NAME); 267 assertThat(request2.getURI()).isEqualTo(URI.create("www.example.com")); 268 } 269 270 @Test shouldRejectUnexpectedCallsToExecute()271 public void shouldRejectUnexpectedCallsToExecute() throws Exception { 272 try { 273 requestDirector.execute(null, new HttpGet("http://example.com"), null); 274 fail(); 275 } catch (RuntimeException expected) { 276 assertThat(expected.getMessage()) 277 .isEqualTo( 278 "Unexpected call to execute, no pending responses are available. " 279 + "See Robolectric.addPendingResponse(). Request was: GET http://example.com"); 280 } 281 } 282 283 @Test shouldRecordExtendedRequestData()284 public void shouldRecordExtendedRequestData() throws Exception { 285 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 286 HttpGet httpGet = new HttpGet("http://example.com"); 287 requestDirector.execute(null, httpGet, null); 288 289 assertSame(FakeHttp.getSentHttpRequestInfo(0).getHttpRequest(), httpGet); 290 ConnectionKeepAliveStrategy strategy = 291 shadowOf((DefaultRequestDirector) FakeHttp.getSentHttpRequestInfo(0).getRequestDirector()) 292 .getConnectionKeepAliveStrategy(); 293 assertSame(strategy, connectionKeepAliveStrategy); 294 } 295 296 @Test getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos()297 public void getNextSentHttpRequestInfo_shouldRemoveHttpRequestInfos() throws Exception { 298 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 299 HttpGet httpGet = new HttpGet("http://example.com"); 300 requestDirector.execute(null, httpGet, null); 301 302 assertSame(FakeHttp.getNextSentHttpRequestInfo().getHttpRequest(), httpGet); 303 assertNull(FakeHttp.getNextSentHttpRequestInfo()); 304 } 305 306 @Test getNextSentHttpRequest_shouldRemoveHttpRequests()307 public void getNextSentHttpRequest_shouldRemoveHttpRequests() throws Exception { 308 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 309 HttpGet httpGet = new HttpGet("http://example.com"); 310 requestDirector.execute(null, httpGet, null); 311 312 assertSame(FakeHttp.getNextSentHttpRequest(), httpGet); 313 assertNull(FakeHttp.getNextSentHttpRequest()); 314 } 315 316 @Test shouldSupportBasicResponseHandlerHandleResponse()317 public void shouldSupportBasicResponseHandlerHandleResponse() throws Exception { 318 FakeHttp.addPendingHttpResponse(200, "OK", new BasicHeader("Content-Type", "text/plain")); 319 320 DefaultHttpClient client = new DefaultHttpClient(); 321 HttpResponse response = client.execute(new HttpGet("http://www.nowhere.org")); 322 323 assertThat(((HttpUriRequest) FakeHttp.getSentHttpRequest(0)).getURI()) 324 .isEqualTo(URI.create("http://www.nowhere.org")); 325 326 Assert.assertNotNull(response); 327 String responseStr = new BasicResponseHandler().handleResponse(response); 328 Assert.assertEquals("OK", responseStr); 329 } 330 331 @Test shouldFindLastRequestMade()332 public void shouldFindLastRequestMade() throws Exception { 333 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 334 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 335 FakeHttp.addPendingHttpResponse(200, "a happy response body"); 336 337 DefaultHttpClient client = new DefaultHttpClient(); 338 client.execute(new HttpGet("http://www.first.org")); 339 client.execute(new HttpGet("http://www.second.org")); 340 client.execute(new HttpGet("http://www.third.org")); 341 342 assertThat(((HttpUriRequest) FakeHttp.getLatestSentHttpRequest()).getURI()) 343 .isEqualTo(URI.create("http://www.third.org")); 344 } 345 346 @Test shouldSupportConnectionTimeoutWithExceptions()347 public void shouldSupportConnectionTimeoutWithExceptions() throws Exception { 348 FakeHttp.setDefaultHttpResponse( 349 new TestHttpResponse() { 350 @Override 351 public HttpParams getParams() { 352 HttpParams httpParams = super.getParams(); 353 HttpConnectionParams.setConnectionTimeout(httpParams, -1); 354 return httpParams; 355 } 356 }); 357 358 DefaultHttpClient client = new DefaultHttpClient(); 359 try { 360 client.execute(new HttpGet("http://www.nowhere.org")); 361 } catch (ConnectTimeoutException x) { 362 return; 363 } 364 365 fail("Exception should have been thrown"); 366 } 367 368 @Test shouldSupportSocketTimeoutWithExceptions()369 public void shouldSupportSocketTimeoutWithExceptions() throws Exception { 370 FakeHttp.setDefaultHttpResponse( 371 new TestHttpResponse() { 372 @Override 373 public HttpParams getParams() { 374 HttpParams httpParams = super.getParams(); 375 HttpConnectionParams.setSoTimeout(httpParams, -1); 376 return httpParams; 377 } 378 }); 379 380 DefaultHttpClient client = new DefaultHttpClient(); 381 try { 382 client.execute(new HttpGet("http://www.nowhere.org")); 383 } catch (ConnectTimeoutException x) { 384 return; 385 } 386 387 fail("Exception should have been thrown"); 388 } 389 390 @Test shouldSupportRealHttpRequests()391 public void shouldSupportRealHttpRequests() { 392 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 393 DefaultHttpClient client = new DefaultHttpClient(); 394 395 assertThrows( 396 IOException.class, 397 () -> 398 client.execute(new HttpGet("http://www.this-host-should-not-exist-123456790.org:999"))); 399 } 400 401 @Test shouldSupportRealHttpRequestsAddingRequestInfo()402 public void shouldSupportRealHttpRequestsAddingRequestInfo() throws Exception { 403 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 404 DefaultHttpClient client = new DefaultHttpClient(); 405 406 // it's really bad to depend on an external server in order to get a test pass, 407 // but this test is about making sure that we can intercept calls to external servers 408 // so, I think that in this specific case, it's appropriate... 409 client.execute(new HttpGet("http://google.com")); 410 411 assertNotNull(FakeHttp.getFakeHttpLayer().getLastSentHttpRequestInfo()); 412 assertNotNull(FakeHttp.getFakeHttpLayer().getLastHttpResponse()); 413 } 414 415 @Test realHttpRequestsShouldMakeContentDataAvailable()416 public void realHttpRequestsShouldMakeContentDataAvailable() throws Exception { 417 FakeHttp.getFakeHttpLayer().interceptHttpRequests(false); 418 FakeHttp.getFakeHttpLayer().interceptResponseContent(true); 419 DefaultHttpClient client = new DefaultHttpClient(); 420 421 client.execute(new HttpGet("http://google.com")); 422 423 byte[] cachedContent = FakeHttp.getFakeHttpLayer().getHttpResposeContentList().get(0); 424 assertThat(cachedContent.length).isNotEqualTo(0); 425 426 InputStream content = 427 FakeHttp.getFakeHttpLayer().getLastHttpResponse().getEntity().getContent(); 428 BufferedReader contentReader = new BufferedReader(new InputStreamReader(content, UTF_8)); 429 String firstLineOfContent = contentReader.readLine(); 430 assertThat(firstLineOfContent).contains("Google"); 431 432 BufferedReader cacheReader = 433 new BufferedReader(new InputStreamReader(new ByteArrayInputStream(cachedContent), UTF_8)); 434 String firstLineOfCachedContent = cacheReader.readLine(); 435 assertThat(firstLineOfCachedContent).isEqualTo(firstLineOfContent); 436 } 437 438 @Test shouldReturnResponseFromHttpResponseGenerator()439 public void shouldReturnResponseFromHttpResponseGenerator() throws Exception { 440 FakeHttp.addPendingHttpResponse(request -> new TestHttpResponse(200, "a happy response body")); 441 HttpResponse response = requestDirector.execute(null, new HttpGet("http://example.com"), null); 442 443 assertNotNull(response); 444 assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); 445 assertThat(getStringContent(response)).isEqualTo("a happy response body"); 446 } 447 getStringContent(HttpResponse response)448 private static String getStringContent(HttpResponse response) throws IOException { 449 return CharStreams.toString(new InputStreamReader(response.getEntity().getContent(), UTF_8)); 450 } 451 } 452