Home | History | Annotate | Download | only in app
      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 android.app;
     18 
     19 import android.app.DownloadManager.Query;
     20 import android.app.DownloadManager.Request;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.os.Environment;
     24 import android.os.ParcelFileDescriptor;
     25 import android.test.suitebuilder.annotation.LargeTest;
     26 
     27 import com.google.mockwebserver.MockResponse;
     28 
     29 import java.io.File;
     30 import java.util.Iterator;
     31 import java.util.Set;
     32 
     33 /**
     34  * Integration tests of the DownloadManager API.
     35  */
     36 public class DownloadManagerFunctionalTest extends DownloadManagerBaseTest {
     37     private static final String TAG = "DownloadManagerFunctionalTest";
     38     private final static String CACHE_DIR =
     39             Environment.getDownloadCacheDirectory().getAbsolutePath();
     40     private final static String PROHIBITED_DIRECTORY =
     41             Environment.getRootDirectory().getAbsolutePath();
     42 
     43     /**
     44      * {@inheritDoc}
     45      */
     46     @Override
     47     public void setUp() throws Exception {
     48         super.setUp();
     49         setWiFiStateOn(true);
     50         removeAllCurrentDownloads();
     51     }
     52 
     53     /**
     54      * {@inheritDoc}
     55      */
     56     @Override
     57     public void tearDown() throws Exception {
     58         super.tearDown();
     59         setWiFiStateOn(true);
     60         removeAllCurrentDownloads();
     61 
     62         if (mReceiver != null) {
     63             mContext.unregisterReceiver(mReceiver);
     64             mReceiver = null;
     65         }
     66     }
     67 
     68     /**
     69      * Verifies a particular error code was received from a download
     70      *
     71      * @param uri The uri to enqueue to the DownloadManager
     72      * @param error The error code expected
     73      * @throws Exception if the test fails
     74      */
     75     public void doErrorTest(Uri uri, int error) throws Exception {
     76         Request request = new Request(uri);
     77         request.setTitle(DEFAULT_FILENAME);
     78 
     79         long dlRequest = mDownloadManager.enqueue(request);
     80         waitForDownloadOrTimeout(dlRequest);
     81 
     82         Cursor cursor = getCursor(dlRequest);
     83         try {
     84             verifyInt(cursor, DownloadManager.COLUMN_REASON, error);
     85         } finally {
     86             cursor.close();
     87         }
     88     }
     89 
     90     /**
     91      * Test a basic download of a binary file 500k in size.
     92      */
     93     @LargeTest
     94     public void testBinaryDownloadToSystemCache() throws Exception {
     95         int fileSize = 1024;
     96         byte[] blobData = generateData(fileSize, DataType.BINARY);
     97 
     98         long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE);
     99         verifyDownload(dlRequest, blobData);
    100         mDownloadManager.remove(dlRequest);
    101     }
    102 
    103     /**
    104      * Tests the basic downloading of a text file 300000 bytes in size.
    105      */
    106     @LargeTest
    107     public void testTextDownloadToSystemCache() throws Exception {
    108         int fileSize = 1024;
    109         byte[] blobData = generateData(fileSize, DataType.TEXT);
    110 
    111         long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE);
    112         verifyDownload(dlRequest, blobData);
    113         mDownloadManager.remove(dlRequest);
    114     }
    115 
    116     /**
    117      * Helper to verify a standard single-file download from the mock server, and clean up after
    118      * verification
    119      *
    120      * Note that this also calls the Download manager's remove, which cleans up the file from cache.
    121      *
    122      * @param requestId The id of the download to remove
    123      * @param fileData The data to verify the file contains
    124      */
    125     private void verifyDownload(long requestId, byte[] fileData)
    126             throws Exception {
    127         int fileSize = fileData.length;
    128         ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(requestId);
    129         Cursor cursor = mDownloadManager.query(new Query().setFilterById(requestId));
    130         try {
    131             assertEquals(1, cursor.getCount());
    132             assertTrue(cursor.moveToFirst());
    133 
    134             verifyFileSize(pfd, fileSize);
    135             verifyFileContents(pfd, fileData);
    136             int colIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
    137             String fileName = cursor.getString(colIndex);
    138             assertTrue(fileName.startsWith(CACHE_DIR));
    139         } finally {
    140             pfd.close();
    141             cursor.close();
    142         }
    143     }
    144 
    145     /**
    146      * Tests trying to download to SD card when the file with same name already exists.
    147      */
    148     @LargeTest
    149     public void testDownloadToExternal_fileExists() throws Exception {
    150         File existentFile = createFileOnSD(null, 1, DataType.TEXT, null);
    151         byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
    152 
    153         // Prepare the mock server with a standard response
    154         enqueueResponse(buildResponse(HTTP_OK, blobData));
    155 
    156         try {
    157             Uri uri = getServerUri(DEFAULT_FILENAME);
    158             Request request = new Request(uri);
    159 
    160             Uri localUri = Uri.fromFile(existentFile);
    161             request.setDestinationUri(localUri);
    162 
    163             long dlRequest = mDownloadManager.enqueue(request);
    164 
    165             // wait for the download to complete
    166             waitForDownloadOrTimeout(dlRequest);
    167             Cursor cursor = getCursor(dlRequest);
    168 
    169             try {
    170                 verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_SUCCESSFUL);
    171             } finally {
    172                 cursor.close();
    173             }
    174         } finally {
    175             existentFile.delete();
    176         }
    177     }
    178 
    179     /**
    180      * Tests trying to download a file to SD card.
    181      */
    182     @LargeTest
    183     public void testDownloadToExternal() throws Exception {
    184         String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath();
    185         File downloadedFile = new File(localDownloadDirectory, DEFAULT_FILENAME);
    186         // make sure the file doesn't already exist in the directory
    187         downloadedFile.delete();
    188 
    189         try {
    190             byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
    191 
    192             // Prepare the mock server with a standard response
    193             enqueueResponse(buildResponse(HTTP_OK, blobData));
    194 
    195             Uri uri = getServerUri(DEFAULT_FILENAME);
    196             Request request = new Request(uri);
    197 
    198             Uri localUri = Uri.fromFile(downloadedFile);
    199             request.setDestinationUri(localUri);
    200 
    201             long dlRequest = mDownloadManager.enqueue(request);
    202 
    203             // wait for the download to complete
    204             waitForDownloadOrTimeout(dlRequest);
    205 
    206             verifyAndCleanupSingleFileDownload(dlRequest, blobData);
    207 
    208             assertEquals(1, mReceiver.numDownloadsCompleted());
    209         } finally {
    210             downloadedFile.delete();
    211         }
    212     }
    213 
    214     /**
    215      * Tests trying to download a file to the system partition.
    216      */
    217     @LargeTest
    218     public void testDownloadToProhibitedDirectory() throws Exception {
    219         File downloadedFile = new File(PROHIBITED_DIRECTORY, DEFAULT_FILENAME);
    220         try {
    221             byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT);
    222 
    223             // Prepare the mock server with a standard response
    224             enqueueResponse(buildResponse(HTTP_OK, blobData));
    225 
    226             Uri uri = getServerUri(DEFAULT_FILENAME);
    227             Request request = new Request(uri);
    228 
    229             Uri localUri = Uri.fromFile(downloadedFile);
    230             request.setDestinationUri(localUri);
    231 
    232             try {
    233                 mDownloadManager.enqueue(request);
    234                 fail("Failed to throw SecurityException when trying to write to /system.");
    235             } catch (SecurityException s) {
    236                 assertFalse(downloadedFile.exists());
    237             }
    238         } finally {
    239             // Just in case file somehow got created, make sure to delete it
    240             downloadedFile.delete();
    241         }
    242     }
    243 
    244     /**
    245      * Tests that we get the correct download ID from the download notification.
    246      */
    247     @LargeTest
    248     public void testGetDownloadIdOnNotification() throws Exception {
    249         byte[] blobData = generateData(3000, DataType.TEXT);  // file size = 3000 bytes
    250 
    251         enqueueResponse(buildResponse(HTTP_OK, blobData));
    252         long dlRequest = doCommonStandardEnqueue();
    253         waitForDownloadOrTimeout(dlRequest);
    254 
    255         Set<Long> ids = mReceiver.getDownloadIds();
    256         assertEquals(1, ids.size());
    257         Iterator<Long> it = ids.iterator();
    258         assertEquals("Download ID received from notification does not match initial id!",
    259                 dlRequest, it.next().longValue());
    260     }
    261 
    262     /**
    263      * Tests the download failure error after too many redirects (>5).
    264      */
    265     @LargeTest
    266     public void testErrorTooManyRedirects() throws Exception {
    267         Uri uri = getServerUri(DEFAULT_FILENAME);
    268 
    269         // force 6 redirects
    270         for (int i = 0; i < 6; ++i) {
    271             final MockResponse resp = buildResponse(HTTP_REDIRECT);
    272             resp.setHeader("Location", uri.toString());
    273             enqueueResponse(resp);
    274         }
    275         doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS);
    276     }
    277 
    278     /**
    279      * Tests the download failure error from an unhandled HTTP status code
    280      */
    281     @LargeTest
    282     public void testErrorUnhandledHttpCode() throws Exception {
    283         Uri uri = getServerUri(DEFAULT_FILENAME);
    284         enqueueResponse(buildResponse(HTTP_PARTIAL_CONTENT));
    285 
    286         doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
    287     }
    288 
    289     /**
    290      * Tests the download failure error from an unhandled HTTP status code
    291      */
    292     @LargeTest
    293     public void testErrorHttpDataError_invalidRedirect() throws Exception {
    294         Uri uri = getServerUri(DEFAULT_FILENAME);
    295         final MockResponse resp = buildResponse(HTTP_REDIRECT);
    296         resp.setHeader("Location", "://blah.blah.blah.com");
    297         enqueueResponse(resp);
    298 
    299         doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR);
    300     }
    301 
    302     /**
    303      * Tests that we can remove a download from the download manager.
    304      */
    305     @LargeTest
    306     public void testRemoveDownload() throws Exception {
    307         int fileSize = 1024;
    308         byte[] blobData = generateData(fileSize, DataType.BINARY);
    309 
    310         long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR);
    311         Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest));
    312         try {
    313             assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount());
    314             mDownloadManager.remove(dlRequest);
    315             cursor.requery();
    316             assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount());
    317         } finally {
    318             cursor.close();
    319         }
    320     }
    321 
    322     /**
    323      * Tests that we can set the title of a download.
    324      */
    325     @LargeTest
    326     public void testSetTitle() throws Exception {
    327         int fileSize = 1024;
    328         byte[] blobData = generateData(fileSize, DataType.BINARY);
    329         enqueueResponse(buildResponse(HTTP_OK, blobData));
    330 
    331         // An arbitrary unicode string title
    332         final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" +
    333                 "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'";
    334 
    335         Uri uri = getServerUri(DEFAULT_FILENAME);
    336         Request request = new Request(uri);
    337         request.setTitle(title);
    338 
    339         long dlRequest = mDownloadManager.enqueue(request);
    340         waitForDownloadOrTimeout(dlRequest);
    341 
    342         Cursor cursor = getCursor(dlRequest);
    343         try {
    344             verifyString(cursor, DownloadManager.COLUMN_TITLE, title);
    345         } finally {
    346             cursor.close();
    347         }
    348     }
    349 
    350     /**
    351      * Tests that a download set for Wifi does not progress while Wifi is disabled, but resumes
    352      * once Wifi is re-enabled.
    353      */
    354     @LargeTest
    355     public void testDownloadNoWifi() throws Exception {
    356         long timeout = 60 * 1000; // wait only 60 seconds before giving up
    357         int fileSize = 1024;  // 140k
    358         byte[] blobData = generateData(fileSize, DataType.TEXT);
    359 
    360         setWiFiStateOn(false);
    361         enqueueResponse(buildResponse(HTTP_OK, blobData));
    362 
    363         try {
    364             Uri uri = getServerUri(DEFAULT_FILENAME);
    365             Request request = new Request(uri);
    366             request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
    367 
    368             long dlRequest = mDownloadManager.enqueue(request);
    369 
    370             // wait for the download to complete
    371             boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest,
    372                     WAIT_FOR_DOWNLOAD_POLL_TIME, timeout);
    373             assertFalse("Download proceeded without Wifi connection!", success);
    374 
    375             setWiFiStateOn(true);
    376             waitForDownloadOrTimeout(dlRequest);
    377 
    378             assertEquals(1, mReceiver.numDownloadsCompleted());
    379         } finally {
    380             setWiFiStateOn(true);
    381         }
    382     }
    383 
    384     /**
    385      * Tests that we get an error code when the server drops the connection during a download.
    386      */
    387     @LargeTest
    388     public void testServerDropConnection_body() throws Exception {
    389         byte[] blobData = generateData(25000, DataType.TEXT);  // file size = 25000 bytes
    390 
    391         final MockResponse resp = buildResponse(HTTP_OK, blobData);
    392         resp.setHeader("Content-Length", "50000");
    393         enqueueResponse(resp);
    394 
    395         long dlRequest = doCommonStandardEnqueue();
    396         waitForDownloadOrTimeout(dlRequest);
    397 
    398         Cursor cursor = getCursor(dlRequest);
    399         try {
    400             verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED);
    401             verifyInt(cursor, DownloadManager.COLUMN_REASON,
    402                     DownloadManager.ERROR_CANNOT_RESUME);
    403         } finally {
    404             cursor.close();
    405         }
    406         // Even tho the server drops the connection, we should still get a completed notification
    407         assertEquals(1, mReceiver.numDownloadsCompleted());
    408     }
    409 }
    410