changeset 133:4a1c8f3d1f62

2008-09-23 Omair Majid <omajid@redhat.com> * unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java sourceDataLine is a memeber variable to allow tearDown to close it if some test accidentallly leaves it open. (testOpenAndClose): Fixed to use sourceDataLine. (testIsActiveAndIsOpen): Likewise. (testPlay): Likewise. (testStartedStopped): Likewise. (test2StartAndStopEvents): Likewise. (test3StartAndStopEvents): Likewise. (testStartOnClosedLine): Likewise. (testStopOnClosedLine): Likewise. (testPlayLessThanFrameSize): Likewise. (testOpenFormat): Likewise. (testFindLineWithFormat): Likewise. (testFindLineWithWrongFormat): Likewise. (testFindControl): Likewise. (testSupportedControls): Likewise. (testVolumeAndMute): Likewise. (testVolumeChanging): Likewise. (testOpenEvent): Likewise. (testCloseEvent): Likewise. (testCloseEventWrongListener): Likewise. (testFramePosition): Likewise. (testFramePositionAfterPlayingTwice): New function. Checks the length of getFramePositionAfterPlaying a file twice. (testMicroseconPosition): New function. Tests getMicrosecondPosition. (testBufferSizes): Fixed to use sourceDataLine. (testHasADefaultFormat): Likewise. (testDefaultFormatWithGetLine): Likewise. (testDrainTwice): Likewise. (testDrainWithoutStart): New function. Tests that for a SourceDataLine, writing some data, not starting it and trying to drain it causes the drain to hang. (testDrainWithoutOpen): Likewise. (testFlushTwice): Likewise. (testFlushWithoutOpen): Likewise. (testMixerKnowsAboutOpenLines): Likewise. (testMixerKnowsAboutOpen2Lines): Likewise (testMixerKnowsAboutOpen3Lines): Likewise. (tearDown): Close sourceDataLine if possible.
author Omair Majid <omajid@redhat.com>
date Tue, 23 Sep 2008 10:29:27 -0400
parents b7a5a39b31ab
children 381f212496eb
files unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java
diffstat 1 files changed, 324 insertions(+), 171 deletions(-) [+]
line wrap: on
line diff
--- a/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Mon Sep 22 14:44:23 2008 -0400
+++ b/unittests/org/classpath/icedtea/pulseaudio/PulseAudioSourceDataLineTest.java	Tue Sep 23 10:29:27 2008 -0400
@@ -64,11 +64,13 @@
 
 public class PulseAudioSourceDataLineTest {
 	Mixer mixer;
-
+	SourceDataLine sourceDataLine;
 	private int listenerCalled = 0;
 
 	int started = 0;
 	int stopped = 0;
+	int opened = 0;
+	int closed = 0;
 
 	AudioFormat aSupportedFormat = new AudioFormat(
 			AudioFormat.Encoding.PCM_UNSIGNED, 44100f, 8, 1, 1, 10, true);
@@ -144,44 +146,48 @@
 
 		mixer.open();
 
+		sourceDataLine = null;
+
 		started = 0;
 		stopped = 0;
+		opened = 0;
+		closed = 0;
 
 	}
 
 	@Test
 	public void testOpenAndClose() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
 
-		line.open();
-		Assert.assertTrue(line.isOpen());
+		sourceDataLine.open();
+		Assert.assertTrue(sourceDataLine.isOpen());
 
-		line.close();
-		Assert.assertFalse(line.isOpen());
+		sourceDataLine.close();
+		Assert.assertFalse(sourceDataLine.isOpen());
 
 	}
 
 	@Test
 	public void testIsActiveAndIsOpen() throws LineUnavailableException {
 
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
 
-		Assert.assertFalse(line.isActive());
-		Assert.assertFalse(line.isOpen());
-		line.open();
-		Assert.assertTrue(line.isOpen());
-		Assert.assertFalse(line.isActive());
-		line.start();
-		Assert.assertTrue(line.isOpen());
-		Assert.assertTrue(line.isActive());
-		line.stop();
-		Assert.assertTrue(line.isOpen());
-		Assert.assertFalse(line.isActive());
-		line.close();
-		Assert.assertFalse(line.isOpen());
-		Assert.assertFalse(line.isActive());
+		Assert.assertFalse(sourceDataLine.isActive());
+		Assert.assertFalse(sourceDataLine.isOpen());
+		sourceDataLine.open();
+		Assert.assertTrue(sourceDataLine.isOpen());
+		Assert.assertFalse(sourceDataLine.isActive());
+		sourceDataLine.start();
+		Assert.assertTrue(sourceDataLine.isOpen());
+		Assert.assertTrue(sourceDataLine.isActive());
+		sourceDataLine.stop();
+		Assert.assertTrue(sourceDataLine.isOpen());
+		Assert.assertFalse(sourceDataLine.isActive());
+		sourceDataLine.close();
+		Assert.assertFalse(sourceDataLine.isOpen());
+		Assert.assertFalse(sourceDataLine.isActive());
 
 	}
 
@@ -195,14 +201,13 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
-		line.open(audioFormat);
+		sourceDataLine.open(audioFormat);
 		System.out.println("opened");
-		line.start();
+		sourceDataLine.start();
 		System.out.println("started");
 		byte[] abData = new byte[1000];
 		int bytesRead = 0;
@@ -210,15 +215,15 @@
 		while (bytesRead >= 0) {
 			bytesRead = audioInputStream.read(abData, 0, abData.length);
 			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
+				sourceDataLine.write(abData, 0, bytesRead);
 			}
 		}
 		System.out.println("done");
 
-		line.drain();
+		sourceDataLine.drain();
 		System.out.println("drained");
-		line.stop();
-		line.close();
+		sourceDataLine.stop();
+		sourceDataLine.close();
 		System.out.println("closed");
 
 	}
@@ -232,12 +237,11 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
-		line.open(audioFormat);
+		sourceDataLine.open(audioFormat);
 
 		LineListener startStopListener = new LineListener() {
 
@@ -258,22 +262,22 @@
 
 		};
 
-		line.addLineListener(startStopListener);
+		sourceDataLine.addLineListener(startStopListener);
 
 		byte[] abData = new byte[1000];
 		int bytesRead = 0;
 
-		line.start();
+		sourceDataLine.start();
 		while (bytesRead >= 0) {
 			bytesRead = audioInputStream.read(abData, 0, abData.length);
 			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
+				sourceDataLine.write(abData, 0, bytesRead);
 			}
 		}
-		line.drain();
+		sourceDataLine.drain();
 
-		line.stop();
-		line.close();
+		sourceDataLine.stop();
+		sourceDataLine.close();
 
 		Assert.assertEquals(1, started);
 		Assert.assertEquals(1, stopped);
@@ -292,10 +296,9 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
 		LineListener startStopListener = new LineListener() {
 
@@ -314,22 +317,22 @@
 
 		};
 
-		line.addLineListener(startStopListener);
+		sourceDataLine.addLineListener(startStopListener);
 		System.out.println("Launching threadWriter");
-		ThreadWriter writer = new ThreadWriter(audioInputStream, line);
+		ThreadWriter writer = new ThreadWriter(audioInputStream, sourceDataLine);
 		writer.start();
 		// System.out.println("started");
 
 		Thread.sleep(1000);
 
-		line.stop();
+		sourceDataLine.stop();
 
 		System.out.println("corked");
 
 		Thread.sleep(1000);
 
 		// UNCORK
-		line.stop();
+		sourceDataLine.start();
 
 		Thread.sleep(1000);
 
@@ -353,10 +356,9 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
 		LineListener startStopListener = new LineListener() {
 
@@ -375,27 +377,27 @@
 
 		};
 
-		line.addLineListener(startStopListener);
+		sourceDataLine.addLineListener(startStopListener);
 		System.out.println("Launching threadWriter");
-		ThreadWriter writer = new ThreadWriter(audioInputStream, line);
+		ThreadWriter writer = new ThreadWriter(audioInputStream, sourceDataLine);
 		writer.start();
 		// System.out.println("started");
 
 		Thread.sleep(1000);
 
-		line.stop();
+		sourceDataLine.stop();
 
 		Thread.sleep(1000);
 
-		line.start();
+		sourceDataLine.start();
 
 		Thread.sleep(1000);
 
-		line.stop();
+		sourceDataLine.stop();
 
 		Thread.sleep(1000);
 
-		line.start();
+		sourceDataLine.start();
 
 		Thread.sleep(1000);
 
@@ -409,23 +411,21 @@
 
 	@Test(expected = IllegalStateException.class)
 	public void testStartOnClosedLine() throws LineUnavailableException {
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
-		line.start();
+		sourceDataLine.start();
 
 	}
 
 	@Test(expected = IllegalStateException.class)
 	public void testStopOnClosedLine() throws LineUnavailableException {
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
 
-		line.stop();
+		sourceDataLine.stop();
 	}
 
 	@Test(expected = IllegalArgumentException.class)
@@ -437,21 +437,20 @@
 		AudioFormat audioFormat = audioInputStream.getFormat();
 		// the audio file must have an even number of channels
 		Assert.assertTrue(audioFormat.getChannels() % 2 == 0);
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
 
 		byte[] data = new byte[1];
 		data[0] = (byte) 'a';
 
-		line.open();
-		line.start();
+		sourceDataLine.open();
+		sourceDataLine.start();
 		try {
-			line.write(data, 0, 1);
+			sourceDataLine.write(data, 0, 1);
 		} finally {
-			line.drain();
-			line.stop();
-			line.close();
+			sourceDataLine.stop();
+			sourceDataLine.close();
 		}
 	}
 
@@ -469,13 +468,12 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
-		line.open();
-		Assert.assertTrue(line.getFormat().matches(audioFormat));
-		line.close();
+		Assert.assertNotNull(sourceDataLine);
+		sourceDataLine.open();
+		Assert.assertTrue(sourceDataLine.getFormat().matches(audioFormat));
+		sourceDataLine.close();
 	}
 
 	@Test
@@ -485,11 +483,12 @@
 		AudioFormat wantedFormat = new AudioFormat(
 				AudioFormat.Encoding.PCM_UNSIGNED, 44100f, 8, 1, 1, 10, true);
 		System.out.println(wantedFormat);
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, wantedFormat));
-		line.open();
-		System.out.println(line.getFormat());
-		line.close();
+		sourceDataLine.open();
+		System.out.println(sourceDataLine.getFormat());
+		sourceDataLine.close();
 
 	}
 
@@ -497,46 +496,46 @@
 	public void testFindLineWithWrongFormat() throws LineUnavailableException {
 		System.out
 				.println("This test tries to acquire a line with incorrect format spec");
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, new AudioFormat(
 						AudioFormat.Encoding.PCM_UNSIGNED, 44100, 10000, 1, 13,
 						10, true)));
-		line.open();
-		line.close();
+		sourceDataLine.open();
+		sourceDataLine.close();
 	}
 
 	@Test
 	public void testFindControl() throws LineUnavailableException {
-		SourceDataLine sourceLine = (SourceDataLine) mixer
-				.getLine(new Line.Info(SourceDataLine.class));
-		sourceLine.open();
-		Control[] controls = sourceLine.getControls();
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+		sourceDataLine.open();
+		Control[] controls = sourceDataLine.getControls();
 		Assert.assertNotNull(controls);
-		Assert.assertTrue(sourceLine.getControls().length > 0);
+		Assert.assertTrue(sourceDataLine.getControls().length > 0);
 		for (Control control : controls) {
 			Assert.assertNotNull(control);
 		}
-		sourceLine.close();
+		sourceDataLine.close();
 	}
 
 	@Test
 	public void testSupportedControls() throws LineUnavailableException {
-		SourceDataLine sourceLine = (SourceDataLine) mixer
-				.getLine(new Line.Info(SourceDataLine.class));
-		sourceLine.open();
-		Assert.assertTrue(sourceLine
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
+		sourceDataLine.open();
+		Assert.assertTrue(sourceDataLine
 				.isControlSupported(FloatControl.Type.VOLUME));
-		Assert.assertTrue(sourceLine
+		Assert.assertTrue(sourceDataLine
 				.isControlSupported(BooleanControl.Type.MUTE));
-		sourceLine.close();
+		sourceDataLine.close();
 	}
 
 	@Test
 	public void testVolumeAndMute() throws Exception {
 
 		Mixer selectedMixer = mixer;
-		SourceDataLine line = (SourceDataLine) selectedMixer
-				.getLine(new Line.Info(SourceDataLine.class));
+		sourceDataLine = (SourceDataLine) selectedMixer.getLine(new Line.Info(
+				SourceDataLine.class));
 
 		File soundFile = new File(new java.io.File(".").getCanonicalPath()
 				+ "/testsounds/logout.wav");
@@ -544,11 +543,11 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		line.open(audioFormat);
-		line.start();
-		FloatControl volume = (FloatControl) line
+		sourceDataLine.open(audioFormat);
+		sourceDataLine.start();
+		FloatControl volume = (FloatControl) sourceDataLine
 				.getControl(FloatControl.Type.VOLUME);
-		BooleanControl mute = (BooleanControl) line
+		BooleanControl mute = (BooleanControl) sourceDataLine
 				.getControl(BooleanControl.Type.MUTE);
 
 		mute.setValue(true);
@@ -562,12 +561,12 @@
 		while (bytesRead >= 0) {
 			bytesRead = audioInputStream.read(abData, 0, abData.length);
 			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
+				sourceDataLine.write(abData, 0, bytesRead);
 			}
 		}
 
-		line.drain();
-		line.close();
+		sourceDataLine.drain();
+		sourceDataLine.close();
 		selectedMixer.close();
 
 	}
@@ -578,8 +577,8 @@
 
 		Mixer selectedMixer = mixer;
 
-		SourceDataLine line = (SourceDataLine) selectedMixer
-				.getLine(new Line.Info(SourceDataLine.class));
+		sourceDataLine = (SourceDataLine) selectedMixer.getLine(new Line.Info(
+				SourceDataLine.class));
 
 		File soundFile = new File(new java.io.File(".").getCanonicalPath()
 				+ "/testsounds/logout.wav");
@@ -587,9 +586,9 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		line.open(audioFormat);
-		line.start();
-		FloatControl volume = (FloatControl) line
+		sourceDataLine.open(audioFormat);
+		sourceDataLine.start();
+		FloatControl volume = (FloatControl) sourceDataLine
 				.getControl(FloatControl.Type.VOLUME);
 
 		volume.setValue(volume.getMinimum());
@@ -600,13 +599,13 @@
 		while (bytesRead >= 0) {
 			bytesRead = audioInputStream.read(abData, 0, abData.length);
 			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
+				sourceDataLine.write(abData, 0, bytesRead);
 				volume.setValue(volume.getValue() + 100);
 			}
 		}
 
-		line.drain();
-		line.close();
+		sourceDataLine.drain();
+		sourceDataLine.close();
 		selectedMixer.close();
 
 	}
@@ -622,12 +621,12 @@
 			}
 		};
 
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		line.addLineListener(openListener);
-		line.open();
-		line.removeLineListener(openListener);
-		line.close();
+		sourceDataLine.addLineListener(openListener);
+		sourceDataLine.open();
+		sourceDataLine.removeLineListener(openListener);
+		sourceDataLine.close();
 		Assert.assertEquals(1, listenerCalled);
 		listenerCalled = 0;
 	}
@@ -642,12 +641,12 @@
 			}
 		};
 
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		line.open();
-		line.addLineListener(closeListener);
-		line.close();
-		line.removeLineListener(closeListener);
+		sourceDataLine.open();
+		sourceDataLine.addLineListener(closeListener);
+		sourceDataLine.close();
+		sourceDataLine.removeLineListener(closeListener);
 		Assert.assertEquals(1, listenerCalled);
 		listenerCalled = 0;
 	}
@@ -661,13 +660,13 @@
 			}
 		};
 
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
 
-		line.open();
-		line.addLineListener(closeListener);
-		line.removeLineListener(closeListener);
-		line.close();
+		sourceDataLine.open();
+		sourceDataLine.addLineListener(closeListener);
+		sourceDataLine.removeLineListener(closeListener);
+		sourceDataLine.close();
 		Assert.assertEquals(0, listenerCalled);
 		listenerCalled = 0;
 
@@ -681,13 +680,106 @@
 				.getAudioInputStream(soundFile);
 		AudioFormat audioFormat = audioInputStream.getFormat();
 
-		SourceDataLine line;
-		line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
+				SourceDataLine.class, audioFormat));
+		Assert.assertNotNull(sourceDataLine);
+
+		sourceDataLine.open(audioFormat);
+		sourceDataLine.start();
+
+		byte[] abData = new byte[1000];
+		int bytesRead = 0;
+
+		while (bytesRead >= 0) {
+			bytesRead = audioInputStream.read(abData, 0, abData.length);
+			if (bytesRead > 0) {
+				sourceDataLine.write(abData, 0, bytesRead);
+			}
+		}
+
+		sourceDataLine.drain();
+		sourceDataLine.stop();
+		System.out.println("frame position: "
+				+ sourceDataLine.getFramePosition());
+		long expected = 136703;
+		long granularity = 100;
+		long pos = sourceDataLine.getFramePosition();
+		Assert.assertTrue(Math.abs(expected - pos) < granularity);
+		sourceDataLine.close();
+	}
+
+	@Test
+	public void testFramePositionAfterPlayingTwice()
+			throws UnsupportedAudioFileException, IOException,
+			LineUnavailableException {
+		File soundFile = new File("testsounds/logout.wav");
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, audioFormat));
-		Assert.assertNotNull(line);
+		Assert.assertNotNull(sourceDataLine);
+
+		sourceDataLine.open(audioFormat);
+		sourceDataLine.start();
+
+		byte[] abData = new byte[1000];
+		int bytesRead = 0;
+
+		while (bytesRead >= 0) {
+			bytesRead = audioInputStream.read(abData, 0, abData.length);
+			if (bytesRead > 0) {
+				sourceDataLine.write(abData, 0, bytesRead);
+			}
+		}
+
+		sourceDataLine.drain();
+		sourceDataLine.stop();
+
+		soundFile = new File("testsounds/logout.wav");
+		audioInputStream = AudioSystem.getAudioInputStream(soundFile);
+		audioFormat = audioInputStream.getFormat();
+
+		sourceDataLine.start();
+
+		abData = new byte[1000];
+		bytesRead = 0;
 
-		line.open(audioFormat);
-		line.start();
+		while (bytesRead >= 0) {
+			bytesRead = audioInputStream.read(abData, 0, abData.length);
+			if (bytesRead > 0) {
+				sourceDataLine.write(abData, 0, bytesRead);
+			}
+		}
+
+		sourceDataLine.drain();
+		sourceDataLine.stop();
+
+		System.out.println("frame position: "
+				+ sourceDataLine.getFramePosition());
+		long expected = 136703 * 2;
+		long granularity = 100;
+		long pos = sourceDataLine.getFramePosition();
+		Assert.assertTrue(Math.abs(expected - pos) < granularity);
+		sourceDataLine.close();
+	}
+
+	@Test
+	public void testMicroSecondPosition() throws UnsupportedAudioFileException,
+			IOException, LineUnavailableException {
+
+		File soundFile = new File("testsounds/logout.wav");
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
+				SourceDataLine.class, audioFormat));
+		Assert.assertNotNull(sourceDataLine);
+
+		sourceDataLine.open(audioFormat);
+		sourceDataLine.start();
 
 		byte[] abData = new byte[1000];
 		int bytesRead = 0;
@@ -695,98 +787,154 @@
 		while (bytesRead >= 0) {
 			bytesRead = audioInputStream.read(abData, 0, abData.length);
 			if (bytesRead > 0) {
-				line.write(abData, 0, bytesRead);
+				sourceDataLine.write(abData, 0, bytesRead);
 			}
 		}
 
-		line.drain();
-		line.stop();
-		System.out.println("time position: " + line.getMicrosecondPosition());
-		Assert.assertEquals(6199L, line.getMicrosecondPosition());
-		line.close();
+		sourceDataLine.drain();
+		sourceDataLine.stop();
+		System.out.println("time position: "
+				+ sourceDataLine.getMicrosecondPosition());
+		long expected = 6200;
+		long granularity = 100;
+		long pos = sourceDataLine.getMicrosecondPosition();
+		Assert.assertTrue(Math.abs(expected - pos) < granularity);
+		sourceDataLine.close();
+
 	}
 
 	@Test
 	public void testBufferSizes() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		line.open(aSupportedFormat, 10000);
-		Assert.assertEquals(10000, line.getBufferSize());
-		line.close();
+		sourceDataLine.open(aSupportedFormat, 10000);
+		Assert.assertEquals(10000, sourceDataLine.getBufferSize());
+		sourceDataLine.close();
 	}
 
 	@Test
 	public void testHasADefaultFormat() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new Line.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
 				SourceDataLine.class));
-		Assert.assertNotNull(line.getFormat());
-		System.out.println(line.getFormat());
+		Assert.assertNotNull(sourceDataLine.getFormat());
+		System.out.println(sourceDataLine.getFormat());
 
 	}
 
 	@Test
 	public void testDefaultFormatWithGetLine() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
-		Assert.assertEquals(aSupportedFormat, line.getFormat());
+		Assert.assertEquals(aSupportedFormat, sourceDataLine.getFormat());
 
 	}
 
 	@Test
 	public void testDefaultBufferSize() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
-		Assert.assertEquals(StreamBufferAttributes.SANE_DEFAULT, line
+		Assert.assertEquals(StreamBufferAttributes.SANE_DEFAULT, sourceDataLine
 				.getBufferSize());
 	}
 
 	@Test
 	public void testDrainTwice() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
 
-		line.open();
-		line.drain();
-		line.drain();
-		line.close();
+		sourceDataLine.open();
+		sourceDataLine.drain();
+		sourceDataLine.drain();
+		sourceDataLine.close();
+
+	}
+
+	@Test
+	public void testDrainWithoutStart() throws LineUnavailableException,
+			UnsupportedAudioFileException, IOException, InterruptedException {
+
+		File soundFile = new File("testsounds/logout.wav");
+		AudioInputStream audioInputStream = AudioSystem
+				.getAudioInputStream(soundFile);
+		AudioFormat audioFormat = audioInputStream.getFormat();
+
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
+				SourceDataLine.class, audioFormat, 1000));
+		Assert.assertNotNull(sourceDataLine);
+		sourceDataLine.open();
+		int available = sourceDataLine.available();
+		Assert.assertTrue(available > 1000);
+
+		byte[] abData = new byte[1000];
+		int bytesRead = 0;
+
+		bytesRead = audioInputStream.read(abData, 0, abData.length);
+		Assert.assertTrue(bytesRead > 0);
+		sourceDataLine.write(abData, 0, bytesRead);
+
+		Runnable blocker = new Runnable() {
+			@Override
+			public void run() {
+				sourceDataLine.drain();
+			}
+		};
+
+		Thread th = new Thread(blocker);
+		th.start();
+
+		th.join(1000);
+
+		if (th.isAlive()) {
+			sourceDataLine.close();
+			th.join(1000);
+			if (th.isAlive()) {
+				Assert
+						.fail("drain() does not return when the line has been closed");
+			} else {
+				sourceDataLine.close();
+			}
+		} else {
+			Assert.fail("drain() does not block when there is data on the "
+					+ "source data line and it hasnt been started");
+		}
 
 	}
 
 	@Test(expected = IllegalStateException.class)
 	public void testDrainWithoutOpen() throws LineUnavailableException {
 
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
 
-		line.drain();
+		sourceDataLine.drain();
 
 	}
 
 	@Test
 	public void testFlushTwice() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
 
-		line.open();
-		line.flush();
-		line.flush();
-		line.close();
+		sourceDataLine.open();
+		sourceDataLine.flush();
+		sourceDataLine.flush();
+		sourceDataLine.close();
 
 	}
 
 	@Test(expected = IllegalStateException.class)
 	public void testFlushWithoutOpen() throws LineUnavailableException {
-		SourceDataLine line = (SourceDataLine) mixer.getLine(new DataLine.Info(
+		sourceDataLine = (SourceDataLine) mixer.getLine(new DataLine.Info(
 				SourceDataLine.class, aSupportedFormat, 1000));
 
-		line.flush();
+		sourceDataLine.flush();
 
 	}
 
 	@Test
 	public void testMixerKnowsAboutOpenLines() throws LineUnavailableException {
-		SourceDataLine sourceDataLine = (SourceDataLine) mixer
-				.getLine(new Line.Info(SourceDataLine.class));
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
 
 		Assert.assertEquals(0, mixer.getSourceLines().length);
 		sourceDataLine.open();
@@ -799,8 +947,8 @@
 
 	@Test
 	public void testMixerKnowsAboutOpen2Lines() throws LineUnavailableException {
-		SourceDataLine sourceDataLine = (SourceDataLine) mixer
-				.getLine(new Line.Info(SourceDataLine.class));
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
 
 		Assert.assertEquals(0, mixer.getSourceLines().length);
 		sourceDataLine.open(aSupportedFormat);
@@ -813,8 +961,8 @@
 
 	@Test
 	public void testMixerKnowsAboutOpen3Lines() throws LineUnavailableException {
-		SourceDataLine sourceDataLine = (SourceDataLine) mixer
-				.getLine(new Line.Info(SourceDataLine.class));
+		sourceDataLine = (SourceDataLine) mixer.getLine(new Line.Info(
+				SourceDataLine.class));
 
 		Assert.assertEquals(0, mixer.getSourceLines().length);
 		sourceDataLine.open(aSupportedFormat, 10000);
@@ -836,9 +984,14 @@
 		started = 0;
 		stopped = 0;
 
+		if (sourceDataLine != null && sourceDataLine.isOpen()) {
+			sourceDataLine.close();
+		}
+
 		if (mixer.isOpen()) {
 			mixer.close();
 		}
+
 	}
 
 }