Fix DefaultAudioSinkTest flakiness.
Some calls to handleBuffer return false while a previous flush is still handled in the background. Fix this by either asserting the method returns true if we don't expect any delay, or calling it repeatedly until it returns true (within a timeout). PiperOrigin-RevId: 460474419
This commit is contained in:
parent
776c8a5544
commit
223922fb11
@ -29,6 +29,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -38,6 +39,9 @@ import org.robolectric.annotation.Config;
|
|||||||
/** Unit tests for {@link DefaultAudioSink}. */
|
/** Unit tests for {@link DefaultAudioSink}. */
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
public final class DefaultAudioSinkTest {
|
public final class DefaultAudioSinkTest {
|
||||||
|
|
||||||
|
private static final long TIMEOUT_MS = 10_000;
|
||||||
|
|
||||||
private static final int CHANNEL_COUNT_MONO = 1;
|
private static final int CHANNEL_COUNT_MONO = 1;
|
||||||
private static final int CHANNEL_COUNT_STEREO = 2;
|
private static final int CHANNEL_COUNT_STEREO = 2;
|
||||||
private static final int BYTES_PER_FRAME_16_BIT = 2;
|
private static final int BYTES_PER_FRAME_16_BIT = 2;
|
||||||
@ -74,28 +78,44 @@ public final class DefaultAudioSinkTest {
|
|||||||
@Test
|
@Test
|
||||||
public void handlesBufferAfterReset() throws Exception {
|
public void handlesBufferAfterReset() throws Exception {
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
// After reset and re-configure we can successfully queue more input.
|
// After reset and re-configure we can successfully queue more input.
|
||||||
defaultAudioSink.reset();
|
defaultAudioSink.reset();
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
retryUntilTrue(
|
||||||
|
() ->
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlesBufferAfterReset_withPlaybackSpeed() throws Exception {
|
public void handlesBufferAfterReset_withPlaybackSpeed() throws Exception {
|
||||||
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f));
|
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f));
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
// After reset and re-configure we can successfully queue more input.
|
// After reset and re-configure we can successfully queue more input.
|
||||||
defaultAudioSink.reset();
|
defaultAudioSink.reset();
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
retryUntilTrue(
|
||||||
|
() ->
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1));
|
||||||
assertThat(defaultAudioSink.getPlaybackParameters())
|
assertThat(defaultAudioSink.getPlaybackParameters())
|
||||||
.isEqualTo(new PlaybackParameters(/* speed= */ 1.5f));
|
.isEqualTo(new PlaybackParameters(/* speed= */ 1.5f));
|
||||||
}
|
}
|
||||||
@ -103,28 +123,44 @@ public final class DefaultAudioSinkTest {
|
|||||||
@Test
|
@Test
|
||||||
public void handlesBufferAfterReset_withFormatChange() throws Exception {
|
public void handlesBufferAfterReset_withFormatChange() throws Exception {
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
// After reset and re-configure we can successfully queue more input.
|
// After reset and re-configure we can successfully queue more input.
|
||||||
defaultAudioSink.reset();
|
defaultAudioSink.reset();
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_MONO);
|
configureDefaultAudioSink(CHANNEL_COUNT_MONO);
|
||||||
|
retryUntilTrue(
|
||||||
|
() ->
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlesBufferAfterReset_withFormatChangeAndPlaybackSpeed() throws Exception {
|
public void handlesBufferAfterReset_withFormatChangeAndPlaybackSpeed() throws Exception {
|
||||||
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f));
|
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(/* speed= */ 1.5f));
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
// After reset and re-configure we can successfully queue more input.
|
// After reset and re-configure we can successfully queue more input.
|
||||||
defaultAudioSink.reset();
|
defaultAudioSink.reset();
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_MONO);
|
configureDefaultAudioSink(CHANNEL_COUNT_MONO);
|
||||||
|
retryUntilTrue(
|
||||||
|
() ->
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1));
|
||||||
assertThat(defaultAudioSink.getPlaybackParameters())
|
assertThat(defaultAudioSink.getPlaybackParameters())
|
||||||
.isEqualTo(new PlaybackParameters(/* speed= */ 1.5f));
|
.isEqualTo(new PlaybackParameters(/* speed= */ 1.5f));
|
||||||
}
|
}
|
||||||
@ -135,8 +171,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
CHANNEL_COUNT_STEREO,
|
CHANNEL_COUNT_STEREO,
|
||||||
/* trimStartFrames= */ TRIM_100_MS_FRAME_COUNT,
|
/* trimStartFrames= */ TRIM_100_MS_FRAME_COUNT,
|
||||||
/* trimEndFrames= */ 0);
|
/* trimEndFrames= */ 0);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
assertThat(arrayAudioBufferSink.output)
|
assertThat(arrayAudioBufferSink.output)
|
||||||
.hasLength(
|
.hasLength(
|
||||||
@ -151,8 +191,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
CHANNEL_COUNT_STEREO,
|
CHANNEL_COUNT_STEREO,
|
||||||
/* trimStartFrames= */ 0,
|
/* trimStartFrames= */ 0,
|
||||||
/* trimEndFrames= */ TRIM_10_MS_FRAME_COUNT);
|
/* trimEndFrames= */ TRIM_10_MS_FRAME_COUNT);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
assertThat(arrayAudioBufferSink.output)
|
assertThat(arrayAudioBufferSink.output)
|
||||||
.hasLength(
|
.hasLength(
|
||||||
@ -167,8 +211,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
CHANNEL_COUNT_STEREO,
|
CHANNEL_COUNT_STEREO,
|
||||||
/* trimStartFrames= */ TRIM_100_MS_FRAME_COUNT,
|
/* trimStartFrames= */ TRIM_100_MS_FRAME_COUNT,
|
||||||
/* trimEndFrames= */ TRIM_10_MS_FRAME_COUNT);
|
/* trimEndFrames= */ TRIM_10_MS_FRAME_COUNT);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
assertThat(arrayAudioBufferSink.output)
|
assertThat(arrayAudioBufferSink.output)
|
||||||
.hasLength(
|
.hasLength(
|
||||||
@ -180,19 +228,23 @@ public final class DefaultAudioSinkTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getCurrentPosition_returnsPositionFromFirstBuffer() throws Exception {
|
public void getCurrentPosition_returnsPositionFromFirstBuffer() throws Exception {
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(),
|
createDefaultSilenceBuffer(),
|
||||||
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
||||||
/* encodedAccessUnitCount= */ 1);
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
||||||
.isEqualTo(5 * C.MICROS_PER_SECOND);
|
.isEqualTo(5 * C.MICROS_PER_SECOND);
|
||||||
|
|
||||||
defaultAudioSink.reset();
|
defaultAudioSink.reset();
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
retryUntilTrue(
|
||||||
|
() ->
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(),
|
createDefaultSilenceBuffer(),
|
||||||
/* presentationTimeUs= */ 8 * C.MICROS_PER_SECOND,
|
/* presentationTimeUs= */ 8 * C.MICROS_PER_SECOND,
|
||||||
/* encodedAccessUnitCount= */ 1);
|
/* encodedAccessUnitCount= */ 1));
|
||||||
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
||||||
.isEqualTo(8 * C.MICROS_PER_SECOND);
|
.isEqualTo(8 * C.MICROS_PER_SECOND);
|
||||||
}
|
}
|
||||||
@ -269,24 +321,32 @@ public final class DefaultAudioSinkTest {
|
|||||||
// This is demonstrating that no Exceptions are thrown as a result of handling a buffer after an
|
// This is demonstrating that no Exceptions are thrown as a result of handling a buffer after an
|
||||||
// experimental flush.
|
// experimental flush.
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(), /* presentationTimeUs= */ 0, /* encodedAccessUnitCount= */ 1);
|
createDefaultSilenceBuffer(),
|
||||||
|
/* presentationTimeUs= */ 0,
|
||||||
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
// After the experimental flush we can successfully queue more input.
|
// After the experimental flush we can successfully queue more input.
|
||||||
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(),
|
createDefaultSilenceBuffer(),
|
||||||
/* presentationTimeUs= */ 5_000,
|
/* presentationTimeUs= */ 5_000,
|
||||||
/* encodedAccessUnitCount= */ 1);
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getCurrentPosition_returnsUnset_afterExperimentalFlush() throws Exception {
|
public void getCurrentPosition_returnsUnset_afterExperimentalFlush() throws Exception {
|
||||||
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
configureDefaultAudioSink(CHANNEL_COUNT_STEREO);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(),
|
createDefaultSilenceBuffer(),
|
||||||
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
||||||
/* encodedAccessUnitCount= */ 1);
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
defaultAudioSink.experimentalFlushWithoutAudioTrackRelease();
|
||||||
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
assertThat(defaultAudioSink.getCurrentPositionUs(/* sourceEnded= */ false))
|
||||||
.isEqualTo(CURRENT_POSITION_NOT_SET);
|
.isEqualTo(CURRENT_POSITION_NOT_SET);
|
||||||
@ -310,10 +370,12 @@ public final class DefaultAudioSinkTest {
|
|||||||
defaultAudioSink.enableTunnelingV21();
|
defaultAudioSink.enableTunnelingV21();
|
||||||
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(2));
|
defaultAudioSink.setPlaybackParameters(new PlaybackParameters(2));
|
||||||
configureDefaultAudioSink(/* channelCount= */ 2);
|
configureDefaultAudioSink(/* channelCount= */ 2);
|
||||||
|
assertThat(
|
||||||
defaultAudioSink.handleBuffer(
|
defaultAudioSink.handleBuffer(
|
||||||
createDefaultSilenceBuffer(),
|
createDefaultSilenceBuffer(),
|
||||||
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
/* presentationTimeUs= */ 5 * C.MICROS_PER_SECOND,
|
||||||
/* encodedAccessUnitCount= */ 1);
|
/* encodedAccessUnitCount= */ 1))
|
||||||
|
.isTrue();
|
||||||
|
|
||||||
assertThat(defaultAudioSink.getPlaybackParameters().speed).isEqualTo(1);
|
assertThat(defaultAudioSink.getPlaybackParameters().speed).isEqualTo(1);
|
||||||
}
|
}
|
||||||
@ -343,6 +405,19 @@ public final class DefaultAudioSinkTest {
|
|||||||
.order(ByteOrder.nativeOrder());
|
.order(ByteOrder.nativeOrder());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface ThrowingBooleanMethod {
|
||||||
|
boolean run() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void retryUntilTrue(ThrowingBooleanMethod booleanMethod) throws Exception {
|
||||||
|
long timeoutTimeMs = System.currentTimeMillis() + TIMEOUT_MS;
|
||||||
|
while (!booleanMethod.run()) {
|
||||||
|
if (System.currentTimeMillis() >= timeoutTimeMs) {
|
||||||
|
throw new TimeoutException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static final class ArrayAudioBufferSink implements TeeAudioProcessor.AudioBufferSink {
|
private static final class ArrayAudioBufferSink implements TeeAudioProcessor.AudioBufferSink {
|
||||||
|
|
||||||
private byte[] output;
|
private byte[] output;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user