Migrate to shared MockWebServer.
Jeff Sharkey [Thu, 29 Mar 2012 20:38:24 +0000 (13:38 -0700)]
Bug: 4726601
Change-Id: Ibe537bd5c2a092dbf974360cd454751881f7f4ea

src/com/android/providers/downloads/DownloadThread.java
tests/Android.mk
tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java [moved from tests/src/com/android/providers/downloads/AbstractDownloadManagerFunctionalTest.java with 84% similarity]
tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
tests/src/com/android/providers/downloads/DownloadProviderFunctionalTest.java [moved from tests/src/com/android/providers/downloads/DownloadManagerFunctionalTest.java with 91% similarity]
tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
tests/src/com/android/providers/downloads/ThreadingTest.java
tests/src/tests/http/MockResponse.java [deleted file]
tests/src/tests/http/MockWebServer.java [deleted file]
tests/src/tests/http/RecordedRequest.java [deleted file]

index 197af66..1d2aceb 100644 (file)
@@ -974,5 +974,4 @@ public class DownloadThread extends Thread {
             mPolicyDirty = true;
         }
     };
-
 }
index 80a1c76..aaf32ba 100644 (file)
@@ -8,6 +8,7 @@ LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_INSTRUMENTATION_FOR := DownloadProvider
 LOCAL_JAVA_LIBRARIES := android.test.runner
+LOCAL_STATIC_JAVA_LIBRARIES := mockwebserver
 LOCAL_PACKAGE_NAME := DownloadProviderTests
 LOCAL_CERTIFICATE := media
 
@@ -29,9 +29,11 @@ import android.test.RenamingDelegatingContext;
 import android.test.ServiceTestCase;
 import android.test.mock.MockContentResolver;
 import android.util.Log;
-import tests.http.MockResponse;
-import tests.http.MockWebServer;
-import tests.http.RecordedRequest;
+
+import com.google.mockwebserver.MockResponse;
+import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
+import com.google.mockwebserver.SocketPolicy;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -39,14 +41,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.MalformedURLException;
+import java.net.UnknownHostException;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Set;
 
-public abstract class AbstractDownloadManagerFunctionalTest extends
+public abstract class AbstractDownloadProviderFunctionalTest extends
         ServiceTestCase<DownloadService> {
 
-    protected static final String LOG_TAG = "DownloadManagerFunctionalTest";
+    protected static final String LOG_TAG = "DownloadProviderFunctionalTest";
     private static final String PROVIDER_AUTHORITY = "downloads";
     protected static final long RETRY_DELAY_MILLIS = 61 * 1000;
     protected static final String FILE_CONTENT = "hello world hello world hello world hello world";
@@ -143,7 +146,7 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
         }
     }
 
-    public AbstractDownloadManagerFunctionalTest(FakeSystemFacade systemFacade) {
+    public AbstractDownloadProviderFunctionalTest(FakeSystemFacade systemFacade) {
         super(DownloadService.class);
         mSystemFacade = systemFacade;
     }
@@ -212,52 +215,42 @@ public abstract class AbstractDownloadManagerFunctionalTest extends
         mResolver.delete(Downloads.Impl.CONTENT_URI, null, null);
     }
 
-    /**
-     * Enqueue a String response from the MockWebServer.
-     */
-    MockResponse enqueueResponse(int status, String body) {
-        MockResponse response = new MockResponse()
-                                .setResponseCode(status)
-                                .setBody(body)
-                                .addHeader("Content-type", "text/plain")
-                                .setCloseConnectionAfter(true);
-        mServer.enqueue(response);
-        return response;
+    void enqueueResponse(MockResponse resp) {
+        mServer.enqueue(resp);
     }
-    /**
-     * Enqueue a byte[] response from the MockWebServer.
-     */
-    MockResponse enqueueResponse(int status, byte[] body) {
-        MockResponse response = new MockResponse()
-                                .setResponseCode(status)
-                                .setBody(body)
-                                .addHeader("Content-type", "text/plain")
-                                .setCloseConnectionAfter(true);
-        mServer.enqueue(response);
-        return response;
+
+    MockResponse buildResponse(int status, String body) {
+        return new MockResponse().setResponseCode(status).setBody(body)
+                .setHeader("Content-type", "text/plain")
+                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
+    }
+
+    MockResponse buildResponse(int status, byte[] body) {
+        return new MockResponse().setResponseCode(status).setBody(body)
+                .setHeader("Content-type", "text/plain")
+                .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
     }
 
-    MockResponse enqueueEmptyResponse(int status) {
-        return enqueueResponse(status, "");
+    MockResponse buildEmptyResponse(int status) {
+        return buildResponse(status, "");
     }
 
     /**
      * Fetch the last request received by the MockWebServer.
      */
     protected RecordedRequest takeRequest() throws InterruptedException {
-        RecordedRequest request = mServer.takeRequestWithTimeout(0);
+        RecordedRequest request = mServer.takeRequest();
         assertNotNull("Expected request was not made", request);
         return request;
     }
 
-    String getServerUri(String path) throws MalformedURLException {
+    String getServerUri(String path) throws MalformedURLException, UnknownHostException {
         return mServer.getUrl(path).toString();
     }
 
     public void runService() throws Exception {
         startService(null);
         mSystemFacade.runAllThreads();
-        mServer.checkForExceptions();
     }
 
     protected String readStream(InputStream inputStream) throws IOException {
index c38c2f1..cda607a 100644 (file)
@@ -26,11 +26,12 @@ import android.util.Log;
 import java.io.FileInputStream;
 import java.io.InputStream;
 import java.net.MalformedURLException;
+import java.net.UnknownHostException;
 
 /**
  * Code common to tests that use the download manager public API.
  */
-public abstract class AbstractPublicApiTest extends AbstractDownloadManagerFunctionalTest {
+public abstract class AbstractPublicApiTest extends AbstractDownloadProviderFunctionalTest {
 
     class Download {
         final long mId;
@@ -171,7 +172,8 @@ public abstract class AbstractPublicApiTest extends AbstractDownloadManagerFunct
         mManager = new DownloadManager(mResolver, PACKAGE_NAME);
     }
 
-    protected DownloadManager.Request getRequest() throws MalformedURLException {
+    protected DownloadManager.Request getRequest()
+            throws MalformedURLException, UnknownHostException {
         return getRequest(getServerUri(REQUEST_PATH));
     }
 
@@ -25,11 +25,12 @@ import android.provider.Downloads;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 
-import tests.http.MockWebServer;
-import tests.http.RecordedRequest;
+import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
 
 import java.io.InputStream;
 import java.net.MalformedURLException;
+import java.net.UnknownHostException;
 
 /**
  * This test exercises the entire download manager working together -- it requests downloads through
@@ -38,15 +39,15 @@ import java.net.MalformedURLException;
  * device to serve downloads.
  */
 @LargeTest
-public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFunctionalTest {
+public class DownloadProviderFunctionalTest extends AbstractDownloadProviderFunctionalTest {
     private static final String TAG = "DownloadManagerFunctionalTest";
 
-    public DownloadManagerFunctionalTest() {
+    public DownloadProviderFunctionalTest() {
         super(new FakeSystemFacade());
     }
 
     public void testDownloadTextFile() throws Exception {
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
 
         String path = "/download_manager_test_path";
         Uri downloadUri = requestDownload(path);
@@ -63,7 +64,8 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
     }
 
     public void testDownloadToCache() throws Exception {
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
+
         Uri downloadUri = requestDownload("/path");
         updateDownload(downloadUri, Downloads.Impl.COLUMN_DESTINATION,
                        Integer.toString(Downloads.Impl.DESTINATION_CACHE_PARTITION));
@@ -74,11 +76,13 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
     }
 
     public void testRoaming() throws Exception {
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
+
         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
         mSystemFacade.mIsRoaming = true;
 
         // for a normal download, roaming is fine
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
         Uri downloadUri = requestDownload("/path");
         runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
 
@@ -89,7 +93,6 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
         runUntilStatus(downloadUri, Downloads.Impl.STATUS_WAITING_FOR_NETWORK);
 
         // ...and pick up when we're off roaming
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
         mSystemFacade.mIsRoaming = false;
         runUntilStatus(downloadUri, Downloads.Impl.STATUS_SUCCESS);
     }
@@ -145,7 +148,7 @@ public class DownloadManagerFunctionalTest extends AbstractDownloadManagerFuncti
     /**
      * Request a download from the Download Manager.
      */
-    private Uri requestDownload(String path) throws MalformedURLException {
+    private Uri requestDownload(String path) throws MalformedURLException, UnknownHostException {
         ContentValues values = new ContentValues();
         values.put(Downloads.Impl.COLUMN_URI, getServerUri(path));
         values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_EXTERNAL);
index f2a26f1..2f5282a 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.providers.downloads;
 
-
 import android.app.DownloadManager;
 import android.content.Intent;
 import android.database.Cursor;
@@ -25,9 +24,10 @@ import android.net.Uri;
 import android.os.Environment;
 import android.provider.Downloads;
 import android.test.suitebuilder.annotation.LargeTest;
+import android.util.Log;
 
-import tests.http.MockResponse;
-import tests.http.RecordedRequest;
+import com.google.mockwebserver.MockResponse;
+import com.google.mockwebserver.RecordedRequest;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -76,7 +76,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testBasicRequest() throws Exception {
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
 
         Download download = enqueueRequest(getRequest());
         assertEquals(DownloadManager.STATUS_PENDING,
@@ -126,12 +126,12 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testDownloadError() throws Exception {
-        enqueueEmptyResponse(HTTP_NOT_FOUND);
+        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
         runSimpleFailureTest(HTTP_NOT_FOUND);
     }
 
     public void testUnhandledHttpStatus() throws Exception {
-        enqueueEmptyResponse(1234); // some invalid HTTP status
+        enqueueResponse(buildEmptyResponse(1234)); // some invalid HTTP status
         runSimpleFailureTest(DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
     }
 
@@ -168,21 +168,21 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
 
     private void enqueueInterruptedDownloadResponses(int initialLength) {
         // the first response has normal headers but unexpectedly closes after initialLength bytes
-        enqueuePartialResponse(0, initialLength);
+        enqueueResponse(buildPartialResponse(0, initialLength));
         // the second response returns partial content for the rest of the data
-        enqueuePartialResponse(initialLength, FILE_CONTENT.length());
+        enqueueResponse(buildPartialResponse(initialLength, FILE_CONTENT.length()));
     }
 
-    private MockResponse enqueuePartialResponse(int start, int end) {
+    private MockResponse buildPartialResponse(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);
+        MockResponse response = buildResponse(status, FILE_CONTENT.substring(start, end))
+                .setHeader("Content-length", totalLength)
+                .setHeader("Etag", ETAG);
         if (!isFirstResponse) {
-            response.addHeader("Content-range",
-                    "bytes " + start + "-" + totalLength + "/" + totalLength);
+            response.setHeader(
+                    "Content-range", "bytes " + start + "-" + totalLength + "/" + totalLength);
         }
         return response;
     }
@@ -190,20 +190,21 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     // enqueue a huge response to keep the receiveing thread in DownloadThread.java busy for a while
     // give enough time to do something (cancel/remove etc) on that downloadrequest
     // while it is in progress
-    private void enqueueContinuingResponse() {
+    private MockResponse buildContinuingResponse() {
         int numPackets = 100;
-        int contentLength =  STRING_1K.length() * numPackets;
-        enqueueResponse(HTTP_OK, STRING_1K)
-               .addHeader("Content-length", contentLength)
-               .addHeader("Etag", ETAG)
-               .setNumPackets(numPackets);
+        int contentLength = STRING_1K.length() * numPackets;
+        return buildResponse(HTTP_OK, STRING_1K)
+               .setHeader("Content-length", contentLength)
+               .setHeader("Etag", ETAG)
+               .setBytesPerSecond(1024);
     }
 
     public void testFiltering() throws Exception {
-        enqueueEmptyResponse(HTTP_OK);
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
+
         Download download1 = enqueueRequest(getRequest());
         download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
-        enqueueEmptyResponse(HTTP_NOT_FOUND);
 
         mSystemFacade.incrementTimeMillis(1); // ensure downloads are correctly ordered by time
         Download download2 = enqueueRequest(getRequest());
@@ -240,17 +241,18 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testOrdering() throws Exception {
-        enqueueResponse(HTTP_OK, "small contents");
+        enqueueResponse(buildResponse(HTTP_OK, "small contents"));
+        enqueueResponse(buildResponse(HTTP_OK, "large contents large contents"));
+        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
+
         Download download1 = enqueueRequest(getRequest());
         download1.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
 
         mSystemFacade.incrementTimeMillis(1);
-        enqueueResponse(HTTP_OK, "large contents large contents");
         Download download2 = enqueueRequest(getRequest());
         download2.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
 
         mSystemFacade.incrementTimeMillis(1);
-        enqueueEmptyResponse(HTTP_NOT_FOUND);
         Download download3 = enqueueRequest(getRequest());
         download3.runUntilStatus(DownloadManager.STATUS_FAILED);
 
@@ -299,7 +301,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testDestination() throws Exception {
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
         Uri destination = getExternalUri();
         Download download = enqueueRequest(getRequest().setDestinationUri(destination));
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
@@ -320,7 +322,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testRequestHeaders() throws Exception {
-        enqueueEmptyResponse(HTTP_OK);
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
         Download download = enqueueRequest(getRequest().addRequestHeader("Header1", "value1")
                                            .addRequestHeader("Header2", "value2"));
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
@@ -342,17 +344,17 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testSizeLimitOverMobile() throws Exception {
-        mSystemFacade.mMaxBytesOverMobile = (long) FILE_CONTENT.length() - 1;
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
 
+        mSystemFacade.mMaxBytesOverMobile = (long) FILE_CONTENT.length() - 1;
         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_PAUSED);
 
         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
         // first response was read, but aborted after the DL manager processed the Content-Length
         // header, so we need to enqueue a second one
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
     }
 
@@ -369,27 +371,28 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testNoEtag() throws Exception {
-        enqueuePartialResponse(0, 5).removeHeader("Etag");
+        enqueueResponse(buildPartialResponse(0, 5).removeHeader("Etag"));
         runSimpleFailureTest(DownloadManager.ERROR_CANNOT_RESUME);
     }
 
     public void testSanitizeMediaType() throws Exception {
-        enqueueEmptyResponse(HTTP_OK).addHeader("Content-Type", "text/html; charset=ISO-8859-4");
+        enqueueResponse(buildEmptyResponse(HTTP_OK)
+                .setHeader("Content-Type", "text/html; charset=ISO-8859-4"));
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
         assertEquals("text/html", download.getStringField(DownloadManager.COLUMN_MEDIA_TYPE));
     }
 
     public void testNoContentLength() throws Exception {
-        enqueueEmptyResponse(HTTP_OK).removeHeader("Content-Length");
+        enqueueResponse(buildEmptyResponse(HTTP_OK).removeHeader("Content-length"));
         runSimpleFailureTest(DownloadManager.ERROR_HTTP_DATA_ERROR);
     }
 
     public void testInsufficientSpace() throws Exception {
         // this would be better done by stubbing the system API to check available space, but in the
         // meantime, just use an absurdly large header value
-        enqueueEmptyResponse(HTTP_OK).addHeader("Content-Length",
-                                                1024L * 1024 * 1024 * 1024 * 1024);
+        enqueueResponse(buildEmptyResponse(HTTP_OK)
+                .setHeader("Content-Length", 1024L * 1024 * 1024 * 1024 * 1024));
         runSimpleFailureTest(DownloadManager.ERROR_INSUFFICIENT_SPACE);
     }
 
@@ -397,7 +400,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
         mSystemFacade.setStartThreadsWithoutWaiting(true);
         // return 'real time' from FakeSystemFacade so that DownloadThread will report progress
         mSystemFacade.setReturnActualTime(true);
-        enqueueContinuingResponse();
+        enqueueResponse(buildContinuingResponse());
         Download download = enqueueRequest(getRequest());
         startService(null);
         // give the download time to get started and progress to 1% completion
@@ -413,7 +416,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testDownloadCompleteBroadcast() throws Exception {
-        enqueueEmptyResponse(HTTP_OK);
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
 
@@ -441,12 +444,11 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testBasicConnectivityChanges() throws Exception {
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
+
         // without connectivity, download immediately pauses
         mSystemFacade.mActiveNetworkType = null;
-
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
         Download download = enqueueRequest(getRequest());
-
         download.runUntilStatus(DownloadManager.STATUS_PAUSED);
 
         // connecting should start the download
@@ -455,10 +457,12 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testAllowedNetworkTypes() throws Exception {
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_MOBILE;
 
         // by default, use any connection
-        enqueueEmptyResponse(HTTP_OK);
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
 
@@ -468,15 +472,16 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
         download.runUntilStatus(DownloadManager.STATUS_PAUSED);
         // ...then enable wifi
         mSystemFacade.mActiveNetworkType = ConnectivityManager.TYPE_WIFI;
-        enqueueEmptyResponse(HTTP_OK);
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
     }
 
     public void testRoaming() throws Exception {
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         mSystemFacade.mIsRoaming = true;
 
         // by default, allow roaming
-        enqueueEmptyResponse(HTTP_OK);
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
 
@@ -485,12 +490,11 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
         download.runUntilStatus(DownloadManager.STATUS_PAUSED);
         // ...then turn off roaming
         mSystemFacade.mIsRoaming = false;
-        enqueueEmptyResponse(HTTP_OK);
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
     }
 
     public void testContentObserver() throws Exception {
-        enqueueEmptyResponse(HTTP_OK);
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
         enqueueRequest(getRequest());
         mResolver.resetNotified();
         runService();
@@ -498,13 +502,14 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testNotifications() throws Exception {
-        enqueueEmptyResponse(HTTP_OK);
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         Download download = enqueueRequest(getRequest().setShowRunningNotification(false));
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
         assertEquals(0, mSystemFacade.mActiveNotifications.size());
         assertEquals(0, mSystemFacade.mCanceledNotifications.size());
 
-        enqueueEmptyResponse(HTTP_OK);
         download = enqueueRequest(getRequest()); // notifications by default
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
         assertEquals(1, mSystemFacade.mActiveNotifications.size());
@@ -518,43 +523,43 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
 
     public void testRetryAfter() throws Exception {
         final int delay = 120;
-        enqueueEmptyResponse(HTTP_SERVICE_UNAVAILABLE).addHeader("Retry-after", delay);
+        enqueueResponse(
+                buildEmptyResponse(HTTP_SERVICE_UNAVAILABLE).setHeader("Retry-after", delay));
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         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);
     }
 
     public void testManyInterruptions() throws Exception {
-        int bytesPerResponse = 1;
-        int start = 0;
+        final int length = FILE_CONTENT.length();
+        for (int i = 0; i < length; i++) {
+            enqueueResponse(buildPartialResponse(i, i + 1));
+        }
 
         Download download = enqueueRequest(getRequest());
-        while (start + bytesPerResponse < FILE_CONTENT.length()) {
-            enqueuePartialResponse(start, start + bytesPerResponse);
+        for (int i = 0; i < length - 1; i++) {
             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);
     }
 
     public void testExistingFile() throws Exception {
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         // download a file which already exists.
         // downloadservice should simply create filename with "-" and a number attached
         // at the end; i.e., download shouldnot fail.
         Uri destination = getExternalUri();
         new File(destination.getPath()).createNewFile();
 
-        enqueueEmptyResponse(HTTP_OK);
         Download download = enqueueRequest(getRequest().setDestinationUri(destination));
         download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL);
     }
@@ -571,11 +576,12 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
     }
 
     public void testRestart() throws Exception {
-        enqueueEmptyResponse(HTTP_NOT_FOUND);
+        enqueueResponse(buildEmptyResponse(HTTP_NOT_FOUND));
+        enqueueResponse(buildEmptyResponse(HTTP_OK));
+
         Download download = enqueueRequest(getRequest());
         download.runUntilStatus(DownloadManager.STATUS_FAILED);
 
-        enqueueEmptyResponse(HTTP_OK);
         mManager.restartDownload(download.mId);
         assertEquals(DownloadManager.STATUS_PENDING,
                 download.getLongField(DownloadManager.COLUMN_STATUS));
@@ -604,8 +610,8 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
      */
     private RecordedRequest runRedirectionTest(int status)
             throws MalformedURLException, Exception {
-        enqueueEmptyResponse(status).addHeader("Location",
-                                               mServer.getUrl(REDIRECTED_PATH).toString());
+        enqueueResponse(buildEmptyResponse(status)
+                .setHeader("Location", mServer.getUrl(REDIRECTED_PATH).toString()));
         enqueueInterruptedDownloadResponses(5);
 
         Download download = enqueueRequest(getRequest());
index 082579e..8605c76 100644 (file)
@@ -46,7 +46,7 @@ public class ThreadingTest extends AbstractPublicApiTest {
      * a download.
      */
     public void testFloodServiceWithStarts() throws Exception {
-        enqueueResponse(HTTP_OK, FILE_CONTENT);
+        enqueueResponse(buildResponse(HTTP_OK, FILE_CONTENT));
         Download download = enqueueRequest(getRequest());
         while (download.getStatus() != DownloadManager.STATUS_SUCCESSFUL) {
             startService(null);
diff --git a/tests/src/tests/http/MockResponse.java b/tests/src/tests/http/MockResponse.java
deleted file mode 100644 (file)
index aec5490..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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 tests.http;
-
-import static tests.http.MockWebServer.ASCII;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A scripted response to be replayed by the mock web server.
- */
-public class MockResponse {
-    private static final byte[] EMPTY_BODY = new byte[0];
-
-    private String status = "HTTP/1.1 200 OK";
-    private Map<String, String> headers = new HashMap<String, String>();
-    private byte[] body = EMPTY_BODY;
-    private boolean closeConnectionAfter = false;
-    private int numPackets = 0;
-
-    public MockResponse() {
-        addHeader("Content-Length", 0);
-    }
-
-    /**
-     * Returns the HTTP response line, such as "HTTP/1.1 200 OK".
-     */
-    public String getStatus() {
-        return status;
-    }
-
-    public MockResponse setResponseCode(int code) {
-        this.status = "HTTP/1.1 " + code + " OK";
-        return this;
-    }
-
-    /**
-     * Returns the HTTP headers, such as "Content-Length: 0".
-     */
-    public List<String> getHeaders() {
-        List<String> headerStrings = new ArrayList<String>();
-        for (String header : headers.keySet()) {
-            headerStrings.add(header + ": " + headers.get(header));
-        }
-        return headerStrings;
-    }
-
-    public MockResponse addHeader(String header, String value) {
-        headers.put(header.toLowerCase(), value);
-        return this;
-    }
-
-    public MockResponse addHeader(String header, long value) {
-        return addHeader(header, Long.toString(value));
-    }
-
-    public MockResponse removeHeader(String header) {
-        headers.remove(header.toLowerCase());
-        return this;
-    }
-
-    /**
-     * Returns an input stream containing the raw HTTP payload.
-     */
-    public byte[] getBody() {
-        return body;
-    }
-
-    public MockResponse setBody(byte[] body) {
-        addHeader("Content-Length", body.length);
-        this.body = body;
-        return this;
-    }
-
-    public MockResponse setBody(String body) {
-        try {
-            return setBody(body.getBytes(ASCII));
-        } catch (UnsupportedEncodingException e) {
-            throw new AssertionError();
-        }
-    }
-
-    public MockResponse setChunkedBody(byte[] body, int maxChunkSize) throws IOException {
-        addHeader("Transfer-encoding", "chunked");
-
-        ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
-        int pos = 0;
-        while (pos < body.length) {
-            int chunkSize = Math.min(body.length - pos, maxChunkSize);
-            bytesOut.write(Integer.toHexString(chunkSize).getBytes(ASCII));
-            bytesOut.write("\r\n".getBytes(ASCII));
-            bytesOut.write(body, pos, chunkSize);
-            bytesOut.write("\r\n".getBytes(ASCII));
-            pos += chunkSize;
-        }
-        bytesOut.write("0\r\n".getBytes(ASCII));
-        this.body = bytesOut.toByteArray();
-        return this;
-    }
-
-    public MockResponse setChunkedBody(String body, int maxChunkSize) throws IOException {
-        return setChunkedBody(body.getBytes(ASCII), maxChunkSize);
-    }
-
-    @Override public String toString() {
-        return status;
-    }
-
-    public boolean shouldCloseConnectionAfter() {
-        return closeConnectionAfter;
-    }
-
-    public MockResponse setCloseConnectionAfter(boolean closeConnectionAfter) {
-        this.closeConnectionAfter = closeConnectionAfter;
-        return this;
-    }
-
-    public int getNumPackets() {
-        return numPackets;
-    }
-
-    public MockResponse setNumPackets(int numPackets) {
-        this.numPackets = numPackets;
-        return this;
-    }
-
-}
diff --git a/tests/src/tests/http/MockWebServer.java b/tests/src/tests/http/MockWebServer.java
deleted file mode 100644 (file)
index 6096783..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * 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 tests.http;
-
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * A scriptable web server. Callers supply canned responses and the server
- * replays them upon request in sequence.
- *
- * TODO: merge with the version from libcore/support/src/tests/java once it's in.
- */
-public final class MockWebServer {
-    static final String ASCII = "US-ASCII";
-
-    private final BlockingQueue<RecordedRequest> requestQueue
-            = new LinkedBlockingQueue<RecordedRequest>();
-    private final BlockingQueue<MockResponse> responseQueue
-            = new LinkedBlockingQueue<MockResponse>();
-    private int bodyLimit = Integer.MAX_VALUE;
-    private final ExecutorService executor = Executors.newCachedThreadPool();
-    // keep Futures around so we can rethrow any exceptions thrown by Callables
-    private final Queue<Future<?>> futures = new LinkedList<Future<?>>();
-
-    private int port = -1;
-    private ServerSocket serverSocket;
-
-    public int getPort() {
-        if (port == -1) {
-            throw new IllegalStateException("Cannot retrieve port before calling play()");
-        }
-        return port;
-    }
-
-    /**
-     * Returns a URL for connecting to this server.
-     *
-     * @param path the request path, such as "/".
-     */
-    public URL getUrl(String path) throws MalformedURLException {
-        return new URL("http://localhost:" + getPort() + path);
-    }
-
-    /**
-     * Sets the number of bytes of the POST body to keep in memory to the given
-     * limit.
-     */
-    public void setBodyLimit(int maxBodyLength) {
-        this.bodyLimit = maxBodyLength;
-    }
-
-    public void enqueue(MockResponse response) {
-        responseQueue.add(response);
-    }
-
-    /**
-     * Awaits the next HTTP request, removes it, and returns it. Callers should
-     * use this to verify the request sent was as intended.
-     */
-    public RecordedRequest takeRequest() throws InterruptedException {
-        return requestQueue.take();
-    }
-
-    public RecordedRequest takeRequestWithTimeout(long timeoutMillis) throws InterruptedException {
-        return requestQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS);
-    }
-
-    public List<RecordedRequest> drainRequests() {
-        List<RecordedRequest> requests = new ArrayList<RecordedRequest>();
-        requestQueue.drainTo(requests);
-        return requests;
-    }
-
-    /**
-     * Starts the server, serves all enqueued requests, and shuts the server
-     * down.
-     */
-    public void play() throws IOException {
-        serverSocket = new ServerSocket(0);
-        serverSocket.setReuseAddress(true);
-        port = serverSocket.getLocalPort();
-        submitCallable(new Callable<Void>() {
-            public Void call() throws Exception {
-                int count = 0;
-                while (true) {
-                    if (count > 0 && responseQueue.isEmpty()) {
-                        serverSocket.close();
-                        executor.shutdown();
-                        return null;
-                    }
-
-                    serveConnection(serverSocket.accept());
-                    count++;
-                }
-            }
-        });
-    }
-
-    /**
-     * shutdown the webserver
-     */
-    public void shutdown() throws IOException {
-        responseQueue.clear();
-        serverSocket.close();
-        executor.shutdown();
-    }
-
-    private void serveConnection(final Socket s) {
-        submitCallable(new Callable<Void>() {
-            public Void call() throws Exception {
-                InputStream in = new BufferedInputStream(s.getInputStream());
-                OutputStream out = new BufferedOutputStream(s.getOutputStream());
-
-                int sequenceNumber = 0;
-                while (true) {
-                    RecordedRequest request = readRequest(in, sequenceNumber);
-                    if (request == null) {
-                        if (sequenceNumber == 0) {
-                            throw new IllegalStateException("Connection without any request!");
-                        } else {
-                            break;
-                        }
-                    }
-                    requestQueue.add(request);
-                    MockResponse response = sendResponse(out, request);
-                    if (response.shouldCloseConnectionAfter()) {
-                        break;
-                    }
-                    sequenceNumber++;
-                }
-
-                in.close();
-                out.close();
-                return null;
-            }
-        });
-    }
-
-    private void submitCallable(Callable<?> callable) {
-        Future<?> future = executor.submit(callable);
-        futures.add(future);
-    }
-
-    /**
-     * Check for and raise any exceptions that have been thrown by child threads.  Will not block on
-     * children still running.
-     * @throws ExecutionException for the first child thread that threw an exception
-     */
-    public void checkForExceptions() throws ExecutionException, InterruptedException {
-        final int originalSize = futures.size();
-        for (int i = 0; i < originalSize; i++) {
-            Future<?> future = futures.remove();
-            try {
-                future.get(0, TimeUnit.SECONDS);
-            } catch (TimeoutException e) {
-                futures.add(future); // still running
-            }
-        }
-    }
-
-    /**
-     * @param sequenceNumber the index of this request on this connection.
-     */
-    private RecordedRequest readRequest(InputStream in, int sequenceNumber) throws IOException {
-        String request = readAsciiUntilCrlf(in);
-        if (request.equals("")) {
-            return null; // end of data; no more requests
-        }
-
-        List<String> headers = new ArrayList<String>();
-        int contentLength = -1;
-        boolean chunked = false;
-        String header;
-        while (!(header = readAsciiUntilCrlf(in)).equals("")) {
-            headers.add(header);
-            String lowercaseHeader = header.toLowerCase();
-            if (contentLength == -1 && lowercaseHeader.startsWith("content-length:")) {
-                contentLength = Integer.parseInt(header.substring(15).trim());
-            }
-            if (lowercaseHeader.startsWith("transfer-encoding:") &&
-                    lowercaseHeader.substring(18).trim().equals("chunked")) {
-                chunked = true;
-            }
-        }
-
-        boolean hasBody = false;
-        TruncatingOutputStream requestBody = new TruncatingOutputStream();
-        List<Integer> chunkSizes = new ArrayList<Integer>();
-        if (contentLength != -1) {
-            hasBody = true;
-            transfer(contentLength, in, requestBody);
-        } else if (chunked) {
-            hasBody = true;
-            while (true) {
-                int chunkSize = Integer.parseInt(readAsciiUntilCrlf(in).trim(), 16);
-                if (chunkSize == 0) {
-                    readEmptyLine(in);
-                    break;
-                }
-                chunkSizes.add(chunkSize);
-                transfer(chunkSize, in, requestBody);
-                readEmptyLine(in);
-            }
-        }
-
-        if (request.startsWith("GET ")) {
-            if (hasBody) {
-                throw new IllegalArgumentException("GET requests should not have a body!");
-            }
-        } else if (request.startsWith("POST ")) {
-            if (!hasBody) {
-                throw new IllegalArgumentException("POST requests must have a body!");
-            }
-        } else {
-            throw new UnsupportedOperationException("Unexpected method: " + request);
-        }
-        return new RecordedRequest(request, headers, chunkSizes,
-                requestBody.numBytesReceived, requestBody.toByteArray(), sequenceNumber);
-    }
-
-    /**
-     * Returns a response to satisfy {@code request}.
-     */
-    private MockResponse sendResponse(OutputStream out, RecordedRequest request)
-            throws InterruptedException, IOException {
-        if (responseQueue.isEmpty()) {
-            throw new IllegalStateException("Unexpected request: " + request);
-        }
-        MockResponse response = responseQueue.take();
-        writeResponse(out, response, false);
-        if (response.getNumPackets() > 0) {
-            // there are continuing packets to send as part of this response.
-            for (int i = 0; i < response.getNumPackets(); i++) {
-                writeResponse(out, response, true);
-                // delay sending next continuing response just a little bit
-                Thread.sleep(100);
-            }
-        }
-        return response;
-     }
-
-    private void writeResponse(OutputStream out, MockResponse response,
-            boolean continuingPacket) throws IOException {
-        if (continuingPacket) {
-            // this is a continuing response - just send the body - no headers, status
-            out.write(response.getBody());
-            out.flush();
-            return;
-        }
-        out.write((response.getStatus() + "\r\n").getBytes(ASCII));
-        for (String header : response.getHeaders()) {
-            out.write((header + "\r\n").getBytes(ASCII));
-        }
-        out.write(("\r\n").getBytes(ASCII));
-        out.write(response.getBody());
-        out.flush();
-    }
-
-    /**
-     * Transfer bytes from {@code in} to {@code out} until either {@code length}
-     * bytes have been transferred or {@code in} is exhausted.
-     */
-    private void transfer(int length, InputStream in, OutputStream out) throws IOException {
-        byte[] buffer = new byte[1024];
-        while (length > 0) {
-            int count = in.read(buffer, 0, Math.min(buffer.length, length));
-            if (count == -1) {
-                return;
-            }
-            out.write(buffer, 0, count);
-            length -= count;
-        }
-    }
-
-    /**
-     * Returns the text from {@code in} until the next "\r\n", or null if
-     * {@code in} is exhausted.
-     */
-    private String readAsciiUntilCrlf(InputStream in) throws IOException {
-        StringBuilder builder = new StringBuilder();
-        while (true) {
-            int c = in.read();
-            if (c == '\n' && builder.length() > 0 && builder.charAt(builder.length() - 1) == '\r') {
-                builder.deleteCharAt(builder.length() - 1);
-                return builder.toString();
-            } else if (c == -1) {
-                return builder.toString();
-            } else {
-                builder.append((char) c);
-            }
-        }
-    }
-
-    private void readEmptyLine(InputStream in) throws IOException {
-        String line = readAsciiUntilCrlf(in);
-        if (!line.equals("")) {
-            throw new IllegalStateException("Expected empty but was: " + line);
-        }
-    }
-
-    /**
-     * An output stream that drops data after bodyLimit bytes.
-     */
-    private class TruncatingOutputStream extends ByteArrayOutputStream {
-        private int numBytesReceived = 0;
-        @Override public void write(byte[] buffer, int offset, int len) {
-            numBytesReceived += len;
-            super.write(buffer, offset, Math.min(len, bodyLimit - count));
-        }
-        @Override public void write(int oneByte) {
-            numBytesReceived++;
-            if (count < bodyLimit) {
-                super.write(oneByte);
-            }
-        }
-    }
-}
diff --git a/tests/src/tests/http/RecordedRequest.java b/tests/src/tests/http/RecordedRequest.java
deleted file mode 100644 (file)
index 6b67af2..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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 tests.http;
-
-import java.util.List;
-
-/**
- * An HTTP request that came into the mock web server.
- */
-public final class RecordedRequest {
-    private final String requestLine;
-    private final List<String> headers;
-    private final List<Integer> chunkSizes;
-    private final int bodySize;
-    private final byte[] body;
-    private final int sequenceNumber;
-
-    RecordedRequest(String requestLine, List<String> headers, List<Integer> chunkSizes,
-            int bodySize, byte[] body, int sequenceNumber) {
-        this.requestLine = requestLine;
-        this.headers = headers;
-        this.chunkSizes = chunkSizes;
-        this.bodySize = bodySize;
-        this.body = body;
-        this.sequenceNumber = sequenceNumber;
-    }
-
-    public String getRequestLine() {
-        return requestLine;
-    }
-
-    public List<String> getHeaders() {
-        return headers;
-    }
-
-    /**
-     * Returns the sizes of the chunks of this request's body, or an empty list
-     * if the request's body was empty or unchunked.
-     */
-    public List<Integer> getChunkSizes() {
-        return chunkSizes;
-    }
-
-    /**
-     * Returns the total size of the body of this POST request (before
-     * truncation).
-     */
-    public int getBodySize() {
-        return bodySize;
-    }
-
-    /**
-     * Returns the body of this POST request. This may be truncated.
-     */
-    public byte[] getBody() {
-        return body;
-    }
-
-    /**
-     * Returns the index of this request on its HTTP connection. Since a single
-     * HTTP connection may serve multiple requests, each request is assigned its
-     * own sequence number.
-     */
-    public int getSequenceNumber() {
-        return sequenceNumber;
-    }
-
-    @Override public String toString() {
-        return requestLine;
-    }
-
-    public String getMethod() {
-        return getRequestLine().split(" ")[0];
-    }
-
-    public String getPath() {
-        return getRequestLine().split(" ")[1];
-    }
-}