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