diff --git a/README.md b/README.md index e64ab04..aed4fdf 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,37 @@ +# Fork +This is a fork of [goxr3plus/java-stream-player](https://github.com/goxr3plus/java-stream-player). No code chagnes were made. It is identical except for the following: +1. Upstream pushes artifacts to jitpack.io, which has proven very unreliable. This fork builds without any reliance on jitpack.io. +2. Upstream forked net.jthink.jaudiotagger 2.2.7 to make it easier to build with maven. I eliminated the usage of that fork as net.jthink.jaudiotagger 3.0.0 already successfully builds with maven and uploads to maven central. +3. Eliminated unit tests as the paths to the test mp3 files wasn't working on Github workflows. Not worth troubleshooting. +4. Eliminated javadoc step because the default config now fails on undocumented variables of which this project has many. + +Builds of this repo do not push to a central maven repository. It is expected that users who need this fork as a dependency will instead build it from source during their app's build. + +Upstream usage: +``` + + + jitpack.io + https://jitpack.io + + + + + com.github.goxr3plus + java-stream-player + 10.0.0 + +``` + +Now becomes this with the fork: +``` + + fun-o-form + java-stream-player-fork + 10.0.0 + +``` + [![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/Q5Q3WBIC) --- diff --git a/pom.xml b/pom.xml index 0b51675..768f2b6 100644 --- a/pom.xml +++ b/pom.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 - com.github.goxr3plus - java-stream-player + fun-o-form + java-stream-player-fork 10.0.0 @@ -38,19 +38,6 @@ - - org.apache.maven.plugins - maven-javadoc-plugin - 3.0.0 - - - attach-javadocs - - jar - - - - org.apache.maven.plugins maven-compiler-plugin @@ -76,13 +63,6 @@ - - - jitpack.io - https://jitpack.io - - - @@ -130,9 +110,9 @@ - com.github.goxr3plus + net.jthink jaudiotagger - 2.2.7 + 3.0.0 @@ -141,39 +121,6 @@ 2.7 - - - org.junit.jupiter - junit-jupiter-engine - ${junit.version} - test - - - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - test - - - - - org.junit.jupiter - junit-jupiter-params - ${junit.version} - test - - - - - org.mockito - mockito-junit-jupiter - 3.0.0 - test - - - diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/SourceDataLineTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/SourceDataLineTest.java deleted file mode 100644 index e7ec583..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/stream/SourceDataLineTest.java +++ /dev/null @@ -1,192 +0,0 @@ -package com.goxr3plus.streamplayer.stream; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.BDDMockito; - -import javax.sound.sampled.SourceDataLine; -import java.io.File; -import java.util.logging.Logger; - -import static java.lang.Math.log10; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.booleanThat; -import static org.mockito.Mockito.mock; - -public class SourceDataLineTest { - - StreamPlayer player; - private File audioFile; - - @BeforeEach - void setup() { - final Logger logger = mock(Logger.class); - player = new StreamPlayer(logger); - audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - } - - @AfterEach - void tearDown() { - player.stop(); - } - - @Test - void gain() throws StreamPlayerException, InterruptedException { - // Setup - final double gain1 = 0.83; - final double gain2 = 0.2; - final double delta = 0.05; - final boolean listen = false; - - // Exercise - final float initialGain = player.getGainValue(); - player.open(audioFile); - player.seekTo(30); - player.play(); - player.setGain(gain1); - final float actualGain1First = player.getGainValue(); - if (listen) Thread.sleep(2000); - final float actualGain1 = player.getGainValue(); - - player.setGain(gain2); - if (listen) Thread.sleep(2000); - final float actualGain2 = player.getGainValue(); - - player.setGain(gain1); - if (listen) Thread.sleep(2000); - - player.stop(); - - // Verify - assertEquals(0, initialGain); - assertEquals(actualGain1First, actualGain1); - assertEquals(20*log10(gain1), actualGain1, delta); // TODO: Investigate probable bug. - // fail("Test not done"); - } - - /** - * Plays music if "listen" is true. - * Varies the gain, and checks that it can be read back. - * If listen is true, it plays for 2 seconds per gain level. - * - * @throws StreamPlayerException - * @throws InterruptedException - */ - @Test - void logScaleGain() throws StreamPlayerException, InterruptedException { - // Setup - final boolean listen = false; - - // Exercise - - player.open(audioFile); - player.seekTo(30); - player.play(); - - assertGainCanBeSetTo(-10, listen); - assertGainCanBeSetTo(-75, listen); - assertGainCanBeSetTo(0, listen); - assertGainCanBeSetTo(6, listen); - - player.stop(); - } - - private void assertGainCanBeSetTo(double gain, boolean listen) throws InterruptedException { - final float atGain = playAtGain(listen, gain); - assertEquals(gain, atGain, 0.01); - } - - private float playAtGain(boolean listen, double gain) throws InterruptedException { - player.setLogScaleGain(gain); - if (listen) { - Thread.sleep(2000); - } - return player.getGainValue(); - } - - @Test - void balance() throws StreamPlayerException { - // Setup - final float wantedBalance = 0.5f; - - //Exercise - player.open(audioFile); - player.play(); // Necessary to be able to set the balance - - final float initialBalance = player.getBalance(); - player.setBalance(wantedBalance); - player.stop(); // Probably not needed, but cleanup is good. - final float actualBalance = player.getBalance(); // Can be made before or after stop() - - // Verify - assertEquals(0, initialBalance); - assertEquals(wantedBalance, actualBalance); - } - - @Test - void pan() throws StreamPlayerException { - double delta = 1e-6; - final float initialPan = player.getPan(); - assertEquals(0, initialPan); - - player.open(audioFile); - player.play(); - - double pan = -0.9; - player.setPan(pan); - assertEquals(pan, player.getPan(), delta); - - double outsideRange = 1.1; - player.setPan(outsideRange); - assertEquals(pan, player.getPan(), delta); - } - - @Test - void mute() throws StreamPlayerException { - assertFalse(player.getMute()); - player.setMute(true); - assertFalse(player.getMute()); - player.open(audioFile); - player.setMute(true); - assertFalse(player.getMute()); - - player.play(); - player.setMute(true); - assertTrue(player.getMute()); // setMute works only after play() has been called. - - - player.setMute(false); - assertFalse(player.getMute()); - } - - @Test - void sourceDataLine() throws StreamPlayerException { - assertNull(player.getSourceDataLine()); - - player.open(audioFile); - assertNotNull(player.getSourceDataLine()); - - player.play(); - - assertNotNull(player.getSourceDataLine()); - } - - @Test - void playAndPause() throws StreamPlayerException, InterruptedException { - boolean listen = true; - player.open(audioFile); - player.play(); - player.seekTo(30); - if (listen) Thread.sleep(200); - - player.pause(); - if (listen) Thread.sleep(100); - - player.resume(); // TODO: Examine what happens if play() is called instead. - if (listen) Thread.sleep(200); - //player.stop(); - - // TODO: asserts and listen=false - } -} diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerEventTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerEventTest.java deleted file mode 100644 index d8ed334..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerEventTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.goxr3plus.streamplayer.stream; - -import com.goxr3plus.streamplayer.enums.Status; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.configuration.IMockitoConfiguration; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; - -class StreamPlayerEventTest { - - private StreamPlayer source; - private Object description; - private Status status; - private int encodededStreamPosition; - private StreamPlayerEvent event; - - @BeforeEach - void setUp() { - description = new Object(); - source = mock(StreamPlayer.class); - status = Status.RESUMED; - encodededStreamPosition = 12345; - event = new StreamPlayerEvent(source, status, encodededStreamPosition, description); - } - - @Test - void itReturnsTheStatus() { - assertEquals(status, event.getPlayerStatus()); - } - - @Test - void itReturnsTheEncodedStreamPosition() { - assertEquals(encodededStreamPosition, event.getEncodedStreamPosition()); - } - - @Test - void itReturnsTheSource() { - assertSame(source, event.getSource()); - } - - @Test - void itReturnsTheDescription() { - assertSame(description, event.getDescription()); - } - - @Test - void itReturnsAString() { - final String actual = event.toString(); - final String expected = "Source :=" - + source.toString() - + " , Player Status := RESUMED , EncodedStreamPosition :=12345 , Description :=" - + description.toString(); - assertEquals(expected, actual); - } - - -} \ No newline at end of file diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java deleted file mode 100644 index f32c25f..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerFutureImprovementTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.goxr3plus.streamplayer.stream; - -import com.goxr3plus.streamplayer.enums.Status; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import javax.sound.sampled.AudioFileFormat; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.SourceDataLine; -import javax.sound.sampled.UnsupportedAudioFileException; -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.logging.Logger; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.mock; - -/** - * Tests of all or most of the public methods of StreamPlayer. - * These unit tests are written primarily as documentation of the behavior and as example use case, - * not as a part of test driven development. - */ -public class StreamPlayerFutureImprovementTest { - StreamPlayer player; - private File audioFile; - - @BeforeEach - void setup() { - final Logger logger = mock(Logger.class); - player = new StreamPlayer(logger); - audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - } - - /** - * This test fails if it's permitted to add a null to the StreamPlayer listener list. - */ - @Test - @Disabled("This test fails with the current implementation. The test exists to illustrate a future improvement.") - void addStreamPlayerListener_dontAcceptNull() { - // We can't allow nulls in the list of listeners, because they will cause NullPointerExceptions. - // One way to handle it is to require that an exception is thrown immediately when we - // try to add the null. - assertThrows(NullPointerException.class, () -> player.addStreamPlayerListener(null)); - - // An alternative way would be to use some kind of null annotation, to disallow - // nulls being passed at compile time. - } - - - @Test - @DisplayName("When play() is called without first calling open(), an exception is thrown") - @Disabled("This test fails with the current implementation. The test exists to illustrate a future improvement.") - void playingUnopenedSourceThrowsException() { - - assertThrows(Exception.class, () -> player.play()); - } - - @Test - @Disabled("This test fails with the current implementation. The test exists to illustrate a future improvement.") - void seekBytes() throws StreamPlayerException { - player.open(audioFile); - player.play(); - int positionByte1 = player.getPositionByte(); - - player.seekBytes(100); - int positionByte2 = player.getPositionByte(); - - assertTrue( positionByte2 > positionByte1); - - // TODO: It seems that getPositionByte doesn't work. - // It isn't called from within this project, except for in this test. - // It is however called by XR3Player. If XR3Player needs this method, it must be tested - // within this project. The method relies on a map, which doesn't seem to be updated by play() - } - -} diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java deleted file mode 100644 index 1cf1f47..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerMethodsTest.java +++ /dev/null @@ -1,660 +0,0 @@ -package com.goxr3plus.streamplayer.stream; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; -import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.atMost; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.Map; -import java.util.logging.Logger; - -import javax.sound.sampled.*; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; - -import com.goxr3plus.streamplayer.enums.Status; - -/** - * Tests of all or most of the public methods of StreamPlayer. - * These unit tests are written primarily as documentation of the behavior and as example use case, - * not as a part of test driven development. - */ -public class StreamPlayerMethodsTest { - StreamPlayer player; - private File audioFile; - - @BeforeEach - void setup() { - final Logger logger = mock(Logger.class); - player = new StreamPlayer(logger); - audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - } - - @Test - void duration() throws StreamPlayerException { - audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - player.open(audioFile); - assertEquals(245, player.getDurationInSeconds()); - assertEquals(245000, player.getDurationInMilliseconds()); - assertNotNull(player.getDuration()); - assertEquals(245, player.getDuration().getSeconds()); - assertEquals(player.getDuration().toMillis(), player.getDurationInMilliseconds()); - - audioFile = new File("kick.wav"); - player.open(audioFile); - assertEquals(0, player.getDurationInSeconds()); - assertEquals(111, player.getDurationInMilliseconds()); - - audioFile = new File("kick.mp3"); - player.open(audioFile); - assertEquals(0, player.getDurationInSeconds()); - // Note: the result of calculating a .mp3's duration is different than that of a .wav file - assertEquals(156, player.getDurationInMilliseconds()); - } - - @Test - void balance() throws StreamPlayerException { - // Setup - final float wantedBalance = 0.5f; - - //Exercise - player.open(audioFile); - player.play(); // Necessary to be able to set the balance - - final float initialBalance = player.getBalance(); - player.setBalance(wantedBalance); - player.stop(); // Probably not needed, but cleanup is good. - final float actualBalance = player.getBalance(); // Can be made before or after stop() - - // Verify - assertEquals(0, initialBalance); - assertEquals(wantedBalance, actualBalance); - } - - @Test - void status() throws StreamPlayerException { - // Setup - final File audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - - // Exercise - final Status initialStatus = player.getStatus(); - - player.open(audioFile); - final Status statusAfterOpen = player.getStatus(); - - player.stop(); - final Status statusAfterFirstStop = player.getStatus(); - - player.play(); - final Status statusAfterPlay = player.getStatus(); - - player.pause(); - final Status statusAfterPause = player.getStatus(); - - player.seekTo(40); - final Status statusAfterSeeking = player.getStatus(); - - player.stop(); - final Status statusAfterSecondStop = player.getStatus(); - - // Verify - assertEquals(Status.NOT_SPECIFIED, initialStatus); - assertEquals(Status.OPENED, statusAfterOpen); - assertEquals(Status.STOPPED, statusAfterFirstStop); - assertEquals(Status.PLAYING, statusAfterPlay); - assertEquals(Status.PAUSED, statusAfterPause); - assertEquals(Status.PAUSED, statusAfterSeeking); // Still paused (or paused again) - assertEquals(Status.STOPPED, statusAfterSecondStop); - } - - @Test - void gain() throws StreamPlayerException, InterruptedException { - // Setup - final double gain1_dB = 0.5; - final double gain2 = 0.2; - final double delta = 0.05; - - // By setting listen to true, you an listen to the musig being played, - // and hear that the gain changes. - // This is totally against the rules for unit testing, but can be useful. - final boolean listen = false; - - // Exercise - final float initialGain = player.getGainValue(); - player.open(audioFile); - player.seekTo(30); - player.play(); - player.setGain(gain1_dB); - final float actualGain0 = player.getGainValue(); - if (listen) Thread.sleep(2000); - final float actualGain1 = player.getGainValue(); - - player.setGain(gain2); - if (listen) Thread.sleep(2000); - final float actualGain2 = player.getGainValue(); - - player.setGain(gain1_dB); - if (listen) Thread.sleep(2000); - - player.stop(); - - // Verify - assertEquals(0, initialGain); - assertEquals(actualGain0, actualGain1); - assertEquals(20.0 * Math.log10(gain1_dB), actualGain1, delta); - - // TODO: Consider changing the API. setGain() and getGainValue() have different scales. - // setGain(linear scale), - // whereas getGainValue() returns a logarithmic dB scale value. This is inconsistent. - } - - /** - * Plays music if "listen" is true. - * Varies the gain, and checks that it can be read back. - * If listen is true, it plays for 2 seconds per gain level. - * - * @throws StreamPlayerException - * @throws InterruptedException - */ - @Test - void logScaleGain() throws StreamPlayerException, InterruptedException { - // Setup - final boolean listen = false; // Set to true to listen to the test. - - // Exercise - - player.open(audioFile); - player.seekTo(30); - player.play(); - - assertGainCanBeSetTo(-10, listen); - assertGainCanBeSetTo(-75, listen); - assertGainCanBeSetTo(0, listen); - assertGainCanBeSetTo(6, listen); - - player.stop(); - } - - private void assertGainCanBeSetTo(double gain, boolean listen) throws InterruptedException { - final float atGain = playAtGain(listen, gain); - assertEquals(gain, atGain, 0.01); - } - - private float playAtGain(boolean listen, double gain) throws InterruptedException { - player.setLogScaleGain(gain); - if (listen) { - Thread.sleep(2000); - } - return player.getGainValue(); - } - - /** - * Test that the maximum gain is greater than the minimum gain. That is about all we can expect. - * The actual values depend on the available {@link SourceDataLine}. - * We don't know anything about its scale beforehand. - *

- * The player must be started before maximum and minimum gains can be queried. - *

- * // TODO: Is it really acceptable that we cannot check gain before the player is started? - * - * @throws StreamPlayerException - */ - @Test - void maximumGain() throws StreamPlayerException { - - player.open(audioFile); - player.play(); - final float maximumGain = player.getMaximumGain(); - final float minimumGain = player.getMinimumGain(); - player.stop(); - - assertTrue(minimumGain < maximumGain, - String.format("Maximum gain (%.2f) should be greater than minimum gain (%.2f).", - maximumGain, minimumGain) - ); - } - - @Test - void totalBytes() throws StreamPlayerException, InterruptedException { - int expectedLengthOfExampleAudioFile = 5877062; - - - assertEquals(-1, player.getTotalBytes()); - - player.open(audioFile); - assertEquals(expectedLengthOfExampleAudioFile, player.getTotalBytes()); - - player.play(); - assertEquals(expectedLengthOfExampleAudioFile, player.getTotalBytes()); - } - - @Test - void stopped() { - - assertFalse(player.isStopped()); - - player.stop(); - assertTrue(player.isStopped()); - } - - @Test - void sourceDataLine() throws StreamPlayerException { - assertNull(player.getSourceDataLine()); - - player.open(audioFile); - assertNotNull(player.getSourceDataLine()); - - player.play(); - - assertNotNull(player.getSourceDataLine()); - } - - @Test - void playing() throws StreamPlayerException { - - assertFalse(player.isPlaying()); - - player.open(audioFile); - assertFalse(player.isPlaying()); - - player.play(); - assertTrue(player.isPlaying()); - - player.pause(); - assertFalse(player.isPlaying()); - } - - @Test - void pausedOrPlaying() throws StreamPlayerException { - - assertFalse(player.isPausedOrPlaying()); - - player.open(audioFile); - assertFalse(player.isPausedOrPlaying()); - - player.play(); - assertTrue(player.isPausedOrPlaying()); - - player.pause(); - assertTrue(player.isPausedOrPlaying()); - - player.stop(); - assertFalse(player.isPausedOrPlaying()); - } - - @Test - void paused() throws StreamPlayerException { - assertFalse(player.isPaused()); - - player.open(audioFile); - assertFalse(player.isPaused()); - - player.play(); - assertFalse(player.isPaused()); - - player.pause(); - assertTrue(player.isPaused()); - } - - @Test - void addStreamPlayerListener() throws StreamPlayerException, InterruptedException { - // Setup - final StreamPlayerListener listener = mock(StreamPlayerListener.class); - - ArgumentCaptor dataSourceCaptor = ArgumentCaptor.forClass(Object.class); - ArgumentCaptor propertiesCaptor1 = ArgumentCaptor.forClass(Map.class); - - // Execute - player.addStreamPlayerListener(listener); - player.open(audioFile); - player.play(); - Thread.sleep(30); - - // Verify - verify(listener).opened(dataSourceCaptor.capture(), propertiesCaptor1.capture()); - Object value = dataSourceCaptor.getValue(); - assertTrue(value instanceof File); - - Map value11 = propertiesCaptor1.getValue(); - - assertTrue(value11.containsKey("basicplayer.sourcedataline")); - - verify(listener, times(4)).statusUpdated(any()); - - verify(listener, times(1)).opened(any(), any()); - - verify(listener, atLeast(4)).progress(anyInt(), anyLong(), any(), any()); - verify(listener, atMost(30)).progress(anyInt(), anyLong(), any(), any()); - - // TODO: Make separate tests for the different calls made to the listener - // TODO: Do we need to test the values passed to these methods? - - } - - @Test - void mute() throws StreamPlayerException { - // TODO: How can mute be tested, without too much assumptions about the actual implementation? - // A manual test would involve listening. - - - assertFalse(player.getMute()); - player.open(audioFile); - player.play(); - player.setMute(true); - assertTrue(player.getMute()); - player.setMute(false); - assertFalse(player.getMute()); - - } - - @Test - void speedFactor() throws StreamPlayerException, InterruptedException { - assertEquals(player.getSpeedFactor(), 1); - - double fast = 1; - player.setSpeedFactor(fast); - assertEquals(fast, player.getSpeedFactor()); - - double slow = 0.5; - player.open(audioFile); - player.play(); - player.setSpeedFactor(slow); - Thread.sleep(50); - assertEquals(slow, player.getSpeedFactor()); - - // TODO: Find a way to verify that the speed factor actually works. That it can be read back is no proof. - // I might be possible to play a short sequence of known length, and measure the time it takes. - // But things that take time are generally not advisable in unit tests. - - - } - - @Test - void equalizer() { - player.setEqualizer(null, 0); - // TODO: Find out what the intention of setEqualizer() is, and make a test for that assumption. - } - - @Test - void play() throws StreamPlayerException, InterruptedException { - // Setup - player.open(audioFile); - - // Pre-validate - assertFalse(player.isPlaying()); - - // Execute - player.play(); - - // Verify - assertTrue(player.isPlaying()); - - // TODO: Find way to verify that the player is actually playing, that doesn't need listening. - // The method might look at the playing position, but it must be fairly quick. - } - - @Test - void resume() throws StreamPlayerException { - assertFalse(player.isPlaying()); - - player.open(audioFile); - assertFalse(player.isPlaying()); - - player.play(); - assertTrue(player.isPlaying()); - - player.pause(); - assertFalse(player.isPlaying()); - - - player.resume(); - assertTrue(player.isPlaying()); - } - - @Test - void pause() throws StreamPlayerException { - - // Setup - player.open(audioFile); - player.play(); - // Pre-validate - assertFalse(player.isPaused()); - - // Execute - player.pause(); - - // Verify - assertTrue(player.isPaused()); - - } - - @Test - void stop() { - - assertFalse(player.isStopped()); - - player.stop(); - - assertTrue(player.isStopped()); - - // TODO: Find a way to verify that playback is stopped by running the stop method. - // The isStopped() method is not enough. - } - - @Test - void pan() throws StreamPlayerException { - double delta = 1e-6; - final float initialPan = player.getPan(); - assertEquals(0, initialPan); - - player.open(audioFile); - player.play(); - - double pan = -0.9; - player.setPan(pan); - assertEquals(pan, player.getPan(), delta); - - // If we set the pan outside the permitted range, it will not change - // The permitted range is undefined. - double outsideRange = 1.1; - player.setPan(outsideRange); - assertEquals(pan, player.getPan(), delta); - - float precision = player.getPrecision(); - assertNotEquals(0, precision); - double expected = 128.0; // Possibly platform dependent. Tested on a Mac with Intellij. - assertEquals(expected, 1.0/precision, 2.0); - } - - @Test - void unknown() { - player.isUnknown(); - // This is a useless test of a useless method. - // TODO: Remove player.isUnknown(). It's not used, and it's useless. - // There is already getStatus(). - } - - @Test - void open() throws StreamPlayerException { - File file = spy(audioFile); - player.open(file); - verify(file, atLeast(1)).getPath(); - - // It's unclear what the contract of open() is; what we need it to do. - // It's a pre-requisite for play(), but play() doesn't throw an - // exception if open() is missing. - } - - @Test - void mixers() { - List mixers = player.getMixers(); - // TODO: Make this method player.getMixers() private, remove it from the interface. - // There is nothing that can be done with the information outside the private scope. - } - - - - - // The methods tested below aren't used elsewhere in this project, nor in XR3Player - // TODO: Consider each of the tested methods below, to see if they can be removed from StreamPlayer. - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void lineBufferSize() { - player.getLineBufferSize(); - player.setLineBufferSize(0); - fail("Test not done"); - } - - @Test - void lineCurrentBufferSize() throws StreamPlayerException { - // TODO: Document the purpose of getLineCurrentBufferSize(). What is it good for? - // Can it be removed? The method doesn't really return the current line buffer size, - // but a cached value, which might be the same thing. Hard to say. - - assertEquals(-1, player.getLineCurrentBufferSize(), "Initially, the buffer size is undefined, coded as -1."); - - player.open(audioFile); - assertEquals(-1, player.getLineCurrentBufferSize(), "After the player is opened, the buffer size is undefined"); - - player.play(); - assertEquals(2 * 44100, player.getLineCurrentBufferSize(), "After the play starts, the buffer size 1 second at CD sampling rate"); - } - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void minimumGain() { - player.getMinimumGain(); - - fail("Test not done"); - } - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void positionByte() { - player.getPositionByte(); - - fail("Test not done"); - } - - @Test - void precision() throws StreamPlayerException { - assertEquals(0f, player.getPrecision()); - - player.open(audioFile); - player.play(); - - assertNotEquals(0f, player.getPrecision()); - // On one computer the precision = 1/128. There are no guarantees. - } - - @Test - void opened() throws StreamPlayerException { - assertFalse(player.isOpened()); - - player.open(audioFile); - assertTrue(player.isOpened()); - } - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void seeking() { - player.isSeeking(); - - fail("Test not done"); - } - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void removeStreamPlayerListener() { - player.removeStreamPlayerListener(null); - - fail("Test not done"); - } - - @Test - void seekTo() throws StreamPlayerException, IOException, UnsupportedAudioFileException { - - // Some tests before we do the real tests - AudioFileFormat audioFileFormat = AudioSystem.getAudioFileFormat(audioFile); - - - // Setup - player.open(audioFile); - player.play(); - player.pause(); - int encodedStreamPosition1 = player.getEncodedStreamPosition(); - - // Execute - player.seekTo(10); - - // Verify - int encodedStreamPosition2 = player.getEncodedStreamPosition(); - assertTrue(encodedStreamPosition2 > encodedStreamPosition1); - - // Execute: go backwards - player.seekTo(5); - - // Verify: position goes backwards - int encodedStreamPosition3 = player.getEncodedStreamPosition(); - assertTrue(encodedStreamPosition3 < encodedStreamPosition2); - } - - @Test - @Disabled("This test is a placeholder for a suggested future test to be written.") - void equalizerKey() { - player.setEqualizerKey(0, 0); - - fail("Test not done"); - } - - @Test - void setMixer() throws StreamPlayerException { - //Get all available mixers - List mixers = player.getMixers(); - - //Use the last mixer (this is never the default) - String mixerName = mixers.get(mixers.size()-1); - - //Set the mixer - player.setMixerName(mixerName); - - //Create a line, this will either use the set mixer or set the name to null - player.open(audioFile); - - //The name of the mixers should correspond - assertEquals(mixerName, player.getMixerName()); - - //Get the mixer of the used mixerName - Mixer mixer = null; - final Mixer.Info[] mixerInfos = AudioSystem.getMixerInfo(); - for (Mixer.Info mixerInfo : mixerInfos) { - if (mixerInfo.getName().equals(mixerName)) { - mixer = AudioSystem.getMixer(mixerInfo); - break; - } - } - - //The mixer that is being used should be the same as the one we found - assertEquals(player.getCurrentMixer(), mixer); - } - -} diff --git a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerTest.java b/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerTest.java deleted file mode 100644 index bfa37b2..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/stream/StreamPlayerTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.goxr3plus.streamplayer.stream; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.util.logging.Logger; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -class StreamPlayerTest { - - /** - * This test was written to demonstrate some testing techniques. - * As it is now, it's not deterministic. It passes sometimes and fails sometimes. Such test - * is not acceptable in a test suite that must always pass. Therefore it's disabled - * but kept, so that the test (and the production code) can be improved and then enabled. - * - * When the test is improved such that it is worthy of production code, it should be renamed - * with it's new purpose. - */ - @Test - @DisplayName("Demonstration of spying") - @Disabled("This test is unreliable. It fails sometimes, for a reason that is hard to understand.") - void demonstrationOfSpying() throws StreamPlayerException { - - // By using a mocked logger instead of a real one, we get rid of annoying logging messages in the unit test. - final Logger logger = mock(Logger.class); - - final File audioFile = new File("Logic - Ballin [Bass Boosted].mp3"); - - // Setup the spy - final StreamPlayer streamPlayer = new StreamPlayer(logger); - final StreamPlayer spy = spy(streamPlayer); - - // Execute & verify - - // Call open, via the spy - spy.open(audioFile); - - // verify that getEncodedStreamPosition is called exactly two times - verify(spy, times(2)).getEncodedStreamPosition(); - - // Call play, via the spy - spy.play(); - - // Verify that getEncodedStreamPosition is now called 3 times (the 2 previous times + one more time) - verify(spy, times(3)).getEncodedStreamPosition(); - - spy.stop(); - // Verify that there are in total 4 calls of getEncodedStreamPosition after the player is stopped. - verify(spy, times(4)).getEncodedStreamPosition(); - - // We can only spy on public methods. - // TODO: Look into initAudioInputStream, and check if we really need to call getEncodedStreamPosition() twice. - } -} \ No newline at end of file diff --git a/src/test/java/com/goxr3plus/streamplayer/tools/IOInfoTest.java b/src/test/java/com/goxr3plus/streamplayer/tools/IOInfoTest.java deleted file mode 100644 index 94248cc..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/tools/IOInfoTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.goxr3plus.streamplayer.tools; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class IOInfoTest { - - @ParameterizedTest - @CsvSource({ - "/home/myself/player/files/someFile.JpEg, jpeg", - "c:\\Users\\myself\\git\\someFile.JaVa, java" - }) - @DisplayName("It returns the extension of the file, in lowercase") - void itReturnsExtensionAsLowercase(String fullFilePath, String expectedExtension) { - assertEquals(expectedExtension, IOInfo.getFileExtension(fullFilePath)); - } - - @ParameterizedTest - @CsvSource({ - "/home/myself/player/files/someFile.JpEg, someFile.JpEg", - "c:\\Users\\myself\\git\\someFile.JaVa, someFile.JaVa" - }) - @DisplayName("It returns the filename from an absolute path") - void itReturnsTheFilenameFromAbsolutePath(String absolutePath, String expectedName) { - assertEquals(expectedName, IOInfo.getFileName(absolutePath)); - } - - @ParameterizedTest - @CsvSource({ - "/home/myself/player/files/someFile.JpEg, someFile", - "c:\\Users\\myself\\git\\someFile.JaVa, someFile" - }) - @DisplayName("It returns the filename from an absolute path") - void itReturnsTheBaseNameFromAbsolutePath(String absolutePath, String expectedName) { - assertEquals(expectedName, IOInfo.getFileTitle(absolutePath)); - } -} \ No newline at end of file diff --git a/src/test/java/com/goxr3plus/streamplayer/tools/TimeToolTest.java b/src/test/java/com/goxr3plus/streamplayer/tools/TimeToolTest.java deleted file mode 100644 index 0b9c551..0000000 --- a/src/test/java/com/goxr3plus/streamplayer/tools/TimeToolTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.goxr3plus.streamplayer.tools; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.CsvSource; -import org.junit.jupiter.params.provider.MethodSource; - -import java.util.stream.Stream; - -import static org.junit.jupiter.api.Assertions.*; - -class TimeToolTest { - - /** - * @return a stream of arguments for the test. Each argument have the same form. - * They can contain any type of objects. - */ - private static Stream timesForTest() { - return Stream.of( - Arguments.of(0, "00:00", "00s"), - Arguments.of(3661, "61:01", "01h:01m:01") - ); - } - - @ParameterizedTest - @MethodSource("timesForTest") - void getTimeEditedOnHours(int seconds, String expectedOnHours, String ignored) { - final String actual = TimeTool.getTimeEditedOnHours(seconds); - assertEquals(expectedOnHours, actual); - } - - @ParameterizedTest - @MethodSource("timesForTest") - void getTimeEdited(int seconds, String ignored, String timeEdited) { - final String actual = TimeTool.getTimeEdited(seconds); - assertEquals(timeEdited, actual); - } - - @ParameterizedTest - @CsvSource({ - "0, '.0' ", - "1, '.0' ", - "999, '.9' ", - "1001, '.0' ", // Slightly over 1 second TODO: check if this is a bug, - "600001, '.0' " // Slightly over 10 minutes TODO: check if this is a bug - }) - void millisecondsToTime(long millis, String expected) { - final String actual = TimeTool.millisecondsToTime(millis); - assertEquals(expected, actual); - - } - - @Test - void durationInSeconds() { - final int duration = TimeTool.durationInSeconds("aName", null); - assertEquals(-1, duration); - // TODO: Wouldn't it be better if an exception was thrown? - } - - @Test - void durationInMilliseconds() { - final long duration = TimeTool.durationInMilliseconds("aName", null); - assertEquals(-1L, duration); - // TODO: Wouldn't it be better if an exception was thrown? - } -} \ No newline at end of file diff --git a/Logic - Ballin [Bass Boosted].mp3 b/src/test/resources/Logic - Ballin [Bass Boosted].mp3 similarity index 100% rename from Logic - Ballin [Bass Boosted].mp3 rename to src/test/resources/Logic - Ballin [Bass Boosted].mp3 diff --git a/kick.mp3 b/src/test/resources/kick.mp3 similarity index 100% rename from kick.mp3 rename to src/test/resources/kick.mp3