f2a26f12026607eb6144d8eaa4936fba4d0900f1
[android/platform/packages/providers/DownloadProvider.git] / tests / src / com / android / providers / downloads / PublicApiFunctionalTest.java
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
17 package com.android.providers.downloads;
18
19
20 import android.app.DownloadManager;
21 import android.content.Intent;
22 import android.database.Cursor;
23 import android.net.ConnectivityManager;
24 import android.net.Uri;
25 import android.os.Environment;
26 import android.provider.Downloads;
27 import android.test.suitebuilder.annotation.LargeTest;
28
29 import tests.http.MockResponse;
30 import tests.http.RecordedRequest;
31
32 import java.io.File;
33 import java.io.FileInputStream;
34 import java.io.FileNotFoundException;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.net.MalformedURLException;
38 import java.util.List;
39
40 @LargeTest
41 public 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 }