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