From dea0a5f8e5804d3aba40eaa7de763dd88058384e Mon Sep 17 00:00:00 2001 From: Steve Howard Date: Tue, 27 Jul 2010 16:28:40 -0700 Subject: Add test for many interruptions to a single download. Adding a new test case for downloads that undergo many interruptions (as may happen with a very large download that takes many hours). Includes some refactoring in the test suite. Early on, this test exposed a race condition in which the download manager got some I/O exception while reading from the MockWebServer. I went in and improved/refactored much of the error logging code in DownloadThread to try and track this down. Unfortunately, once I finished, the race condition no longer seems to be reproducible, even with hundreds of runs of the test case. So I've given up on it for now. In any event, error logging is better and much duplicate code has been eliminated. --- .../AbstractDownloadManagerFunctionalTest.java | 7 ++- .../downloads/PublicApiFunctionalTest.java | 64 +++++++++++++++------- 2 files changed, 48 insertions(+), 23 deletions(-) (limited to 'tests/src/com/android') diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java index 9e7ef0f9..3e4bccc3 100644 --- a/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java @@ -49,7 +49,7 @@ public abstract class AbstractDownloadManagerFunctionalTest extends protected static final String LOG_TAG = "DownloadManagerFunctionalTest"; private static final String PROVIDER_AUTHORITY = "downloads"; protected static final long RETRY_DELAY_MILLIS = 61 * 1000; - protected static final String FILE_CONTENT = "hello world"; + protected static final String FILE_CONTENT = "hello world hello world hello world 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; @@ -209,8 +209,9 @@ public abstract class AbstractDownloadManagerFunctionalTest extends MockResponse enqueueResponse(int status, String body) { MockResponse response = new MockResponse() .setResponseCode(status) - .setBody(body); - response.addHeader("Content-type", "text/plain"); + .setBody(body) + .addHeader("Content-type", "text/plain") + .setCloseConnectionAfter(true); mServer.enqueue(response); return response; } diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java index c1a015af..d33e458d 100644 --- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java @@ -102,7 +102,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { assertEquals(mSystemFacade.currentTimeMillis(), download.getLongField(DownloadManager.COLUMN_LAST_MODIFIED_TIMESTAMP)); - assertEquals(FILE_CONTENT, download.getContents()); + checkCompleteDownload(download); } public void testTitleAndDescription() throws Exception { @@ -138,9 +138,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS); download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); - assertEquals(FILE_CONTENT.length(), - download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); - assertEquals(FILE_CONTENT, download.getContents()); + checkCompleteDownload(download); List headers = takeRequest().getHeaders(); assertTrue("No Range header: " + headers, @@ -150,30 +148,32 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { public void testInterruptedExternalDownload() throws Exception { enqueueInterruptedDownloadResponses(5); - Uri destination = getExternalUri(); - Download download = enqueueRequest(getRequest().setDestinationUri(destination)); + Download download = enqueueRequest(getRequest().setDestinationUri(getExternalUri())); download.runUntilStatus(DownloadManager.STATUS_PAUSED); mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS); download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); - assertEquals(FILE_CONTENT, download.getContents()); + checkCompleteDownload(download); } private void enqueueInterruptedDownloadResponses(int initialLength) { - int totalLength = FILE_CONTENT.length(); // the first response has normal headers but unexpectedly closes after initialLength bytes - enqueuePartialResponse(initialLength); + enqueuePartialResponse(0, initialLength); // the second response returns partial content for the rest of the data - enqueueResponse(HTTP_PARTIAL_CONTENT, FILE_CONTENT.substring(initialLength)) - .addHeader("Content-range", - "bytes " + initialLength + "-" + totalLength + "/" + totalLength) - .addHeader("Etag", ETAG); + enqueuePartialResponse(initialLength, FILE_CONTENT.length()); } - private MockResponse enqueuePartialResponse(int initialLength) { - return enqueueResponse(HTTP_OK, FILE_CONTENT.substring(0, initialLength)) - .addHeader("Content-length", FILE_CONTENT.length()) - .addHeader("Etag", ETAG) - .setCloseConnectionAfter(true); + private MockResponse enqueuePartialResponse(int start, int end) { + int totalLength = FILE_CONTENT.length(); + boolean isFirstResponse = (start == 0); + int status = isFirstResponse ? HTTP_OK : HTTP_PARTIAL_CONTENT; + MockResponse response = enqueueResponse(status, FILE_CONTENT.substring(start, end)) + .addHeader("Content-length", totalLength) + .addHeader("Etag", ETAG); + if (!isFirstResponse) { + response.addHeader("Content-range", + "bytes " + start + "-" + totalLength + "/" + totalLength); + } + return response; } public void testFiltering() throws Exception { @@ -304,7 +304,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { } public void testNoEtag() throws Exception { - enqueuePartialResponse(5).removeHeader("Etag"); + enqueuePartialResponse(0, 5).removeHeader("Etag"); runSimpleFailureTest(HTTP_LENGTH_REQUIRED); } @@ -334,7 +334,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { } public void testCancel() throws Exception { - enqueuePartialResponse(5); + enqueuePartialResponse(0, 5); Download download = enqueueRequest(getRequest()); download.runUntilStatus(DownloadManager.STATUS_PAUSED); @@ -463,6 +463,30 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); } + public void testManyInterruptions() throws Exception { + int bytesPerResponse = 1; + int start = 0; + + Download download = enqueueRequest(getRequest()); + while (start + bytesPerResponse < FILE_CONTENT.length()) { + enqueuePartialResponse(start, start + bytesPerResponse); + download.runUntilStatus(DownloadManager.STATUS_PAUSED); + takeRequest(); + start += bytesPerResponse; + mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS); + } + + enqueuePartialResponse(start, FILE_CONTENT.length()); + download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); + checkCompleteDownload(download); + } + + private void checkCompleteDownload(Download download) throws Exception { + assertEquals(FILE_CONTENT.length(), + download.getLongField(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); + assertEquals(FILE_CONTENT, download.getContents()); + } + private void runSimpleFailureTest(int expectedErrorCode) throws Exception { Download download = enqueueRequest(getRequest()); download.runUntilStatus(DownloadManager.STATUS_FAILED); -- cgit v1.2.3