10cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson/* 20cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * Copyright (C) 2010 The Android Open Source Project 30cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * 40cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 50cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * you may not use this file except in compliance with the License. 60cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * You may obtain a copy of the License at 70cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * 80cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 90cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * 100cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * Unless required by applicable law or agreed to in writing, software 110cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 120cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * See the License for the specific language governing permissions and 140cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * limitations under the License. 150cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson */ 160cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 170cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonpackage android.net.http; 180cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 197ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport com.google.mockwebserver.MockResponse; 207ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport com.google.mockwebserver.MockWebServer; 217ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport com.google.mockwebserver.SocketPolicy; 227ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END; 237ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport static com.google.mockwebserver.SocketPolicy.SHUTDOWN_INPUT_AT_END; 247ad00e6f5ccaf975a49870cdd267d28ae144314eJesse Wilsonimport static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END; 250cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport java.io.IOException; 260cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport java.io.InputStreamReader; 270cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport java.io.Reader; 280cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport java.io.StringWriter; 290cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport junit.framework.TestCase; 300cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport org.apache.http.HttpResponse; 31df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilsonimport org.apache.http.auth.AuthenticationException; 32df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilsonimport org.apache.http.auth.UsernamePasswordCredentials; 330cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport org.apache.http.client.methods.HttpGet; 34df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilsonimport org.apache.http.impl.auth.DigestScheme; 350cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonimport org.apache.http.impl.client.DefaultHttpClient; 36df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilsonimport org.apache.http.message.BasicHeader; 370cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 38df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson/** 39df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson * Tests for various regressions and problems with DefaultHttpClient. This is 40df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson * not a comprehensive test! 41df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson */ 420cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilsonpublic final class DefaultHttpClientTest extends TestCase { 430cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 440cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson private MockWebServer server = new MockWebServer(); 450cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 460cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson @Override protected void tearDown() throws Exception { 470cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson server.shutdown(); 480cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson super.tearDown(); 490cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 500cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 510cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson public void testServerClosesSocket() throws Exception { 520cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson testServerClosesOutput(DISCONNECT_AT_END); 530cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 540cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 550cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson public void testServerShutdownInput() throws Exception { 560cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson testServerClosesOutput(SHUTDOWN_INPUT_AT_END); 570cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 580cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 590cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson /** 600cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * DefaultHttpClient fails if the server shutdown the output after the 610cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson * response was sent. http://b/2612240 620cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson */ 630cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson public void testServerShutdownOutput() throws Exception { 640cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END); 650cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 660cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 670cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception { 680cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson server.enqueue(new MockResponse() 690cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson .setBody("This connection won't pool properly") 700cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson .setSocketPolicy(socketPolicy)); 710cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson server.enqueue(new MockResponse() 720cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson .setBody("This comes after a busted connection")); 730cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson server.play(); 740cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 750cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson DefaultHttpClient client = new DefaultHttpClient(); 760cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 770cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson HttpResponse a = client.execute(new HttpGet(server.getUrl("/a").toURI())); 780cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson assertEquals("This connection won't pool properly", contentToString(a)); 790cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 800cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 810cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson HttpResponse b = client.execute(new HttpGet(server.getUrl("/b").toURI())); 820cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson assertEquals("This comes after a busted connection", contentToString(b)); 830cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson // sequence number 0 means the HTTP socket connection was not reused 840cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson assertEquals(0, server.takeRequest().getSequenceNumber()); 850cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 860cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson 870cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson private String contentToString(HttpResponse response) throws IOException { 880cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson StringWriter writer = new StringWriter(); 890cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson char[] buffer = new char[1024]; 900cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson Reader reader = new InputStreamReader(response.getEntity().getContent()); 910cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson int length; 920cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson while ((length = reader.read(buffer)) != -1) { 930cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson writer.write(buffer, 0, length); 940cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 950cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson reader.close(); 960cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson return writer.toString(); 970cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson } 98df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson 99df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson // http://code.google.com/p/android/issues/detail?id=16051 100df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson public void testDigestSchemeAlgorithms() throws Exception { 101df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD5"); 102df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD5-sess"); 103df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("md5"); 104df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("md5-sess"); 105df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("md5-SESS"); 106df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD5-SESS"); 107df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson try { 108df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD5-"); 109df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } catch (AuthenticationException expected) { 110df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 111df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson try { 112df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD6"); 113df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } catch (AuthenticationException expected) { 114df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 115df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson try { 116df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm("MD"); 117df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } catch (AuthenticationException expected) { 118df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 119df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson try { 120df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson authenticateDigestAlgorithm(""); 121df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } catch (AuthenticationException expected) { 122df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 123df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 124df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson 125df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson private void authenticateDigestAlgorithm(String algorithm) throws Exception { 126df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson String challenge = "Digest realm=\"protected area\", " 127df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", " 128df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson + "algorithm=" + algorithm; 129df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson DigestScheme digestScheme = new DigestScheme(); 130df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge)); 131df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson HttpGet get = new HttpGet(); 132df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get); 133df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson } 1340cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson} 135