summaryrefslogtreecommitdiffstats
path: root/core/tests
diff options
context:
space:
mode:
Diffstat (limited to 'core/tests')
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/unit/WifiClientTest.java2
-rw-r--r--core/tests/coretests/AndroidManifest.xml3
-rw-r--r--core/tests/coretests/src/android/app/DownloadManagerBaseTest.java77
-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.java53
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk3
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerBaseTest.java816
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java1
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;