mirror of
https://github.com/2OOP/pism.git
synced 2026-02-04 02:44:50 +00:00
Unit tests for MusicManager.java
This commit is contained in:
@@ -28,13 +28,10 @@ public class MusicManager<T extends AudioResource> implements org.toop.framework
|
||||
}
|
||||
|
||||
// Used in unit testing
|
||||
MusicManager(Class<T> type, Dispatcher dispatcher, ResourceManager resourceManager) {
|
||||
MusicManager(List<T> resources, Dispatcher dispatcher) {
|
||||
this.dispatcher = dispatcher;
|
||||
this.resources = new ArrayList<>(resourceManager.getAllOfType((Class<? extends BaseResource>) type)
|
||||
.stream()
|
||||
.map(e -> (T) e.getResource())
|
||||
.toList());
|
||||
createShuffled();
|
||||
this.resources = new ArrayList<>(resources);
|
||||
backgroundMusic.addAll(resources);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,7 +39,7 @@ public class MusicManager<T extends AudioResource> implements org.toop.framework
|
||||
return backgroundMusic;
|
||||
}
|
||||
|
||||
private void addBackgroundMusic(T musicAsset) {
|
||||
void addBackgroundMusic(T musicAsset) {
|
||||
backgroundMusic.add(musicAsset);
|
||||
}
|
||||
|
||||
@@ -65,6 +62,20 @@ public class MusicManager<T extends AudioResource> implements org.toop.framework
|
||||
playCurrentTrack();
|
||||
}
|
||||
|
||||
// Used in testing
|
||||
void play(int index) {
|
||||
if (playing) {
|
||||
logger.warn("MusicManager is already playing.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (backgroundMusic.isEmpty()) return;
|
||||
|
||||
playingIndex = index;
|
||||
playing = true;
|
||||
playCurrentTrack();
|
||||
}
|
||||
|
||||
private void playCurrentTrack() {
|
||||
if (playingIndex >= backgroundMusic.size()) {
|
||||
playingIndex = 0;
|
||||
@@ -80,20 +91,26 @@ public class MusicManager<T extends AudioResource> implements org.toop.framework
|
||||
dispatcher.run(() -> {
|
||||
current.play();
|
||||
|
||||
current.setOnEnd(() -> {
|
||||
playingIndex++;
|
||||
playCurrentTrack();
|
||||
});
|
||||
setTrackRunnable(current);
|
||||
|
||||
current.setOnError(() -> {
|
||||
logger.error("Error playing track: {}", current);
|
||||
backgroundMusic.remove(current);
|
||||
if (!backgroundMusic.isEmpty()) {
|
||||
playCurrentTrack();
|
||||
} else {
|
||||
playing = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private void setTrackRunnable(T track) {
|
||||
track.setOnEnd(() -> {
|
||||
playingIndex++;
|
||||
playCurrentTrack();
|
||||
});
|
||||
|
||||
track.setOnError(() -> {
|
||||
logger.error("Error playing track: {}", track);
|
||||
backgroundMusic.remove(track);
|
||||
|
||||
if (!backgroundMusic.isEmpty()) {
|
||||
playCurrentTrack();
|
||||
} else {
|
||||
playing = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
package org.toop.framework.audio;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.toop.framework.audio.interfaces.Dispatcher;
|
||||
import org.toop.framework.resource.resources.BaseResource;
|
||||
import org.toop.framework.resource.types.AudioResource;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class MockAudioResource extends BaseResource implements AudioResource {
|
||||
boolean played = false;
|
||||
boolean stopped = false;
|
||||
Runnable onEnd;
|
||||
Runnable onError;
|
||||
|
||||
public MockAudioResource(String name) {
|
||||
super(new File(name));
|
||||
}
|
||||
|
||||
public void triggerError() {
|
||||
if (onError != null) {
|
||||
onError.run();
|
||||
}
|
||||
}
|
||||
|
||||
public void triggerEnd() {
|
||||
if (onEnd != null) {
|
||||
onEnd.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
played = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnEnd(Runnable callback) {
|
||||
onEnd = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnError(Runnable callback) {
|
||||
onError = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateVolume(double volume) {}
|
||||
}
|
||||
|
||||
public class MusicManagerTest {
|
||||
|
||||
private Dispatcher dispatcher;
|
||||
private MockAudioResource track1;
|
||||
private MockAudioResource track2;
|
||||
private MockAudioResource track3;
|
||||
private MusicManager<MockAudioResource> manager;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
dispatcher = Runnable::run;
|
||||
|
||||
track1 = new MockAudioResource("track1");
|
||||
track2 = new MockAudioResource("track2");
|
||||
track3 = new MockAudioResource("track3");
|
||||
|
||||
List<MockAudioResource> resources = List.of(track1, track2, track3);
|
||||
|
||||
manager = new MusicManager<>(resources, dispatcher);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlaySingleTrack() {
|
||||
manager.play();
|
||||
assertTrue(track1.played || track2.played || track3.played,
|
||||
"At least one track should have played");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlayMultipleTimesDoesNotRestart() {
|
||||
manager.play();
|
||||
track1.played = false;
|
||||
manager.play();
|
||||
assertFalse(track1.played, "Second play call should not restart tracks");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testStopStopsAllTracks() {
|
||||
manager.play();
|
||||
manager.stop();
|
||||
assertTrue(track1.stopped && track2.stopped && track3.stopped,
|
||||
"All tracks should be stopped");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAutoAdvanceTracks() {
|
||||
track1.played = false;
|
||||
track2.played = false;
|
||||
track3.played = false;
|
||||
|
||||
manager.play();
|
||||
track1.triggerEnd();
|
||||
track2.triggerEnd();
|
||||
|
||||
assertTrue(track1.played, "Track1 should play, played %s instead");
|
||||
assertTrue(track2.played, "Track2 should play after track1 ends");
|
||||
assertTrue(track3.played, "Track3 should play after track2 ends");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTrackErrorRemovesTrackAndPlaysNext() {
|
||||
manager.play();
|
||||
track1.triggerError();
|
||||
|
||||
assertFalse(manager.getActiveAudio().contains(track1),
|
||||
"Track1 should be removed after error");
|
||||
assertTrue(track2.played, "Track2 should play after track1 error");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlayWithEmptyPlaylistDoesNothing() {
|
||||
manager.getActiveAudio().clear();
|
||||
manager.play();
|
||||
assertFalse(track1.played || track2.played || track3.played,
|
||||
"No tracks should play if playlist is empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultiplePlayStopSequences() {
|
||||
manager.play();
|
||||
manager.stop();
|
||||
manager.play();
|
||||
assertTrue(track1.played || track2.played || track3.played,
|
||||
"Tracks should play again after stopping");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPlayingIndexWrapsAround() {
|
||||
track1.played = false;
|
||||
track2.played = false;
|
||||
track3.played = false;
|
||||
|
||||
manager.play();
|
||||
track1.triggerEnd();
|
||||
track2.triggerEnd();
|
||||
track3.triggerEnd();
|
||||
|
||||
assertTrue(track1.played, "Track1 should play again after loop");
|
||||
assertTrue(track2.played, "Track2 should play");
|
||||
assertTrue(track3.played, "Track3 should play");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for many tracks playing sequentially one after another
|
||||
*/
|
||||
@Test
|
||||
void testSequentialMultipleTracks() {
|
||||
List<MockAudioResource> manyTracks = new ArrayList<>();
|
||||
for (int i = 1; i <= 1_000; i++) {
|
||||
manyTracks.add(new MockAudioResource("track" + i));
|
||||
}
|
||||
|
||||
MusicManager<MockAudioResource> multiManager = new MusicManager<>(manyTracks, dispatcher);
|
||||
|
||||
for (int i = 0; i < manyTracks.size() - 1; i++) {
|
||||
multiManager.play();
|
||||
manyTracks.get(i).triggerEnd();
|
||||
}
|
||||
|
||||
for (int i = 0; i < manyTracks.size(); i++) {
|
||||
assertTrue(manyTracks.get(i).played, "Track " + (i + 1) + " should have played sequentially");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user