1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.http; 18 19 import com.google.mockwebserver.MockResponse; 20 import com.google.mockwebserver.MockWebServer; 21 import com.google.mockwebserver.SocketPolicy; 22 import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 23 import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; 24 import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; 25 import java.io.IOException; 26 import java.io.InputStreamReader; 27 import java.io.Reader; 28 import java.io.StringWriter; 29 import junit.framework.TestCase; 30 import org.apache.http.HttpResponse; 31 import org.apache.http.auth.AuthenticationException; 32 import org.apache.http.auth.UsernamePasswordCredentials; 33 import org.apache.http.client.methods.HttpGet; 34 import org.apache.http.impl.auth.DigestScheme; 35 import org.apache.http.impl.client.DefaultHttpClient; 36 import org.apache.http.message.BasicHeader; 37 38 /** 39 * Tests for various regressions and problems with DefaultHttpClient. This is 40 * not a comprehensive test! 41 */ 42 public final class DefaultHttpClientTest extends TestCase { 43 44 private MockWebServer server = new MockWebServer(); 45 46 @Override protected void tearDown() throws Exception { 47 server.shutdown(); 48 super.tearDown(); 49 } 50 51 public void testServerClosesSocket() throws Exception { 52 testServerClosesOutput(DISCONNECT_AT_END); 53 } 54 55 public void testServerShutdownInput() throws Exception { 56 testServerClosesOutput(SHUTDOWN_INPUT_AT_END); 57 } 58 59 /** 60 * DefaultHttpClient fails if the server shutdown the output after the 61 * response was sent. http://b/2612240 62 */ 63 public void testServerShutdownOutput() throws Exception { 64 testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END); 65 } 66 67 private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception { 68 server.enqueue(new MockResponse() 69 .setBody("This connection won't pool properly") 70 .setSocketPolicy(socketPolicy)); 71 server.enqueue(new MockResponse() 72 .setBody("This comes after a busted connection")); 73 server.play(); 74 75 DefaultHttpClient client = new DefaultHttpClient(); 76 77 HttpResponse a = client.execute(new HttpGet(server.getUrl("/a").toURI())); 78 assertEquals("This connection won't pool properly", contentToString(a)); 79 assertEquals(0, server.takeRequest().getSequenceNumber()); 80 81 HttpResponse b = client.execute(new HttpGet(server.getUrl("/b").toURI())); 82 assertEquals("This comes after a busted connection", contentToString(b)); 83 // sequence number 0 means the HTTP socket connection was not reused 84 assertEquals(0, server.takeRequest().getSequenceNumber()); 85 } 86 87 private String contentToString(HttpResponse response) throws IOException { 88 StringWriter writer = new StringWriter(); 89 char[] buffer = new char[1024]; 90 Reader reader = new InputStreamReader(response.getEntity().getContent()); 91 int length; 92 while ((length = reader.read(buffer)) != -1) { 93 writer.write(buffer, 0, length); 94 } 95 reader.close(); 96 return writer.toString(); 97 } 98 99 // http://code.google.com/p/android/issues/detail?id=16051 100 public void testDigestSchemeAlgorithms() throws Exception { 101 authenticateDigestAlgorithm("MD5"); 102 authenticateDigestAlgorithm("MD5-sess"); 103 authenticateDigestAlgorithm("md5"); 104 authenticateDigestAlgorithm("md5-sess"); 105 authenticateDigestAlgorithm("md5-SESS"); 106 authenticateDigestAlgorithm("MD5-SESS"); 107 try { 108 authenticateDigestAlgorithm("MD5-"); 109 } catch (AuthenticationException expected) { 110 } 111 try { 112 authenticateDigestAlgorithm("MD6"); 113 } catch (AuthenticationException expected) { 114 } 115 try { 116 authenticateDigestAlgorithm("MD"); 117 } catch (AuthenticationException expected) { 118 } 119 try { 120 authenticateDigestAlgorithm(""); 121 } catch (AuthenticationException expected) { 122 } 123 } 124 125 private void authenticateDigestAlgorithm(String algorithm) throws Exception { 126 String challenge = "Digest realm=\"protected area\", " 127 + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " 128 + "algorithm=" + algorithm; 129 DigestScheme digestScheme = new DigestScheme(); 130 digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge)); 131 HttpGet get = new HttpGet(); 132 digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get); 133 } 134 } 135