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 17package android.net.http; 18 19import com.google.mockwebserver.MockResponse; 20import com.google.mockwebserver.MockWebServer; 21import com.google.mockwebserver.SocketPolicy; 22import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 23import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; 24import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; 25import java.io.IOException; 26import java.io.InputStreamReader; 27import java.io.Reader; 28import java.io.StringWriter; 29import junit.framework.TestCase; 30import org.apache.http.HttpResponse; 31import org.apache.http.auth.AuthenticationException; 32import org.apache.http.auth.UsernamePasswordCredentials; 33import org.apache.http.client.methods.HttpGet; 34import org.apache.http.impl.auth.DigestScheme; 35import org.apache.http.impl.client.DefaultHttpClient; 36import org.apache.http.message.BasicHeader; 37 38/** 39 * Tests for various regressions and problems with DefaultHttpClient. This is 40 * not a comprehensive test! 41 */ 42public final class DefaultHttpClientTest extends TestCase { 43 44 private MockWebServer server; 45 46 @Override 47 public void setUp() throws Exception { 48 super.setUp(); 49 server = new MockWebServer(); 50 } 51 52 @Override protected void tearDown() throws Exception { 53 server.shutdown(); 54 super.tearDown(); 55 } 56 57 public void testServerClosesSocket() throws Exception { 58 testServerClosesOutput(DISCONNECT_AT_END); 59 } 60 61 public void testServerShutdownInput() throws Exception { 62 testServerClosesOutput(SHUTDOWN_INPUT_AT_END); 63 } 64 65 /** 66 * DefaultHttpClient fails if the server shutdown the output after the 67 * response was sent. http://b/2612240 68 */ 69 public void testServerShutdownOutput() throws Exception { 70 testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END); 71 } 72 73 private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception { 74 server.enqueue(new MockResponse() 75 .setBody("This connection won't pool properly") 76 .setSocketPolicy(socketPolicy)); 77 server.enqueue(new MockResponse() 78 .setBody("This comes after a busted connection")); 79 server.play(); 80 81 DefaultHttpClient client = new DefaultHttpClient(); 82 83 HttpResponse a = client.execute(new HttpGet(server.getUrl("/a").toURI())); 84 assertEquals("This connection won't pool properly", contentToString(a)); 85 assertEquals(0, server.takeRequest().getSequenceNumber()); 86 87 HttpResponse b = client.execute(new HttpGet(server.getUrl("/b").toURI())); 88 assertEquals("This comes after a busted connection", contentToString(b)); 89 // sequence number 0 means the HTTP socket connection was not reused 90 assertEquals(0, server.takeRequest().getSequenceNumber()); 91 } 92 93 private String contentToString(HttpResponse response) throws IOException { 94 StringWriter writer = new StringWriter(); 95 char[] buffer = new char[1024]; 96 Reader reader = new InputStreamReader(response.getEntity().getContent()); 97 int length; 98 while ((length = reader.read(buffer)) != -1) { 99 writer.write(buffer, 0, length); 100 } 101 reader.close(); 102 return writer.toString(); 103 } 104 105 // http://code.google.com/p/android/issues/detail?id=16051 106 public void testDigestSchemeAlgorithms() throws Exception { 107 authenticateDigestAlgorithm("MD5"); 108 authenticateDigestAlgorithm("MD5-sess"); 109 authenticateDigestAlgorithm("md5"); 110 authenticateDigestAlgorithm("md5-sess"); 111 authenticateDigestAlgorithm("md5-SESS"); 112 authenticateDigestAlgorithm("MD5-SESS"); 113 try { 114 authenticateDigestAlgorithm("MD5-"); 115 } catch (AuthenticationException expected) { 116 } 117 try { 118 authenticateDigestAlgorithm("MD6"); 119 } catch (AuthenticationException expected) { 120 } 121 try { 122 authenticateDigestAlgorithm("MD"); 123 } catch (AuthenticationException expected) { 124 } 125 try { 126 authenticateDigestAlgorithm(""); 127 } catch (AuthenticationException expected) { 128 } 129 } 130 131 private void authenticateDigestAlgorithm(String algorithm) throws Exception { 132 String challenge = "Digest realm=\"protected area\", " 133 + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " 134 + "algorithm=" + algorithm; 135 DigestScheme digestScheme = new DigestScheme(); 136 digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge)); 137 HttpGet get = new HttpGet(); 138 digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get); 139 } 140} 141