1/*
2 * Copyright (C) 2007 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.core;
18
19import android.net.http.RequestHandle;
20import android.net.http.RequestQueue;
21import android.test.AndroidTestCase;
22import android.test.suitebuilder.annotation.Suppress;
23import android.util.Log;
24import android.webkit.CookieSyncManager;
25
26import java.io.ByteArrayInputStream;
27import java.io.InputStream;
28import java.util.HashMap;
29import java.util.Map;
30
31/**
32 * Container class for all RequestAPI tests
33 */
34//http://b/issue?id=1200337
35@Suppress
36public class RequestAPITest extends AndroidTestCase implements HttpConstants {
37    private static final String LOGTAG = "http";
38
39    /*
40      Other tests to write
41      GET, HEAD, POST with differing parameters to RequestQueue
42      More reuse and pipelining tests - testing for server closing unexpectedly
43    */
44
45    // Sync object for synchronizing end of each test that does communications
46    public static Object syncObj = new Object();
47
48    private RequestQueue mRequestQueue;
49    private TestWebServer mTestWebServer;
50
51    protected void setUp() throws Exception {
52        super.setUp();
53        Log.d(LOGTAG, "Base setup context = " + mContext);
54        mRequestQueue = new RequestQueue(mContext);
55        CookieSyncManager.createInstance(mContext);
56
57        mTestWebServer = new TestWebServer();
58        mTestWebServer.initServer(8080, true);
59    }
60
61    protected void tearDown() throws Exception {
62        Log.d(LOGTAG, "Base tearDown");
63        mTestWebServer.close();
64        Log.d(LOGTAG, "Base teardown done");
65
66        super.tearDown();
67    }
68
69    public void verifyFailure(Map<String, String> headers) {
70        try {
71            RequestHandle handle =
72                    mRequestQueue.queueRequest(
73                            "http://localhost:8080/test1", "GET", headers, null,
74                            null, 0);
75
76            handle.waitUntilComplete();
77            fail("expected exception not thrown");
78        } catch (RuntimeException e) {
79            // expected
80        }
81    }
82
83    public void testRequestAddNullHeader() throws Exception {
84        /**
85         * Test Request.addHeader throws a NullPointerException if a null
86         * header is attempted to be set
87         */
88        Log.d(LOGTAG, "testRequestAddNullHeader start ");
89        Map<String, String> headers = new HashMap<>();
90        headers.put(null, null);
91        verifyFailure(headers);
92        Log.d(LOGTAG, "testRequestAddNullHeader - returning");
93    }
94
95    public void testRequestAddNullValue() throws Exception {
96        /**
97         * Test Request.addHeader throws a RuntimeException if a null
98         * value is attempted to be set
99         */
100        Log.d(LOGTAG, "testRequestAddNullValue start ");
101        Map<String, String> headers = new HashMap<>();
102        headers.put("TestHeader", null);
103        verifyFailure(headers);
104        Log.d(LOGTAG, "testRequestAddNullValue - returning");
105    }
106
107    public void testRequestAddEmptyValue() throws Exception {
108        /**
109         * Test Request.addEmptyValue throws a RuntimeException if an empty
110         * header is attempted to be set
111         */
112        Log.d(LOGTAG, "testRequestAddEmptyValue start ");
113        Map<String, String> headers = new HashMap<>();
114        headers.put("TestHeader", "");
115        verifyFailure(headers);
116        Log.d(LOGTAG, "testRequestAddEmptyValue - returning");
117    }
118
119    public void verifySuccess(Map<String, String> headers) {
120        mTestWebServer.setKeepAlive(false);
121        RequestHandle handle = mRequestQueue.queueRequest(
122                "http://localhost:8080/test1", "GET", headers, null,
123                null, 0);
124        handle.waitUntilComplete();
125    }
126
127    public void testRequestAddHeader() throws Exception {
128        /**
129         * Test Request.addHeader with a valid header and value can be set without
130         * generating and exception
131         */
132        Log.d(LOGTAG, "testRequestAddHeader start ");
133        Map<String, String> headers = new HashMap<>();
134        headers.put("TestHeader", "RequestAddHeader");
135        verifySuccess(headers);
136        Log.d(LOGTAG, "testRequestAddHeader - returning");
137    }
138
139    public void testRequestAddMultiHeader() throws Exception {
140        /**
141         * Test multiple calls to Request.addHeader with valid headers and values
142         * can be set without generating and exception
143         */
144        Log.d(LOGTAG, "testRequestAddMultiHeader start ");
145        Map<String, String> headers = new HashMap<>();
146        headers.put("TestHeader", "RequestAddMultiHeader");
147        headers.put("TestHeader2", "RequestAddMultiHeader");
148        headers.put("TestHeader3", "RequestAddMultiHeader");
149        verifySuccess(headers);
150        Log.d(LOGTAG, "testRequestAddMultiHeader - returning");
151    }
152
153    public void testRequestAddSameHeader() throws Exception {
154        /**
155         * Test multiple calls to Request.addHeader with valid identical headers
156         * and values can be set without generating and exception
157         */
158        Log.d(LOGTAG, "testRequestAddSameHeader start ");
159        Map<String, String> headers = new HashMap<>();
160        headers.put("TestHeader", "RequestAddSameHeader");
161        headers.put("TestHeader", "RequestAddSameHeader");
162        headers.put("TestHeader", "RequestAddSameHeader");
163        verifySuccess(headers);
164        Log.d(LOGTAG, "testRequestAddSameHeader - returning");
165    }
166
167    public void testRequestAddNullHeaders() throws Exception {
168        /**
169         * Test Request.addHeaders with a null header map. This should not generate
170         * any exceptions but accept that there are no headers to add.
171         */
172        Log.d(LOGTAG, "testRequestAddNullHeaders start ");
173        verifySuccess(null);
174        Log.d(LOGTAG, "testRequestAddNullHeaders - returning");
175    }
176
177    public void testGet() throws Exception {
178        /**
179         * Test sending a GET request. Test will pass if the events received
180         * correspond with the expected response. This should respond with the
181         * test data requested.
182         */
183        TestEventHandler testEventHandler = new TestEventHandler();
184
185        mTestWebServer.setKeepAlive(false);
186
187        Log.d(LOGTAG, "testGet start ");
188
189        // Load up expected response
190        testEventHandler.expectStatus(200);
191        testEventHandler.expectHeaders();
192        testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONNECTION], "Close");
193        testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_LENGTH], "52");
194        testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_TYPE], "text/html");
195        testEventHandler.expectData(52);
196
197        RequestHandle handle = mRequestQueue.queueRequest(
198                "http://localhost:8080/test1", "GET", null, testEventHandler,
199                null, 0);
200
201        Log.d(LOGTAG, "testGet - sent request. Waiting");
202        handle.waitUntilComplete();
203        Log.d(LOGTAG, "testGet - sent request. Notified");
204
205        if (!testEventHandler.expectPassed()) {
206            Log.d(LOGTAG, testEventHandler.getFailureMessage());
207            fail("expectPassed was false " + testEventHandler.getFailureMessage());
208        }
209    }
210
211    public void testReuse() throws Exception {
212        /**
213         * Test sending two GET requests. Test will pass if the events
214         * received correspond with the expected response.
215         */
216        final String TEST_NAME = "testReuse";
217        Log.d(LOGTAG, TEST_NAME + " start ");
218
219        TestEventHandler testEventHandler = new TestEventHandler();
220
221        // Load up expected response
222        testEventHandler.expectStatus(200);
223        testEventHandler.expectHeaders();
224
225        TestEventHandler testEventHandler2 = new TestEventHandler();
226        testEventHandler2.expectStatus(200);
227        testEventHandler2.expectHeaders();
228
229        mTestWebServer.setAcceptLimit(2);
230
231        RequestHandle handle0 = mRequestQueue.queueRequest(
232                "http://localhost:8080/test1", "GET", null, testEventHandler,
233                null, 0);
234        handle0.waitUntilComplete();
235        RequestHandle handle1 = mRequestQueue.queueRequest(
236                "http://localhost:8080/test1", "GET", null, testEventHandler2,
237                null, 0);
238        handle1.waitUntilComplete();
239
240        /* It's not correct to use same listener for multiple
241           requests.  Otherwise there would be no distiction between
242           events delivered for either request. */
243
244        if (!testEventHandler.expectPassed() && !testEventHandler2.expectPassed()) {
245            Log.d(LOGTAG, testEventHandler.getFailureMessage());
246            Log.d(LOGTAG, testEventHandler2.getFailureMessage());
247            fail();
248        }
249        Log.d(LOGTAG, TEST_NAME + " - sent request. Notified");
250    }
251
252    public void testHead() throws Exception {
253        /**
254         * Test sending a HEAD request. Test will pass if the events
255         * delivered match the expected response.
256         */
257        TestEventHandler testEventHandler = new TestEventHandler();
258
259        // Load up expected response
260        testEventHandler.expectStatus(200);
261        testEventHandler.expectHeaders();
262        testEventHandler.expectNoData();
263
264        mTestWebServer.setKeepAlive(false);
265        mTestWebServer.setAcceptLimit(1);
266
267
268        Log.d(LOGTAG, "testHead start - rq = " + mRequestQueue);
269
270        RequestHandle handle = mRequestQueue.queueRequest(
271                "http://localhost:8080/test1", "HEAD", null, testEventHandler,
272                null, 0);
273
274        Log.d(LOGTAG, "testHead - sent request waiting");
275        handle.waitUntilComplete();
276
277        if (!testEventHandler.expectPassed()) {
278            Log.d(LOGTAG, testEventHandler.getFailureMessage());
279            fail("expectPassed was false " + testEventHandler.getFailureMessage());
280        }
281    }
282
283    public void testChunked() throws Exception {
284        TestEventHandler testEventHandler = new TestEventHandler();
285
286        // Load up expected response
287        testEventHandler.expectStatus(200);
288        testEventHandler.expectHeaders();
289
290        mTestWebServer.setKeepAlive(false);
291        mTestWebServer.setChunked(true);
292        mTestWebServer.setAcceptLimit(1);
293
294
295        Log.d(LOGTAG, "testChunked start - rq = " + mRequestQueue);
296
297        RequestHandle handle = mRequestQueue.queueRequest(
298                "http://localhost:8080/test1", "GET", null, testEventHandler,
299                null, 0);
300
301        Log.d(LOGTAG, "testChunked - sent request waiting");
302        handle.waitUntilComplete();
303
304        if (!testEventHandler.expectPassed()) {
305            Log.d(LOGTAG, testEventHandler.getFailureMessage());
306            fail("expectPassed was false " + testEventHandler.getFailureMessage());
307        }
308    }
309
310    public void verifyRedirect(int statusCode, String testName) throws Exception {
311        final String REDIRECT_TO = "http://localhost:8081/test1";
312
313        mTestWebServer.setKeepAlive(false);
314        TestWebServer redirectWebServer = new TestWebServer();
315        redirectWebServer.initServer(8081, true);
316        redirectWebServer.setKeepAlive(false);
317
318        try {
319            TestEventHandler testEventHandler = new TestEventHandler();
320            // Load up expected response
321            testEventHandler.expectStatus(statusCode);
322            testEventHandler.expectHeaders();
323            testEventHandler.expectHeaderAdd(requestHeaders[REQ_LOCATION], REDIRECT_TO);
324
325            mTestWebServer.setAcceptLimit(1);
326            mTestWebServer.setRedirect(REDIRECT_TO, statusCode);
327            redirectWebServer.setAcceptLimit(1);
328
329            Log.d(LOGTAG, testName + " start - rq = " + mRequestQueue);
330
331            RequestHandle requestHandle = mRequestQueue.queueRequest(
332                    "http://localhost:8080/test1", "GET", null, testEventHandler, null, 0);
333            Log.d(LOGTAG, testName + " - sent request waiting");
334
335            requestHandle.waitUntilComplete();
336
337            if (!testEventHandler.expectPassed()) {
338                Log.d(LOGTAG, testEventHandler.getFailureMessage());
339                fail("expectPassed was false " + testEventHandler.getFailureMessage());
340            }
341
342            requestHandle.setupRedirect(REDIRECT_TO, statusCode, new HashMap<String, String>());
343
344            testEventHandler.expectStatus(HttpConstants.HTTP_OK);
345            testEventHandler.expectHeaders();
346            testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_LENGTH], "52");
347            testEventHandler.expectHeaderAdd(requestHeaders[REQ_CONTENT_TYPE], "text/html");
348            // Server name should be TestWebServer+port
349            // we ignore the server tag, so don't test it
350            // testEventHandler.expectHeaderAdd(requestHeaders[REQ_SERVER], "TestWebServer8081");
351            testEventHandler.expectData(52);
352            testEventHandler.expectEndData();
353
354            requestHandle.waitUntilComplete();
355
356            if (!testEventHandler.expectPassed()) {
357                Log.d(LOGTAG, testEventHandler.getFailureMessage());
358                fail("expectPassed was false " + testEventHandler.getFailureMessage());
359             }
360        } finally {
361            Log.d(LOGTAG, testName + " - returning");
362            redirectWebServer.close();
363        }
364    }
365
366    public void testRedirect301() throws Exception {
367        verifyRedirect(HttpConstants.HTTP_MOVED_PERM, "testRedirect301");
368    }
369
370    public void testRedirect302() throws Exception {
371        verifyRedirect(HttpConstants.HTTP_MOVED_TEMP, "testRedirect302");
372    }
373
374    public void testRedirect303() throws Exception {
375        verifyRedirect(HttpConstants.HTTP_SEE_OTHER, "testRedirect303");
376    }
377
378    public void testRedirect307() throws Exception {
379        verifyRedirect(307, "testRedirect307");
380    }
381
382    public void testGetAndHead() throws Exception {
383        /**
384         * Test sending a GET and a HEAD request. Test will pass if the
385         * event received correspond with the expected response. The two
386         * requests should respond the same test data.
387         */
388        mTestWebServer.setKeepAlive(true);
389        mTestWebServer.setAcceptLimit(2);
390
391        TestEventHandler testEventHandler = new TestEventHandler();
392        testEventHandler.expectStatus(200);
393        testEventHandler.expectHeaders();
394
395        TestEventHandler leh2 = new TestEventHandler();
396        leh2.expectStatus(200);
397        leh2.expectHeaders();
398
399        RequestHandle handle0 = mRequestQueue.queueRequest(
400                "http://localhost:8080/test1", "GET", null, testEventHandler, null, 0);
401        handle0.waitUntilComplete();
402        RequestHandle handle1 = mRequestQueue.queueRequest(
403                "http://localhost:8080/test1", "HEAD", null, testEventHandler, null, 0);
404
405        Log.d(LOGTAG, "testGetAndHead - sent request. Waiting");
406        handle1.waitUntilComplete();
407
408        if (!testEventHandler.expectPassed() && !leh2.expectPassed()) {
409            Log.d(LOGTAG, testEventHandler.getFailureMessage());
410            Log.d(LOGTAG, leh2.getFailureMessage());
411            fail();
412        }
413    }
414
415    public void testPost() throws Exception {
416        /**
417         * Test sending a POST request with no body data. Test will pass if the event
418         * received correspond with the expected response. This should respond with
419         * the test data requested.
420         */
421        TestEventHandler testEventHandler = new TestEventHandler();
422
423        // Load up expected response
424        testEventHandler.expectStatus(200);
425        testEventHandler.expectHeaders();
426        testEventHandler.expectData(52);
427
428        mTestWebServer.setKeepAlive(false);
429        mTestWebServer.setAcceptLimit(1);
430
431        Log.d(LOGTAG, "testPost start - rq = " + mRequestQueue);
432
433        RequestHandle handle = mRequestQueue.queueRequest(
434                "http://localhost:8080/test1", "POST", null, testEventHandler, null, 0);
435
436        Log.d(LOGTAG, "testPost - sent request waiting");
437        handle.waitUntilComplete();
438
439        if (!testEventHandler.expectPassed()) {
440            Log.d(LOGTAG, testEventHandler.getFailureMessage());
441            fail("expectPassed was false " + testEventHandler.getFailureMessage());
442        }
443    }
444
445
446    public void testPostWithData() throws Exception {
447        /**
448         * Test sending a POST request with body data. Test will pass if the event
449         * received correspond with the expected response. This should respond with
450         * the test data requested.
451         */
452
453        TestEventHandler testEventHandler = new TestEventHandler();
454        // Load up expected response
455        testEventHandler.expectStatus(200);
456        testEventHandler.expectHeaders();
457        testEventHandler.expectData(52);
458
459        mTestWebServer.setKeepAlive(false);
460        mTestWebServer.setAcceptLimit(1);
461
462        Log.d(LOGTAG, "testPostWithData start - rq = " + mRequestQueue);
463
464        String mBody = TestWebData.postContent;
465        int bodyLength = mBody.length();
466        if (bodyLength > 0) {
467            Log.v(LOGTAG, "testPostWithData: body " + mBody);
468        }
469        InputStream bodyProvider = new ByteArrayInputStream(mBody.getBytes());
470
471        RequestHandle handle = mRequestQueue.queueRequest(
472                "http://localhost:8080/test1", "POST", null, testEventHandler, bodyProvider, bodyLength);
473
474        Log.d(LOGTAG, "testPostWithData - sent request waiting");
475        handle.waitUntilComplete();
476
477        if (!testEventHandler.expectPassed()) {
478            Log.d(LOGTAG, testEventHandler.getFailureMessage());
479            fail("expectPassed was false " + testEventHandler.getFailureMessage());
480        }
481    }
482}
483