summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/AndroidManifest.xml2
-rw-r--r--tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java36
-rw-r--r--tests/src/com/android/providers/downloads/AbstractPublicApiTest.java15
-rw-r--r--tests/src/com/android/providers/downloads/FakeSystemFacade.java4
-rw-r--r--tests/src/com/android/providers/downloads/HelpersTest.java68
-rw-r--r--tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java14
-rw-r--r--tests/src/com/android/providers/downloads/StorageTest.java248
-rw-r--r--tests/src/com/android/providers/downloads/ThreadingTest.java11
8 files changed, 352 insertions, 46 deletions
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index d520123f..ec73ca2e 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -19,6 +19,8 @@
package="com.android.providers.downloads.tests"
android:sharedUserId="android.media">
+ <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED" />
+
<application>
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java b/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
index 3b937389..28c5dc7d 100644
--- a/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractDownloadProviderFunctionalTest.java
@@ -74,15 +74,18 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
static class MockContentResolverWithNotify extends MockContentResolver {
public boolean mNotifyWasCalled = false;
+ public MockContentResolverWithNotify(Context context) {
+ super(context);
+ }
+
public synchronized void resetNotified() {
mNotifyWasCalled = false;
}
@Override
- public synchronized void notifyChange(Uri uri, ContentObserver observer,
- boolean syncToNetwork) {
+ public synchronized void notifyChange(
+ Uri uri, ContentObserver observer, boolean syncToNetwork) {
mNotifyWasCalled = true;
- notifyAll();
}
}
@@ -94,20 +97,17 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
static class TestContext extends RenamingDelegatingContext {
private static final String FILENAME_PREFIX = "test.";
- private ContentResolver mResolver;
+ private final ContentResolver mResolver;
private final NotificationManager mNotifManager;
boolean mHasServiceBeenStarted = false;
public TestContext(Context realContext) {
super(realContext, FILENAME_PREFIX);
+ mResolver = new MockContentResolverWithNotify(this);
mNotifManager = mock(NotificationManager.class);
}
- public void setResolver(ContentResolver resolver) {
- mResolver = resolver;
- }
-
/**
* Direct DownloadService to our test instance of DownloadProvider.
*/
@@ -156,12 +156,20 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString());
final Context realContext = getContext();
+
mTestContext = new TestContext(realContext);
- setupProviderAndResolver();
- mTestContext.setResolver(mResolver);
+ mResolver = (MockContentResolverWithNotify) mTestContext.getContentResolver();
+
+ final DownloadProvider provider = new DownloadProvider();
+ provider.mSystemFacade = mSystemFacade;
+ provider.attachInfo(mTestContext, null);
+
+ mResolver.addProvider(PROVIDER_AUTHORITY, provider);
+
setContext(mTestContext);
setupService();
getService().mSystemFacade = mSystemFacade;
+
mSystemFacade.setUp();
assertTrue(isDatabaseEmpty()); // ensure we're not messing with real data
mServer = new MockWebServer();
@@ -186,14 +194,6 @@ public abstract class AbstractDownloadProviderFunctionalTest extends
}
}
- void setupProviderAndResolver() {
- DownloadProvider provider = new DownloadProvider();
- provider.mSystemFacade = mSystemFacade;
- provider.attachInfo(mTestContext, null);
- mResolver = new MockContentResolverWithNotify();
- mResolver.addProvider(PROVIDER_AUTHORITY, provider);
- }
-
/**
* Remove any downloaded files and delete any lingering downloads.
*/
diff --git a/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
index 348dbd1b..2846c7af 100644
--- a/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
+++ b/tests/src/com/android/providers/downloads/AbstractPublicApiTest.java
@@ -28,6 +28,9 @@ import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.util.Log;
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
@@ -91,19 +94,23 @@ public abstract class AbstractPublicApiTest extends AbstractDownloadProviderFunc
}
}
- String getContents() throws Exception {
+ byte[] getRawContents() throws Exception {
ParcelFileDescriptor downloadedFile = mManager.openDownloadedFile(mId);
assertTrue("Invalid file descriptor: " + downloadedFile,
downloadedFile.getFileDescriptor().valid());
- final InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(
+ final InputStream is = new ParcelFileDescriptor.AutoCloseInputStream(
downloadedFile);
try {
- return readStream(stream);
+ return Streams.readFully(is);
} finally {
- stream.close();
+ IoUtils.closeQuietly(is);
}
}
+ String getContents() throws Exception {
+ return new String(getRawContents());
+ }
+
void runUntilStatus(int status) throws TimeoutException {
final long startMillis = mSystemFacade.currentTimeMillis();
startService(null);
diff --git a/tests/src/com/android/providers/downloads/FakeSystemFacade.java b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
index d54c1224..5a15d399 100644
--- a/tests/src/com/android/providers/downloads/FakeSystemFacade.java
+++ b/tests/src/com/android/providers/downloads/FakeSystemFacade.java
@@ -64,12 +64,12 @@ public class FakeSystemFacade implements SystemFacade {
@Override
public Long getMaxBytesOverMobile() {
- return mMaxBytesOverMobile ;
+ return mMaxBytesOverMobile;
}
@Override
public Long getRecommendedMaxBytesOverMobile() {
- return mRecommendedMaxBytesOverMobile ;
+ return mRecommendedMaxBytesOverMobile;
}
@Override
diff --git a/tests/src/com/android/providers/downloads/HelpersTest.java b/tests/src/com/android/providers/downloads/HelpersTest.java
index 50f4c44c..121b7cda 100644
--- a/tests/src/com/android/providers/downloads/HelpersTest.java
+++ b/tests/src/com/android/providers/downloads/HelpersTest.java
@@ -16,29 +16,73 @@
package com.android.providers.downloads;
+import android.net.Uri;
import android.provider.Downloads;
import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
/**
* This test exercises methods in the {@Helpers} utility class.
*/
-@LargeTest
+@SmallTest
public class HelpersTest extends AndroidTestCase {
- public HelpersTest() {
+ @Override
+ protected void tearDown() throws Exception {
+ IoUtils.deleteContents(getContext().getFilesDir());
+ IoUtils.deleteContents(getContext().getCacheDir());
+
+ super.tearDown();
+ }
+
+ public void testGenerateSaveFile() throws Exception {
+ final File expected = new File(getContext().getFilesDir(), "file.mp4");
+ final String actual = Helpers.generateSaveFile(getContext(),
+ "http://example.com/file.txt", null, null, null,
+ "video/mp4", Downloads.Impl.DESTINATION_CACHE_PARTITION);
+ assertEquals(expected.getAbsolutePath(), actual);
+ }
+
+ public void testGenerateSaveFileDupes() throws Exception {
+ final File expected1 = new File(getContext().getFilesDir(), "file.txt");
+ final String actual1 = Helpers.generateSaveFile(getContext(), "http://example.com/file.txt",
+ null, null, null, null, Downloads.Impl.DESTINATION_CACHE_PARTITION);
+
+ final File expected2 = new File(getContext().getFilesDir(), "file-1.txt");
+ final String actual2 = Helpers.generateSaveFile(getContext(), "http://example.com/file.txt",
+ null, null, null, null, Downloads.Impl.DESTINATION_CACHE_PARTITION);
+
+ assertEquals(expected1.getAbsolutePath(), actual1);
+ assertEquals(expected2.getAbsolutePath(), actual2);
}
- public void testGetFullPath() throws Exception {
- String hint = "file:///com.android.providers.downloads/test";
+ public void testGenerateSaveFileNoExtension() throws Exception {
+ final File expected = new File(getContext().getFilesDir(), "file.mp4");
+ final String actual = Helpers.generateSaveFile(getContext(),
+ "http://example.com/file", null, null, null,
+ "video/mp4", Downloads.Impl.DESTINATION_CACHE_PARTITION);
+ assertEquals(expected.getAbsolutePath(), actual);
+ }
+
+ public void testGenerateSaveFileHint() throws Exception {
+ final File expected = new File(getContext().getFilesDir(), "meow");
+ final String hint = Uri.fromFile(expected).toString();
- // Test that we never change requested filename.
- String fileName = Helpers.getFullPath(
- hint,
- "video/mp4", // MIME type corresponding to file extension .mp4
- Downloads.Impl.DESTINATION_FILE_URI,
- null);
- assertEquals(hint, fileName);
+ // Test that we never change requested filename.
+ final String actual = Helpers.generateSaveFile(getContext(), "url", hint,
+ "dispo", "locat", "video/mp4", Downloads.Impl.DESTINATION_FILE_URI);
+ assertEquals(expected.getAbsolutePath(), actual);
}
+ public void testGenerateSaveFileDisposition() throws Exception {
+ final File expected = new File(getContext().getFilesDir(), "real.mp4");
+ final String actual = Helpers.generateSaveFile(getContext(),
+ "http://example.com/file.txt", null, "attachment; filename=\"subdir/real.pdf\"",
+ null, "video/mp4", Downloads.Impl.DESTINATION_CACHE_PARTITION);
+ assertEquals(expected.getAbsolutePath(), actual);
+ }
}
diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
index bde95815..d7b389c5 100644
--- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
+++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java
@@ -53,6 +53,8 @@ import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;
+import libcore.io.IoUtils;
+
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -83,9 +85,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
mTestDirectory = new File(Environment.getExternalStorageDirectory() + File.separator
+ "download_manager_functional_test");
if (mTestDirectory.exists()) {
- for (File file : mTestDirectory.listFiles()) {
- file.delete();
- }
+ IoUtils.deleteContents(mTestDirectory);
} else {
mTestDirectory.mkdir();
}
@@ -94,9 +94,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
@Override
protected void tearDown() throws Exception {
if (mTestDirectory != null && mTestDirectory.exists()) {
- for (File file : mTestDirectory.listFiles()) {
- file.delete();
- }
+ IoUtils.deleteContents(mTestDirectory);
mTestDirectory.delete();
}
super.tearDown();
@@ -223,7 +221,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
boolean isFirstResponse = (start == 0);
int status = isFirstResponse ? HTTP_OK : HTTP_PARTIAL;
MockResponse response = buildResponse(status, FILE_CONTENT.substring(start, end))
- .setHeader("Content-length", totalLength)
+ .setHeader("Content-length", isFirstResponse ? totalLength : (end - start))
.setHeader("Etag", ETAG);
if (!isFirstResponse) {
response.setHeader(
@@ -475,7 +473,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest {
// 2. Try resuming A, but fail ETag check
mSystemFacade.incrementTimeMillis(RETRY_DELAY_MILLIS);
download.runUntilStatus(STATUS_FAILED);
- assertEquals(HTTP_PRECON_FAILED, download.getReason());
+ assertEquals(DownloadManager.ERROR_CANNOT_RESUME, download.getReason());
req = takeRequest();
assertEquals("bytes=2-", getHeaderValue(req, "Range"));
assertEquals(A, getHeaderValue(req, "If-Match"));
diff --git a/tests/src/com/android/providers/downloads/StorageTest.java b/tests/src/com/android/providers/downloads/StorageTest.java
new file mode 100644
index 00000000..eaac3bdc
--- /dev/null
+++ b/tests/src/com/android/providers/downloads/StorageTest.java
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2014 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 static android.app.DownloadManager.COLUMN_REASON;
+import static android.app.DownloadManager.ERROR_INSUFFICIENT_SPACE;
+import static android.app.DownloadManager.STATUS_FAILED;
+import static android.app.DownloadManager.STATUS_SUCCESSFUL;
+import static android.provider.Downloads.Impl.DESTINATION_CACHE_PARTITION;
+import static android.provider.Downloads.Impl.DESTINATION_SYSTEMCACHE_PARTITION;
+
+import android.app.DownloadManager;
+import android.content.pm.PackageManager;
+import android.os.Environment;
+import android.os.StatFs;
+import android.provider.Downloads.Impl;
+import android.test.MoreAsserts;
+import android.util.Log;
+
+import com.android.providers.downloads.StorageUtils.ObserverLatch;
+import com.google.mockwebserver.MockResponse;
+import com.google.mockwebserver.SocketPolicy;
+
+import libcore.io.ErrnoException;
+import libcore.io.ForwardingOs;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.Os;
+import libcore.io.StructStatVfs;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+public class StorageTest extends AbstractPublicApiTest {
+ private static final String TAG = "StorageTest";
+
+ private static final int DOWNLOAD_SIZE = 512 * 1024;
+ private static final byte[] DOWNLOAD_BODY;
+
+ static {
+ DOWNLOAD_BODY = new byte[DOWNLOAD_SIZE];
+ for (int i = 0; i < DOWNLOAD_SIZE; i++) {
+ DOWNLOAD_BODY[i] = (byte) (i % 32);
+ }
+ }
+
+ private Os mOriginal;
+ private long mStealBytes;
+
+ public StorageTest() {
+ super(new FakeSystemFacade());
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ StorageUtils.sForceFullEviction = true;
+ mStealBytes = 0;
+
+ mOriginal = Libcore.os;
+ Libcore.os = new ForwardingOs(mOriginal) {
+ @Override
+ public StructStatVfs statvfs(String path) throws ErrnoException {
+ return stealBytes(os.statvfs(path));
+ }
+
+ @Override
+ public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException {
+ return stealBytes(os.fstatvfs(fd));
+ }
+
+ private StructStatVfs stealBytes(StructStatVfs s) {
+ final long stealBlocks = (mStealBytes + (s.f_bsize - 1)) / s.f_bsize;
+ final long f_bavail = s.f_bavail - stealBlocks;
+ return new StructStatVfs(s.f_bsize, s.f_frsize, s.f_blocks, s.f_bfree, f_bavail,
+ s.f_files, s.f_ffree, s.f_favail, s.f_fsid, s.f_flag, s.f_namemax);
+ }
+ };
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ StorageUtils.sForceFullEviction = false;
+ mStealBytes = 0;
+
+ if (mOriginal != null) {
+ Libcore.os = mOriginal;
+ }
+ }
+
+ private enum CacheStatus { CLEAN, DIRTY }
+ private enum BodyType { COMPLETE, CHUNKED }
+
+ public void testDataDirtyComplete() throws Exception {
+ prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
+ CacheStatus.DIRTY, BodyType.COMPLETE,
+ STATUS_SUCCESSFUL, -1);
+ }
+
+ public void testDataDirtyChunked() throws Exception {
+ prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
+ CacheStatus.DIRTY, BodyType.CHUNKED,
+ STATUS_SUCCESSFUL, -1);
+ }
+
+ public void testDataCleanComplete() throws Exception {
+ prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
+ CacheStatus.CLEAN, BodyType.COMPLETE,
+ STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
+ }
+
+ public void testDataCleanChunked() throws Exception {
+ prepareAndRunDownload(DESTINATION_CACHE_PARTITION,
+ CacheStatus.CLEAN, BodyType.CHUNKED,
+ STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
+ }
+
+ public void testCacheDirtyComplete() throws Exception {
+ prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
+ CacheStatus.DIRTY, BodyType.COMPLETE,
+ STATUS_SUCCESSFUL, -1);
+ }
+
+ public void testCacheDirtyChunked() throws Exception {
+ prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
+ CacheStatus.DIRTY, BodyType.CHUNKED,
+ STATUS_SUCCESSFUL, -1);
+ }
+
+ public void testCacheCleanComplete() throws Exception {
+ prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
+ CacheStatus.CLEAN, BodyType.COMPLETE,
+ STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
+ }
+
+ public void testCacheCleanChunked() throws Exception {
+ prepareAndRunDownload(DESTINATION_SYSTEMCACHE_PARTITION,
+ CacheStatus.CLEAN, BodyType.CHUNKED,
+ STATUS_FAILED, ERROR_INSUFFICIENT_SPACE);
+ }
+
+ private void prepareAndRunDownload(
+ int dest, CacheStatus cache, BodyType body, int expectedStatus, int expectedReason)
+ throws Exception {
+
+ // Ensure that we've purged everything possible for destination
+ final File dirtyDir;
+ if (dest == DESTINATION_CACHE_PARTITION) {
+ final PackageManager pm = getContext().getPackageManager();
+ final ObserverLatch observer = new ObserverLatch();
+ pm.freeStorageAndNotify(Long.MAX_VALUE, observer);
+
+ try {
+ if (!observer.latch.await(30, TimeUnit.SECONDS)) {
+ throw new IOException("Timeout while freeing disk space");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ dirtyDir = getContext().getCacheDir();
+
+ } else if (dest == DESTINATION_SYSTEMCACHE_PARTITION) {
+ IoUtils.deleteContents(Environment.getDownloadCacheDirectory());
+ dirtyDir = Environment.getDownloadCacheDirectory();
+
+ } else {
+ throw new IllegalArgumentException("Unknown destination");
+ }
+
+ // Allocate a cache file, if requested, making it large enough and old
+ // enough to clear.
+ final File dirtyFile;
+ if (cache == CacheStatus.DIRTY) {
+ dirtyFile = new File(dirtyDir, "cache_file.bin");
+ assertTrue(dirtyFile.createNewFile());
+ final FileOutputStream os = new FileOutputStream(dirtyFile);
+ final int dirtySize = (DOWNLOAD_SIZE * 3) / 2;
+ Libcore.os.posix_fallocate(os.getFD(), 0, dirtySize);
+ IoUtils.closeQuietly(os);
+
+ dirtyFile.setLastModified(
+ System.currentTimeMillis() - (StorageUtils.MIN_DELETE_AGE * 2));
+ } else {
+ dirtyFile = null;
+ }
+
+ // At this point, hide all other disk space to make the download fail;
+ // if we have a dirty cache file it can be cleared to let us proceed.
+ final long targetFree = StorageUtils.RESERVED_BYTES + (DOWNLOAD_SIZE / 2);
+
+ final StatFs stat = new StatFs(dirtyDir.getAbsolutePath());
+ Log.d(TAG, "Available bytes (before steal): " + stat.getAvailableBytes());
+ mStealBytes = stat.getAvailableBytes() - targetFree;
+
+ stat.restat(dirtyDir.getAbsolutePath());
+ Log.d(TAG, "Available bytes (after steal): " + stat.getAvailableBytes());
+
+ final MockResponse resp = new MockResponse().setResponseCode(200)
+ .setHeader("Content-type", "text/plain")
+ .setSocketPolicy(SocketPolicy.DISCONNECT_AT_END);
+ if (body == BodyType.CHUNKED) {
+ resp.setChunkedBody(DOWNLOAD_BODY, 1021);
+ } else {
+ resp.setBody(DOWNLOAD_BODY);
+ }
+ enqueueResponse(resp);
+
+ final DownloadManager.Request req = getRequest();
+ if (dest == Impl.DESTINATION_SYSTEMCACHE_PARTITION) {
+ req.setDestinationToSystemCache();
+ }
+ final Download download = enqueueRequest(req);
+ download.runUntilStatus(expectedStatus);
+
+ if (expectedStatus == STATUS_SUCCESSFUL) {
+ MoreAsserts.assertEquals(DOWNLOAD_BODY, download.getRawContents());
+ }
+
+ if (expectedReason != -1) {
+ assertEquals(expectedReason, download.getLongField(COLUMN_REASON));
+ }
+
+ if (dirtyFile != null) {
+ assertFalse(dirtyFile.exists());
+ }
+ }
+}
diff --git a/tests/src/com/android/providers/downloads/ThreadingTest.java b/tests/src/com/android/providers/downloads/ThreadingTest.java
index 920f703b..1e501444 100644
--- a/tests/src/com/android/providers/downloads/ThreadingTest.java
+++ b/tests/src/com/android/providers/downloads/ThreadingTest.java
@@ -27,6 +27,7 @@ import com.google.android.collect.Sets;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.SocketPolicy;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -60,9 +61,10 @@ public class ThreadingTest extends AbstractPublicApiTest {
public void testFilenameRace() throws Exception {
final List<Pair<Download, String>> downloads = Lists.newArrayList();
+ final HashSet<String> expectedBodies = Sets.newHashSet();
// Request dozen files at once with same name
- for (int i = 0; i < 12; i++) {
+ for (int i = 0; i < 32; i++) {
final String body = "DOWNLOAD " + i + " CONTENTS";
enqueueResponse(new MockResponse().setResponseCode(HTTP_OK).setBody(body)
.setHeader("Content-type", "text/plain")
@@ -70,6 +72,7 @@ public class ThreadingTest extends AbstractPublicApiTest {
final Download d = enqueueRequest(getRequest());
downloads.add(Pair.create(d, body));
+ expectedBodies.add(body);
}
// Kick off downloads in parallel
@@ -82,6 +85,7 @@ public class ThreadingTest extends AbstractPublicApiTest {
// Ensure that contents are clean and filenames unique
final Set<String> seenFiles = Sets.newHashSet();
+ final HashSet<String> actualBodies = Sets.newHashSet();
for (Pair<Download, String> d : downloads) {
final String file = d.first.getStringField(DownloadManager.COLUMN_LOCAL_FILENAME);
@@ -91,7 +95,10 @@ public class ThreadingTest extends AbstractPublicApiTest {
final String expected = d.second;
final String actual = d.first.getContents();
- assertEquals(expected, actual);
+
+ actualBodies.add(actual);
}
+
+ assertEquals(expectedBodies, actualBodies);
}
}