Merge pull request #3477 from orionlee/test_download_service_event_posting
Test download service event posting
This commit is contained in:
commit
8f5ff42f6a
|
@ -0,0 +1,52 @@
|
|||
package de.danoeh.antennapod.core.service.download;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import de.danoeh.antennapod.core.util.Consumer;
|
||||
|
||||
public class StubDownloader extends Downloader {
|
||||
|
||||
private final long downloadTime;
|
||||
|
||||
@NonNull
|
||||
private final Consumer<DownloadStatus> onDownloadComplete;
|
||||
|
||||
public StubDownloader(@NonNull DownloadRequest request, long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) {
|
||||
super(request);
|
||||
this.downloadTime = downloadTime;
|
||||
this.onDownloadComplete = onDownloadComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void download() {
|
||||
try {
|
||||
Thread.sleep(downloadTime);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
onDownloadComplete.accept(result);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DownloadRequest getDownloadRequest() {
|
||||
return super.getDownloadRequest();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DownloadStatus getResult() {
|
||||
return super.getResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return super.isFinished();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
super.cancel();
|
||||
result.setCancelled();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package de.test.antennapod.service.download;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.awaitility.core.ConditionTimeoutException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadRequest;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.service.download.StubDownloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.Consumer;
|
||||
|
||||
import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @see HttpDownloaderTest for the test of actual download (and saving the file)
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DownloadServiceTest {
|
||||
|
||||
private CountDownLatch latch = null;
|
||||
private Feed testFeed = null;
|
||||
private FeedMedia testMedia11 = null;
|
||||
|
||||
private DownloadService.DownloaderFactory origFactory = null;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
origFactory = DownloadService.getDownloaderFactory();
|
||||
testFeed = setUpTestFeeds();
|
||||
testMedia11 = testFeed.getItemAtIndex(0).getMedia();
|
||||
}
|
||||
|
||||
private Feed setUpTestFeeds() throws Exception {
|
||||
Feed feed = new Feed("url", null, "Test Feed title 1");
|
||||
List<FeedItem> items = new ArrayList<>();
|
||||
feed.setItems(items);
|
||||
FeedItem item1 = new FeedItem(0, "Item 1-1", "Item 1-1", "url", new Date(), FeedItem.NEW, feed);
|
||||
items.add(item1);
|
||||
FeedMedia media1 = new FeedMedia(0, item1, 123, 1, 1, "audio/mp3", null, "http://example.com/episode.mp3", false, null, 0, 0);
|
||||
item1.setMedia(media1);
|
||||
|
||||
DBWriter.setFeedItem(item1).get();
|
||||
return feed;
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
DownloadService.setDownloaderFactory(origFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEventsGeneratedCaseMediaDownloadSuccess() throws Exception {
|
||||
// create a stub download that returns successful
|
||||
//
|
||||
// OPEN: Ideally, I'd like the download time long enough so that multiple in-progress DownloadEvents
|
||||
// are generated (to simulate typical download), but it'll make download time quite long (1-2 seconds)
|
||||
// to do so
|
||||
DownloadService.setDownloaderFactory(new StubDownloaderFactory(50, downloadStatus -> {
|
||||
downloadStatus.setSuccessful();
|
||||
}));
|
||||
|
||||
withFeedItemEventListener(feedItemEventListener -> {
|
||||
try {
|
||||
assertEquals(0, feedItemEventListener.getEvents().size());
|
||||
assertFalse("The media in test should not yet been downloaded",
|
||||
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
|
||||
|
||||
DownloadRequester.getInstance().downloadMedia(InstrumentationRegistry.getTargetContext(),
|
||||
testMedia11);
|
||||
Awaitility.await()
|
||||
.atMost(1000, TimeUnit.MILLISECONDS)
|
||||
.until(() -> feedItemEventListener.getEvents().size() > 0);
|
||||
assertTrue("After media download has completed, FeedMedia object in db should indicate so.",
|
||||
DBReader.getFeedMedia(testMedia11.getId()).isDownloaded());
|
||||
} catch (ConditionTimeoutException cte) {
|
||||
fail("The expected FeedItemEvent (for media download complete) has not been posted. "
|
||||
+ cte.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class StubDownloaderFactory implements DownloadService.DownloaderFactory {
|
||||
private final long downloadTime;
|
||||
|
||||
@NonNull
|
||||
private final Consumer<DownloadStatus> onDownloadComplete;
|
||||
|
||||
StubDownloaderFactory(long downloadTime, @NonNull Consumer<DownloadStatus> onDownloadComplete) {
|
||||
this.downloadTime = downloadTime;
|
||||
this.onDownloadComplete = onDownloadComplete;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Downloader create(@NonNull DownloadRequest request) {
|
||||
return new StubDownloader(request, downloadTime, onDownloadComplete);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,6 @@ import android.support.test.filters.LargeTest;
|
|||
|
||||
import org.awaitility.Awaitility;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -18,7 +17,6 @@ import java.util.List;
|
|||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import de.danoeh.antennapod.core.event.FeedItemEvent;
|
||||
import de.danoeh.antennapod.core.event.QueueEvent;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
|
@ -29,8 +27,8 @@ import de.danoeh.antennapod.core.storage.DBReader;
|
|||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
|
||||
import static de.test.antennapod.util.event.FeedItemEventListener.withFeedItemEventListener;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -168,35 +166,6 @@ public class PlaybackServiceTaskManagerTest {
|
|||
pstm.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an listener subscribing to {@link FeedItemEvent} that the callers can use
|
||||
*
|
||||
* Note: it uses RxJava's version of {@link Consumer} because it allows exceptions to be thrown.
|
||||
*/
|
||||
private static void withFeedItemEventListener(Consumer<FeedItemEventListener> consumer) throws Exception {
|
||||
FeedItemEventListener feedItemEventListener = new FeedItemEventListener();
|
||||
try {
|
||||
EventBus.getDefault().register(feedItemEventListener);
|
||||
consumer.accept(feedItemEventListener);
|
||||
} finally {
|
||||
EventBus.getDefault().unregister(feedItemEventListener);
|
||||
}
|
||||
}
|
||||
|
||||
private static class FeedItemEventListener {
|
||||
|
||||
private final List<FeedItemEvent> events = new ArrayList<>();
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(FeedItemEvent event) {
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
List<? extends FeedItemEvent> getEvents() {
|
||||
return events;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartPositionSaver() throws InterruptedException {
|
||||
final Context c = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
package de.test.antennapod.util.event;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.event.FeedItemEvent;
|
||||
import io.reactivex.functions.Consumer;
|
||||
|
||||
/**
|
||||
* Test helpers to listen {@link FeedItemEvent} and handle them accordingly
|
||||
*
|
||||
*/
|
||||
public class FeedItemEventListener {
|
||||
private final List<FeedItemEvent> events = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Provides an listener subscribing to {@link FeedItemEvent} that the callers can use
|
||||
*
|
||||
* Note: it uses RxJava's version of {@link Consumer} because it allows exceptions to be thrown.
|
||||
*/
|
||||
public static void withFeedItemEventListener(@NonNull Consumer<FeedItemEventListener> consumer)
|
||||
throws Exception {
|
||||
FeedItemEventListener feedItemEventListener = new FeedItemEventListener();
|
||||
try {
|
||||
EventBus.getDefault().register(feedItemEventListener);
|
||||
consumer.accept(feedItemEventListener);
|
||||
} finally {
|
||||
EventBus.getDefault().unregister(feedItemEventListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onEvent(FeedItemEvent event) {
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<? extends FeedItemEvent> getEvents() {
|
||||
return events;
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import android.os.Handler;
|
|||
import android.os.IBinder;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
@ -434,12 +435,40 @@ public class DownloadService extends Service {
|
|||
queryDownloads();
|
||||
}
|
||||
|
||||
private Downloader getDownloader(DownloadRequest request) {
|
||||
if (!URLUtil.isHttpUrl(request.getSource()) && !URLUtil.isHttpsUrl(request.getSource())) {
|
||||
Log.e(TAG, "Could not find appropriate downloader for " + request.getSource());
|
||||
return null;
|
||||
@VisibleForTesting
|
||||
public interface DownloaderFactory {
|
||||
@Nullable
|
||||
Downloader create(@NonNull DownloadRequest request);
|
||||
}
|
||||
|
||||
private static class DefaultDownloaderFactory implements DownloaderFactory {
|
||||
@Nullable
|
||||
@Override
|
||||
public Downloader create(@NonNull DownloadRequest request) {
|
||||
if (!URLUtil.isHttpUrl(request.getSource()) && !URLUtil.isHttpsUrl(request.getSource())) {
|
||||
Log.e(TAG, "Could not find appropriate downloader for " + request.getSource());
|
||||
return null;
|
||||
}
|
||||
return new HttpDownloader(request);
|
||||
}
|
||||
return new HttpDownloader(request);
|
||||
}
|
||||
|
||||
private static DownloaderFactory downloaderFactory = new DefaultDownloaderFactory();
|
||||
|
||||
@VisibleForTesting
|
||||
public static DownloaderFactory getDownloaderFactory() {
|
||||
return downloaderFactory;
|
||||
}
|
||||
|
||||
// public scope rather than package private,
|
||||
// because androidTest put classes in the non-standard de.test.antennapod hierarchy
|
||||
@VisibleForTesting
|
||||
public static void setDownloaderFactory(DownloaderFactory downloaderFactory) {
|
||||
DownloadService.downloaderFactory = downloaderFactory;
|
||||
}
|
||||
|
||||
private Downloader getDownloader(@NonNull DownloadRequest request) {
|
||||
return downloaderFactory.create(request);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue