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
446f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller    private MockWebServer server;
456f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller
466f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller    @Override
476f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller    public void setUp() throws Exception {
486f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller        super.setUp();
496f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller        server = new MockWebServer();
506f04b2e76a81b2457d7b00cd952ab7eb248606ccNeil Fuller    }
510cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
520cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    @Override protected void tearDown() throws Exception {
530cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        server.shutdown();
540cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        super.tearDown();
550cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
560cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
570cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    public void testServerClosesSocket() throws Exception {
580cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        testServerClosesOutput(DISCONNECT_AT_END);
590cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
600cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
610cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    public void testServerShutdownInput() throws Exception {
620cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        testServerClosesOutput(SHUTDOWN_INPUT_AT_END);
630cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
640cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
650cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    /**
660cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson     * DefaultHttpClient fails if the server shutdown the output after the
670cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson     * response was sent. http://b/2612240
680cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson     */
690cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    public void testServerShutdownOutput() throws Exception {
700cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        testServerClosesOutput(SHUTDOWN_OUTPUT_AT_END);
710cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
720cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
730cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    private void testServerClosesOutput(SocketPolicy socketPolicy) throws Exception {
740cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        server.enqueue(new MockResponse()
750cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson                .setBody("This connection won't pool properly")
760cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson                .setSocketPolicy(socketPolicy));
770cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        server.enqueue(new MockResponse()
780cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson                .setBody("This comes after a busted connection"));
790cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        server.play();
800cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
810cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        DefaultHttpClient client = new DefaultHttpClient();
820cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
830cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        HttpResponse a = client.execute(new HttpGet(server.getUrl("/a").toURI()));
840cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        assertEquals("This connection won't pool properly", contentToString(a));
850cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        assertEquals(0, server.takeRequest().getSequenceNumber());
860cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
870cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        HttpResponse b = client.execute(new HttpGet(server.getUrl("/b").toURI()));
880cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        assertEquals("This comes after a busted connection", contentToString(b));
890cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        // sequence number 0 means the HTTP socket connection was not reused
900cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        assertEquals(0, server.takeRequest().getSequenceNumber());
910cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
920cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson
930cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    private String contentToString(HttpResponse response) throws IOException {
940cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        StringWriter writer = new StringWriter();
950cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        char[] buffer = new char[1024];
960cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        Reader reader = new InputStreamReader(response.getEntity().getContent());
970cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        int length;
980cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        while ((length = reader.read(buffer)) != -1) {
990cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson            writer.write(buffer, 0, length);
1000cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        }
1010cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        reader.close();
1020cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson        return writer.toString();
1030cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson    }
104df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson
105df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson    // http://code.google.com/p/android/issues/detail?id=16051
106df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson    public void testDigestSchemeAlgorithms() throws Exception {
107df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("MD5");
108df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("MD5-sess");
109df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("md5");
110df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("md5-sess");
111df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("md5-SESS");
112df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        authenticateDigestAlgorithm("MD5-SESS");
113df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        try {
114df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson            authenticateDigestAlgorithm("MD5-");
115df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        } catch (AuthenticationException expected) {
116df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        }
117df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        try {
118df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson            authenticateDigestAlgorithm("MD6");
119df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        } catch (AuthenticationException expected) {
120df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        }
121df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        try {
122df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson            authenticateDigestAlgorithm("MD");
123df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        } catch (AuthenticationException expected) {
124df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        }
125df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        try {
126df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson            authenticateDigestAlgorithm("");
127df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        } catch (AuthenticationException expected) {
128df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        }
129df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson    }
130df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson
131df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson    private void authenticateDigestAlgorithm(String algorithm) throws Exception {
132df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        String challenge = "Digest realm=\"protected area\", "
133df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson                + "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", "
134df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson                + "algorithm=" + algorithm;
135df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        DigestScheme digestScheme = new DigestScheme();
136df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        digestScheme.processChallenge(new BasicHeader("WWW-Authenticate", challenge));
137df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        HttpGet get = new HttpGet();
138df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson        digestScheme.authenticate(new UsernamePasswordCredentials("username", "password"), get);
139df867f8f8025c778a2d2eb4c4e364d967808743cJesse Wilson    }
1400cb0d7a2d43874895e764fabed6a6692818dc89dJesse Wilson}
141