diff options
Diffstat (limited to 'core/tests')
-rw-r--r-- | core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java | 2 | ||||
-rw-r--r-- | core/tests/coretests/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | core/tests/coretests/src/android/app/DownloadManagerBaseTest.java | 77 | ||||
-rw-r--r-- | core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java (renamed from core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java) | 440 | ||||
-rw-r--r-- | core/tests/coretests/src/android/app/DownloadManagerStressTest.java | 53 | ||||
-rw-r--r-- | core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk | 3 | ||||
-rw-r--r-- | core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java | 816 | ||||
-rw-r--r-- | core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java | 1 |
8 files changed, 1115 insertions, 280 deletions
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java index 6717bda..e0a3ee6 100644 --- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java +++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java @@ -77,7 +77,7 @@ public class WifiClientTest extends AndroidTestCase { List<WifiConfiguration> configList = mWifiManager.getConfiguredNetworks(); boolean found = false; for (WifiConfiguration c : configList) { - if (c.networkId == netId) { + if (c.networkId == netId && c.SSID.equals(config.SSID)) { found = true; } } diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml index b1e38ee..f2857fa 100644 --- a/core/tests/coretests/AndroidManifest.xml +++ b/core/tests/coretests/AndroidManifest.xml @@ -36,6 +36,9 @@ android:description="@string/permdesc_testDenied" /> <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" /> + <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> + <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" /> + <uses-permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> diff --git a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java index 8df37ad..1bb2a57 100644 --- a/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java +++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java @@ -16,8 +16,12 @@ package android.app; +import coretestutils.http.MockResponse; +import coretestutils.http.MockWebServer; + import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; +import android.app.DownloadManagerBaseTest.DataType; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -27,11 +31,10 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.net.wifi.WifiManager; -import android.os.Bundle; import android.os.Environment; import android.os.ParcelFileDescriptor; -import android.os.SystemClock; import android.os.ParcelFileDescriptor.AutoCloseInputStream; +import android.os.SystemClock; import android.provider.Settings; import android.test.InstrumentationTestCase; import android.util.Log; @@ -43,19 +46,12 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; -import java.util.concurrent.TimeoutException; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; -import java.util.List; import java.util.Random; import java.util.Set; -import java.util.Vector; - -import junit.framework.AssertionFailedError; - -import coretestutils.http.MockResponse; -import coretestutils.http.MockWebServer; +import java.util.concurrent.TimeoutException; /** * Base class for Instrumented tests for the Download Manager. @@ -67,7 +63,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { protected String mFileType = "text/plain"; protected Context mContext = null; protected MultipleDownloadsCompletedReceiver mReceiver = null; - protected static final int DEFAULT_FILE_SIZE = 130 * 1024; // 130kb + protected static final int DEFAULT_FILE_SIZE = 10 * 1024; // 10kb protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024; protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest"; @@ -85,6 +81,9 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes + protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1; + protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2; + // Just a few popular file types used to return from a download protected enum DownloadFileType { PLAINTEXT, @@ -888,30 +887,46 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { */ protected void removeAllCurrentDownloads() { Log.i(LOG_TAG, "Removing all current registered downloads..."); + ArrayList<Long> ids = new ArrayList<Long>(); Cursor cursor = mDownloadManager.query(new Query()); try { if (cursor.moveToFirst()) { do { int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID); long downloadId = cursor.getLong(index); - - mDownloadManager.remove(downloadId); + ids.add(downloadId); } while (cursor.moveToNext()); } } finally { cursor.close(); } + // delete all ids + for (long id : ids) { + mDownloadManager.remove(id); + } + // make sure the database is empty + cursor = mDownloadManager.query(new Query()); + try { + assertEquals(0, cursor.getCount()); + } finally { + cursor.close(); + } } /** * Helper to perform a standard enqueue of data to the mock server. + * download is performed to the downloads cache dir (NOT systemcache dir) * * @param body The body to return in the response from the server */ protected long doStandardEnqueue(byte[] body) throws Exception { + return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); + } + + protected long enqueueDownloadRequest(byte[] body, int location) throws Exception { // Prepare the mock server with a standard response enqueueResponse(HTTP_OK, body); - return doCommonStandardEnqueue(); + return doEnqueue(location); } /** @@ -920,9 +935,13 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { * @param body The body to return in the response from the server, contained in the file */ protected long doStandardEnqueue(File body) throws Exception { + return enqueueDownloadRequest(body, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); + } + + protected long enqueueDownloadRequest(File body, int location) throws Exception { // Prepare the mock server with a standard response enqueueResponse(HTTP_OK, body); - return doCommonStandardEnqueue(); + return doEnqueue(location); } /** @@ -930,13 +949,17 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { * doing a standard enqueue request to the server. */ protected long doCommonStandardEnqueue() throws Exception { + return doEnqueue(DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); + } + + private long doEnqueue(int location) throws Exception { Uri uri = getServerUri(DEFAULT_FILENAME); - Request request = new Request(uri); - request.setTitle(DEFAULT_FILENAME); + Request request = new Request(uri).setTitle(DEFAULT_FILENAME); + if (location == DOWNLOAD_TO_SYSTEM_CACHE) { + request.setDestinationToSystemCache(); + } - long dlRequest = mDownloadManager.enqueue(request); - Log.i(LOG_TAG, "request ID: " + dlRequest); - return dlRequest; + return mDownloadManager.enqueue(request); } /** @@ -997,4 +1020,16 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase { return cursor; } + /** + * Helper that does the actual basic download verification. + */ + protected long doBasicDownload(byte[] blobData, int location) throws Exception { + long dlRequest = enqueueDownloadRequest(blobData, location); + + // wait for the download to complete + waitForDownloadOrTimeout(dlRequest); + + assertEquals(1, mReceiver.numDownloadsCompleted()); + return dlRequest; + } }
\ No newline at end of file diff --git a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java index 4f79108..06f3ba4 100644 --- a/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java +++ b/core/tests/coretests/src/android/app/DownloadManagerFunctionalTest.java @@ -16,51 +16,35 @@ package android.app; +import coretestutils.http.MockResponse; + import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; import android.app.DownloadManagerBaseTest.DataType; -import android.app.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; -import android.net.wifi.WifiManager; import android.os.Environment; import android.os.ParcelFileDescriptor; import android.os.StatFs; -import android.os.SystemClock; -import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.LargeTest; -import android.test.suitebuilder.annotation.MediumTest; -import android.test.suitebuilder.annotation.SmallTest; import android.util.Log; import java.io.File; import java.io.FileOutputStream; -import java.io.FileWriter; import java.io.IOException; -import java.net.URL; import java.util.Iterator; import java.util.Random; import java.util.Set; -import junit.framework.AssertionFailedError; - -import coretestutils.http.MockResponse; -import coretestutils.http.MockWebServer; - /** * Integration tests of the DownloadManager API. */ -public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { - - private final static String LOG_TAG = "android.net.DownloadManagerIntegrationTest"; - private final static String PROHIBITED_DIRECTORY = - Environment.getRootDirectory().getAbsolutePath(); +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} @@ -89,26 +73,12 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { } /** - * Helper that does the actual basic download verification. - */ - protected long doBasicDownload(byte[] blobData) throws Exception { - long dlRequest = doStandardEnqueue(blobData); - - // wait for the download to complete - waitForDownloadOrTimeout(dlRequest); - - assertEquals(1, mReceiver.numDownloadsCompleted()); - return dlRequest; - } - - /** * 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 an Exception if the test fails + * @throws Exception if the test fails */ - @LargeTest public void doErrorTest(Uri uri, int error) throws Exception { Request request = new Request(uri); request.setTitle(DEFAULT_FILENAME); @@ -128,66 +98,57 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { * Test a basic download of a binary file 500k in size. */ @LargeTest - public void testBasicBinaryDownload() throws Exception { - int fileSize = 500 * 1024; // 500k + public void testBinaryDownloadToSystemCache() throws Exception { + int fileSize = 1024; byte[] blobData = generateData(fileSize, DataType.BINARY); - long dlRequest = doBasicDownload(blobData); - verifyAndCleanupSingleFileDownload(dlRequest, blobData); + 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 testBasicTextDownload() throws Exception { - int fileSize = 300000; + public void testTextDownloadToSystemCache() throws Exception { + int fileSize = 1024; byte[] blobData = generateData(fileSize, DataType.TEXT); - long dlRequest = doBasicDownload(blobData); - verifyAndCleanupSingleFileDownload(dlRequest, blobData); + long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE); + verifyDownload(dlRequest, blobData); + mDownloadManager.remove(dlRequest); } - + /** - * Tests when the server drops the connection after all headers (but before any data send). - */ - @LargeTest - public void testDropConnection_headers() throws Exception { - byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); - - MockResponse response = enqueueResponse(HTTP_OK, blobData); - response.setCloseConnectionAfterHeader("content-length"); - long dlRequest = doCommonStandardEnqueue(); - - // Download will never complete when header is dropped - boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest, DEFAULT_WAIT_POLL_TIME, - DEFAULT_MAX_WAIT_TIME); - - assertFalse(success); - } - - /** - * Tests that we get an error code when the server drops the connection during a download. + * 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 */ - @LargeTest - public void testServerDropConnection_body() throws Exception { - byte[] blobData = generateData(25000, DataType.TEXT); // file size = 25000 bytes + 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()); - MockResponse response = enqueueResponse(HTTP_OK, blobData); - response.setCloseConnectionAfterXBytes(15382); - long dlRequest = doCommonStandardEnqueue(); - waitForDownloadOrTimeout(dlRequest); + mServer.checkForExceptions(); - Cursor cursor = getCursor(dlRequest); - try { - verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED); - verifyInt(cursor, DownloadManager.COLUMN_REASON, - DownloadManager.ERROR_CANNOT_RESUME); + verifyFileSize(pfd, fileSize); + verifyFileContents(pfd, fileData); + int colIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME); + String fileName = cursor.getString(colIndex); + assertTrue(fileName.startsWith(CACHE_DIR)); } finally { + pfd.close(); cursor.close(); } - // Even tho the server drops the connection, we should still get a completed notification - assertEquals(1, mReceiver.numDownloadsCompleted()); } /** @@ -198,7 +159,7 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { // need to be sure all current downloads have stopped first removeAllCurrentDownloads(); int NUM_FILES = 10; - int MAX_FILE_SIZE = 500 * 1024; // 500 kb + int MAX_FILE_SIZE = 10 * 1024; // 10 kb Random r = new LoggingRng(); for (int i=0; i<NUM_FILES; ++i) { @@ -213,7 +174,6 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { enqueueResponse(HTTP_OK, blobData); long requestID = mDownloadManager.enqueue(request); - Log.i(LOG_TAG, "request: " + i + " -- requestID: " + requestID); } waitForDownloadsOrTimeout(WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME); @@ -236,8 +196,6 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { assertEquals(NUM_FILES, mReceiver.numDownloadsCompleted()); } finally { - Log.i(LOG_TAG, "All download IDs: " + mReceiver.getDownloadIds().toString()); - Log.i(LOG_TAG, "Total downloads completed: " + mReceiver.getDownloadIds().size()); cursor.close(); } } @@ -258,7 +216,6 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { Request request = new Request(uri); Uri localUri = Uri.fromFile(existentFile); - Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath()); request.setDestinationUri(localUri); long dlRequest = mDownloadManager.enqueue(request); @@ -268,9 +225,7 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { Cursor cursor = getCursor(dlRequest); try { - verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED); - verifyInt(cursor, DownloadManager.COLUMN_REASON, - DownloadManager.ERROR_FILE_ALREADY_EXISTS); + verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_SUCCESSFUL); } finally { cursor.close(); } @@ -299,7 +254,6 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { Request request = new Request(uri); Uri localUri = Uri.fromFile(downloadedFile); - Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath()); request.setDestinationUri(localUri); long dlRequest = mDownloadManager.enqueue(request); @@ -331,7 +285,6 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { Request request = new Request(uri); Uri localUri = Uri.fromFile(downloadedFile); - Log.i(LOG_TAG, "setting localUri to: " + localUri.getPath()); request.setDestinationUri(localUri); try { @@ -347,13 +300,117 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { } /** + * 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 + + MockResponse response = enqueueResponse(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) { + MockResponse response = enqueueResponse(HTTP_REDIRECT); + response.addHeader("Location", uri.toString()); + } + 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); + MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT); + + doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE); + } + + /** + * Tests the download failure error from an unhandled HTTP status code + */ + @LargeTest + public void testErrorHttpDataError_invalidRedirect() throws Exception { + Uri uri = getServerUri(DEFAULT_FILENAME); + MockResponse response = enqueueResponse(HTTP_REDIRECT); + response.addHeader("Location", "://blah.blah.blah.com"); + + doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR); + } + + /** + * 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); + MockResponse response = enqueueResponse(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 = 140 * 1024; // 140k + int fileSize = 1024; // 140k byte[] blobData = generateData(fileSize, DataType.TEXT); setWiFiStateOn(false); @@ -381,21 +438,63 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { } /** - * Tests downloading a file to cache when there isn't enough space in the cache to hold the - * entire file. + * Tests when the server drops the connection after all headers (but before any data send). */ @LargeTest - public void testDownloadToCache_whenFull() throws Exception { - int DOWNLOAD_FILE_SIZE = 500000; + public void testDropConnection_headers() throws Exception { + byte[] blobData = generateData(DEFAULT_FILE_SIZE, DataType.TEXT); - StatFs fs = new StatFs(CACHE_DIR); - Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks()); - Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize()); + MockResponse response = enqueueResponse(HTTP_OK, blobData); + response.setCloseConnectionAfterHeader("content-length"); + long dlRequest = doCommonStandardEnqueue(); + + // Download will never complete when header is dropped + boolean success = waitForDownloadOrTimeoutNoThrow(dlRequest, DEFAULT_WAIT_POLL_TIME, + DEFAULT_MAX_WAIT_TIME); + + assertFalse(success); + } + + /** + * 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 + + MockResponse response = enqueueResponse(HTTP_OK, blobData); + response.setCloseConnectionAfterXBytes(15382); + 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()); + } + + /** + * 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; - File outFile = null; + 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 @@ -408,13 +507,7 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { FileOutputStream fo = null; try { - outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR)); - Log.v(LOG_TAG, "writing " + writeSizeBlocks + " blocks to file " - + outFile.getAbsolutePath()); - fo = new FileOutputStream(outFile); - - byte[] buffer = new byte[blockSize]; while (fs.getAvailableBlocks() >= remainderSizeBlocks) { fo.write(buffer); fs.restat(CACHE_DIR); @@ -429,12 +522,15 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { } } - Log.i(LOG_TAG, "Done creating filler file."); - assertTrue(DOWNLOAD_FILE_SIZE > (fs.getAvailableBlocks() * blockSize)); + // /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); + long dlRequest = doBasicDownload(blobData, DOWNLOAD_TO_SYSTEM_CACHE); verifyAndCleanupSingleFileDownload(dlRequest, blobData); - } finally { if (outFile != null) { outFile.delete(); @@ -447,31 +543,29 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { * run out of space. */ @LargeTest - public void testDownloadCacheNonPurgeable() throws Exception { - int fileSize = 10000000; + public void testDownloadToCacheNonPurgeableWithFullCache() throws Exception { + int fileSize = 1024 * 1024; // 1MB byte[] blobData = generateData(fileSize, DataType.BINARY); long dlRequest = -1; - // Fill up the cache partition until there's not enough room for another download. - // Note that we need to initiate a download first, then check for the available space. This - // is b/c there could be some files that are still left in the cache that can (and will be) - // cleared out, but not until DM gets a request for a download and reclaims that - // space first. + // Fill up the cache partition with DOWNLOAD_CACHE_NON_PURGEABLE downloads + // until 500KB is left. boolean spaceAvailable = true; while (spaceAvailable) { - dlRequest = doStandardEnqueue(blobData); + // since this tests package has android.permission.DOWNLOAD_CACHE_NON_PURGEABLE + // permission, downloads are automatically set to be DOWNLOAD_CACHE_NON_PURGEABLE + dlRequest = enqueueDownloadRequest(blobData, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); waitForDownloadOrTimeout(dlRequest); // Check if we've filled up the cache yet - StatFs fs = new StatFs(CACHE_DIR); - Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks()); - Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize()); + StatFs fs = new StatFs(Environment.getDownloadCacheDirectory().getAbsolutePath()); int availableBytes = fs.getBlockSize() * fs.getAvailableBlocks(); + Log.i(TAG, "available space in /cache: " + availableBytes); spaceAvailable = (availableBytes > fileSize) ? true : false; } - // Now add one more download (should not fit in the space left over) - dlRequest = doStandardEnqueue(blobData); + // Now add one more 1MB download (should not fit in the space left over) + dlRequest = enqueueDownloadRequest(blobData, DOWNLOAD_TO_DOWNLOAD_CACHE_DIR); waitForDownloadOrTimeout(dlRequest); // For the last download we should have failed b/c there is not enough space left in cache @@ -483,108 +577,4 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest { cursor.close(); } } - - /** - * 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 - - MockResponse response = enqueueResponse(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) { - MockResponse response = enqueueResponse(HTTP_REDIRECT); - response.addHeader("Location", uri.toString()); - } - 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); - MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT); - - doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE); - } - - /** - * Tests the download failure error from an unhandled HTTP status code - */ - @LargeTest - public void testErrorHttpDataError_invalidRedirect() throws Exception { - Uri uri = getServerUri(DEFAULT_FILENAME); - MockResponse response = enqueueResponse(HTTP_REDIRECT); - response.addHeader("Location", "://blah.blah.blah.com"); - - doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR); - } - - /** - * Tests that we can remove a download from the download manager. - */ - @LargeTest - public void testRemoveDownload() throws Exception { - int fileSize = 100 * 1024; // 100k - byte[] blobData = generateData(fileSize, DataType.BINARY); - - long dlRequest = doBasicDownload(blobData); - 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 = 50 * 1024; // 50k - byte[] blobData = generateData(fileSize, DataType.BINARY); - MockResponse response = enqueueResponse(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(); - } - } } diff --git a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java index e0b28d0..18b279f 100644 --- a/core/tests/coretests/src/android/app/DownloadManagerStressTest.java +++ b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java @@ -16,19 +16,21 @@ package android.app; -import java.io.File; -import java.util.Random; import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; import android.database.Cursor; import android.net.Uri; import android.os.ParcelFileDescriptor; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.Suppress; import android.util.Log; +import java.io.File; +import java.util.Random; + public class DownloadManagerStressTest extends DownloadManagerBaseTest { - private static String LOG_TAG = "android.net.DownloadManagerStressTest"; /** * {@inheritDoc} @@ -42,8 +44,25 @@ public class DownloadManagerStressTest extends DownloadManagerBaseTest { } /** + * {@inheritDoc} + */ + @Override + public void tearDown() throws Exception { + super.tearDown(); + setWiFiStateOn(true); + removeAllCurrentDownloads(); + + if (mReceiver != null) { + mContext.unregisterReceiver(mReceiver); + mReceiver = null; + } + } + + /** * Attempts to downloading thousands of files simultaneously + * don't run this test - downloadmanager needs to allow only a few simultaneous downloads. */ + @Suppress public void testDownloadThousands() throws Exception { int NUM_FILES = 1500; int MAX_FILE_SIZE = 3000; @@ -106,6 +125,7 @@ public class DownloadManagerStressTest extends DownloadManagerBaseTest { /** * 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 File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null); @@ -129,31 +149,4 @@ public class DownloadManagerStressTest extends DownloadManagerBaseTest { largeFile.delete(); } } - - /** - * Tests trying to download a large file (~600M bytes) when there's not enough space in cache - */ - public void testInsufficientSpace() throws Exception { - // @TODO: Rework this to fill up cache partition with a dynamically calculated size - long fileSize = 600000000L; - File largeFile = createFileOnSD(null, fileSize, DataType.TEXT, null); - - Cursor cursor = null; - try { - long dlRequest = doStandardEnqueue(largeFile); - - // wait for the download to complete - waitForDownloadOrTimeout(dlRequest); - - cursor = getCursor(dlRequest); - verifyInt(cursor, DownloadManager.COLUMN_STATUS, DownloadManager.STATUS_FAILED); - verifyInt(cursor, DownloadManager.COLUMN_REASON, - DownloadManager.ERROR_INSUFFICIENT_SPACE); - } finally { - if (cursor != null) { - cursor.close(); - } - largeFile.delete(); - } - } } diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk index 7206f4a..a419068 100644 --- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk @@ -18,8 +18,7 @@ include $(CLEAR_VARS) LOCAL_MODULE_TAGS := tests -LOCAL_SRC_FILES := $(call all-java-files-under, src) \ - ../../../coretests/src/android/app/DownloadManagerBaseTest.java +LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib LOCAL_SDK_VERSION := current diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java new file mode 100644 index 0000000..acd2a18 --- /dev/null +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java @@ -0,0 +1,816 @@ +/* + * 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 com.android.frameworks.downloadmanagertests; + +import android.app.DownloadManager; +import android.app.DownloadManager.Query; +import android.app.DownloadManager.Request; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.database.Cursor; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.net.Uri; +import android.net.wifi.WifiManager; +import android.os.Bundle; +import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.os.SystemClock; +import android.os.ParcelFileDescriptor.AutoCloseInputStream; +import android.provider.Settings; +import android.test.InstrumentationTestCase; +import android.util.Log; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.concurrent.TimeoutException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Random; +import java.util.Set; +import java.util.Vector; + +import junit.framework.AssertionFailedError; + +import coretestutils.http.MockResponse; +import coretestutils.http.MockWebServer; + +/** + * Base class for Instrumented tests for the Download Manager. + */ +public class DownloadManagerBaseTest extends InstrumentationTestCase { + + protected DownloadManager mDownloadManager = null; + protected MockWebServer mServer = null; + protected String mFileType = "text/plain"; + protected Context mContext = null; + protected MultipleDownloadsCompletedReceiver mReceiver = null; + protected static final int DEFAULT_FILE_SIZE = 10 * 1024; // 10kb + protected static final int FILE_BLOCK_READ_SIZE = 1024 * 1024; + + protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest"; + protected static final int HTTP_OK = 200; + protected static final int HTTP_REDIRECT = 307; + protected static final int HTTP_PARTIAL_CONTENT = 206; + protected static final int HTTP_NOT_FOUND = 404; + protected static final int HTTP_SERVICE_UNAVAILABLE = 503; + protected String DEFAULT_FILENAME = "somefile.txt"; + + protected static final int DEFAULT_MAX_WAIT_TIME = 2 * 60 * 1000; // 2 minutes + protected static final int DEFAULT_WAIT_POLL_TIME = 5 * 1000; // 5 seconds + + protected static final int WAIT_FOR_DOWNLOAD_POLL_TIME = 1 * 1000; // 1 second + protected static final int MAX_WAIT_FOR_DOWNLOAD_TIME = 5 * 60 * 1000; // 5 minutes + protected static final int MAX_WAIT_FOR_LARGE_DOWNLOAD_TIME = 15 * 60 * 1000; // 15 minutes + + protected static final int DOWNLOAD_TO_SYSTEM_CACHE = 1; + protected static final int DOWNLOAD_TO_DOWNLOAD_CACHE_DIR = 2; + + // Just a few popular file types used to return from a download + protected enum DownloadFileType { + PLAINTEXT, + APK, + GIF, + GARBAGE, + UNRECOGNIZED, + ZIP + } + + protected enum DataType { + TEXT, + BINARY + } + + public static class LoggingRng extends Random { + + /** + * Constructor + * + * Creates RNG with self-generated seed value. + */ + public LoggingRng() { + this(SystemClock.uptimeMillis()); + } + + /** + * Constructor + * + * Creats RNG with given initial seed value + + * @param seed The initial seed value + */ + public LoggingRng(long seed) { + super(seed); + Log.i(LOG_TAG, "Seeding RNG with value: " + seed); + } + } + + public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver { + private volatile int mNumDownloadsCompleted = 0; + private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>()); + + /** + * {@inheritDoc} + */ + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equalsIgnoreCase(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) { + synchronized(this) { + long id = intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID); + Log.i(LOG_TAG, "Received Notification for download: " + id); + if (!downloadIds.contains(id)) { + ++mNumDownloadsCompleted; + Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " + + intent.getAction() + " --> total count: " + mNumDownloadsCompleted); + downloadIds.add(id); + + DownloadManager dm = (DownloadManager)context.getSystemService( + Context.DOWNLOAD_SERVICE); + + Cursor cursor = dm.query(new Query().setFilterById(id)); + try { + if (cursor.moveToFirst()) { + int status = cursor.getInt(cursor.getColumnIndex( + DownloadManager.COLUMN_STATUS)); + Log.i(LOG_TAG, "Download status is: " + status); + } else { + fail("No status found for completed download!"); + } + } finally { + cursor.close(); + } + } else { + Log.i(LOG_TAG, "Notification for id: " + id + " has already been made."); + } + } + } + } + + /** + * Gets the number of times the {@link #onReceive} callback has been called for the + * {@link DownloadManager.ACTION_DOWNLOAD_COMPLETED} action, indicating the number of + * downloads completed thus far. + * + * @return the number of downloads completed so far. + */ + public int numDownloadsCompleted() { + return mNumDownloadsCompleted; + } + + /** + * Gets the list of download IDs. + * @return A Set<Long> with the ids of the completed downloads. + */ + public Set<Long> getDownloadIds() { + synchronized(this) { + Set<Long> returnIds = new HashSet<Long>(downloadIds); + return returnIds; + } + } + + } + + public static class WiFiChangedReceiver extends BroadcastReceiver { + private Context mContext = null; + + /** + * Constructor + * + * Sets the current state of WiFi. + * + * @param context The current app {@link Context}. + */ + public WiFiChangedReceiver(Context context) { + mContext = context; + } + + /** + * {@inheritDoc} + */ + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equalsIgnoreCase(ConnectivityManager.CONNECTIVITY_ACTION)) { + Log.i(LOG_TAG, "ConnectivityManager state change: " + intent.getAction()); + synchronized (this) { + this.notify(); + } + } + } + + /** + * Gets the current state of WiFi. + * + * @return Returns true if WiFi is on, false otherwise. + */ + public boolean getWiFiIsOn() { + ConnectivityManager connManager = (ConnectivityManager)mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + NetworkInfo info = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI); + Log.i(LOG_TAG, "WiFi Connection state is currently: " + info.isConnected()); + return info.isConnected(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void setUp() throws Exception { + mContext = getInstrumentation().getContext(); + mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE); + mServer = new MockWebServer(); + mReceiver = registerNewMultipleDownloadsReceiver(); + // Note: callers overriding this should call mServer.play() with the desired port # + } + + /** + * Helper to enqueue a response from the MockWebServer. + * + * @param status The HTTP status code to return for this response + * @param body The body to return in this response + * @return Returns the mock web server response that was queued (which can be modified) + */ + private MockResponse enqueueResponse(int status, byte[] body) { + return doEnqueueResponse(status).setBody(body); + + } + + /** + * Helper to enqueue a response from the MockWebServer. + * + * @param status The HTTP status code to return for this response + * @param bodyFile The body to return in this response + * @return Returns the mock web server response that was queued (which can be modified) + */ + private MockResponse enqueueResponse(int status, File bodyFile) { + return doEnqueueResponse(status).setBody(bodyFile); + } + + /** + * Helper for enqueue'ing a response from the MockWebServer. + * + * @param status The HTTP status code to return for this response + * @return Returns the mock web server response that was queued (which can be modified) + */ + private MockResponse doEnqueueResponse(int status) { + MockResponse response = new MockResponse().setResponseCode(status); + response.addHeader("Content-type", mFileType); + mServer.enqueue(response); + return response; + } + + /** + * Helper to generate a random blob of bytes using a given RNG. + * + * @param size The size of the data to generate + * @param type The type of data to generate: currently, one of {@link DataType.TEXT} or + * {@link DataType.BINARY}. + * @param rng (optional) The RNG to use; pass null to use + * @return The random data that is generated. + */ + private byte[] generateData(int size, DataType type, Random rng) { + int min = Byte.MIN_VALUE; + int max = Byte.MAX_VALUE; + + // Only use chars in the HTTP ASCII printable character range for Text + if (type == DataType.TEXT) { + min = 32; + max = 126; + } + byte[] result = new byte[size]; + Log.i(LOG_TAG, "Generating data of size: " + size); + + if (rng == null) { + rng = new LoggingRng(); + } + + for (int i = 0; i < size; ++i) { + result[i] = (byte) (min + rng.nextInt(max - min + 1)); + } + return result; + } + + /** + * Helper to verify the size of a file. + * + * @param pfd The input file to compare the size of + * @param size The expected size of the file + */ + protected void verifyFileSize(ParcelFileDescriptor pfd, long size) { + assertEquals(pfd.getStatSize(), size); + } + + /** + * Helper to verify the contents of a downloaded file versus a byte[]. + * + * @param actual The file of whose contents to verify + * @param expected The data we expect to find in the aforementioned file + * @throws IOException if there was a problem reading from the file + */ + private void verifyFileContents(ParcelFileDescriptor actual, byte[] expected) + throws IOException { + AutoCloseInputStream input = new ParcelFileDescriptor.AutoCloseInputStream(actual); + long fileSize = actual.getStatSize(); + + assertTrue(fileSize <= Integer.MAX_VALUE); + assertEquals(expected.length, fileSize); + + byte[] actualData = new byte[expected.length]; + assertEquals(input.read(actualData), fileSize); + compareByteArrays(actualData, expected); + } + + /** + * Helper to compare 2 byte arrays. + * + * @param actual The array whose data we want to verify + * @param expected The array of data we expect to see + */ + private void compareByteArrays(byte[] actual, byte[] expected) { + assertEquals(actual.length, expected.length); + int length = actual.length; + for (int i = 0; i < length; ++i) { + // assert has a bit of overhead, so only do the assert when the values are not the same + if (actual[i] != expected[i]) { + fail("Byte arrays are not equal."); + } + } + } + + /** + * Gets the MIME content string for a given type + * + * @param type The MIME type to return + * @return the String representation of that MIME content type + */ + protected String getMimeMapping(DownloadFileType type) { + switch (type) { + case APK: + return "application/vnd.android.package-archive"; + case GIF: + return "image/gif"; + case ZIP: + return "application/x-zip-compressed"; + case GARBAGE: + return "zip\\pidy/doo/da"; + case UNRECOGNIZED: + return "application/new.undefined.type.of.app"; + } + return "text/plain"; + } + + /** + * Gets the Uri that should be used to access the mock server + * + * @param filename The name of the file to try to retrieve from the mock server + * @return the Uri to use for access the file on the mock server + */ + private Uri getServerUri(String filename) throws Exception { + URL url = mServer.getUrl("/" + filename); + return Uri.parse(url.toString()); + } + + /** + * Helper to create and register a new MultipleDownloadCompletedReciever + * + * This is used to track many simultaneous downloads by keeping count of all the downloads + * that have completed. + * + * @return A new receiver that records and can be queried on how many downloads have completed. + */ + protected MultipleDownloadsCompletedReceiver registerNewMultipleDownloadsReceiver() { + MultipleDownloadsCompletedReceiver receiver = new MultipleDownloadsCompletedReceiver(); + mContext.registerReceiver(receiver, new IntentFilter( + DownloadManager.ACTION_DOWNLOAD_COMPLETE)); + return receiver; + } + + /** + * Enables or disables WiFi. + * + * Note: Needs the following permissions: + * android.permission.ACCESS_WIFI_STATE + * android.permission.CHANGE_WIFI_STATE + * @param enable true if it should be enabled, false if it should be disabled + */ + protected void setWiFiStateOn(boolean enable) throws Exception { + Log.i(LOG_TAG, "Setting WiFi State to: " + enable); + WifiManager manager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE); + + manager.setWifiEnabled(enable); + + String timeoutMessage = "Timed out waiting for Wifi to be " + + (enable ? "enabled!" : "disabled!"); + + WiFiChangedReceiver receiver = new WiFiChangedReceiver(mContext); + mContext.registerReceiver(receiver, new IntentFilter( + ConnectivityManager.CONNECTIVITY_ACTION)); + + synchronized (receiver) { + long timeoutTime = SystemClock.elapsedRealtime() + DEFAULT_MAX_WAIT_TIME; + boolean timedOut = false; + + while (receiver.getWiFiIsOn() != enable && !timedOut) { + try { + receiver.wait(DEFAULT_WAIT_POLL_TIME); + + if (SystemClock.elapsedRealtime() > timeoutTime) { + timedOut = true; + } + } + catch (InterruptedException e) { + // ignore InterruptedExceptions + } + } + if (timedOut) { + fail(timeoutMessage); + } + } + assertEquals(enable, receiver.getWiFiIsOn()); + } + + /** + * Helper to enables or disables airplane mode. If successful, it also broadcasts an intent + * indicating that the mode has changed. + * + * Note: Needs the following permission: + * android.permission.WRITE_SETTINGS + * @param enable true if airplane mode should be ON, false if it should be OFF + */ + protected void setAirplaneModeOn(boolean enable) throws Exception { + int state = enable ? 1 : 0; + + // Change the system setting + Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON, + state); + + String timeoutMessage = "Timed out waiting for airplane mode to be " + + (enable ? "enabled!" : "disabled!"); + + // wait for airplane mode to change state + int currentWaitTime = 0; + while (Settings.System.getInt(mContext.getContentResolver(), + Settings.System.AIRPLANE_MODE_ON, -1) != state) { + timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, DEFAULT_MAX_WAIT_TIME, + timeoutMessage); + } + + // Post the intent + Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); + intent.putExtra("state", true); + mContext.sendBroadcast(intent); + } + + /** + * Helper to wait for a particular download to finish, or else a timeout to occur + * + * Does not wait for a receiver notification of the download. + * + * @param id The download id to query on (wait for) + */ + private void waitForDownloadOrTimeout_skipNotification(long id) throws TimeoutException, + InterruptedException { + waitForDownloadOrTimeout(id, WAIT_FOR_DOWNLOAD_POLL_TIME, MAX_WAIT_FOR_DOWNLOAD_TIME); + } + + /** + * Helper to wait for a particular download to finish, or else a timeout to occur + * + * Also guarantees a notification has been posted for the download. + * + * @param id The download id to query on (wait for) + */ + protected void waitForDownloadOrTimeout(long id) throws TimeoutException, + InterruptedException { + waitForDownloadOrTimeout_skipNotification(id); + waitForReceiverNotifications(1); + } + + /** + * Helper to wait for a particular download to finish, or else a timeout to occur + * + * Also guarantees a notification has been posted for the download. + * + * @param id The download id to query on (wait for) + * @param poll The amount of time to wait + * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete + */ + protected void waitForDownloadOrTimeout(long id, long poll, long timeoutMillis) + throws TimeoutException, InterruptedException { + doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis); + waitForReceiverNotifications(1); + } + + /** + * Helper to wait for all downloads to finish, or else a specified timeout to occur + * + * Makes no guaranee that notifications have been posted for all downloads. + * + * @param poll The amount of time to wait + * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete + */ + protected void waitForDownloadsOrTimeout(long poll, long timeoutMillis) throws TimeoutException, + InterruptedException { + doWaitForDownloadsOrTimeout(new Query(), poll, timeoutMillis); + } + + /** + * Helper to wait for all downloads to finish, or else a timeout to occur, but does not throw + * + * Also guarantees a notification has been posted for the download. + * + * @param id The id of the download to query against + * @param poll The amount of time to wait + * @param timeoutMillis The max time (in ms) to wait for the download(s) to complete + * @return true if download completed successfully (didn't timeout), false otherwise + */ + private boolean waitForDownloadOrTimeoutNoThrow(long id, long poll, long timeoutMillis) { + try { + doWaitForDownloadsOrTimeout(new Query().setFilterById(id), poll, timeoutMillis); + waitForReceiverNotifications(1); + } catch (TimeoutException e) { + return false; + } + return true; + } + + /** + * Helper function to synchronously wait, or timeout if the maximum threshold has been exceeded. + * + * @param currentTotalWaitTime The total time waited so far + * @param poll The amount of time to wait + * @param maxTimeoutMillis The total wait time threshold; if we've waited more than this long, + * we timeout and fail + * @param timedOutMessage The message to display in the failure message if we timeout + * @return The new total amount of time we've waited so far + * @throws TimeoutException if timed out waiting for SD card to mount + */ + private int timeoutWait(int currentTotalWaitTime, long poll, long maxTimeoutMillis, + String timedOutMessage) throws TimeoutException { + long now = SystemClock.elapsedRealtime(); + long end = now + poll; + + // if we get InterruptedException's, ignore them and just keep sleeping + while (now < end) { + try { + Thread.sleep(end - now); + } catch (InterruptedException e) { + // ignore interrupted exceptions + } + now = SystemClock.elapsedRealtime(); + } + + currentTotalWaitTime += poll; + if (currentTotalWaitTime > maxTimeoutMillis) { + throw new TimeoutException(timedOutMessage); + } + return currentTotalWaitTime; + } + + /** + * Helper to wait for all downloads to finish, or else a timeout to occur + * + * @param query The query to pass to the download manager + * @param poll The poll time to wait between checks + * @param timeoutMillis The max amount of time (in ms) to wait for the download(s) to complete + */ + private void doWaitForDownloadsOrTimeout(Query query, long poll, long timeoutMillis) + throws TimeoutException { + int currentWaitTime = 0; + while (true) { + query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_PAUSED + | DownloadManager.STATUS_RUNNING); + Cursor cursor = mDownloadManager.query(query); + + try { + if (cursor.getCount() == 0) { + Log.i(LOG_TAG, "All downloads should be done..."); + break; + } + currentWaitTime = timeoutWait(currentWaitTime, poll, timeoutMillis, + "Timed out waiting for all downloads to finish"); + } finally { + cursor.close(); + } + } + } + + /** + * Synchronously waits for external store to be mounted (eg: SD Card). + * + * @throws InterruptedException if interrupted + * @throws Exception if timed out waiting for SD card to mount + */ + protected void waitForExternalStoreMount() throws Exception { + String extStorageState = Environment.getExternalStorageState(); + int currentWaitTime = 0; + while (!extStorageState.equals(Environment.MEDIA_MOUNTED)) { + Log.i(LOG_TAG, "Waiting for SD card..."); + currentWaitTime = timeoutWait(currentWaitTime, DEFAULT_WAIT_POLL_TIME, + DEFAULT_MAX_WAIT_TIME, "Timed out waiting for SD Card to be ready!"); + extStorageState = Environment.getExternalStorageState(); + } + } + + /** + * Synchronously waits for a download to start. + * + * @param dlRequest the download request id used by Download Manager to track the download. + * @throws Exception if timed out while waiting for SD card to mount + */ + protected void waitForDownloadToStart(long dlRequest) throws Exception { + Cursor cursor = getCursor(dlRequest); + try { + int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); + int value = cursor.getInt(columnIndex); + int currentWaitTime = 0; + + while (value != DownloadManager.STATUS_RUNNING && + (value != DownloadManager.STATUS_FAILED) && + (value != DownloadManager.STATUS_SUCCESSFUL)) { + Log.i(LOG_TAG, "Waiting for download to start..."); + currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, + MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download to start!"); + cursor.requery(); + assertTrue(cursor.moveToFirst()); + columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS); + value = cursor.getInt(columnIndex); + } + assertFalse("Download failed immediately after start", + value == DownloadManager.STATUS_FAILED); + } finally { + cursor.close(); + } + } + + /** + * Synchronously waits for our receiver to receive notification for a given number of + * downloads. + * + * @param targetNumber The number of notifications for unique downloads to wait for; pass in + * -1 to not wait for notification. + * @throws Exception if timed out while waiting + */ + private void waitForReceiverNotifications(int targetNumber) throws TimeoutException { + int count = mReceiver.numDownloadsCompleted(); + int currentWaitTime = 0; + + while (count < targetNumber) { + Log.i(LOG_TAG, "Waiting for notification of downloads..."); + currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, + MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for download notifications!" + + " Received " + count + "notifications."); + count = mReceiver.numDownloadsCompleted(); + } + } + + /** + * Synchronously waits for a file to increase in size (such as to monitor that a download is + * progressing). + * + * @param file The file whose size to track. + * @throws Exception if timed out while waiting for the file to grow in size. + */ + protected void waitForFileToGrow(File file) throws Exception { + int currentWaitTime = 0; + + // File may not even exist yet, so wait until it does (or we timeout) + while (!file.exists()) { + Log.i(LOG_TAG, "Waiting for file to exist..."); + currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, + MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be created."); + } + + // Get original file size... + long originalSize = file.length(); + + while (file.length() <= originalSize) { + Log.i(LOG_TAG, "Waiting for file to be written to..."); + currentWaitTime = timeoutWait(currentWaitTime, WAIT_FOR_DOWNLOAD_POLL_TIME, + MAX_WAIT_FOR_DOWNLOAD_TIME, "Timed out waiting for file to be written to."); + } + } + + /** + * Helper to remove all downloads that are registered with the DL Manager. + * + * Note: This gives us a clean slate b/c it includes downloads that are pending, running, + * paused, or have completed. + */ + protected void removeAllCurrentDownloads() { + Log.i(LOG_TAG, "Removing all current registered downloads..."); + Cursor cursor = mDownloadManager.query(new Query()); + try { + if (cursor.moveToFirst()) { + do { + int index = cursor.getColumnIndex(DownloadManager.COLUMN_ID); + long downloadId = cursor.getLong(index); + + mDownloadManager.remove(downloadId); + } while (cursor.moveToNext()); + } + } finally { + cursor.close(); + } + } + + /** + * Helper to perform a standard enqueue of data to the mock server. + * download is performed to the downloads cache dir (NOT systemcache dir) + * + * @param body The body to return in the response from the server + */ + private long doStandardEnqueue(byte[] body) throws Exception { + // Prepare the mock server with a standard response + enqueueResponse(HTTP_OK, body); + return doCommonStandardEnqueue(); + } + + /** + * Helper to perform a standard enqueue of data to the mock server. + * + * @param body The body to return in the response from the server, contained in the file + */ + private long doStandardEnqueue(File body) throws Exception { + // Prepare the mock server with a standard response + enqueueResponse(HTTP_OK, body); + return doCommonStandardEnqueue(); + } + + /** + * Helper to do the additional steps (setting title and Uri of default filename) when + * doing a standard enqueue request to the server. + */ + private long doCommonStandardEnqueue() throws Exception { + Uri uri = getServerUri(DEFAULT_FILENAME); + Request request = new Request(uri).setTitle(DEFAULT_FILENAME); + return mDownloadManager.enqueue(request); + } + + /** + * Helper to verify an int value in a Cursor + * + * @param cursor The cursor containing the query results + * @param columnName The name of the column to query + * @param expected The expected int value + */ + private void verifyInt(Cursor cursor, String columnName, int expected) { + int index = cursor.getColumnIndex(columnName); + int actual = cursor.getInt(index); + assertEquals(expected, actual); + } + + /** + * Performs a query based on ID and returns a Cursor for the query. + * + * @param id The id of the download in DL Manager; pass -1 to query all downloads + * @return A cursor for the query results + */ + protected Cursor getCursor(long id) throws Exception { + Query query = new Query(); + if (id != -1) { + query.setFilterById(id); + } + + Cursor cursor = mDownloadManager.query(query); + int currentWaitTime = 0; + + try { + while (!cursor.moveToFirst()) { + Thread.sleep(DEFAULT_WAIT_POLL_TIME); + currentWaitTime += DEFAULT_WAIT_POLL_TIME; + if (currentWaitTime > DEFAULT_MAX_WAIT_TIME) { + fail("timed out waiting for a non-null query result"); + } + cursor.requery(); + } + } catch (Exception e) { + cursor.close(); + throw e; + } + return cursor; + } +}
\ No newline at end of file diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java index e1d7b4c..ba5ee2c 100644 --- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java +++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java @@ -18,7 +18,6 @@ package com.android.frameworks.downloadmanagertests; import android.app.DownloadManager; import android.app.DownloadManager.Query; import android.app.DownloadManager.Request; -import android.app.DownloadManagerBaseTest; import android.content.Context; import android.content.Intent; import android.database.Cursor; |