PublicApiFunctionalTest.java revision 961024389b3782936a40a7d090d670290bb66c3c
1/*
2 * Copyright (C) 2010 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 com.android.providers.downloads;
18
19
20import android.app.DownloadManager;
21import android.content.Intent;
22import android.database.Cursor;
23import android.net.ConnectivityManager;
24import android.net.Uri;
25import android.os.Environment;
26import android.provider.Downloads;
27import android.test.suitebuilder.annotation.LargeTest;
28
29import tests.http.MockResponse;
30import tests.http.RecordedRequest;
31
32import java.io.File;
33import java.io.FileInputStream;
34import java.io.FileNotFoundException;
35import java.io.IOException;
36import java.io.InputStream;
37import java.net.MalformedURLException;
38import java.util.List;
39
40@LargeTest
41public class PublicApiFunctionalTest extends AbstractPublicApiTest {
42    private static final String REDIRECTED_PATH = "/other_path";
43    private static final String ETAG = "my_etag";
44
45    protected File mTestDirectory;
46
47    public PublicApiFunctionalTest() {
48        super(new FakeSystemFacade());
49    }
50
51    @Override
52    protected void setUp() throws Exception {
53        super.setUp();
54
55        mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
56                                  + "download_manager_functional_test");
57        if (mTestDirectory.exists()) {
58            for (File file : mTestDirectory.listFiles()) {
59                file.delete();
60            }
61        } else {
62            mTestDirectory.mkdir();
63        }
64        mSystemFacade.setStartThreadsWithoutWaiting(false);
65    }
66
67    @Override
68    protected void tearDown() throws Exception {
69        if (mTestDirectory != null && mTestDirectory.exists()) {
70            for (File file : mTestDirectory.listFiles()) {
71                file.delete();
72            }
73            mTestDirectory.delete();
74        }
75        super.tearDown();
76    }
77
78    public void testBasicRequest() throws Exception {
79        enqueueResponse(HTTP_OK, FILE_CONTENT);
80
81        Download download = enqueueRequest(getRequest());
82        assertEquals(DownloadManager.STATUS_PENDING,
83                     download.getLongField(DownloadManager.COLUMN_STATUS));
84        assertEquals(getServerUri(REQUEST_PATH),
85                     download.getStringField(DownloadManager.COLUMN_URI));
86        assertEquals(download.mId, download.getLongField(DownloadManager.COLUMN_ID));
87        assertEquals(mSystemFacade.currentTimeMillis(),
88                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
89
90        mSystemFacade.incrementTimeMillis(10);
91        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
92        RecordedRequest request = takeRequest();
93        assertEquals("GET", request.getMethod());
94        assertEquals(REQUEST_PATH, request.getPath());
95
96        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
97        assertEquals("content", localUri.getScheme());
98        checkUriContent(localUri);
99        assertEquals("text/plain", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
100
101        int size = FILE_CONTENT.length();
102        assertEquals(size, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
103        assertEquals(size, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
104        assertEquals(mSystemFacade.currentTimeMillis(),
105                     download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
106
107        checkCompleteDownload(download);
108    }
109
110    private void checkUriContent(Uri uri) throws FileNotFoundException, IOException {
111        InputStream inputStream = mResolver.openInputStream(uri);
112        try {
113            assertEquals(FILE_CONTENT, readStream(inputStream));
114        } finally {
115            inputStream.close();
116        }
117    }
118
119    public void testTitleAndDescription() throws Exception {
120        Download download = enqueueRequest(getRequest()
121                                           .setTitle("my title")
122                                           .setDescription("my description"));
123        assertEquals("my title", download.getStringField(DownloadManager.COLUMN_TITLE));
124        assertEquals("my description",
125                     download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
126    }
127
128    public void testDownloadError() throws Exception {
129        enqueueEmptyResponse(HTTP_NOT_FOUND);
130        runSimpleFailureTest(HTTP_NOT_FOUND);
131    }
132
133    public void testUnhandledHttpStatus() throws Exception {
134        enqueueEmptyResponse(1234); // some invalid HTTP status
135        runSimpleFailureTest(DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
136    }
137
138    public void testInterruptedDownload() throws Exception {
139        int initialLength = 5;
140        enqueueInterruptedDownloadResponses(initialLength);
141
142        Download download = enqueueRequest(getRequest());
143        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
144        assertEquals(initialLength,
145                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
146        assertEquals(FILE_CONTENT.length(),
147                     download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
148        takeRequest(); // get the first request out of the queue
149
150        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
151        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
152        checkCompleteDownload(download);
153
154        List<String> headers = takeRequest().getHeaders();
155        assertTrue("No Range header: " + headers,
156                   headers.contains("Range: bytes=" + initialLength + "-"));
157        assertTrue("No ETag header: " + headers, headers.contains("If-Match: " + ETAG));
158    }
159
160    public void testInterruptedExternalDownload() throws Exception {
161        enqueueInterruptedDownloadResponses(5);
162        Download download = enqueueRequest(getRequest().setDestinationUri(getExternalUri()));
163        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
164        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
165        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
166        checkCompleteDownload(download);
167    }
168
169    private void enqueueInterruptedDownloadResponses(int initialLength) {
170        // the first response has normal headers but unexpectedly closes after initialLength bytes
171        enqueuePartialResponse(0, initialLength);
172        // the second response returns partial content for the rest of the data
173        enqueuePartialResponse(initialLength, FILE_CONTENT.length());
174    }
175
176    private MockResponse enqueuePartialResponse(int start, int end) {
177        int totalLength = FILE_CONTENT.length();
178        boolean isFirstResponse = (start == 0);
179        int status = isFirstResponse ? HTTP_OK : HTTP_PARTIAL_CONTENT;
180        MockResponse response = enqueueResponse(status, FILE_CONTENT.substring(start, end))
181                               .addHeader("Content-length", totalLength)
182                               .addHeader("Etag", ETAG);
183        if (!isFirstResponse) {
184            response.addHeader("Content-range",
185                    "bytes " + start + "-" + totalLength + "/" + totalLength);
186        }
187        return response;
188    }
189
190    // enqueue a huge response to keep the receiveing thread in DownloadThread.java busy for a while
191    // give enough time to do something (cancel/remove etc) on that downloadrequest
192    // while it is in progress
193    private void enqueueContinuingResponse() {
194        int numPackets = 100;
195        int contentLength =  STRING_1K.length() * numPackets;
196        enqueueResponse(HTTP_OK, STRING_1K)
197               .addHeader("Content-length", contentLength)
198               .addHeader("Etag", ETAG)
199               .setNumPackets(numPackets);
200    }
201
202    public void testFiltering() throws Exception {
203        enqueueEmptyResponse(HTTP_OK);
204        Download download1 = enqueueRequest(getRequest());
205        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
206        enqueueEmptyResponse(HTTP_NOT_FOUND);
207
208        mSystemFacade.incrementTimeMillis(1); // ensure downloads are correctly ordered by time
209        Download download2 = enqueueRequest(getRequest());
210        download2.runUntilStatus(DownloadManager.STATUS_FAILED);
211
212        mSystemFacade.incrementTimeMillis(1);
213        Download download3 = enqueueRequest(getRequest());
214
215        Cursor cursor = mManager.query(new DownloadManager.Query());
216        checkAndCloseCursor(cursor, download3, download2, download1);
217
218        cursor = mManager.query(new DownloadManager.Query().setFilterById(download2.mId));
219        checkAndCloseCursor(cursor, download2);
220
221        cursor = mManager.query(new DownloadManager.Query()
222                                .setFilterByStatus(DownloadManager.STATUS_PENDING));
223        checkAndCloseCursor(cursor, download3);
224
225        cursor = mManager.query(new DownloadManager.Query()
226                                .setFilterByStatus(DownloadManager.STATUS_FAILED
227                                              | DownloadManager.STATUS_SUCCESSFUL));
228        checkAndCloseCursor(cursor, download2, download1);
229
230        cursor = mManager.query(new DownloadManager.Query()
231                                .setFilterByStatus(DownloadManager.STATUS_RUNNING));
232        checkAndCloseCursor(cursor);
233
234        mSystemFacade.incrementTimeMillis(1);
235        Download invisibleDownload = enqueueRequest(getRequest().setVisibleInDownloadsUi(false));
236        cursor = mManager.query(new DownloadManager.Query());
237        checkAndCloseCursor(cursor, invisibleDownload, download3, download2, download1);
238        cursor = mManager.query(new DownloadManager.Query().setOnlyIncludeVisibleInDownloadsUi(true));
239        checkAndCloseCursor(cursor, download3, download2, download1);
240    }
241
242    public void testOrdering() throws Exception {
243        enqueueResponse(HTTP_OK, "small contents");
244        Download download1 = enqueueRequest(getRequest());
245        download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
246
247        mSystemFacade.incrementTimeMillis(1);
248        enqueueResponse(HTTP_OK, "large contents large contents");
249        Download download2 = enqueueRequest(getRequest());
250        download2.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
251
252        mSystemFacade.incrementTimeMillis(1);
253        enqueueEmptyResponse(HTTP_NOT_FOUND);
254        Download download3 = enqueueRequest(getRequest());
255        download3.runUntilStatus(DownloadManager.STATUS_FAILED);
256
257        // default ordering -- by timestamp descending
258        Cursor cursor = mManager.query(new DownloadManager.Query());
259        checkAndCloseCursor(cursor, download3, download2, download1);
260
261        cursor = mManager.query(new DownloadManager.Query()
262                .orderBy(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP,
263                        DownloadManager.Query.ORDER_ASCENDING));
264        checkAndCloseCursor(cursor, download1, download2, download3);
265
266        cursor = mManager.query(new DownloadManager.Query()
267                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
268                        DownloadManager.Query.ORDER_DESCENDING));
269        checkAndCloseCursor(cursor, download2, download1, download3);
270
271        cursor = mManager.query(new DownloadManager.Query()
272                .orderBy(DownloadManager.COLUMN_TOTAL_SIZE_BYTES,
273                        DownloadManager.Query.ORDER_ASCENDING));
274        checkAndCloseCursor(cursor, download3, download1, download2);
275    }
276
277    private void checkAndCloseCursor(Cursor cursor, Download... downloads) {
278        try {
279            int idIndex = cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
280            assertEquals(downloads.length, cursor.getCount());
281            cursor.moveToFirst();
282            for (Download download : downloads) {
283                assertEquals(download.mId, cursor.getLong(idIndex));
284                cursor.moveToNext();
285            }
286        } finally {
287            cursor.close();
288        }
289    }
290
291    public void testInvalidUri() throws Exception {
292        try {
293            enqueueRequest(getRequest("/no_host"));
294        } catch (IllegalArgumentException exc) { // expected
295            return;
296        }
297
298        fail("No exception thrown for invalid URI");
299    }
300
301    public void testDestination() throws Exception {
302        enqueueResponse(HTTP_OK, FILE_CONTENT);
303        Uri destination = getExternalUri();
304        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
305        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
306
307        Uri localUri = Uri.parse(download.getStringField(DownloadManager.COLUMN_LOCAL_URI));
308        assertEquals(destination, localUri);
309
310        InputStream stream = new FileInputStream(destination.getPath());
311        try {
312            assertEquals(FILE_CONTENT, readStream(stream));
313        } finally {
314            stream.close();
315        }
316    }
317
318    private Uri getExternalUri() {
319        return Uri.fromFile(mTestDirectory).buildUpon().appendPath("testfile.txt").build();
320    }
321
322    public void testRequestHeaders() throws Exception {
323        enqueueEmptyResponse(HTTP_OK);
324        Download download = enqueueRequest(getRequest().addRequestHeader("Header1", "value1")
325                                           .addRequestHeader("Header2", "value2"));
326        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
327
328        List<String> headers = takeRequest().getHeaders();
329        assertTrue(headers.contains("Header1: value1"));
330        assertTrue(headers.contains("Header2: value2"));
331    }
332
333    public void testDelete() throws Exception {
334        Download download = enqueueRequest(getRequest().addRequestHeader("header", "value"));
335        mManager.remove(download.mId);
336        Cursor cursor = mManager.query(new DownloadManager.Query());
337        try {
338            assertEquals(0, cursor.getCount());
339        } finally {
340            cursor.close();
341        }
342    }
343
344    public void testSizeLimitOverMobile() throws Exception {
345        mSystemFacade.mMaxBytesOverMobile = (long) FILE_CONTENT.length() - 1;
346
347        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
348        enqueueResponse(HTTP_OK, FILE_CONTENT);
349        Download download = enqueueRequest(getRequest());
350        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
351
352        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
353        // first response was read, but aborted after the DL manager processed the Content-Length
354        // header, so we need to enqueue a second one
355        enqueueResponse(HTTP_OK, FILE_CONTENT);
356        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
357    }
358
359    public void testRedirect301() throws Exception {
360        RecordedRequest lastRequest = runRedirectionTest(301);
361        // for 301, upon retry/resume, we reuse the redirected URI
362        assertEquals(REDIRECTED_PATH, lastRequest.getPath());
363    }
364
365    public void testRedirect302() throws Exception {
366        RecordedRequest lastRequest = runRedirectionTest(302);
367        // for 302, upon retry/resume, we use the original URI
368        assertEquals(REQUEST_PATH, lastRequest.getPath());
369    }
370
371    public void testNoEtag() throws Exception {
372        enqueuePartialResponse(0, 5).removeHeader("Etag");
373        runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
374    }
375
376    public void testSanitizeMediaType() throws Exception {
377        enqueueEmptyResponse(HTTP_OK).addHeader("Content-Type", "text/html; charset=ISO-8859-4");
378        Download download = enqueueRequest(getRequest());
379        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
380        assertEquals("text/html", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
381    }
382
383    public void testNoContentLength() throws Exception {
384        enqueueEmptyResponse(HTTP_OK).removeHeader("Content-Length");
385        runSimpleFailureTest(DownloadManager.ERROR_HTTP_DATA_ERROR);
386    }
387
388    public void testInsufficientSpace() throws Exception {
389        // this would be better done by stubbing the system API to check available space, but in the
390        // meantime, just use an absurdly large header value
391        enqueueEmptyResponse(HTTP_OK).addHeader("Content-Length",
392                                                1024L * 1024 * 1024 * 1024 * 1024);
393        runSimpleFailureTest(DownloadManager.ERROR_INSUFFICIENT_SPACE);
394    }
395
396    public void testCancel() throws Exception {
397        mSystemFacade.setStartThreadsWithoutWaiting(true);
398        // return 'real time' from FakeSystemFacade so that DownloadThread will report progress
399        mSystemFacade.setReturnActualTime(true);
400        enqueueContinuingResponse();
401        Download download = enqueueRequest(getRequest());
402        startService(null);
403        // give the download time to get started and progress to 1% completion
404        // before cancelling it.
405        boolean rslt = download.runUntilProgress(1);
406        assertTrue(rslt);
407        mManager.remove(download.mId);
408        startService(null);
409        int status = download.runUntilDone();
410        // make sure the row is gone from the database
411        assertEquals(-1, status);
412        mSystemFacade.setReturnActualTime(false);
413    }
414
415    public void testDownloadCompleteBroadcast() throws Exception {
416        enqueueEmptyResponse(HTTP_OK);
417        Download download = enqueueRequest(getRequest());
418        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
419
420        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
421        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
422        assertEquals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, broadcast.getAction());
423        assertEquals(PACKAGE_NAME, broadcast.getPackage());
424        long intentId = broadcast.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID);
425        assertEquals(download.mId, intentId);
426    }
427
428    public void testNotificationClickedBroadcast() throws Exception {
429        Download download = enqueueRequest(getRequest());
430
431        DownloadReceiver receiver = new DownloadReceiver();
432        receiver.mSystemFacade = mSystemFacade;
433        Intent intent = new Intent(Constants.ACTION_LIST);
434        intent.setData(Uri.parse(Downloads.Impl.CONTENT_URI + "/" + download.mId));
435        receiver.onReceive(mContext, intent);
436
437        assertEquals(1, mSystemFacade.mBroadcastsSent.size());
438        Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
439        assertEquals(DownloadManager.ACTION_NOTIFICATION_CLICKED, broadcast.getAction());
440        assertEquals(PACKAGE_NAME, broadcast.getPackage());
441    }
442
443    public void testBasicConnectivityChanges() throws Exception {
444        // without connectivity, download immediately pauses
445        mSystemFacade.mActiveNetworkType = null;
446
447        enqueueResponse(HTTP_OK, FILE_CONTENT);
448        Download download = enqueueRequest(getRequest());
449
450        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
451
452        // connecting should start the download
453        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
454        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
455    }
456
457    public void testAllowedNetworkTypes() throws Exception {
458        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
459
460        // by default, use any connection
461        enqueueEmptyResponse(HTTP_OK);
462        Download download = enqueueRequest(getRequest());
463        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
464
465        // restrict a download to wifi...
466        download = enqueueRequest(getRequest()
467                                  .setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI));
468        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
469        // ...then enable wifi
470        mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
471        enqueueEmptyResponse(HTTP_OK);
472        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
473    }
474
475    public void testRoaming() throws Exception {
476        mSystemFacade.mIsRoaming = true;
477
478        // by default, allow roaming
479        enqueueEmptyResponse(HTTP_OK);
480        Download download = enqueueRequest(getRequest());
481        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
482
483        // disallow roaming for a download...
484        download = enqueueRequest(getRequest().setAllowedOverRoaming(false));
485        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
486        // ...then turn off roaming
487        mSystemFacade.mIsRoaming = false;
488        enqueueEmptyResponse(HTTP_OK);
489        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
490    }
491
492    public void testContentObserver() throws Exception {
493        enqueueEmptyResponse(HTTP_OK);
494        enqueueRequest(getRequest());
495        mResolver.resetNotified();
496        runService();
497        assertTrue(mResolver.mNotifyWasCalled);
498    }
499
500    public void testNotifications() throws Exception {
501        enqueueEmptyResponse(HTTP_OK);
502        Download download = enqueueRequest(getRequest().setShowRunningNotification(false));
503        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
504        assertEquals(0, mSystemFacade.mActiveNotifications.size());
505        assertEquals(0, mSystemFacade.mCanceledNotifications.size());
506
507        enqueueEmptyResponse(HTTP_OK);
508        download = enqueueRequest(getRequest()); // notifications by default
509        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
510        assertEquals(1, mSystemFacade.mActiveNotifications.size());
511
512        // The notification doesn't actually get canceled until the UpdateThread runs again, which
513        // gets triggered by the DownloadThread updating the status in the provider.
514        runService();
515        assertEquals(0, mSystemFacade.mActiveNotifications.size());
516        assertEquals(1, mSystemFacade.mCanceledNotifications.size());
517    }
518
519    public void testRetryAfter() throws Exception {
520        final int delay = 120;
521        enqueueEmptyResponse(HTTP_SERVICE_UNAVAILABLE).addHeader("Retry-after", delay);
522        Download download = enqueueRequest(getRequest());
523        download.runUntilStatus(DownloadManager.STATUS_PAUSED);
524
525        // download manager adds random 0-30s offset
526        mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
527
528        enqueueEmptyResponse(HTTP_OK);
529        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
530    }
531
532    public void testManyInterruptions() throws Exception {
533        int bytesPerResponse = 1;
534        int start = 0;
535
536        Download download = enqueueRequest(getRequest());
537        while (start + bytesPerResponse < FILE_CONTENT.length()) {
538            enqueuePartialResponse(start, start + bytesPerResponse);
539            download.runUntilStatus(DownloadManager.STATUS_PAUSED);
540            takeRequest();
541            start += bytesPerResponse;
542            mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
543        }
544
545        enqueuePartialResponse(start, FILE_CONTENT.length());
546        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
547        checkCompleteDownload(download);
548    }
549
550    public void testExistingFile() throws Exception {
551        // download a file which already exists.
552        // downloadservice should simply create filename with "-" and a number attached
553        // at the end; i.e., download shouldnot fail.
554        Uri destination = getExternalUri();
555        new File(destination.getPath()).createNewFile();
556
557        enqueueEmptyResponse(HTTP_OK);
558        Download download = enqueueRequest(getRequest().setDestinationUri(destination));
559        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
560    }
561
562    public void testEmptyFields() throws Exception {
563        Download download = enqueueRequest(getRequest());
564        assertEquals("", download.getStringField(DownloadManager.COLUMN_TITLE));
565        assertEquals("", download.getStringField(DownloadManager.COLUMN_DESCRIPTION));
566        assertNull(download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
567        assertEquals(0, download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
568        assertEquals(-1, download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
569        // just ensure no exception is thrown
570        download.getLongField(DownloadManager.COLUMN_REASON);
571    }
572
573    public void testRestart() throws Exception {
574        enqueueEmptyResponse(HTTP_NOT_FOUND);
575        Download download = enqueueRequest(getRequest());
576        download.runUntilStatus(DownloadManager.STATUS_FAILED);
577
578        enqueueEmptyResponse(HTTP_OK);
579        mManager.restartDownload(download.mId);
580        assertEquals(DownloadManager.STATUS_PENDING,
581                download.getLongField(DownloadManager.COLUMN_STATUS));
582        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
583    }
584
585    private void checkCompleteDownload(Download download) throws Exception {
586        assertEquals(FILE_CONTENT.length(),
587                     download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
588        assertEquals(FILE_CONTENT, download.getContents());
589    }
590
591    private void runSimpleFailureTest(int expectedErrorCode) throws Exception {
592        Download download = enqueueRequest(getRequest());
593        download.runUntilStatus(DownloadManager.STATUS_FAILED);
594        assertEquals(expectedErrorCode,
595                     download.getLongField(DownloadManager.COLUMN_REASON));
596    }
597
598    /**
599     * Run a redirection test consisting of
600     * 1) Request to REQUEST_PATH with 3xx response redirecting to another URI
601     * 2) Request to REDIRECTED_PATH with interrupted partial response
602     * 3) Resume request to complete download
603     * @return the last request sent to the server, resuming after the interruption
604     */
605    private RecordedRequest runRedirectionTest(int status)
606            throws MalformedURLException, Exception {
607        enqueueEmptyResponse(status).addHeader("Location",
608                                               mServer.getUrl(REDIRECTED_PATH).toString());
609        enqueueInterruptedDownloadResponses(5);
610
611        Download download = enqueueRequest(getRequest());
612        runService();
613        assertEquals(REQUEST_PATH, takeRequest().getPath());
614        assertEquals(REDIRECTED_PATH, takeRequest().getPath());
615
616        mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
617        download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
618        return takeRequest();
619    }
620}
621