Skip to content

Commit 9bbb4da

Browse files
committed
1) Test cases were not stopping AudioService before ending test case 2) Changed Audio to be a good singleton, previously because of Audio being bad singleton, test cases which were using static methods could have caused intermittent failures. 3) Made some other refactorings as well
1 parent db33cc5 commit 9bbb4da

File tree

3 files changed

+64
-38
lines changed

3 files changed

+64
-38
lines changed

event-queue/src/main/java/com/iluwatar/event/queue/App.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ public class App {
4747
* @throws IOException when there is a problem with the audio file loading
4848
* @throws UnsupportedAudioFileException when the loaded audio file is unsupported
4949
*/
50-
public static void main(String[] args) throws UnsupportedAudioFileException, IOException {
51-
Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
52-
Audio.playSound(Audio.getAudioStream("./etc/Closed-Hi-Hat-1.wav"), -8.0f);
50+
public static void main(String[] args) throws UnsupportedAudioFileException, IOException, InterruptedException {
51+
Audio audio = Audio.getInstance();
52+
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
53+
audio.playSound(audio.getAudioStream("./etc/Closed-Hi-Hat-1.wav"), -8.0f);
5354

5455
System.out.println("Press Enter key to stop the program...");
55-
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
56-
br.read();
57-
Audio.stopService();
56+
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
57+
br.read();
58+
}
59+
audio.stopService();
5860
}
5961
}

event-queue/src/main/java/com/iluwatar/event/queue/Audio.java

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,46 +41,51 @@ public class Audio {
4141

4242
private static final int MAX_PENDING = 16;
4343

44-
private static int headIndex;
44+
private int headIndex;
4545

46-
private static int tailIndex;
46+
private int tailIndex;
4747

48-
private static Thread updateThread = null;
48+
private volatile Thread updateThread = null;
4949

50-
private static PlayMessage[] pendingAudio = new PlayMessage[MAX_PENDING];
50+
private PlayMessage[] pendingAudio = new PlayMessage[MAX_PENDING];
51+
52+
// Visible only for testing purposes
53+
Audio() {
54+
55+
}
56+
57+
public static Audio getInstance() {
58+
return SingletonHolder.getAudioInstance();
59+
}
5160

5261
/**
53-
* This method stops the Update Method's thread.
62+
* This method stops the Update Method's thread and waits till service stops.
5463
*/
55-
public static synchronized void stopService() {
64+
public synchronized void stopService() throws InterruptedException {
5665
if (updateThread != null) {
5766
updateThread.interrupt();
5867
}
68+
updateThread.join();
69+
updateThread = null;
5970
}
6071

6172
/**
6273
* This method check the Update Method's thread is started.
6374
* @return boolean
6475
*/
65-
public static synchronized boolean isServiceRunning() {
66-
if (updateThread != null && updateThread.isAlive() ) {
67-
return true;
68-
} else {
69-
return false;
70-
}
76+
public synchronized boolean isServiceRunning() {
77+
return updateThread != null && updateThread.isAlive();
7178
}
7279

7380
/**
7481
* Starts the thread for the Update Method pattern if it was not started previously.
7582
* Also when the thread is is ready initializes the indexes of the queue
7683
*/
77-
public static void init() {
84+
public void init() {
7885
if (updateThread == null) {
79-
updateThread = new Thread(new Runnable() {
80-
public void run() {
81-
while (!Thread.currentThread().isInterrupted()) {
82-
Audio.update();
83-
}
86+
updateThread = new Thread(() -> {
87+
while (!Thread.currentThread().isInterrupted()) {
88+
update();
8489
}
8590
});
8691
}
@@ -90,7 +95,7 @@ public void run() {
9095
/**
9196
* This is a synchronized thread starter
9297
*/
93-
public static synchronized void startThread() {
98+
private synchronized void startThread() {
9499
if (!updateThread.isAlive()) {
95100
updateThread.start();
96101
headIndex = 0;
@@ -103,7 +108,7 @@ public static synchronized void startThread() {
103108
* @param stream is the AudioInputStream for the method
104109
* @param volume is the level of the audio's volume
105110
*/
106-
public static void playSound(AudioInputStream stream, float volume) {
111+
public void playSound(AudioInputStream stream, float volume) {
107112
init();
108113
// Walk the pending requests.
109114
for (int i = headIndex; i != tailIndex; i = (i + 1) % MAX_PENDING) {
@@ -123,7 +128,7 @@ public static void playSound(AudioInputStream stream, float volume) {
123128
* This method uses the Update Method pattern.
124129
* It takes the audio from the queue and plays it
125130
*/
126-
public static void update() {
131+
private void update() {
127132
// If there are no pending requests, do nothing.
128133
if (headIndex == tailIndex) {
129134
return;
@@ -143,6 +148,7 @@ public static void update() {
143148
e.printStackTrace();
144149
} catch (IllegalArgumentException e) {
145150
System.err.println("The system doesn't support the sound: " + e.getMessage());
151+
e.printStackTrace();
146152
}
147153
}
148154

@@ -153,7 +159,7 @@ public static void update() {
153159
* @throws UnsupportedAudioFileException when the audio file is not supported
154160
* @throws IOException when the file is not readable
155161
*/
156-
public static AudioInputStream getAudioStream(String filePath)
162+
public AudioInputStream getAudioStream(String filePath)
157163
throws UnsupportedAudioFileException, IOException {
158164
return AudioSystem.getAudioInputStream(new File(filePath).getAbsoluteFile());
159165
}
@@ -162,8 +168,15 @@ public static AudioInputStream getAudioStream(String filePath)
162168
* Returns with the message array of the queue
163169
* @return PlayMessage[]
164170
*/
165-
public static PlayMessage[] getPendingAudio() {
171+
public PlayMessage[] getPendingAudio() {
166172
return pendingAudio;
167173
}
168174

175+
private static class SingletonHolder {
176+
private static final Audio INSTANCE = new Audio();
177+
178+
static Audio getAudioInstance() {
179+
return INSTANCE;
180+
}
181+
}
169182
}

event-queue/src/test/java/com/iluwatar/event/queue/AudioTest.java

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
package com.iluwatar.event.queue;
2525

26+
import org.junit.jupiter.api.BeforeEach;
2627
import org.junit.jupiter.api.Test;
2728

2829
import javax.sound.sampled.UnsupportedAudioFileException;
@@ -39,6 +40,12 @@
3940
*/
4041
public class AudioTest {
4142

43+
private Audio audio;
44+
45+
@BeforeEach
46+
void createAudioInstance() {
47+
audio = new Audio();
48+
}
4249
/**
4350
* Test here that the playSound method works correctly
4451
* @throws UnsupportedAudioFileException when the audio file is not supported
@@ -47,13 +54,15 @@ public class AudioTest {
4754
*/
4855
@Test
4956
public void testPlaySound() throws UnsupportedAudioFileException, IOException, InterruptedException {
50-
Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
57+
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.wav"), -10.0f);
5158
// test that service is started
52-
assertTrue(Audio.isServiceRunning());
59+
assertTrue(audio.isServiceRunning());
5360
// adding a small pause to be sure that the sound is ended
5461
Thread.sleep(5000);
62+
63+
audio.stopService();
5564
// test that service is finished
56-
assertFalse(!Audio.isServiceRunning());
65+
assertFalse(audio.isServiceRunning());
5766
}
5867

5968
/**
@@ -64,16 +73,18 @@ public void testPlaySound() throws UnsupportedAudioFileException, IOException, I
6473
*/
6574
@Test
6675
public void testQueue() throws UnsupportedAudioFileException, IOException, InterruptedException {
67-
Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
68-
Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
69-
Audio.playSound(Audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
70-
assertTrue(Audio.getPendingAudio().length > 0);
76+
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
77+
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
78+
audio.playSound(audio.getAudioStream("./etc/Bass-Drum-1.aif"), -10.0f);
79+
assertTrue(audio.getPendingAudio().length > 0);
7180
// test that service is started
72-
assertTrue(Audio.isServiceRunning());
81+
assertTrue(audio.isServiceRunning());
7382
// adding a small pause to be sure that the sound is ended
7483
Thread.sleep(10000);
84+
85+
audio.stopService();
7586
// test that service is finished
76-
assertFalse(!Audio.isServiceRunning());
87+
assertFalse(audio.isServiceRunning());
7788
}
7889

7990
}

0 commit comments

Comments
 (0)