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