mirror of
https://github.com/androidx/media.git
synced 2025-05-06 23:20:42 +08:00
Move runUntil method to TestUtil as it's used by multiple tests.
We started using this method from other tests unrelated to TestExoPlayer, so the method is better placed inside a generic Util class. PiperOrigin-RevId: 316675067
This commit is contained in:
parent
b7233c28e9
commit
cc97bcb469
@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.google.android.exoplayer2.source;
|
||||
|
||||
import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.net.Uri;
|
||||
@ -24,7 +25,6 @@ import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.drm.DrmSessionManager;
|
||||
import com.google.android.exoplayer2.extractor.Extractor;
|
||||
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor;
|
||||
import com.google.android.exoplayer2.testutil.TestExoPlayer;
|
||||
import com.google.android.exoplayer2.upstream.AssetDataSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultAllocator;
|
||||
import com.google.android.exoplayer2.upstream.DefaultLoadErrorHandlingPolicy;
|
||||
@ -72,7 +72,7 @@ public final class ProgressiveMediaPeriodTest {
|
||||
}
|
||||
},
|
||||
/* positionUs= */ 0);
|
||||
TestExoPlayer.runUntil(prepareCallbackCalled::get);
|
||||
runMainLooperUntil(prepareCallbackCalled::get);
|
||||
mediaPeriod.release();
|
||||
|
||||
assertThat(sourceInfoRefreshCalledBeforeOnPrepared.get()).isTrue();
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.google.android.exoplayer2.testutil;
|
||||
|
||||
import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
@ -36,11 +37,8 @@ import com.google.android.exoplayer2.upstream.BandwidthMeter;
|
||||
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.android.exoplayer2.util.Supplier;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.google.android.exoplayer2.video.VideoListener;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@ -52,30 +50,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
*/
|
||||
public class TestExoPlayer {
|
||||
|
||||
/**
|
||||
* The default timeout applied when calling one of the {@code runUntil} methods. This timeout
|
||||
* should be sufficient for any condition using a Robolectric test.
|
||||
*/
|
||||
public static final long DEFAULT_TIMEOUT_MS = 10_000;
|
||||
|
||||
/** Reflectively call Robolectric ShadowLooper#runOneTask. */
|
||||
private static final Object shadowLooper;
|
||||
|
||||
private static final Method runOneTaskMethod;
|
||||
|
||||
static {
|
||||
try {
|
||||
Class<?> clazz = Class.forName("org.robolectric.Shadows");
|
||||
Method shadowOfMethod =
|
||||
Assertions.checkNotNull(clazz.getDeclaredMethod("shadowOf", Looper.class));
|
||||
shadowLooper =
|
||||
Assertions.checkNotNull(shadowOfMethod.invoke(new Object(), Looper.getMainLooper()));
|
||||
runOneTaskMethod = shadowLooper.getClass().getDeclaredMethod("runOneTask");
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** A builder of {@link SimpleExoPlayer} instances for testing. */
|
||||
public static class Builder {
|
||||
|
||||
@ -317,7 +291,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param expectedState The expected {@link Player.State}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilPlaybackState(Player player, @Player.State int expectedState)
|
||||
throws TimeoutException {
|
||||
@ -336,7 +311,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(receivedExpectedState::get);
|
||||
runMainLooperUntil(receivedExpectedState::get);
|
||||
player.removeListener(listener);
|
||||
}
|
||||
|
||||
@ -346,7 +321,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param expectedPlayWhenReady The expected value for {@link Player#getPlayWhenReady()}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilPlayWhenReady(Player player, boolean expectedPlayWhenReady)
|
||||
throws TimeoutException {
|
||||
@ -366,7 +342,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(receivedExpectedPlayWhenReady::get);
|
||||
runMainLooperUntil(receivedExpectedPlayWhenReady::get);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -375,7 +351,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param expectedTimeline The expected {@link Timeline}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilTimelineChanged(Player player, Timeline expectedTimeline)
|
||||
throws TimeoutException {
|
||||
@ -395,7 +372,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(receivedExpectedTimeline::get);
|
||||
runMainLooperUntil(receivedExpectedTimeline::get);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -403,7 +380,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @return The new {@link Timeline}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static Timeline runUntilTimelineChanged(Player player) throws TimeoutException {
|
||||
verifyMainTestThread(player);
|
||||
@ -417,7 +395,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(() -> receivedTimeline.get() != null);
|
||||
runMainLooperUntil(() -> receivedTimeline.get() != null);
|
||||
return receivedTimeline.get();
|
||||
}
|
||||
|
||||
@ -428,7 +406,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @param expectedReason The expected {@link Player.DiscontinuityReason}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilPositionDiscontinuity(
|
||||
Player player, @Player.DiscontinuityReason int expectedReason) throws TimeoutException {
|
||||
@ -444,7 +423,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(receivedCallback::get);
|
||||
runMainLooperUntil(receivedCallback::get);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -452,7 +431,8 @@ public class TestExoPlayer {
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @return The raised {@link ExoPlaybackException}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static ExoPlaybackException runUntilError(Player player) throws TimeoutException {
|
||||
verifyMainTestThread(player);
|
||||
@ -466,7 +446,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addListener(listener);
|
||||
runUntil(() -> receivedError.get() != null);
|
||||
runMainLooperUntil(() -> receivedError.get() != null);
|
||||
return receivedError.get();
|
||||
}
|
||||
|
||||
@ -475,7 +455,8 @@ public class TestExoPlayer {
|
||||
* callback has been called.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilRenderedFirstFrame(SimpleExoPlayer player) throws TimeoutException {
|
||||
verifyMainTestThread(player);
|
||||
@ -489,7 +470,7 @@ public class TestExoPlayer {
|
||||
}
|
||||
};
|
||||
player.addVideoListener(listener);
|
||||
runUntil(receivedCallback::get);
|
||||
runMainLooperUntil(receivedCallback::get);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -497,7 +478,8 @@ public class TestExoPlayer {
|
||||
* commands on the internal playback thread.
|
||||
*
|
||||
* @param player The {@link Player}.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS default timeout} is exceeded.
|
||||
* @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
|
||||
* exceeded.
|
||||
*/
|
||||
public static void runUntilPendingCommandsAreFullyHandled(ExoPlayer player)
|
||||
throws TimeoutException {
|
||||
@ -510,41 +492,7 @@ public class TestExoPlayer {
|
||||
.createMessage((type, data) -> receivedMessageCallback.set(true))
|
||||
.setHandler(Util.createHandler())
|
||||
.send();
|
||||
runUntil(receivedMessageCallback::get);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks of the main {@link Looper} until the {@code condition} returns {@code true}.
|
||||
*
|
||||
* @param condition The condition.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS} is exceeded.
|
||||
*/
|
||||
public static void runUntil(Supplier<Boolean> condition) throws TimeoutException {
|
||||
runUntil(condition, DEFAULT_TIMEOUT_MS, Clock.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks of the main {@link Looper} until the {@code condition} returns {@code true}.
|
||||
*
|
||||
* @param condition The condition.
|
||||
* @param timeoutMs The timeout in milliseconds.
|
||||
* @param clock The {@link Clock} to measure the timeout.
|
||||
* @throws TimeoutException If the {@code timeoutMs timeout} is exceeded.
|
||||
*/
|
||||
public static void runUntil(Supplier<Boolean> condition, long timeoutMs, Clock clock)
|
||||
throws TimeoutException {
|
||||
verifyMainTestThread();
|
||||
try {
|
||||
long timeoutTimeMs = clock.currentTimeMillis() + timeoutMs;
|
||||
while (!condition.get()) {
|
||||
if (clock.currentTimeMillis() >= timeoutTimeMs) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
runOneTaskMethod.invoke(shadowLooper);
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
runMainLooperUntil(receivedMessageCallback::get);
|
||||
}
|
||||
|
||||
private static void verifyMainTestThread(Player player) {
|
||||
@ -553,10 +501,4 @@ public class TestExoPlayer {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private static void verifyMainTestThread() {
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.media.MediaCodec;
|
||||
import android.net.Uri;
|
||||
import android.os.Looper;
|
||||
import com.google.android.exoplayer2.C;
|
||||
import com.google.android.exoplayer2.database.DatabaseProvider;
|
||||
import com.google.android.exoplayer2.database.DefaultDatabaseProvider;
|
||||
@ -40,21 +41,38 @@ import com.google.android.exoplayer2.upstream.DataSpec;
|
||||
import com.google.android.exoplayer2.util.Assertions;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.android.exoplayer2.util.ConditionVariable;
|
||||
import com.google.android.exoplayer2.util.Supplier;
|
||||
import com.google.android.exoplayer2.util.SystemClock;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
|
||||
/**
|
||||
* Utility methods for tests.
|
||||
*/
|
||||
public class TestUtil {
|
||||
|
||||
/**
|
||||
* The default timeout applied when calling {@link #runMainLooperUntil(Supplier)}. This timeout
|
||||
* should be sufficient for any condition using a Robolectric test.
|
||||
*/
|
||||
public static final long DEFAULT_TIMEOUT_MS = 10_000;
|
||||
|
||||
/** Reflectively loaded Robolectric ShadowLooper#runOneTask. */
|
||||
private static @MonotonicNonNull Object shadowLooper;
|
||||
|
||||
private static @MonotonicNonNull Method runOneTaskMethod;
|
||||
|
||||
private TestUtil() {}
|
||||
|
||||
/**
|
||||
@ -484,4 +502,64 @@ public class TestUtil {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks of the main Robolectric {@link Looper} until the {@code condition} returns {@code
|
||||
* true}.
|
||||
*
|
||||
* <p>Must be called on the main test thread.
|
||||
*
|
||||
* @param condition The condition.
|
||||
* @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS} is exceeded.
|
||||
*/
|
||||
public static void runMainLooperUntil(Supplier<Boolean> condition) throws TimeoutException {
|
||||
runMainLooperUntil(condition, DEFAULT_TIMEOUT_MS, Clock.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs tasks of the main Robolectric {@link Looper} until the {@code condition} returns {@code
|
||||
* true}.
|
||||
*
|
||||
* @param condition The condition.
|
||||
* @param timeoutMs The timeout in milliseconds.
|
||||
* @param clock The {@link Clock} to measure the timeout.
|
||||
* @throws TimeoutException If the {@code timeoutMs timeout} is exceeded.
|
||||
*/
|
||||
public static void runMainLooperUntil(Supplier<Boolean> condition, long timeoutMs, Clock clock)
|
||||
throws TimeoutException {
|
||||
if (Looper.myLooper() != Looper.getMainLooper()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
maybeInitShadowLooperAndRunOneTaskMethod();
|
||||
try {
|
||||
long timeoutTimeMs = clock.currentTimeMillis() + timeoutMs;
|
||||
while (!condition.get()) {
|
||||
if (clock.currentTimeMillis() >= timeoutTimeMs) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
runOneTaskMethod.invoke(shadowLooper);
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalStateException(e);
|
||||
} catch (InvocationTargetException e) {
|
||||
throw new IllegalStateException(e.getCause());
|
||||
}
|
||||
}
|
||||
|
||||
@EnsuresNonNull({"shadowLooper", "runOneTaskMethod"})
|
||||
private static void maybeInitShadowLooperAndRunOneTaskMethod() {
|
||||
if (shadowLooper != null && runOneTaskMethod != null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class<?> clazz = Class.forName("org.robolectric.Shadows");
|
||||
Method shadowOfMethod =
|
||||
Assertions.checkNotNull(clazz.getDeclaredMethod("shadowOf", Looper.class));
|
||||
shadowLooper =
|
||||
Assertions.checkNotNull(shadowOfMethod.invoke(new Object(), Looper.getMainLooper()));
|
||||
runOneTaskMethod = shadowLooper.getClass().getDeclaredMethod("runOneTask");
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.google.android.exoplayer2.testutil;
|
||||
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.Mockito.atMost;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.android.exoplayer2.util.Supplier;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
|
||||
/** Unit test for {@link TestExoPlayer}. */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LooperMode(LooperMode.Mode.PAUSED)
|
||||
public final class TestExoPlayerTest {
|
||||
|
||||
@Test
|
||||
public void runUntil_withConditionAlreadyTrue_returnsImmediately() throws Exception {
|
||||
Clock mockClock = mock(Clock.class);
|
||||
|
||||
TestExoPlayer.runUntil(() -> true, /* timeoutMs= */ 0, mockClock);
|
||||
|
||||
verify(mockClock, atMost(1)).currentTimeMillis();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runUntil_withConditionThatNeverBecomesTrue_timesOut() {
|
||||
Clock mockClock = mock(Clock.class);
|
||||
when(mockClock.currentTimeMillis()).thenReturn(0L, 41L, 42L);
|
||||
|
||||
assertThrows(
|
||||
TimeoutException.class,
|
||||
() -> TestExoPlayer.runUntil(() -> false, /* timeoutMs= */ 42, mockClock));
|
||||
|
||||
verify(mockClock, times(3)).currentTimeMillis();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void runUntil_whenConditionBecomesTrueAfterDelay_returnsWhenConditionBecomesTrue()
|
||||
throws Exception {
|
||||
Supplier<Boolean> mockCondition = mock(Supplier.class);
|
||||
when(mockCondition.get())
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(true);
|
||||
|
||||
TestExoPlayer.runUntil(mockCondition, /* timeoutMs= */ 5674, mock(Clock.class));
|
||||
|
||||
verify(mockCondition, times(5)).get();
|
||||
}
|
||||
}
|
@ -16,9 +16,18 @@
|
||||
package com.google.android.exoplayer2.testutil;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.Mockito.atMost;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.google.android.exoplayer2.util.Clock;
|
||||
import com.google.android.exoplayer2.util.ConditionVariable;
|
||||
import com.google.android.exoplayer2.util.Supplier;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@ -43,4 +52,43 @@ public class TestUtilTest {
|
||||
long endTimeMs = System.currentTimeMillis();
|
||||
assertThat(endTimeMs - startTimeMs).isAtLeast(500);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runMainLooperUntil_withConditionAlreadyTrue_returnsImmediately() throws Exception {
|
||||
Clock mockClock = mock(Clock.class);
|
||||
|
||||
TestUtil.runMainLooperUntil(() -> true, /* timeoutMs= */ 0, mockClock);
|
||||
|
||||
verify(mockClock, atMost(1)).currentTimeMillis();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void runMainLooperUntil_withConditionThatNeverBecomesTrue_timesOut() {
|
||||
Clock mockClock = mock(Clock.class);
|
||||
when(mockClock.currentTimeMillis()).thenReturn(0L, 41L, 42L);
|
||||
|
||||
assertThrows(
|
||||
TimeoutException.class,
|
||||
() -> TestUtil.runMainLooperUntil(() -> false, /* timeoutMs= */ 42, mockClock));
|
||||
|
||||
verify(mockClock, times(3)).currentTimeMillis();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void
|
||||
runMainLooperUntil_whenConditionBecomesTrueAfterDelay_returnsWhenConditionBecomesTrue()
|
||||
throws Exception {
|
||||
Supplier<Boolean> mockCondition = mock(Supplier.class);
|
||||
when(mockCondition.get())
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(false)
|
||||
.thenReturn(true);
|
||||
|
||||
TestUtil.runMainLooperUntil(mockCondition, /* timeoutMs= */ 5674, mock(Clock.class));
|
||||
|
||||
verify(mockCondition, times(5)).get();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user