/* * 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.os.StatFs; import android.test.suitebuilder.annotation.LargeTest; import android.util.Log; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Random; /** * Integration tests of the DownloadManager API. */ public class DownloadManagerStressTest extends DownloadManagerBaseTest { private static final String TAG = "DownloadManagerStressTest"; private final static String CACHE_DIR = Environment.getDownloadCacheDirectory().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; } } /** * Attempts to download several files simultaneously */ @LargeTest public void testMultipleDownloads() throws Exception { // need to be sure all current downloads have stopped first removeAllCurrentDownloads(); int NUM_FILES = 10; int MAX_FILE_SIZE = 10 * 1024; // 10 kb Random r = new LoggingRng(); for (int i=0; i<NUM_FILES; ++i) { int size = r.nextInt(MAX_FILE_SIZE); byte[] blobData = generateData(size, DataType.TEXT); Uri uri = getServerUri(DEFAULT_FILENAME + i); Request request = new Request(uri); request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i)); // Prepare the mock server with a standard response enqueueResponse(buildResponse(HTTP_OK, blobData)); long requestID = mDownloadManager.enqueue(request); } waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME); Cursor cursor = mDownloadManager.query(new Query()); try { assertEquals(NUM_FILES, cursor.getCount()); if (cursor.moveToFirst()) { do { int status = cursor.getInt(cursor.getColumnIndex( DownloadManager.COLUMN_STATUS)); String filename = cursor.getString(cursor.getColumnIndex( DownloadManager.COLUMN_URI)); String errorString = String.format( "File %s failed to download successfully. Status code: %d", filename, status); assertEquals(errorString, DownloadManager.STATUS_SUCCESSFUL, status); } while (cursor.moveToNext()); } assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted()); } finally { cursor.close(); } } /** * Tests trying to download a large file (50M bytes). */ @LargeTest public void testDownloadLargeFile() throws Exception { long fileSize = 50000000L; // note: kept relatively small to not exceed /cache dir size Log.i(TAG, "creating a file of size: " + fileSize); File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null); Log.i(TAG, "DONE creating a file of size: " + fileSize); MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver(); try { long dlRequest = doStandardEnqueue(largeFile); // wait for the download to complete waitForDownloadOrTimeout(dlRequest); ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest); verifyFileContents(pfd, largeFile); verifyFileSize(pfd, largeFile.length()); assertEquals(1, receiver.numDownloadsCompleted()); mContext.unregisterReceiver(receiver); } catch (Exception e) { throw e; } finally { largeFile.delete(); } } /** * Tests downloading a file to system cache when there isn't enough space in the system cache * to hold the entire file. DownloadManager deletes enough files to make space for the * new download. */ @LargeTest public void testDownloadToCacheWithAlmostFullCache() throws Exception { int DOWNLOAD_FILE_SIZE = 1024 * 1024; // 1MB StatFs fs = new StatFs(CACHE_DIR); int blockSize = fs.getBlockSize(); int availableBlocks = fs.getAvailableBlocks(); int availableBytes = blockSize * availableBlocks; Log.i(TAG, "INITIAL stage, available space in /cache: " + availableBytes); File outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR)); byte[] buffer = new byte[blockSize]; try { // fill cache to ensure we don't have enough space - take half the size of the // download size, and leave that much freespace left on the cache partition if (DOWNLOAD_FILE_SIZE <= availableBytes) { int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2); int writeSizeBlocks = writeSizeBytes / blockSize; int remainderSizeBlocks = availableBlocks - writeSizeBlocks; FileOutputStream fo = null; try { fo = new FileOutputStream(outFile); while (fs.getAvailableBlocks() >= remainderSizeBlocks) { fo.write(buffer); fs.restat(CACHE_DIR); } } catch (IOException e) { Log.e(LOG_TAG, "error filling file: ", e); throw e; } finally { if (fo != null) { fo.close(); } } } // /cache should now be almost full. long spaceAvailable = fs.getAvailableBlocks() * blockSize; Log.i(TAG, "BEFORE download, available space in /cache: " + spaceAvailable); assertTrue(DOWNLOAD_FILE_SIZE > spaceAvailable); // try to download 1MB file into /cache - and it should succeed byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT); long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE); verifyAndCleanupSingleFileDownload(dlRequest, blobData); } finally { if (outFile != null) { outFile.delete(); } } } }