summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java99
-rw-r--r--tests/src/com/android/providers/downloads/AbstractPublicApiTest.java110
-rw-r--r--tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java63
-rw-r--r--tests/src/com/android/providers/downloads/FakeSystemFacade.java14
-rw-r--r--tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java177
-rw-r--r--tests/src/com/android/providers/downloads/ThreadingTest.java56
6 files changed, 257 insertions, 262 deletions
diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
index a401a5b8..9e7ef0f9 100644
--- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java
@@ -48,23 +48,18 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
protected static final String LOG_TAG = "DownloadManagerFunctionalTest";
private static final String PROVIDER_AUTHORITY = "downloads";
- protected static final long REQUEST_TIMEOUT_MILLIS = 10 * 1000;
protected static final long RETRY_DELAY_MILLIS = 61 * 1000;
protected static final String FILE_CONTENT = "hello world";
protected static final int HTTP_OK = 200;
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 MockWebServer mServer;
protected MockContentResolverWithNotify mResolver;
protected TestContext mTestContext;
protected FakeSystemFacade mSystemFacade;
- static interface StatusReader {
- public int getStatus();
- public boolean isComplete(int status);
- }
-
static class MockContentResolverWithNotify extends MockContentResolver {
public boolean mNotifyWasCalled = false;
@@ -140,15 +135,15 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
}
}
- public AbstractDownloadManagerFunctionalTest() {
+ public AbstractDownloadManagerFunctionalTest(FakeSystemFacade systemFacade) {
super(DownloadService.class);
+ mSystemFacade = systemFacade;
}
@Override
protected void setUp() throws Exception {
super.setUp();
- mSystemFacade = new FakeSystemFacade();
Context realContext = getContext();
mTestContext = new TestContext(realContext);
setupProviderAndResolver();
@@ -165,28 +160,10 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
@Override
protected void tearDown() throws Exception {
- waitForThreads();
cleanUpDownloads();
super.tearDown();
}
- private void waitForThreads() throws InterruptedException {
- DownloadService service = getService();
- if (service == null) {
- return;
- }
-
- long startTimeMillis = System.currentTimeMillis();
- while (service.mUpdateThread != null
- && System.currentTimeMillis() < startTimeMillis + 1000) {
- Thread.sleep(50);
- }
-
- // We can't explicitly wait for DownloadThreads, so just throw this last sleep in. Ugly,
- // but necessary to avoid unbearable flakiness until I can find a better solution.
- Thread.sleep(50);
- }
-
private boolean isDatabaseEmpty() {
Cursor cursor = mResolver.query(Downloads.CONTENT_URI, null, null, null, null);
try {
@@ -230,16 +207,10 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
* Enqueue a response from the MockWebServer.
*/
MockResponse enqueueResponse(int status, String body) {
- return enqueueResponse(status, body, true);
- }
-
- MockResponse enqueueResponse(int status, String body, boolean includeContentType) {
MockResponse response = new MockResponse()
.setResponseCode(status)
.setBody(body);
- if (includeContentType) {
- response.addHeader("Content-type", "text/plain");
- }
+ response.addHeader("Content-type", "text/plain");
mServer.enqueue(response);
return response;
}
@@ -249,11 +220,11 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
}
/**
- * Wait for a request to come to the MockWebServer and return it.
+ * Fetch the last request received by the MockWebServer.
*/
- RecordedRequest takeRequest() throws InterruptedException {
- RecordedRequest request = mServer.takeRequestWithTimeout(REQUEST_TIMEOUT_MILLIS);
- assertNotNull("Timed out waiting for request", request);
+ protected RecordedRequest takeRequest() throws InterruptedException {
+ RecordedRequest request = mServer.takeRequestWithTimeout(0);
+ assertNotNull("Expected request was not made", request);
return request;
}
@@ -261,58 +232,10 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
return mServer.getUrl(path).toString();
}
- /**
- * Run the service and wait for a request and for the download to reach the given status.
- * @return the request received
- */
- protected RecordedRequest runUntilStatus(StatusReader reader, int status) throws Exception {
+ public void runService() throws Exception {
startService(null);
- RecordedRequest request = takeRequest();
- waitForDownloadToStop(reader, status);
- return request;
- }
-
- /**
- * Wait for a download to given a given status, with a timeout. Fails if the download reaches
- * any other final status.
- */
- protected void waitForDownloadToStop(StatusReader reader, int expectedStatus)
- throws Exception {
- long startTimeMillis = System.currentTimeMillis();
- long endTimeMillis = startTimeMillis + REQUEST_TIMEOUT_MILLIS;
- int status = reader.getStatus();
- while (status != expectedStatus) {
- if (reader.isComplete(status)) {
- fail("Download completed with unexpected status: " + status);
- }
- waitForChange(endTimeMillis);
- if (startTimeMillis > endTimeMillis) {
- fail("Download timed out with status " + status);
- }
- mServer.checkForExceptions();
- status = reader.getStatus();
- }
-
- long delta = System.currentTimeMillis() - startTimeMillis;
- Log.d(LOG_TAG, "Status " + status + " reached after " + delta + "ms");
- }
-
- /**
- * Wait until mResolver gets notifyChange() called, or endTimeMillis is reached.
- */
- private void waitForChange(long endTimeMillis) {
- synchronized(mResolver) {
- long now = System.currentTimeMillis();
- while (!mResolver.mNotifyWasCalled && now < endTimeMillis) {
- try {
- mResolver.wait(endTimeMillis - now);
- } catch (InterruptedException exc) {
- // no problem
- }
- now = System.currentTimeMillis();
- }
- mResolver.resetNotified();
- }
+ mSystemFacade.runAllThreads();
+ mServer.checkForExceptions();
}
protected String readStream(InputStream inputStream) throws IOException {
diff --git a/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
new file mode 100644
index 00000000..db6b2468
--- /dev/null
+++ b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
@@ -0,0 +1,110 @@
+/*
+ * 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.providers.downloads;
+
+import android.database.Cursor;
+import android.net.DownloadManager;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+
+/**
+ * Code common to tests that use the download manager public API.
+ */
+public abstract class AbstractPublicApiTest extends AbstractDownloadManagerFunctionalTest {
+
+ class Download {
+ final long mId;
+
+ private Download(long downloadId) {
+ this.mId = downloadId;
+ }
+
+ public int getStatus() {
+ return (int) getLongField(DownloadManager.COLUMN_STATUS);
+ }
+
+ String getStringField(String field) {
+ Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
+ try {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ return cursor.getString(cursor.getColumnIndexOrThrow(field));
+ } finally {
+ cursor.close();
+ }
+ }
+
+ long getLongField(String field) {
+ Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
+ try {
+ assertEquals(1, cursor.getCount());
+ cursor.moveToFirst();
+ return cursor.getLong(cursor.getColumnIndexOrThrow(field));
+ } finally {
+ cursor.close();
+ }
+ }
+
+ String getContents() throws Exception {
+ ParcelFileDescriptor downloadedFile = mManager.openDownloadedFile(mId);
+ assertTrue("Invalid file descriptor: " + downloadedFile,
+ downloadedFile.getFileDescriptor().valid());
+ InputStream stream = new FileInputStream(downloadedFile.getFileDescriptor());
+ try {
+ return readStream(stream);
+ } finally {
+ stream.close();
+ }
+ }
+
+ void runUntilStatus(int status) throws Exception {
+ runService();
+ assertEquals(status, getStatus());
+ }
+ }
+
+ protected static final String PACKAGE_NAME = "my.package.name";
+ protected static final String REQUEST_PATH = "/path";
+
+ protected DownloadManager mManager;
+
+ public AbstractPublicApiTest(FakeSystemFacade systemFacade) {
+ super(systemFacade);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mManager = new DownloadManager(mResolver, PACKAGE_NAME);
+ }
+
+ protected DownloadManager.Request getRequest() throws MalformedURLException {
+ return getRequest(getServerUri(REQUEST_PATH));
+ }
+
+ protected DownloadManager.Request getRequest(String path) {
+ return new DownloadManager.Request(Uri.parse(path));
+ }
+
+ protected Download enqueueRequest(DownloadManager.Request request) {
+ return new Download(mManager.enqueue(request));
+ }
+}
diff --git a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
index 822ab54d..350c63d4 100644
--- a/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java
@@ -28,7 +28,6 @@ import tests.http.RecordedRequest;
import java.io.InputStream;
import java.net.MalformedURLException;
-import java.util.List;
/**
* This test exercises the entire download manager working together -- it requests downloads through
@@ -38,6 +37,10 @@ import java.util.List;
*/
@LargeTest
public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFunctionalTest {
+ public DownloadManagerFunctionalTest() {
+ super(new FakeSystemFacade());
+ }
+
public void testBasicRequest() throws Exception {
enqueueResponse(HTTP_OK, FILE_CONTENT);
@@ -46,7 +49,8 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
assertEquals(Downloads.STATUS_PENDING, getDownloadStatus(downloadUri));
assertTrue(mTestContext.mHasServiceBeenStarted);
- RecordedRequest request = runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
+ RecordedRequest request = takeRequest();
assertEquals("GET", request.getMethod());
assertEquals(path, request.getPath());
assertEquals(FILE_CONTENT, getDownloadContents(downloadUri));
@@ -65,40 +69,6 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
getDownloadFilename(downloadUri));
}
- public void testFileNotFound() throws Exception {
- enqueueEmptyResponse(HTTP_NOT_FOUND);
- Uri downloadUri = requestDownload("/nonexistent_path");
- assertEquals(Downloads.STATUS_PENDING, getDownloadStatus(downloadUri));
- runUntilStatus(downloadUri, HTTP_NOT_FOUND);
- }
-
- public void testRetryAfter() throws Exception {
- final int delay = 120;
- enqueueEmptyResponse(HTTP_SERVICE_UNAVAILABLE).addHeader("Retry-after", delay);
- Uri downloadUri = requestDownload("/path");
- runUntilStatus(downloadUri, Downloads.STATUS_RUNNING_PAUSED);
-
- // download manager adds random 0-30s offset
- mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
-
- enqueueResponse(HTTP_OK, FILE_CONTENT);
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
- }
-
- public void testBasicConnectivityChanges() throws Exception {
- enqueueResponse(HTTP_OK, FILE_CONTENT);
- Uri downloadUri = requestDownload("/path");
-
- // without connectivity, download immediately pauses
- mSystemFacade.mActiveNetworkType = null;
- startService(null);
- waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED);
-
- // connecting should start the download
- mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
- runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
- }
-
public void testRoaming() throws Exception {
mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
mSystemFacade.mIsRoaming = true;
@@ -106,15 +76,13 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
// for a normal download, roaming is fine
enqueueResponse(HTTP_OK, FILE_CONTENT);
Uri downloadUri = requestDownload("/path");
- startService(null);
runUntilStatus(downloadUri, Downloads.STATUS_SUCCESS);
// when roaming is disallowed, the download should pause...
downloadUri = requestDownload("/path");
updateDownload(downloadUri, Downloads.COLUMN_DESTINATION,
Integer.toString(Downloads.DESTINATION_CACHE_PARTITION_NOROAMING));
- startService(null);
- waitForDownloadToStop(getStatusReader(downloadUri), Downloads.STATUS_RUNNING_PAUSED);
+ runUntilStatus(downloadUri, Downloads.STATUS_RUNNING_PAUSED);
// ...and pick up when we're off roaming
enqueueResponse(HTTP_OK, FILE_CONTENT);
@@ -134,20 +102,9 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
}
}
- private RecordedRequest runUntilStatus(Uri downloadUri, int status) throws Exception {
- return super.runUntilStatus(getStatusReader(downloadUri), status);
- }
-
- private StatusReader getStatusReader(final Uri downloadUri) {
- return new StatusReader() {
- public int getStatus() {
- return getDownloadStatus(downloadUri);
- }
-
- public boolean isComplete(int status) {
- return !Downloads.isStatusInformational(status);
- }
- };
+ private void runUntilStatus(Uri downloadUri, int status) throws Exception {
+ runService();
+ assertEquals(status, getDownloadStatus(downloadUri));
}
protected int getDownloadStatus(Uri downloadUri) {
diff --git a/tests/src/com/android/providers/downloads/FakeSystemFacade.java b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
index d35b558b..297c1d3a 100644
--- a/tests/src/com/android/providers/downloads/FakeSystemFacade.java
+++ b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
@@ -8,8 +8,10 @@ import android.test.AssertionFailedError;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Queue;
public class FakeSystemFacade implements SystemFacade {
long mTimeMillis = 0;
@@ -19,6 +21,7 @@ public class FakeSystemFacade implements SystemFacade {
List<Intent> mBroadcastsSent = new ArrayList<Intent>();
Map<Integer,Notification> mActiveNotifications = new HashMap<Integer,Notification>();
List<Notification> mCanceledNotifications = new ArrayList<Notification>();
+ Queue<Thread> mStartedThreads = new LinkedList<Thread>();
void incrementTimeMillis(long delta) {
mTimeMillis += delta;
@@ -72,4 +75,15 @@ public class FakeSystemFacade implements SystemFacade {
cancelNotification(id);
}
}
+
+ @Override
+ public void startThread(Thread thread) {
+ mStartedThreads.add(thread);
+ }
+
+ public void runAllThreads() {
+ while (!mStartedThreads.isEmpty()) {
+ mStartedThreads.poll().run();
+ }
+ }
}
diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
index 00419a3d..ba3059b6 100644
--- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
@@ -22,7 +22,6 @@ import android.net.ConnectivityManager;
import android.net.DownloadManager;
import android.net.Uri;
import android.os.Environment;
-import android.os.ParcelFileDescriptor;
import android.provider.Downloads;
import android.test.suitebuilder.annotation.LargeTest;
import tests.http.MockResponse;
@@ -35,77 +34,21 @@ import java.net.MalformedURLException;
import java.util.List;
@LargeTest
-public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTest {
- private static final String PACKAGE_NAME = "my.package.name";
+public class PublicApiFunctionalTest extends AbstractPublicApiTest {
private static final int HTTP_NOT_ACCEPTABLE = 406;
private static final int HTTP_LENGTH_REQUIRED = 411;
- private static final String REQUEST_PATH = "/path";
private static final String REDIRECTED_PATH = "/other_path";
private static final String ETAG = "my_etag";
- class Download implements StatusReader {
- final long mId;
+ protected File mTestDirectory;
- private Download(long downloadId) {
- this.mId = downloadId;
- }
-
- public int getStatus() {
- return (int) getLongField(DownloadManager.COLUMN_STATUS);
- }
-
- public boolean isComplete(int status) {
- return status != DownloadManager.STATUS_PENDING
- && status != DownloadManager.STATUS_RUNNING
- && status != DownloadManager.STATUS_PAUSED;
- }
-
- String getStringField(String field) {
- Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
- try {
- assertEquals(1, cursor.getCount());
- cursor.moveToFirst();
- return cursor.getString(cursor.getColumnIndexOrThrow(field));
- } finally {
- cursor.close();
- }
- }
-
- long getLongField(String field) {
- Cursor cursor = mManager.query(new DownloadManager.Query().setFilterById(mId));
- try {
- assertEquals(1, cursor.getCount());
- cursor.moveToFirst();
- return cursor.getLong(cursor.getColumnIndexOrThrow(field));
- } finally {
- cursor.close();
- }
- }
-
- String getContents() throws Exception {
- ParcelFileDescriptor downloadedFile = mManager.openDownloadedFile(mId);
- assertTrue("Invalid file descriptor: " + downloadedFile,
- downloadedFile.getFileDescriptor().valid());
- InputStream stream = new FileInputStream(downloadedFile.getFileDescriptor());
- try {
- return readStream(stream);
- } finally {
- stream.close();
- }
- }
-
- RecordedRequest runUntilStatus(int status) throws Exception {
- return PublicApiFunctionalTest.this.runUntilStatus(this, status);
- }
+ public PublicApiFunctionalTest() {
+ super(new FakeSystemFacade());
}
- private DownloadManager mManager;
- private File mTestDirectory;
-
@Override
protected void setUp() throws Exception {
super.setUp();
- mManager = new DownloadManager(mResolver, PACKAGE_NAME);
mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
+ "download_manager_functional_test");
@@ -142,7 +85,8 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP));
mSystemFacade.incrementTimeMillis(10);
- RecordedRequest request = download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ RecordedRequest request = takeRequest();
assertEquals("GET", request.getMethod());
assertEquals(REQUEST_PATH, request.getPath());
@@ -190,14 +134,15 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
assertEquals(FILE_CONTENT.length(),
download.getLongField(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
+ takeRequest(); // get the first request out of the queue
mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
- RecordedRequest request = download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
assertEquals(FILE_CONTENT.length(),
download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
assertEquals(FILE_CONTENT, download.getContents());
- List<String> headers = request.getHeaders();
+ List<String> headers = takeRequest().getHeaders();
assertTrue("No Range header: " + headers,
headers.contains("Range: bytes=" + initialLength + "-"));
assertTrue("No ETag header: " + headers, headers.contains("If-Match: " + ETAG));
@@ -299,10 +244,11 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
enqueueEmptyResponse(HTTP_OK);
Download download = enqueueRequest(getRequest().setRequestHeader("Header1", "value1")
.setRequestHeader("Header2", "value2"));
- RecordedRequest request = download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
- assertTrue(request.getHeaders().contains("Header1: value1"));
- assertTrue(request.getHeaders().contains("Header2: value2"));
+ List<String> headers = takeRequest().getHeaders();
+ assertTrue(headers.contains("Header1: value1"));
+ assertTrue(headers.contains("Header2: value2"));
}
public void testDelete() throws Exception {
@@ -331,19 +277,6 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
}
- /**
- * Test for race conditions when the service is flooded with startService() calls while running
- * a download.
- */
- public void testFloodServiceWithStarts() throws Exception {
- enqueueResponse(HTTP_OK, FILE_CONTENT);
- Download download = enqueueRequest(getRequest());
- while (download.getStatus() != DownloadManager.STATUS_SUCCESSFUL) {
- startService(null);
- Thread.sleep(10);
- }
- }
-
public void testRedirect301() throws Exception {
RecordedRequest lastRequest = runRedirectionTest(301);
// for 301, upon retry, we reuse the redirected URI
@@ -375,7 +308,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
}
public void testNoContentType() throws Exception {
- enqueueResponse(HTTP_OK, "", false);
+ enqueueResponse(HTTP_OK, "").removeHeader("Content-Type");
runSimpleFailureTest(HTTP_NOT_ACCEPTABLE);
}
@@ -394,8 +327,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
mManager.remove(download.mId);
mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
- startService(null);
- Thread.sleep(500); // TODO: eliminate this when we can run the service synchronously
+ runService();
// if the cancel didn't work, we should get an unexpected request to the HTTP server
}
@@ -404,13 +336,6 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
Download download = enqueueRequest(getRequest());
download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
- long startTimeMillis = System.currentTimeMillis();
- while (mSystemFacade.mBroadcastsSent.isEmpty()) {
- Thread.sleep(100);
- if (System.currentTimeMillis() > startTimeMillis + 500) {
- fail("Timed out waiting for broadcast intent");
- }
- }
assertEquals(1, mSystemFacade.mBroadcastsSent.size());
Intent broadcast = mSystemFacade.mBroadcastsSent.get(0);
assertEquals(DownloadManager.ACTION_DOWNLOAD_COMPLETE, broadcast.getAction());
@@ -435,6 +360,19 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
assertEquals(PACKAGE_NAME, broadcast.getPackage());
}
+ public void testBasicConnectivityChanges() throws Exception {
+ enqueueResponse(HTTP_OK, FILE_CONTENT);
+ Download download = enqueueRequest(getRequest());
+
+ // without connectivity, download immediately pauses
+ mSystemFacade.mActiveNetworkType = null;
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
+
+ // connecting should start the download
+ mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ }
+
public void testAllowedNetworkTypes() throws Exception {
mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
@@ -446,8 +384,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
// restrict a download to wifi...
download = enqueueRequest(getRequest()
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI));
- startService(null);
- waitForDownloadToStop(download, DownloadManager.STATUS_PAUSED);
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
// ...then enable wifi
mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
enqueueEmptyResponse(HTTP_OK);
@@ -464,8 +401,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
// disallow roaming for a download...
download = enqueueRequest(getRequest().setAllowedOverRoaming(false));
- startService(null);
- waitForDownloadToStop(download, DownloadManager.STATUS_PAUSED);
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
// ...then turn off roaming
mSystemFacade.mIsRoaming = false;
enqueueEmptyResponse(HTTP_OK);
@@ -476,12 +412,7 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
enqueueEmptyResponse(HTTP_OK);
enqueueRequest(getRequest());
mResolver.resetNotified();
- startService(null);
- synchronized(mResolver) {
- if (!mResolver.mNotifyWasCalled) {
- mResolver.wait(2000);
- }
- }
+ runService();
assertTrue(mResolver.mNotifyWasCalled);
}
@@ -491,16 +422,32 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
assertEquals(0, mSystemFacade.mActiveNotifications.size());
assertEquals(0, mSystemFacade.mCanceledNotifications.size());
-
+
enqueueEmptyResponse(HTTP_OK);
download = enqueueRequest(
getRequest()
.setShowNotification(DownloadManager.Request.NOTIFICATION_WHEN_RUNNING));
download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
assertEquals(1, mSystemFacade.mActiveNotifications.size());
+
// The notification doesn't actually get canceled until the UpdateThread runs again, which
- // gets triggered by the DownloadThread updating the status in the provider. This is
- // tough to test right now, so I'll leave it until the overall structure is changed.
+ // gets triggered by the DownloadThread updating the status in the provider.
+ runService();
+ assertEquals(0, mSystemFacade.mActiveNotifications.size());
+ assertEquals(1, mSystemFacade.mCanceledNotifications.size());
+ }
+
+ public void testRetryAfter() throws Exception {
+ final int delay = 120;
+ enqueueEmptyResponse(HTTP_SERVICE_UNAVAILABLE).addHeader("Retry-after", delay);
+ Download download = enqueueRequest(getRequest());
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
+
+ // download manager adds random 0-30s offset
+ mSystemFacade.incrementTimeMillis((delay + 31) * 1000);
+
+ enqueueEmptyResponse(HTTP_OK);
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
}
private void runSimpleFailureTest(int expectedErrorCode) throws Exception {
@@ -524,27 +471,15 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe
enqueueInterruptedDownloadResponses(5);
Download download = enqueueRequest(getRequest());
- RecordedRequest request = download.runUntilStatus(DownloadManager.STATUS_PAUSED);
- assertEquals(REQUEST_PATH, request.getPath());
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
+ assertEquals(REQUEST_PATH, takeRequest().getPath());
mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
- request = download.runUntilStatus(DownloadManager.STATUS_PAUSED);
- assertEquals(REDIRECTED_PATH, request.getPath());
+ download.runUntilStatus(DownloadManager.STATUS_PAUSED);
+ assertEquals(REDIRECTED_PATH, takeRequest().getPath());
mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
- request = download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
- return request;
- }
-
- private DownloadManager.Request getRequest() throws MalformedURLException {
- return getRequest(getServerUri(REQUEST_PATH));
- }
-
- private DownloadManager.Request getRequest(String path) {
- return new DownloadManager.Request(Uri.parse(path));
- }
-
- private Download enqueueRequest(DownloadManager.Request request) {
- return new Download(mManager.enqueue(request));
+ download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
+ return takeRequest();
}
}
diff --git a/tests/src/com/android/providers/downloads/ThreadingTest.java b/tests/src/com/android/providers/downloads/ThreadingTest.java
new file mode 100644
index 00000000..e8d86d66
--- /dev/null
+++ b/tests/src/com/android/providers/downloads/ThreadingTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.providers.downloads;
+
+import android.net.DownloadManager;
+import android.test.suitebuilder.annotation.LargeTest;
+
+/**
+ * Download manager tests that require multithreading.
+ */
+@LargeTest
+public class ThreadingTest extends AbstractPublicApiTest {
+ private static class FakeSystemFacadeWithThreading extends FakeSystemFacade {
+ @Override
+ public void startThread(Thread thread) {
+ thread.start();
+ }
+ }
+
+ public ThreadingTest() {
+ super(new FakeSystemFacadeWithThreading());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ Thread.sleep(50); // give threads a chance to finish
+ super.tearDown();
+ }
+
+ /**
+ * Test for race conditions when the service is flooded with startService() calls while running
+ * a download.
+ */
+ public void testFloodServiceWithStarts() throws Exception {
+ enqueueResponse(HTTP_OK, FILE_CONTENT);
+ Download download = enqueueRequest(getRequest());
+ while (download.getStatus() != DownloadManager.STATUS_SUCCESSFUL) {
+ startService(null);
+ Thread.sleep(10);
+ }
+ }
+}