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.os.StatFs; 26 import android.util.Log; 27 28 import androidx.test.filters.LargeTest; 29 import androidx.test.filters.Suppress; 30 31 import java.io.File; 32 import java.io.FileOutputStream; 33 import java.io.IOException; 34 import java.util.Random; 35 36 /** 37 * Integration tests of the DownloadManager API. 38 */ 39 @Suppress // Failing. 40 public class DownloadManagerStressTest extends DownloadManagerBaseTest { 41 private static final String TAG = "DownloadManagerStressTest"; 42 private final static String CACHE_DIR = 43 Environment.getDownloadCacheDirectory().getAbsolutePath(); 44 45 /** 46 * {@inheritDoc} 47 */ 48 @Override setUp()49 public void setUp() throws Exception { 50 super.setUp(); 51 setWiFiStateOn(true); 52 removeAllCurrentDownloads(); 53 } 54 55 /** 56 * {@inheritDoc} 57 */ 58 @Override tearDown()59 public void tearDown() throws Exception { 60 super.tearDown(); 61 setWiFiStateOn(true); 62 removeAllCurrentDownloads(); 63 64 if (mReceiver != null) { 65 mContext.unregisterReceiver(mReceiver); 66 mReceiver = null; 67 } 68 } 69 70 /** 71 * Attempts to download several files simultaneously 72 */ 73 @LargeTest testMultipleDownloads()74 public void testMultipleDownloads() throws Exception { 75 // need to be sure all current downloads have stopped first 76 removeAllCurrentDownloads(); 77 int NUM_FILES = 10; 78 int MAX_FILE_SIZE = 10 * 1024; // 10 kb 79 80 Random r = new LoggingRng(); 81 for (int i=0; i<NUM_FILES; ++i) { 82 int size = r.nextInt(MAX_FILE_SIZE); 83 byte[] blobData = generateData(size, DataType.TEXT); 84 85 Uri uri = getServerUri(DEFAULT_FILENAME + i); 86 Request request = new Request(uri); 87 request.setTitle(String.format("%s--%d", DEFAULT_FILENAME + i, i)); 88 89 // Prepare the mock server with a standard response 90 enqueueResponse(buildResponse(HTTP_OK, blobData)); 91 92 long requestID = mDownloadManager.enqueue(request); 93 } 94 95 waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME); 96 Cursor cursor = mDownloadManager.query(new Query()); 97 try { 98 assertEquals(NUM_FILES, cursor.getCount()); 99 100 if (cursor.moveToFirst()) { 101 do { 102 int status = cursor.getInt(cursor.getColumnIndex( 103 DownloadManager.COLUMN_STATUS)); 104 String filename = cursor.getString(cursor.getColumnIndex( 105 DownloadManager.COLUMN_URI)); 106 String errorString = String.format( 107 "File %s failed to download successfully. Status code: %d", 108 filename, status); 109 assertEquals(errorString, DownloadManager.STATUS_SUCCESSFUL, status); 110 } while (cursor.moveToNext()); 111 } 112 113 assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted()); 114 } finally { 115 cursor.close(); 116 } 117 } 118 /** 119 * Tests trying to download a large file (50M bytes). 120 */ 121 @LargeTest testDownloadLargeFile()122 public void testDownloadLargeFile() throws Exception { 123 long fileSize = 50000000L; // note: kept relatively small to not exceed /cache dir size 124 Log.i(TAG, "creating a file of size: " + fileSize); 125 File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null); 126 Log.i(TAG, "DONE creating a file of size: " + fileSize); 127 MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver(); 128 129 try { 130 long dlRequest = doStandardEnqueue(largeFile); 131 132 // wait for the download to complete 133 waitForDownloadOrTimeout(dlRequest); 134 135 ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest); 136 verifyFileContents(pfd, largeFile); 137 verifyFileSize(pfd, largeFile.length()); 138 139 assertEquals(1, receiver.numDownloadsCompleted()); 140 mContext.unregisterReceiver(receiver); 141 } catch (Exception e) { 142 throw e; 143 } finally { 144 largeFile.delete(); 145 } 146 } 147 148 149 /** 150 * Tests downloading a file to system cache when there isn't enough space in the system cache 151 * to hold the entire file. DownloadManager deletes enough files to make space for the 152 * new download. 153 */ 154 @LargeTest testDownloadToCacheWithAlmostFullCache()155 public void testDownloadToCacheWithAlmostFullCache() throws Exception { 156 int DOWNLOAD_FILE_SIZE = 1024 * 1024; // 1MB 157 158 StatFs fs = new StatFs(CACHE_DIR); 159 int blockSize = fs.getBlockSize(); 160 int availableBlocks = fs.getAvailableBlocks(); 161 int availableBytes = blockSize * availableBlocks; 162 Log.i(TAG, "INITIAL stage, available space in /cache: " + availableBytes); 163 File outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR)); 164 byte[] buffer = new byte[blockSize]; 165 166 try { 167 // fill cache to ensure we don't have enough space - take half the size of the 168 // download size, and leave that much freespace left on the cache partition 169 if (DOWNLOAD_FILE_SIZE <= availableBytes) { 170 int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2); 171 172 int writeSizeBlocks = writeSizeBytes / blockSize; 173 int remainderSizeBlocks = availableBlocks - writeSizeBlocks; 174 175 FileOutputStream fo = null; 176 try { 177 fo = new FileOutputStream(outFile); 178 while (fs.getAvailableBlocks() >= remainderSizeBlocks) { 179 fo.write(buffer); 180 fs.restat(CACHE_DIR); 181 } 182 } catch (IOException e) { 183 Log.e(LOG_TAG, "error filling file: ", e); 184 throw e; 185 } finally { 186 if (fo != null) { 187 fo.close(); 188 } 189 } 190 } 191 192 // /cache should now be almost full. 193 long spaceAvailable = fs.getAvailableBlocks() * blockSize; 194 Log.i(TAG, "BEFORE download, available space in /cache: " + spaceAvailable); 195 assertTrue(DOWNLOAD_FILE_SIZE > spaceAvailable); 196 197 // try to download 1MB file into /cache - and it should succeed 198 byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT); 199 long dlRequest = doBasicDownload(blobData); 200 verifyAndCleanupSingleFileDownload(dlRequest, blobData); 201 } finally { 202 if (outFile != null) { 203 outFile.delete(); 204 } 205 } 206 } 207 } 208