1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5package org.chromium.cronet_test_apk;
6
7import android.os.ConditionVariable;
8
9import android.test.suitebuilder.annotation.SmallTest;
10
11import org.chromium.base.test.util.Feature;
12import org.chromium.net.ChromiumUrlRequest;
13import org.chromium.net.HttpUrlRequest;
14import org.chromium.net.HttpUrlRequestFactoryConfig;
15import org.chromium.net.HttpUrlRequestListener;
16
17import java.io.File;
18import java.util.HashMap;
19
20/**
21 * Example test that just starts the cronet sample.
22 */
23public class CronetUrlTest extends CronetTestBase {
24    // URL used for base tests.
25    private static final String URL = "http://127.0.0.1:8000";
26
27    @SmallTest
28    @Feature({"Cronet"})
29    public void testLoadUrl() throws Exception {
30        CronetTestActivity activity = launchCronetTestAppWithUrl(URL);
31
32        // Make sure the activity was created as expected.
33        assertNotNull(activity);
34
35        waitForActiveShellToBeDoneLoading();
36
37        // Make sure that the URL is set as expected.
38        assertEquals(URL, activity.getUrl());
39        assertEquals(200, activity.getHttpStatusCode());
40    }
41
42    @SmallTest
43    @Feature({"Cronet"})
44    public void testInvalidUrl() throws Exception {
45        CronetTestActivity activity = launchCronetTestAppWithUrl(
46                "127.0.0.1:8000");
47
48        // Make sure the activity was created as expected.
49        assertNotNull(activity);
50
51        waitForActiveShellToBeDoneLoading();
52
53        // The load should fail.
54        assertEquals(0, activity.getHttpStatusCode());
55    }
56
57    @SmallTest
58    @Feature({"Cronet"})
59    public void testPostData() throws Exception {
60        String[] commandLineArgs = {
61                CronetTestActivity.POST_DATA_KEY, "test" };
62        CronetTestActivity activity =
63                launchCronetTestAppWithUrlAndCommandLineArgs(URL,
64                                                             commandLineArgs);
65
66        // Make sure the activity was created as expected.
67        assertNotNull(activity);
68
69        waitForActiveShellToBeDoneLoading();
70
71        // Make sure that the URL is set as expected.
72        assertEquals(URL, activity.getUrl());
73        assertEquals(200, activity.getHttpStatusCode());
74    }
75
76    @SmallTest
77    @Feature({"Cronet"})
78    public void testNetLog() throws Exception {
79        CronetTestActivity activity = launchCronetTestAppWithUrl(
80                "127.0.0.1:8000");
81
82        // Make sure the activity was created as expected.
83        assertNotNull(activity);
84
85        waitForActiveShellToBeDoneLoading();
86        File file = File.createTempFile("cronet", "json");
87        activity.mChromiumRequestFactory.getRequestContext().startNetLogToFile(
88                file.getPath());
89        activity.startWithURL(URL);
90        Thread.sleep(5000);
91        activity.mChromiumRequestFactory.getRequestContext().stopNetLog();
92        assertTrue(file.exists());
93        assertTrue(file.length() != 0);
94        assertTrue(file.delete());
95        assertTrue(!file.exists());
96    }
97
98    class SimpleHttpUrlRequestListener implements HttpUrlRequestListener {
99        ConditionVariable mComplete = new ConditionVariable();
100        public String negotiatedProtocol;
101        public int httpStatusCode = 0;
102        public byte httpResponseData[];
103
104        public SimpleHttpUrlRequestListener() {
105        }
106
107        @Override
108        public void onResponseStarted(HttpUrlRequest request) {
109            negotiatedProtocol = request.getNegotiatedProtocol();
110            httpStatusCode = request.getHttpStatusCode();
111        }
112
113        @Override
114        public void onRequestComplete(HttpUrlRequest request) {
115            httpResponseData = request.getResponseAsBytes();
116            mComplete.open();
117        }
118
119        public void blockForComplete() {
120            mComplete.block();
121        }
122
123        public void resetComplete() {
124            mComplete.close();
125        }
126    }
127
128    class BadHttpUrlRequestListener extends SimpleHttpUrlRequestListener {
129        static final String THROW_TAG = "BadListener";
130
131        public BadHttpUrlRequestListener() {
132        }
133
134        @Override
135        public void onResponseStarted(HttpUrlRequest request) {
136            throw new NullPointerException(THROW_TAG);
137        }
138    }
139
140    @SmallTest
141    @Feature({"Cronet"})
142    public void testCalledByNativeException() throws Exception {
143        CronetTestActivity activity = launchCronetTestAppWithUrl(URL);
144
145        // Make sure the activity was created as expected.
146        assertNotNull(activity);
147
148        waitForActiveShellToBeDoneLoading();
149
150        HashMap<String, String> headers = new HashMap<String, String>();
151        BadHttpUrlRequestListener listener = new BadHttpUrlRequestListener();
152
153        // Create request with bad listener to trigger an exception.
154        HttpUrlRequest request = activity.mChromiumRequestFactory.createRequest(
155                URL, HttpUrlRequest.REQUEST_PRIORITY_MEDIUM, headers, listener);
156        request.start();
157        listener.blockForComplete();
158        assertTrue(request.isCanceled());
159        assertNotNull(request.getException());
160        assertEquals(listener.THROW_TAG,
161                     request.getException().getCause().getMessage());
162    }
163
164    @SmallTest
165    @Feature({"Cronet"})
166    public void testSetUploadDataWithNullContentType() throws Exception {
167        CronetTestActivity activity = launchCronetTestAppWithUrl(URL);
168
169        // Make sure the activity was created as expected.
170        assertNotNull(activity);
171
172        waitForActiveShellToBeDoneLoading();
173
174        HashMap<String, String> headers = new HashMap<String, String>();
175        BadHttpUrlRequestListener listener = new BadHttpUrlRequestListener();
176
177        // Create request.
178        HttpUrlRequest request = activity.mChromiumRequestFactory.createRequest(
179                URL, HttpUrlRequest.REQUEST_PRIORITY_MEDIUM, headers, listener);
180        byte[] uploadData = new byte[] {1, 2, 3};
181        try {
182            request.setUploadData(null, uploadData);
183            fail("setUploadData should throw on null content type");
184        } catch (NullPointerException e) {
185            // Nothing to do here.
186        }
187    }
188
189    @SmallTest
190    @Feature({"Cronet"})
191    public void disabled_testQuicLoadUrl() throws Exception {
192        HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig();
193        // TODO(mef): Test Quic end-to-end using local QUIC server.
194        String quicURL = "https://www.google.com:443";
195        String quicNegotiatedProtocol = "quic/1+spdy/3";
196        config.enableQUIC(true);
197        config.addQuicHint("www.google.com", 443, 443);
198
199        String[] commandLineArgs = {
200                CronetTestActivity.CONFIG_KEY, config.toString() };
201        CronetTestActivity activity =
202                launchCronetTestAppWithUrlAndCommandLineArgs(quicURL,
203                                                             commandLineArgs);
204
205        // Make sure the activity was created as expected.
206        assertNotNull(activity);
207        waitForActiveShellToBeDoneLoading();
208
209        HashMap<String, String> headers = new HashMap<String, String>();
210        SimpleHttpUrlRequestListener listener =
211                new SimpleHttpUrlRequestListener();
212
213        // Try several times as first request may not use QUIC.
214        // TODO(mef): Remove loop after adding http server properties manager.
215        for (int i = 0; i < 10; ++i) {
216            ChromiumUrlRequest request =
217                    activity.mChromiumRequestFactory.createRequest(
218                            quicURL,
219                            HttpUrlRequest.REQUEST_PRIORITY_MEDIUM,
220                            headers,
221                            listener);
222            request.start();
223            listener.blockForComplete();
224            assertEquals(200, listener.httpStatusCode);
225            if (listener.negotiatedProtocol.equals(quicNegotiatedProtocol))
226                break;
227
228            Thread.sleep(1000);
229            listener.resetComplete();
230        }
231
232        assertEquals(quicNegotiatedProtocol, listener.negotiatedProtocol);
233    }
234
235    @SmallTest
236    @Feature({"Cronet"})
237    public void testLegacyLoadUrl() throws Exception {
238        HttpUrlRequestFactoryConfig config = new HttpUrlRequestFactoryConfig();
239        config.enableLegacyMode(true);
240        // TODO(mef) fix tests so that library isn't loaded for legacy stack
241        config.setLibraryName("cronet_tests");
242
243        String[] commandLineArgs = {
244                CronetTestActivity.CONFIG_KEY, config.toString() };
245        CronetTestActivity activity =
246                launchCronetTestAppWithUrlAndCommandLineArgs(URL,
247                                                             commandLineArgs);
248
249        // Make sure the activity was created as expected.
250        assertNotNull(activity);
251
252        waitForActiveShellToBeDoneLoading();
253
254        // Make sure that the URL is set as expected.
255        assertEquals(URL, activity.getUrl());
256        assertEquals(200, activity.getHttpStatusCode());
257    }
258
259    @SmallTest
260    @Feature({"Cronet"})
261    public void testRequestHead() throws Exception {
262        CronetTestActivity activity = launchCronetTestAppWithUrl(URL);
263
264        // Make sure the activity was created as expected.
265        waitForActiveShellToBeDoneLoading();
266
267        HashMap<String, String> headers = new HashMap<String, String>();
268        SimpleHttpUrlRequestListener listener =
269                new SimpleHttpUrlRequestListener();
270
271        // Create request.
272        HttpUrlRequest request = activity.mChromiumRequestFactory.createRequest(
273                URL, HttpUrlRequest.REQUEST_PRIORITY_MEDIUM, headers, listener);
274        request.setHttpMethod("HEAD");
275        request.start();
276        listener.blockForComplete();
277        assertEquals(200, listener.httpStatusCode);
278        // HEAD requests do not get any response data and Content-Length must be
279        // ignored.
280        assertEquals(0, listener.httpResponseData.length);
281    }
282}
283