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