From 691fc58e9a61d99ab5018c5ddc8349ed413e4470 Mon Sep 17 00:00:00 2001 From: Steve Howard Date: Fri, 23 Jul 2010 18:30:16 -0700 Subject: Test + utilize change notification in DownloadProvider Now that I've learned how ContentResolver.notifyChange() works, add a test to explicitly check it's being called in DownloadProvider, and take advantage of it in waitForDownloadToStop to get rid of the ugly old polling mechanism. Change-Id: Iba71bdf1b0d31454cc4e186ceb4fdd9fdb5faad5 --- .../AbstractDownloadManagerFunctionalTest.java | 47 +++++++++++++++++++--- .../downloads/PublicApiFunctionalTest.java | 13 ++++++ 2 files changed, 54 insertions(+), 6 deletions(-) (limited to 'tests/src/com') diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java index 7af98c17..cb4ad8c9 100644 --- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java @@ -20,7 +20,9 @@ import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.database.ContentObserver; import android.database.Cursor; +import android.net.Uri; import android.provider.Downloads; import android.test.MoreAsserts; import android.test.RenamingDelegatingContext; @@ -54,7 +56,7 @@ public abstract class AbstractDownloadManagerFunctionalTest extends protected static final int HTTP_NOT_FOUND = 404; protected static final int HTTP_SERVICE_UNAVAILABLE = 503; protected MockWebServer mServer; - protected MockContentResolver mResolver; + protected MockContentResolverWithNotify mResolver; protected TestContext mTestContext; protected FakeSystemFacade mSystemFacade; @@ -63,6 +65,21 @@ public abstract class AbstractDownloadManagerFunctionalTest extends public boolean isComplete(int status); } + static class MockContentResolverWithNotify extends MockContentResolver { + public boolean mNotifyWasCalled = false; + + public synchronized void resetNotified() { + mNotifyWasCalled = false; + } + + @Override + public synchronized void notifyChange(Uri uri, ContentObserver observer, + boolean syncToNetwork) { + mNotifyWasCalled = true; + notifyAll(); + } + } + /** * Context passed to the provider and the service. Allows most methods to pass through to the * real Context (this is a LargeTest), with a few exceptions, including renaming file operations @@ -179,7 +196,7 @@ public abstract class AbstractDownloadManagerFunctionalTest extends DownloadProvider provider = new DownloadProvider(); provider.mSystemFacade = mSystemFacade; provider.attachInfo(mTestContext, null); - mResolver = new MockContentResolver(); + mResolver = new MockContentResolverWithNotify(); mResolver.addProvider(PROVIDER_AUTHORITY, provider); } @@ -257,25 +274,43 @@ public abstract class AbstractDownloadManagerFunctionalTest extends */ protected void waitForDownloadToStop(StatusReader reader, int expectedStatus) throws Exception { - // TODO(showard): find a better way to accomplish this 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); } - if (System.currentTimeMillis() > startTimeMillis + REQUEST_TIMEOUT_MILLIS) { + waitForChange(endTimeMillis); + if (startTimeMillis > endTimeMillis) { fail("Download timed out with status " + status); } - Thread.sleep(100); mServer.checkForExceptions(); status = reader.getStatus(); } - long delta = System.currentTimeMillis() - startTimeMillis; + long delta = startTimeMillis - 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(); + } + } + protected String readStream(InputStream inputStream) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); try { diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java index 7982ef4a..3d32ae3c 100644 --- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java @@ -472,6 +472,19 @@ public class PublicApiFunctionalTest extends AbstractDownloadManagerFunctionalTe download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); } + public void testContentObserver() throws Exception { + enqueueEmptyResponse(HTTP_OK); + enqueueRequest(getRequest()); + mResolver.resetNotified(); + startService(null); + synchronized(mResolver) { + if (!mResolver.mNotifyWasCalled) { + mResolver.wait(2000); + } + } + assertTrue(mResolver.mNotifyWasCalled); + } + private void runSimpleFailureTest(int expectedErrorCode) throws Exception { Download download = enqueueRequest(getRequest()); download.runUntilStatus(DownloadManager.STATUS_FAILED); -- cgit v1.2.3