зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1232984 - Add basic set of tests for downloadable content. r=rnewman
--HG-- extra : commitid : 98BvL0dXkuv extra : rebase_source : 3ddf99f5979e3a05ff5b1049d5be6ae4569c22ae
This commit is contained in:
Родитель
8e726581e9
Коммит
8699452fa5
|
@ -123,6 +123,7 @@ dependencies {
|
|||
testCompile 'junit:junit:4.12'
|
||||
testCompile 'org.robolectric:robolectric:3.0'
|
||||
testCompile 'org.simpleframework:simple-http:4.1.13'
|
||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
||||
}
|
||||
|
||||
apply plugin: 'idea'
|
||||
|
|
|
@ -73,6 +73,7 @@ public class DownloadAction extends BaseAction {
|
|||
File destinationFile = getDestinationFile(context, content);
|
||||
if (destinationFile.exists() && verify(destinationFile, content.getChecksum())) {
|
||||
Log.d(LOGTAG, "Content already exists and is up-to-date.");
|
||||
catalog.markAsDownloaded(content);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,10 @@ public class DownloadContent {
|
|||
return location;
|
||||
}
|
||||
|
||||
public long getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
package org.mozilla.gecko.dlc.catalog;
|
||||
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentBootstrap;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.util.AtomicFile;
|
||||
import android.util.Log;
|
||||
|
@ -39,12 +37,17 @@ public class DownloadContentCatalog {
|
|||
private boolean hasCatalogChanged; // Guarded by 'this'
|
||||
|
||||
public DownloadContentCatalog(Context context) {
|
||||
content = Collections.emptyList();
|
||||
file = new AtomicFile(new File(context.getApplicationInfo().dataDir, FILE_NAME));
|
||||
this(new AtomicFile(new File(context.getApplicationInfo().dataDir, FILE_NAME)));
|
||||
|
||||
startLoadFromDisk();
|
||||
}
|
||||
|
||||
// For injecting mocked AtomicFile objects during test
|
||||
protected DownloadContentCatalog(AtomicFile file) {
|
||||
this.content = Collections.emptyList();
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
public synchronized List<DownloadContent> getContentWithoutState() {
|
||||
awaitLoadingCatalogLocked();
|
||||
|
||||
|
@ -145,14 +148,18 @@ public class DownloadContentCatalog {
|
|||
}
|
||||
}
|
||||
|
||||
private synchronized void loadFromDisk() {
|
||||
protected synchronized boolean hasCatalogChanged() {
|
||||
return hasCatalogChanged;
|
||||
}
|
||||
|
||||
protected synchronized void loadFromDisk() {
|
||||
Log.d(LOGTAG, "Loading from disk");
|
||||
|
||||
if (hasLoadedCatalog) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<DownloadContent> content = new ArrayList<DownloadContent>();
|
||||
List<DownloadContent> content = new ArrayList<>();
|
||||
|
||||
try {
|
||||
JSONArray array;
|
||||
|
@ -180,15 +187,19 @@ public class DownloadContentCatalog {
|
|||
Log.d(LOGTAG, "Can't read catalog due to IOException", e);
|
||||
}
|
||||
|
||||
this.content = content;
|
||||
this.hasLoadedCatalog = true;
|
||||
onCatalogLoaded(content);
|
||||
|
||||
notifyAll();
|
||||
|
||||
Log.d(LOGTAG, "Loaded " + content.size() + " elements");
|
||||
}
|
||||
|
||||
private synchronized void writeToDisk() {
|
||||
protected void onCatalogLoaded(List<DownloadContent> content) {
|
||||
this.content = content;
|
||||
this.hasLoadedCatalog = true;
|
||||
}
|
||||
|
||||
protected synchronized void writeToDisk() {
|
||||
if (!hasCatalogChanged) {
|
||||
Log.v(LOGTAG, "Not persisting: Catalog has not changed");
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.dlc;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.background.testhelpers.TestRunner;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContent;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpResponse;
|
||||
import ch.boye.httpclientandroidlib.StatusLine;
|
||||
import ch.boye.httpclientandroidlib.client.HttpClient;
|
||||
import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* DownloadAction: Download content that has been scheduled during "study" or "verify".
|
||||
*/
|
||||
@RunWith(TestRunner.class)
|
||||
public class TestDownloadAction {
|
||||
private static final String TEST_URL = "http://example.org";
|
||||
|
||||
/**
|
||||
* Scenario: The current network is metered.
|
||||
*
|
||||
* Verify that:
|
||||
* * No download is performed on a metered network
|
||||
*/
|
||||
@Test
|
||||
public void testNothingIsDoneOnMeteredNetwork() throws Exception {
|
||||
DownloadAction action = spy(new DownloadAction(null));
|
||||
doReturn(true).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||
|
||||
action.perform(RuntimeEnvironment.application, null);
|
||||
|
||||
verify(action, never()).buildHttpClient();
|
||||
verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Content is scheduled for download but already exists locally (with correct checksum).
|
||||
*
|
||||
* Verify that:
|
||||
* * No download is performed for existing file
|
||||
* * Content is marked as downloaded in the catalog
|
||||
*/
|
||||
@Test
|
||||
public void testExistingAndVerifiedFilesAreNotDownloadedAgain() throws Exception {
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads();
|
||||
|
||||
DownloadAction action = spy(new DownloadAction(null));
|
||||
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||
|
||||
File file = mock(File.class);
|
||||
doReturn(true).when(file).exists();
|
||||
doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||
doReturn(true).when(action).verify(eq(file), anyString());
|
||||
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(action, never()).download(any(HttpClient.class), anyString(), any(File.class));
|
||||
verify(catalog).markAsDownloaded(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Server returns a server error (HTTP 500).
|
||||
*
|
||||
* Verify that:
|
||||
* * Situation is treated as recoverable (RecoverableDownloadContentException)
|
||||
*/
|
||||
@Test(expected=BaseAction.RecoverableDownloadContentException.class)
|
||||
public void testServerErrorsAreRecoverable() throws Exception {
|
||||
StatusLine status = mock(StatusLine.class);
|
||||
doReturn(500).when(status).getStatusCode();
|
||||
|
||||
HttpResponse response = mock(HttpResponse.class);
|
||||
doReturn(status).when(response).getStatusLine();
|
||||
|
||||
HttpClient client = mock(HttpClient.class);
|
||||
doReturn(response).when(client).execute(any(HttpUriRequest.class));
|
||||
|
||||
DownloadAction action = spy(new DownloadAction(null));
|
||||
action.download(client, TEST_URL, null);
|
||||
|
||||
verify(client).execute(any(HttpUriRequest.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Server returns a client error (HTTP 404).
|
||||
*
|
||||
* Verify that:
|
||||
* * Situation is treated as unrecoverable (UnrecoverableDownloadContentException)
|
||||
*/
|
||||
@Test(expected=BaseAction.UnrecoverableDownloadContentException.class)
|
||||
public void testClientErrorsAreUnrecoverable() throws Exception {
|
||||
StatusLine status = mock(StatusLine.class);
|
||||
doReturn(404).when(status).getStatusCode();
|
||||
|
||||
HttpResponse response = mock(HttpResponse.class);
|
||||
doReturn(status).when(response).getStatusLine();
|
||||
|
||||
HttpClient client = mock(HttpClient.class);
|
||||
doReturn(response).when(client).execute(any(HttpUriRequest.class));
|
||||
|
||||
DownloadAction action = spy(new DownloadAction(null));
|
||||
action.download(client, TEST_URL, null);
|
||||
|
||||
verify(client).execute(any(HttpUriRequest.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: A successful download has been performed.
|
||||
*
|
||||
* Verify that:
|
||||
* * The content will be extracted to the destination
|
||||
* * The content is marked as downloaded in the catalog
|
||||
*/
|
||||
@Test
|
||||
public void testSuccessfulDownloadsAreMarkedAsDownloaded() throws Exception {
|
||||
DownloadContent content = new DownloadContent.Builder()
|
||||
.setKind(DownloadContent.KIND_FONT)
|
||||
.setType(DownloadContent.TYPE_ASSET_ARCHIVE)
|
||||
.build();
|
||||
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
doReturn(Collections.singletonList(content)).when(catalog).getScheduledDownloads();
|
||||
|
||||
DownloadAction action = spy(new DownloadAction(null));
|
||||
doReturn(false).when(action).isActiveNetworkMetered(RuntimeEnvironment.application);
|
||||
|
||||
File file = mock(File.class);
|
||||
doReturn(false).when(file).exists();
|
||||
doReturn(file).when(action).createTemporaryFile(RuntimeEnvironment.application, content);
|
||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||
|
||||
doReturn(false).when(action).verify(eq(file), anyString());
|
||||
doNothing().when(action).download(any(HttpClient.class), anyString(), eq(file));
|
||||
doReturn(true).when(action).verify(eq(file), anyString());
|
||||
doNothing().when(action).extract(eq(file), eq(file), anyString());
|
||||
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(action).buildHttpClient();
|
||||
verify(action).download(any(HttpClient.class), anyString(), eq(file));
|
||||
verify(action).extract(eq(file), eq(file), anyString());
|
||||
verify(catalog).markAsDownloaded(content);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.dlc;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.background.testhelpers.TestRunner;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContent;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* StudyAction: Scan the catalog for "new" content available for download.
|
||||
*/
|
||||
@RunWith(TestRunner.class)
|
||||
public class TestStudyAction {
|
||||
/**
|
||||
* Scenario: Catalog is empty.
|
||||
*
|
||||
* Verify that:
|
||||
* * No download is scheduled
|
||||
* * Download action is not started
|
||||
*/
|
||||
@Test
|
||||
public void testPerformWithEmptyCatalog() {
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getContentWithoutState()).thenReturn(new ArrayList<DownloadContent>());
|
||||
|
||||
StudyAction action = spy(new StudyAction());
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(catalog).getContentWithoutState();
|
||||
verify(catalog, never()).markAsDownloaded(any(DownloadContent.class));
|
||||
verify(action, never()).startDownloads(any(Context.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Catalog contains two items that have not been downloaded yet.
|
||||
*
|
||||
* Verify that:
|
||||
* * Both items are scheduled to be downloaded
|
||||
*/
|
||||
@Test
|
||||
public void testPerformWithNewContent() {
|
||||
DownloadContent content1 = new DownloadContent.Builder()
|
||||
.setType(DownloadContent.TYPE_ASSET_ARCHIVE)
|
||||
.setKind(DownloadContent.KIND_FONT)
|
||||
.build();
|
||||
DownloadContent content2 = new DownloadContent.Builder()
|
||||
.setType(DownloadContent.TYPE_ASSET_ARCHIVE)
|
||||
.setKind(DownloadContent.KIND_FONT)
|
||||
.build();
|
||||
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getContentWithoutState()).thenReturn(Arrays.asList(content1, content2));
|
||||
|
||||
StudyAction action = spy(new StudyAction());
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(catalog).scheduleDownload(content1);
|
||||
verify(catalog).scheduleDownload(content2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Catalog contains item that are scheduled for download.
|
||||
*
|
||||
* Verify that:
|
||||
* * Download action is started
|
||||
*/
|
||||
@Test
|
||||
public void testStartingDownloadsAfterScheduling() {
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.hasScheduledDownloads()).thenReturn(true);
|
||||
|
||||
StudyAction action = spy(new StudyAction());
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(action).startDownloads(any(Context.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Catalog contains unknown content.
|
||||
*
|
||||
* Verify that:
|
||||
* * Unknown content is not scheduled for download.
|
||||
*/
|
||||
@Test
|
||||
public void testPerformWithUnknownContent() {
|
||||
DownloadContent content = new DownloadContent.Builder()
|
||||
.setType("Unknown-Type")
|
||||
.setKind("Unknown-Kind")
|
||||
.build();
|
||||
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getContentWithoutState()).thenReturn(Collections.singletonList(content));
|
||||
|
||||
StudyAction action = spy(new StudyAction());
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(catalog, never()).scheduleDownload(content);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.dlc;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.background.testhelpers.TestRunner;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContent;
|
||||
import org.mozilla.gecko.dlc.catalog.DownloadContentCatalog;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* VerifyAction: Validate downloaded content. Does it still exist and does it have the correct checksum?
|
||||
*/
|
||||
@RunWith(TestRunner.class)
|
||||
public class TestVerifyAction {
|
||||
/**
|
||||
* Scenario: Downloaded file does not exist anymore.
|
||||
*
|
||||
* Verify that:
|
||||
* * Content is re-scheduled for download.
|
||||
*/
|
||||
@Test
|
||||
public void testReschedulingIfFileDoesNotExist() throws Exception {
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getDownloadedContent()).thenReturn(Collections.singletonList(content));
|
||||
|
||||
File file = mock(File.class);
|
||||
when(file.exists()).thenReturn(false);
|
||||
|
||||
VerifyAction action = spy(new VerifyAction());
|
||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(catalog).scheduleDownload(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Content has been scheduled for download.
|
||||
*
|
||||
* Verify that:
|
||||
* * Download action is started
|
||||
*/
|
||||
@Test
|
||||
public void testStartingDownloadsAfterScheduling() {
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.hasScheduledDownloads()).thenReturn(true);
|
||||
|
||||
VerifyAction action = spy(new VerifyAction());
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(action).startDownloads(any(Context.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Checksum of existing file does not match expectation.
|
||||
*
|
||||
* Verify that:
|
||||
* * Content is re-scheduled for download.
|
||||
*/
|
||||
@Test
|
||||
public void testReschedulingIfVerificationFailed() throws Exception {
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getDownloadedContent()).thenReturn(Collections.singletonList(content));
|
||||
|
||||
File file = mock(File.class);
|
||||
when(file.exists()).thenReturn(true);
|
||||
|
||||
VerifyAction action = spy(new VerifyAction());
|
||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||
doReturn(false).when(action).verify(eq(file), anyString());
|
||||
|
||||
action.perform(RuntimeEnvironment.application, catalog);
|
||||
|
||||
verify(catalog).scheduleDownload(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Downloaded file exists and has the correct checksum.
|
||||
*
|
||||
* Verify that:
|
||||
* * No download is scheduled
|
||||
* * Download action is not started
|
||||
*/
|
||||
@Test
|
||||
public void testSuccessfulVerification() throws Exception {
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
DownloadContentCatalog catalog = mock(DownloadContentCatalog.class);
|
||||
when(catalog.getDownloadedContent()).thenReturn(Collections.singletonList(content));
|
||||
|
||||
File file = mock(File.class);
|
||||
when(file.exists()).thenReturn(true);
|
||||
|
||||
VerifyAction action = spy(new VerifyAction());
|
||||
doReturn(file).when(action).getDestinationFile(RuntimeEnvironment.application, content);
|
||||
doReturn(true).when(action).verify(eq(file), anyString());
|
||||
|
||||
verify(catalog, never()).scheduleDownload(content);
|
||||
verify(action, never()).startDownloads(RuntimeEnvironment.application);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
package org.mozilla.gecko.dlc.catalog;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.background.testhelpers.TestRunner;
|
||||
|
||||
@RunWith(TestRunner.class)
|
||||
public class TestDownloadContent {
|
||||
/**
|
||||
* Verify that the values passed to the builder are all set on the DownloadContent object.
|
||||
*/
|
||||
@Test
|
||||
public void testBuilder() {
|
||||
DownloadContent content = createTestContent();
|
||||
|
||||
Assert.assertEquals("Some-ID", content.getId());
|
||||
Assert.assertEquals("/somewhere/something", content.getLocation());
|
||||
Assert.assertEquals("some.file", content.getFilename());
|
||||
Assert.assertEquals("Some-checksum", content.getChecksum());
|
||||
Assert.assertEquals("Some-download-checksum", content.getDownloadChecksum());
|
||||
Assert.assertEquals(4223, content.getLastModified());
|
||||
Assert.assertEquals("Some-type", content.getType());
|
||||
Assert.assertEquals("Some-kind", content.getKind());
|
||||
Assert.assertEquals(27, content.getSize());
|
||||
Assert.assertEquals(DownloadContent.STATE_SCHEDULED, content.getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that a DownloadContent object exported to JSON and re-imported from JSON does not change.
|
||||
*/
|
||||
public void testJSONSerializationAndDeserialization() throws JSONException {
|
||||
DownloadContent content = DownloadContent.fromJSON(createTestContent().toJSON());
|
||||
|
||||
Assert.assertEquals("Some-ID", content.getId());
|
||||
Assert.assertEquals("/somewhere/something", content.getLocation());
|
||||
Assert.assertEquals("some.file", content.getFilename());
|
||||
Assert.assertEquals("Some-checksum", content.getChecksum());
|
||||
Assert.assertEquals("Some-download-checksum", content.getDownloadChecksum());
|
||||
Assert.assertEquals(4223, content.getLastModified());
|
||||
Assert.assertEquals("Some-type", content.getType());
|
||||
Assert.assertEquals("Some-kind", content.getKind());
|
||||
Assert.assertEquals(27, content.getSize());
|
||||
Assert.assertEquals(DownloadContent.STATE_SCHEDULED, content.getState());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DownloadContent object with arbitrary data.
|
||||
*/
|
||||
private DownloadContent createTestContent() {
|
||||
return new DownloadContent.Builder()
|
||||
.setId("Some-ID")
|
||||
.setLocation("/somewhere/something")
|
||||
.setFilename("some.file")
|
||||
.setChecksum("Some-checksum")
|
||||
.setDownloadChecksum("Some-download-checksum")
|
||||
.setLastModified(4223)
|
||||
.setType("Some-type")
|
||||
.setKind("Some-kind")
|
||||
.setSize(27)
|
||||
.setState(DownloadContent.STATE_SCHEDULED)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.dlc.catalog;
|
||||
|
||||
import android.support.v4.util.AtomicFile;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mozilla.gecko.background.testhelpers.TestRunner;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@RunWith(TestRunner.class)
|
||||
public class TestDownloadContentCatalog {
|
||||
/**
|
||||
* Scenario: Create a new, fresh catalog.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog has not changed
|
||||
* * Unchanged catalog will not be saved to disk
|
||||
*/
|
||||
@Test
|
||||
public void testUntouchedCatalogHasNotChangedAndWillNotBePersisted() throws Exception {
|
||||
AtomicFile file = mock(AtomicFile.class);
|
||||
doReturn("[]".getBytes("UTF-8")).when(file).readFully();
|
||||
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(file));
|
||||
catalog.loadFromDisk();
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.writeToDisk();
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
verify(file, never()).startWrite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Create a new, fresh catalog.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog is bootstrapped with items.
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogIsBootstrapedIfFileDoesNotExist() throws Exception {
|
||||
AtomicFile file = mock(AtomicFile.class);
|
||||
doThrow(FileNotFoundException.class).when(file).readFully();
|
||||
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(file));
|
||||
catalog.loadFromDisk();
|
||||
|
||||
Assert.assertTrue("Catalog is not empty", catalog.getContentWithoutState().size() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Schedule downloading an item from the catalog.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog has changed
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogHasChangedWhenDownloadIsScheduled() throws Exception {
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(mock(AtomicFile.class)));
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
catalog.onCatalogLoaded(Collections.singletonList(content));
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.scheduleDownload(content);
|
||||
|
||||
Assert.assertTrue("Catalog has changed", catalog.hasCatalogChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Mark an item in the catalog as downloaded.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog has changed
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogHasChangedWhenContentIsDownloaded() throws Exception {
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(mock(AtomicFile.class)));
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
catalog.onCatalogLoaded(Collections.singletonList(content));
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.markAsDownloaded(content);
|
||||
|
||||
Assert.assertTrue("Catalog has changed", catalog.hasCatalogChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Mark an item in the catalog as permanently failed.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog has changed
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogHasChangedIfDownloadHasFailedPermanently() throws Exception {
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(mock(AtomicFile.class)));
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
catalog.onCatalogLoaded(Collections.singletonList(content));
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.markAsPermanentlyFailed(content);
|
||||
|
||||
Assert.assertTrue("Catalog has changed", catalog.hasCatalogChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: Mark an item in the catalog as ignored.
|
||||
*
|
||||
* Verify that:
|
||||
* * Catalog has changed
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogHasChangedIfContentIsIgnored() throws Exception {
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(mock(AtomicFile.class)));
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
catalog.onCatalogLoaded(Collections.singletonList(content));
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.markAsIgnored(content);
|
||||
|
||||
Assert.assertTrue("Catalog has changed", catalog.hasCatalogChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: A changed catalog is written to disk.
|
||||
*
|
||||
* Verify that:
|
||||
* * Before write: Catalog has changed
|
||||
* * After write: Catalog has not changed.
|
||||
*/
|
||||
@Test
|
||||
public void testCatalogHasNotChangedAfterWritingToDisk() throws Exception {
|
||||
AtomicFile file = mock(AtomicFile.class);
|
||||
doReturn(mock(FileOutputStream.class)).when(file).startWrite();
|
||||
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(file));
|
||||
DownloadContent content = new DownloadContent.Builder().build();
|
||||
catalog.onCatalogLoaded(Collections.singletonList(content));
|
||||
|
||||
catalog.scheduleDownload(content);
|
||||
|
||||
Assert.assertTrue("Catalog has changed", catalog.hasCatalogChanged());
|
||||
|
||||
catalog.writeToDisk();
|
||||
|
||||
Assert.assertFalse("Catalog has not changed", catalog.hasCatalogChanged());
|
||||
}
|
||||
|
||||
/**
|
||||
* Scenario: A catalog with multiple items in different states.
|
||||
*
|
||||
* Verify that:
|
||||
* * getContentWithoutState(), getDownloadedContent() and getScheduledDownloads() returns
|
||||
* the correct items depenending on their state.
|
||||
*/
|
||||
@Test
|
||||
public void testContentClassification() {
|
||||
DownloadContentCatalog catalog = spy(new DownloadContentCatalog(mock(AtomicFile.class)));
|
||||
|
||||
DownloadContent content1 = new DownloadContent.Builder().setState(DownloadContent.STATE_NONE).build();
|
||||
DownloadContent content2 = new DownloadContent.Builder().setState(DownloadContent.STATE_NONE).build();
|
||||
DownloadContent content3 = new DownloadContent.Builder().setState(DownloadContent.STATE_SCHEDULED).build();
|
||||
DownloadContent content4 = new DownloadContent.Builder().setState(DownloadContent.STATE_SCHEDULED).build();
|
||||
DownloadContent content5 = new DownloadContent.Builder().setState(DownloadContent.STATE_SCHEDULED).build();
|
||||
DownloadContent content6 = new DownloadContent.Builder().setState(DownloadContent.STATE_DOWNLOADED).build();
|
||||
DownloadContent content7 = new DownloadContent.Builder().setState(DownloadContent.STATE_FAILED).build();
|
||||
DownloadContent content8 = new DownloadContent.Builder().setState(DownloadContent.STATE_IGNORED).build();
|
||||
DownloadContent content9 = new DownloadContent.Builder().setState(DownloadContent.STATE_IGNORED).build();
|
||||
|
||||
|
||||
catalog.onCatalogLoaded(Arrays.asList(content1, content2, content3, content4, content5, content6,
|
||||
content7, content8, content9));
|
||||
|
||||
Assert.assertEquals(2, catalog.getContentWithoutState().size());
|
||||
Assert.assertEquals(1, catalog.getDownloadedContent().size());
|
||||
Assert.assertEquals(3, catalog.getScheduledDownloads().size());
|
||||
|
||||
Assert.assertTrue(catalog.getContentWithoutState().contains(content1));
|
||||
Assert.assertTrue(catalog.getContentWithoutState().contains(content2));
|
||||
|
||||
Assert.assertTrue(catalog.getDownloadedContent().contains(content6));
|
||||
|
||||
Assert.assertTrue(catalog.getScheduledDownloads().contains(content3));
|
||||
Assert.assertTrue(catalog.getScheduledDownloads().contains(content4));
|
||||
Assert.assertTrue(catalog.getScheduledDownloads().contains(content5));
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче