1 /***
2 * Ambient - A music player for the Android platform
3 Copyright (C) 2007 Martin Vysny
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 package sk.baka.ambient.playlist;
19
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import junit.framework.TestCase;
24 import sk.baka.ambient.collection.TrackMetadataBean;
25 import sk.baka.ambient.collection.TrackOriginEnum;
26 import sk.baka.ambient.collection.TrackMetadataBean.Builder;
27 import sk.baka.ambient.commons.Interval;
28
29 /***
30 * Common utility methods for testing a playlist strategy.
31 *
32 * @author mvy
33 */
34 public abstract class AbstractPlaylistStrategyTest extends TestCase {
35 /***
36 * Returns the strategy instance.
37 *
38 * @return the strategy instance. The strategy playlist must be empty.
39 */
40 protected abstract IPlaylistStrategy getStrategy();
41
42 /***
43 * Contains 30 test tracks.
44 */
45 protected List<TrackMetadataBean> tracks;
46
47 /***
48 * The strategy instance being tested.
49 */
50 protected IPlaylistStrategy strategy;
51
52 @Override
53 protected void setUp() throws Exception {
54 super.setUp();
55 tracks = new ArrayList<TrackMetadataBean>();
56 for (int i = 0; i < 30; i++) {
57 final Builder track = TrackMetadataBean.newBuilder();
58 track.setOrigin(TrackOriginEnum.LocalFs).setLocation(
59 "/sdcard/" + i + ".mp3");
60 track.setLength(100 * i).setFileSize(100 * i);
61 tracks.add(track.build(i));
62 }
63 strategy = getStrategy();
64 }
65
66 /***
67 * @throws Exception
68 */
69 public void testEmptyPlaylist() throws Exception {
70 assertEquals(0, strategy.size());
71 assertEquals(-1, strategy.previous());
72 }
73
74 /***
75 * @throws Exception
76 */
77 public void testAdding30Tracks() throws Exception {
78 strategy.add(0, tracks);
79 assertEquals(tracks, strategy.getPlayItems());
80 }
81
82 /***
83 * @throws Exception
84 */
85 public void testQueuingTracks() throws Exception {
86 for (final Random r : Random.values()) {
87 strategy = getStrategy();
88 strategy.setRandom(r);
89 strategy.add(0, tracks);
90
91 Interval queueInterval = new Interval(5, 5);
92 strategy.queue(queueInterval);
93 assertEquals(tracks.size(), strategy.size());
94 assertEqualsQueue(tracks.subList(5, 10));
95 verifyQueueProperties(5);
96
97 queueInterval = new Interval(15, 5);
98 strategy.queue(queueInterval);
99 List<TrackMetadataBean> expectedQueue = new ArrayList<TrackMetadataBean>(
100 tracks.subList(5, 10));
101 expectedQueue.addAll(tracks.subList(15, 20));
102 assertEqualsQueue(expectedQueue);
103 verifyQueueProperties(10);
104 }
105 }
106
107 /***
108 */
109 public void testPlayingQueuedTracks() {
110 for (final Random r : Random.values()) {
111 strategy = getStrategy();
112 strategy.setRandom(r);
113 strategy.add(0, tracks);
114
115 Interval queueInterval = new Interval(5, 5);
116 strategy.queue(queueInterval);
117 assertNextTracks(tracks.subList(5, 10), false);
118 verifyQueueProperties(0);
119 strategy.next();
120 verifyQueueProperties(0);
121 }
122 }
123
124 /***
125 * Asserts that next x tracks will be in same ordering as in the
126 * <code>tracks</code> list.
127 *
128 * @param tracks
129 * expect this ordering when playing next tracks.
130 * @param playlistEnd
131 * if <code>true</code> then the playlist must end after given
132 * tracks.
133 */
134 protected void assertNextTracks(final List<TrackMetadataBean> tracks,
135 boolean playlistEnd) {
136 for (final TrackMetadataBean track : tracks) {
137 final int trackIndex = strategy.next();
138 assertEquals(trackIndex, strategy.getCurrentlyPlaying());
139 assertTrue("There should be more tracks to play", trackIndex >= 0);
140 assertEquals(track, strategy.getPlayItems().get(trackIndex).track);
141 }
142 if (playlistEnd) {
143 final int i = strategy.next();
144 if (i >= 0) {
145 fail("There are items left in the playlist; "
146 + getCurrentlyPlaying());
147 }
148 }
149 }
150
151 /***
152 * Compares current {@link #strategy}
153 * {@link IPlaylistStrategy#getPlayItems()} to tracks in {@link #tracks}.
154 *
155 * @param trackNumbers
156 * indexes to the {@link #tracks} list. <code>null</code>
157 * values are skipped.
158 * @param startIndex
159 * where to start
160 */
161 protected void assertTracks(final List<Integer> trackNumbers, int startIndex) {
162 int i = startIndex;
163 for (final Integer index : trackNumbers) {
164 if (index != null) {
165 final TrackMetadataBean expected = tracks.get(index);
166 final TrackMetadataBean got = strategy.getPlayItems().get(i).track;
167 assertEquals(expected, got);
168 }
169 i++;
170 }
171 }
172
173 /***
174 * Asserts that next x tracks matches tracks in given <code>tracks</code>
175 * list. The number of tracks must match, however the track ordering is
176 * irrelevant (as opposed to {@link #assertNextTracks(List, boolean)}).
177 *
178 * @param tracks
179 * expect these tracks when playing next tracks.
180 * @param playlistEnd
181 * if <code>true</code> then the playlist must end after given
182 * tracks.
183 */
184 protected void assertNextTracksUnordered(
185 final List<TrackMetadataBean> tracks, boolean playlistEnd) {
186 final List<TrackMetadataBean> tracks_ = new ArrayList<TrackMetadataBean>(
187 tracks);
188 while (!tracks_.isEmpty()) {
189 final int trackIndex = strategy.next();
190 assertTrue("No more tracks - tracks not present in the playlist: "
191 + tracks_, trackIndex >= 0);
192 final TrackMetadataBean track = strategy.getPlayItems().get(
193 trackIndex).track;
194 assertTrue(
195 "Track "
196 + track
197 + " was provided by the playlist but not present in the track list",
198 tracks_.remove(track));
199 }
200 if (playlistEnd) {
201 assertEquals("There are items left in the playlist; "
202 + getCurrentlyPlaying(), -1, strategy.next());
203 }
204 }
205
206 /***
207 * Checks if the queue has correct queue count etc.
208 *
209 * @param expectedQueueLength
210 */
211 protected void verifyQueueProperties(final int expectedQueueLength) {
212 final List<Integer> queue = strategy.getQueue();
213 assertEquals(expectedQueueLength, queue.size());
214
215 for (int i = 0; i < queue.size(); i++) {
216 final PlaylistItem pi = strategy.getPlayItems().get(queue.get(i));
217 assertEquals(pi.toString() + " must be queued", i + 1,
218 pi.queueOrder);
219 }
220
221 for (int i = 0; i < strategy.getPlayItems().size(); i++) {
222 if (queue.contains(i))
223 continue;
224 final PlaylistItem pi = strategy.getPlayItems().get(i);
225 assertEquals(pi.toString() + " must not be queued", 0,
226 pi.queueOrder);
227 }
228 }
229
230 /***
231 * Compares given track list with a playlist.
232 *
233 * @param expected
234 * the expected track list
235 * @param actual
236 * the playlist
237 */
238 public static void assertEquals(
239 final List<? extends TrackMetadataBean> expected,
240 final List<? extends PlaylistItem> actual) {
241 for (int i = 0; i < expected.size(); i++) {
242 assertEquals("At index i=" + i, expected.get(i), actual.get(i)
243 .getTrack());
244 }
245 assertEquals(expected.size(), actual.size());
246 }
247
248 /***
249 * Compares given track list with a playlist.
250 *
251 * @param expected
252 * the expected track list
253 */
254 protected void assertEqualsQueue(
255 final List<? extends TrackMetadataBean> expected) {
256 final List<? extends Integer> actual = strategy.getQueue();
257 assertEquals(expected.size(), actual.size());
258 for (int i = 0; i < expected.size(); i++) {
259 assertEquals(expected.get(i), strategy.getPlayItems().get(
260 actual.get(i)).getTrack());
261 }
262 }
263
264 /***
265 * Asserts that given list has given content.
266 *
267 * @param expected
268 * @param actual
269 */
270 public static void assertEquals(final Object[] expected,
271 final List<?> actual) {
272 assertEquals(expected.length, actual.size());
273 for (int i = 0; i < expected.length; i++) {
274 assertEquals(expected[i], actual.get(i));
275 }
276 }
277
278 /***
279 */
280 public void testPlaySameTrack() {
281 strategy.add(0, tracks);
282 strategy.play(6);
283 int i = strategy.getCurrentlyPlaying();
284
285
286 assertTrue(i >= 0);
287 strategy.play(i);
288 assertEquals(i, strategy.getCurrentlyPlaying());
289 strategy.play(-1);
290 assertEquals(-1, strategy.getCurrentlyPlaying());
291 strategy.play(-1);
292 assertEquals(-1, strategy.getCurrentlyPlaying());
293 }
294
295 /***
296 *
297 */
298 public void testNormalOrder() {
299 strategy.add(0, tracks);
300 assertNextTracks(tracks, false);
301 }
302
303 /***
304 */
305 public void testRemovingPlayedTrackRandom() {
306 strategy.setRandom(Random.TRACK);
307 strategy.add(0, tracks);
308 strategy.play(strategy.size() - 1);
309 strategy.remove(new Interval(0, strategy.size()));
310 assertEquals(-1, strategy.getCurrentlyPlaying());
311 }
312
313 /***
314 */
315 public void testRemovingTracksPreservesCurrentlyPlayedTrack() {
316 strategy.add(0, tracks);
317 strategy.play(15);
318 TrackMetadataBean track = getCurrentlyPlaying();
319 strategy.remove(new Interval(20, 5));
320 assertEquals(track, getCurrentlyPlaying());
321 strategy.remove(new Interval(5, 5));
322 assertEquals(track, getCurrentlyPlaying());
323 }
324
325 /***
326 * Returns {@link #strategy strategy} currently played track.
327 *
328 * @return never <code>null</code>. Fails if no track is being played.
329 */
330 protected TrackMetadataBean getCurrentlyPlaying() {
331 final int i = strategy.getCurrentlyPlaying();
332 assertTrue("No track is being played", i >= 0);
333 return strategy.getPlayItems().get(i).getTrack();
334 }
335
336 /***
337 *
338 */
339 public void testSetRandomModePreservesCurrentTrack() {
340 strategy.add(0, tracks);
341 strategy.next();
342 strategy.next();
343 strategy.next();
344 TrackMetadataBean old = getCurrentlyPlaying();
345 strategy.setRandom(Random.TRACK);
346 assertEquals(old, getCurrentlyPlaying());
347 strategy.setRandom(Random.ALBUM);
348 assertEquals(old, getCurrentlyPlaying());
349 strategy.setRandom(Random.NONE);
350 assertEquals(old, getCurrentlyPlaying());
351 }
352 }