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 
17 package android.core;
18 
19 import android.net.http.RequestHandle;
20 import android.net.http.RequestQueue;
21 import android.test.AndroidTestCase;
22 import android.test.suitebuilder.annotation.Suppress;
23 import android.util.Log;
24 import android.webkit.CookieSyncManager;
25 
26 import java.io.ByteArrayInputStream;
27 import java.io.InputStream;
28 import java.util.HashMap;
29 import java.util.Map;
30 
31 /**
32  * Container class for all RequestAPI tests
33  */
34 //http://b/issue?id=1200337
35 @Suppress
36 public 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 
setUp()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 
tearDown()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 
verifyFailure(Map<String, String> headers)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 
testRequestAddNullHeader()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 
testRequestAddNullValue()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 
testRequestAddEmptyValue()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 
verifySuccess(Map<String, String> headers)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 
testRequestAddHeader()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 
testRequestAddMultiHeader()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 
testRequestAddSameHeader()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 
testRequestAddNullHeaders()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 
testGet()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 
testReuse()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 
testHead()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 
testChunked()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 
verifyRedirect(int statusCode, String testName)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 
testRedirect301()366     public void testRedirect301() throws Exception {
367         verifyRedirect(HttpConstants.HTTP_MOVED_PERM, "testRedirect301");
368     }
369 
testRedirect302()370     public void testRedirect302() throws Exception {
371         verifyRedirect(HttpConstants.HTTP_MOVED_TEMP, "testRedirect302");
372     }
373 
testRedirect303()374     public void testRedirect303() throws Exception {
375         verifyRedirect(HttpConstants.HTTP_SEE_OTHER, "testRedirect303");
376     }
377 
testRedirect307()378     public void testRedirect307() throws Exception {
379         verifyRedirect(307, "testRedirect307");
380     }
381 
testGetAndHead()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 
testPost()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 
testPostWithData()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