1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
package de.test.antennapod.storage;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
import de.danoeh.antennapod.storage.preferences.UserPreferences;
import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
import de.danoeh.antennapod.core.storage.DBReader;
import de.danoeh.antennapod.core.storage.DBTasks;
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
import de.test.antennapod.EspressoTestUtils;
import de.test.antennapod.ui.UITestUtils;
import org.awaitility.Awaitility;
import org.awaitility.core.ConditionTimeoutException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class AutoDownloadTest {
private Context context;
private UITestUtils stubFeedsServer;
private StubDownloadAlgorithm stubDownloadAlgorithm;
@Before
public void setUp() throws Exception {
context = ApplicationProvider.getApplicationContext();
stubFeedsServer = new UITestUtils(context);
stubFeedsServer.setup();
EspressoTestUtils.clearPreferences();
EspressoTestUtils.clearDatabase();
UserPreferences.setAllowMobileStreaming(true);
// Setup: enable automatic download
// it is not needed, as the actual automatic download is stubbed.
stubDownloadAlgorithm = new StubDownloadAlgorithm();
DBTasks.setDownloadAlgorithm(stubDownloadAlgorithm);
}
@After
public void tearDown() throws Exception {
DBTasks.setDownloadAlgorithm(new AutomaticDownloadAlgorithm());
EspressoTestUtils.tryKillPlaybackService();
stubFeedsServer.tearDown();
}
/**
* A cross-functional test, ensuring playback's behavior works with Auto Download in boundary condition.
*
* Scenario:
* - For setting enqueue location AFTER_CURRENTLY_PLAYING
* - when playback of an episode is complete and the app advances to the next episode (continuous playback on)
* - when automatic download kicks in,
* - ensure the next episode is the current playing one, needed for AFTER_CURRENTLY_PLAYING enqueue location.
*/
@Test
public void downloadsEnqueuedToAfterCurrent_CurrentAdvancedToNextOnPlaybackComplete() throws Exception {
UserPreferences.setFollowQueue(true); // continuous playback
// Setup: feeds and queue
// downloads 3 of them, leave some in new state (auto-downloadable)
stubFeedsServer.addLocalFeedData(false);
List<FeedItem> queue = DBReader.getQueue();
assertTrue(queue.size() > 1);
FeedItem item0 = queue.get(0);
FeedItem item1 = queue.get(1);
// Actual test
// Play the first one in the queue
playEpisode(item0);
try {
// when playback is complete, advances to the next one, and auto download kicks in,
// ensure that currently playing has been advanced to the next one by this point.
Awaitility.await("advanced to the next episode")
.atMost(6000, MILLISECONDS) // the test mp3 media is 3-second long. twice should be enough
.until(() -> item1.getMedia().getId() == stubDownloadAlgorithm.getCurrentlyPlayingAtDownload());
} catch (ConditionTimeoutException cte) {
long actual = stubDownloadAlgorithm.getCurrentlyPlayingAtDownload();
fail("when auto download is triggered, the next episode should be playing: ("
+ item1.getId() + ", " + item1.getTitle() + ") . "
+ "Actual playing: (" + actual + ")"
);
}
}
private void playEpisode(@NonNull FeedItem item) {
FeedMedia media = item.getMedia();
new PlaybackServiceStarter(context, media)
.callEvenIfRunning(true)
.start();
Awaitility.await("episode is playing")
.atMost(2000, MILLISECONDS)
.until(() -> item.getMedia().getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId());
}
private static class StubDownloadAlgorithm extends AutomaticDownloadAlgorithm {
private long currentlyPlaying = -1;
@Override
public Runnable autoDownloadUndownloadedItems(Context context) {
return () -> {
if (currentlyPlaying == -1) {
currentlyPlaying = PlaybackPreferences.getCurrentlyPlayingFeedMediaId();
} else {
throw new AssertionError("Stub automatic download should be invoked once and only once");
}
};
}
long getCurrentlyPlayingAtDownload() {
return currentlyPlaying;
}
}
}
|