| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.app; |
| |
| import android.app.DownloadManager.Query; |
| import android.app.DownloadManager.Request; |
| import android.database.Cursor; |
| import android.net.Uri; |
| import android.os.Environment; |
| import android.os.ParcelFileDescriptor; |
| import android.test.suitebuilder.annotation.LargeTest; |
| import com.google.mockwebserver.MockResponse; |
| |
| import java.io.File; |
| import java.util.concurrent.TimeoutException; |
| import java.util.Iterator; |
| import java.util.Set; |
| |
| /** |
| * Integration tests of the DownloadManager API. |
| */ |
| public class DownloadManagerFunctionalTest extends DownloadManagerBaseTest { |
| private static final String TAG = "DownloadManagerFunctionalTest"; |
| private final static String CACHE_DIR = |
| Environment.getDownloadCacheDirectory().getAbsolutePath(); |
| private final static String PROHIBITED_DIRECTORY = |
| Environment.getRootDirectory().getAbsolutePath(); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| setWiFiStateOn(true); |
| removeAllCurrentDownloads(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void tearDown() throws Exception { |
| super.tearDown(); |
| setWiFiStateOn(true); |
| removeAllCurrentDownloads(); |
| |
| if (mReceiver != null) { |
| mContext.unregisterReceiver(mReceiver); |
| mReceiver = null; |
| } |
| } |
| |
| /** |
| * Verifies a particular error code was received from a download |
| * |
| * @param uri The uri to enqueue to the DownloadManager |
| * @param error The error code expected |
| * @throws Exception if the test fails |
| */ |
| public void doErrorTest(Uri uri, int error) throws Exception { |
| Request request = new Request(uri); |
| request.setTitle(DEFAULT_FILENAME); |
| |
| long dlRequest = mDownloadManager.enqueue(request); |
| try { |
| waitForDownloadOrTimeout(dlRequest); |
| } catch (TimeoutException ex) { |
| // it is expected to timeout as download never finishes |
| } |
| |
| Cursor cursor = getCursor(dlRequest); |
| try { |
| verifyInt(cursor, DownloadManager.COLUMN_REASON, error); |
| } finally { |
| cursor.close(); |
| } |
| } |
| |
| /** |
| * Test a basic download of a binary file 500k in size. |
| */ |
| @LargeTest |
| public void testBinaryDownloadToSystemCache() throws Exception { |
| int fileSize = 1024; |
| byte[] blobData = generateData(fileSize, DataType.BINARY); |
| |
| long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE); |
| verifyDownload(dlRequest, blobData); |
| mDownloadManager.remove(dlRequest); |
| } |
| |
| /** |
| * Tests the basic downloading of a text file 300000 bytes in size. |
| */ |
| @LargeTest |
| public void testTextDownloadToSystemCache() throws Exception { |
| int fileSize = 1024; |
| byte[] blobData = generateData(fileSize, DataType.TEXT); |
| |
| long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE); |
| verifyDownload(dlRequest, blobData); |
| mDownloadManager.remove(dlRequest); |
| } |
| |
| /** |
| * Helper to verify a standard single-file download from the mock server, and clean up after |
| * verification |
| * |
| * Note that this also calls the Download manager's remove, which cleans up the file from cache. |
| * |
| * @param requestId The id of the download to remove |
| * @param fileData The data to verify the file contains |
| */ |
| private void verifyDownload(long requestId, byte[] fileData) |
| throws Exception { |
| int fileSize = fileData.length; |
| ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(requestId); |
| Cursor cursor = mDownloadManager.query(new Query().setFilterById(requestId)); |
| try { |
| assertEquals(1, cursor.getCount()); |
| assertTrue(cursor.moveToFirst()); |
| |
| verifyFileSize(pfd, fileSize); |
| verifyFileContents(pfd, fileData); |
| assertTrue(new File(CACHE_DIR + "/" + DEFAULT_FILENAME).exists()); |
| } finally { |
| pfd.close(); |
| cursor.close(); |
| } |
| } |
| |
| /** |
| * Tests trying to download to SD card when the file with same name already exists. |
| */ |
| @LargeTest |
| public void testDownloadToExternal_fileExists() throws Exception { |
| File existentFile = createFileOnSD(null, 1, DataType.TEXT, null); |
| byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); |
| |
| // Prepare the mock server with a standard response |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| try { |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| Request request = new Request(uri); |
| |
| Uri localUri = Uri.fromFile(existentFile); |
| request.setDestinationUri(localUri); |
| long dlRequest = mDownloadManager.enqueue(request); |
| |
| // wait for the download to complete |
| waitForDownloadOrTimeout(dlRequest); |
| Cursor cursor = getCursor(dlRequest); |
| |
| try { |
| verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_SUCCESSFUL); |
| } finally { |
| cursor.close(); |
| } |
| } finally { |
| existentFile.delete(); |
| } |
| } |
| |
| /** |
| * Tests trying to download a file to SD card. |
| */ |
| @LargeTest |
| public void testDownloadToExternal() throws Exception { |
| String localDownloadDirectory = Environment.getExternalStorageDirectory().getPath(); |
| File downloadedFile = new File(localDownloadDirectory, DEFAULT_FILENAME); |
| // make sure the file doesn't already exist in the directory |
| downloadedFile.delete(); |
| |
| try { |
| byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); |
| |
| // Prepare the mock server with a standard response |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| Request request = new Request(uri); |
| |
| Uri localUri = Uri.fromFile(downloadedFile); |
| request.setDestinationUri(localUri); |
| |
| long dlRequest = mDownloadManager.enqueue(request); |
| |
| // wait for the download to complete |
| waitForDownloadOrTimeout(dlRequest); |
| |
| verifyAndCleanupSingleFileDownload(dlRequest, blobData); |
| |
| assertEquals(1, mReceiver.numDownloadsCompleted()); |
| } finally { |
| downloadedFile.delete(); |
| } |
| } |
| |
| /** |
| * Tests trying to download a file to the system partition. |
| */ |
| @LargeTest |
| public void testDownloadToProhibitedDirectory() throws Exception { |
| File downloadedFile = new File(PROHIBITED_DIRECTORY, DEFAULT_FILENAME); |
| try { |
| byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); |
| |
| // Prepare the mock server with a standard response |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| Request request = new Request(uri); |
| |
| Uri localUri = Uri.fromFile(downloadedFile); |
| request.setDestinationUri(localUri); |
| |
| try { |
| mDownloadManager.enqueue(request); |
| fail("Failed to throw SecurityException when trying to write to /system."); |
| } catch (SecurityException s) { |
| assertFalse(downloadedFile.exists()); |
| } |
| } finally { |
| // Just in case file somehow got created, make sure to delete it |
| downloadedFile.delete(); |
| } |
| } |
| |
| /** |
| * Tests that we get the correct download ID from the download notification. |
| */ |
| @LargeTest |
| public void testGetDownloadIdOnNotification() throws Exception { |
| byte[] blobData = generateData(3000, DataType.TEXT); // file size = 3000 bytes |
| |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| long dlRequest = doCommonStandardEnqueue(); |
| waitForDownloadOrTimeout(dlRequest); |
| |
| Set<Long> ids = mReceiver.getDownloadIds(); |
| assertEquals(1, ids.size()); |
| Iterator<Long> it = ids.iterator(); |
| assertEquals("Download ID received from notification does not match initial id!", |
| dlRequest, it.next().longValue()); |
| } |
| |
| /** |
| * Tests the download failure error after too many redirects (>5). |
| */ |
| @LargeTest |
| public void testErrorTooManyRedirects() throws Exception { |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| |
| // force 6 redirects |
| for (int i = 0; i < 6; ++i) { |
| final MockResponse resp = buildResponse(HTTP_REDIRECT); |
| resp.setHeader("Location", uri.toString()); |
| enqueueResponse(resp); |
| } |
| doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS); |
| } |
| |
| /** |
| * Tests the download failure error from an unhandled HTTP status code |
| */ |
| @LargeTest |
| public void testErrorUnhandledHttpCode() throws Exception { |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| enqueueResponse(buildResponse(HTTP_PARTIAL_CONTENT)); |
| |
| doErrorTest(uri, DownloadManager.ERROR_CANNOT_RESUME); |
| } |
| |
| /** |
| * Tests the download failure error from an unhandled HTTP status code |
| */ |
| @LargeTest |
| public void testRelativeRedirect() throws Exception { |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| final MockResponse resp = buildResponse(HTTP_REDIRECT); |
| resp.setHeader("Location", ":" + uri.getSchemeSpecificPart()); |
| enqueueResponse(resp); |
| |
| byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| Request request = new Request(uri); |
| request.setTitle(DEFAULT_FILENAME); |
| |
| long dlRequest = mDownloadManager.enqueue(request); |
| waitForDownloadOrTimeout(dlRequest); |
| |
| verifyAndCleanupSingleFileDownload(dlRequest, blobData); |
| assertEquals(1, mReceiver.numDownloadsCompleted()); |
| } |
| |
| /** |
| * Tests that we can remove a download from the download manager. |
| */ |
| @LargeTest |
| public void testRemoveDownload() throws Exception { |
| int fileSize = 1024; |
| byte[] blobData = generateData(fileSize, DataType.BINARY); |
| |
| long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); |
| Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest)); |
| try { |
| assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount()); |
| mDownloadManager.remove(dlRequest); |
| cursor.requery(); |
| assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount()); |
| } finally { |
| cursor.close(); |
| } |
| } |
| |
| /** |
| * Tests that we can set the title of a download. |
| */ |
| @LargeTest |
| public void testSetTitle() throws Exception { |
| int fileSize = 1024; |
| byte[] blobData = generateData(fileSize, DataType.BINARY); |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| // An arbitrary unicode string title |
| final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" + |
| "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'"; |
| |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| Request request = new Request(uri); |
| request.setTitle(title); |
| |
| long dlRequest = mDownloadManager.enqueue(request); |
| waitForDownloadOrTimeout(dlRequest); |
| |
| Cursor cursor = getCursor(dlRequest); |
| try { |
| verifyString(cursor, DownloadManager.COLUMN_TITLE, title); |
| } finally { |
| cursor.close(); |
| } |
| } |
| |
| /** |
| * Tests that a download set for Wifi does not progress while Wifi is disabled, but resumes |
| * once Wifi is re-enabled. |
| */ |
| @LargeTest |
| public void testDownloadNoWifi() throws Exception { |
| long timeout = 60 * 1000; // wait only 60 seconds before giving up |
| int fileSize = 1024; // 140k |
| byte[] blobData = generateData(fileSize, DataType.TEXT); |
| |
| setWiFiStateOn(false); |
| enqueueResponse(buildResponse(HTTP_OK, blobData)); |
| |
| try { |
| Uri uri = getServerUri(DEFAULT_FILENAME); |
| Request request = new Request(uri); |
| request.setAllowedNetworkTypes(Request.NETWORK_WIFI); |
| |
| long dlRequest = mDownloadManager.enqueue(request); |
| |
| // wait for the download to complete |
| boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest, |
| WAIT_FOR_DOWNLOAD_POLL_TIME, timeout); |
| assertFalse("Download proceeded without Wifi connection!", success); |
| |
| setWiFiStateOn(true); |
| waitForDownloadOrTimeout(dlRequest); |
| |
| assertEquals(1, mReceiver.numDownloadsCompleted()); |
| } finally { |
| setWiFiStateOn(true); |
| } |
| } |
| |
| /** |
| * Tests that we get an error code when the server drops the connection during a download. |
| */ |
| @LargeTest |
| public void testServerDropConnection_body() throws Exception { |
| byte[] blobData = generateData(25000, DataType.TEXT); // file size = 25000 bytes |
| |
| final MockResponse resp = buildResponse(HTTP_OK, blobData); |
| resp.setHeader("Content-Length", "50000"); |
| enqueueResponse(resp); |
| |
| long dlRequest = doCommonStandardEnqueue(); |
| waitForDownloadOrTimeout(dlRequest); |
| |
| Cursor cursor = getCursor(dlRequest); |
| try { |
| verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED); |
| verifyInt(cursor, DownloadManager.COLUMN_REASON, |
| DownloadManager.ERROR_CANNOT_RESUME); |
| } finally { |
| cursor.close(); |
| } |
| // Even tho the server drops the connection, we should still get a completed notification |
| assertEquals(1, mReceiver.numDownloadsCompleted()); |
| } |
| } |