diff --git a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
index 47fb993299..d6ed7ac107 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/ExoPlayerTest.java
@@ -15,14 +15,14 @@
*/
package com.google.android.exoplayer2;
+import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil;
+import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.playUntilStartOfWindow;
+import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilPlaybackState;
+import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilReceiveOffloadSchedulingEnabledNewState;
+import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilSleepingForOffload;
+import static com.google.android.exoplayer2.robolectric.TestPlayerRunHelper.runUntilTimelineChanged;
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.END_OF_STREAM_ITEM;
import static com.google.android.exoplayer2.testutil.FakeSampleStream.FakeSampleStreamItem.oneByteSample;
-import static com.google.android.exoplayer2.testutil.TestPlayerRunHelper.playUntilStartOfWindow;
-import static com.google.android.exoplayer2.testutil.TestPlayerRunHelper.runUntilPlaybackState;
-import static com.google.android.exoplayer2.testutil.TestPlayerRunHelper.runUntilReceiveOffloadSchedulingEnabledNewState;
-import static com.google.android.exoplayer2.testutil.TestPlayerRunHelper.runUntilSleepingForOffload;
-import static com.google.android.exoplayer2.testutil.TestPlayerRunHelper.runUntilTimelineChanged;
-import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertThrows;
@@ -58,6 +58,7 @@ import com.google.android.exoplayer2.drm.DrmSessionEventListener;
import com.google.android.exoplayer2.drm.DrmSessionManager;
import com.google.android.exoplayer2.metadata.Metadata;
import com.google.android.exoplayer2.metadata.id3.TextInformationFrame;
+import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.source.ClippingMediaSource;
import com.google.android.exoplayer2.source.CompositeMediaSource;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
@@ -97,7 +98,6 @@ import com.google.android.exoplayer2.testutil.FakeTrackSelection;
import com.google.android.exoplayer2.testutil.FakeTrackSelector;
import com.google.android.exoplayer2.testutil.NoUidTimeline;
import com.google.android.exoplayer2.testutil.TestExoPlayerBuilder;
-import com.google.android.exoplayer2.testutil.TestPlayerRunHelper;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java
index 3497b06834..7319d1576c 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/EndToEndGaplessTest.java
@@ -27,8 +27,8 @@ import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.robolectric.RandomizedMp3Decoder;
+import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock;
-import com.google.android.exoplayer2.testutil.TestPlayerRunHelper;
import com.google.android.exoplayer2.util.Assertions;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Bytes;
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java
index 85fcae4383..aa50b16003 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/Mp4PlaybackTest.java
@@ -25,9 +25,9 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.robolectric.PlaybackOutput;
import com.google.android.exoplayer2.robolectric.ShadowMediaCodecConfig;
+import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock;
import com.google.android.exoplayer2.testutil.DumpFileAsserts;
-import com.google.android.exoplayer2.testutil.TestPlayerRunHelper;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java
index 8db6f668d4..4dee97a824 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/e2etest/TsPlaybackTest.java
@@ -23,9 +23,9 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.robolectric.PlaybackOutput;
import com.google.android.exoplayer2.robolectric.ShadowMediaCodecConfig;
+import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock;
import com.google.android.exoplayer2.testutil.DumpFileAsserts;
-import com.google.android.exoplayer2.testutil.TestPlayerRunHelper;
import com.google.common.collect.ImmutableList;
import org.junit.Rule;
import org.junit.Test;
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
index d5959584ad..1444b0484c 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/offline/DownloadManagerTest.java
@@ -15,6 +15,7 @@
*/
package com.google.android.exoplayer2.offline;
+import static com.google.android.exoplayer2.robolectric.RobolectricUtil.createRobolectricConditionVariable;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
@@ -24,11 +25,11 @@ import androidx.annotation.Nullable;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.robolectric.TestDownloadManagerListener;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.testutil.DownloadBuilder;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable;
-import com.google.android.exoplayer2.testutil.TestDownloadManagerListener;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.ConditionVariable;
@@ -834,10 +835,10 @@ public class DownloadManagerTest {
private FakeDownloader(DownloadRequest request) {
this.request = request;
- downloadStarted = TestUtil.createRobolectricConditionVariable();
- removeStarted = TestUtil.createRobolectricConditionVariable();
- finished = TestUtil.createRobolectricConditionVariable();
- blocker = TestUtil.createRobolectricConditionVariable();
+ downloadStarted = createRobolectricConditionVariable();
+ removeStarted = createRobolectricConditionVariable();
+ finished = createRobolectricConditionVariable();
+ blocker = createRobolectricConditionVariable();
startCount = new AtomicInteger();
bytesDownloaded = new AtomicInteger();
}
diff --git a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java
index ecdb43f150..90b29b30d5 100644
--- a/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java
+++ b/library/core/src/test/java/com/google/android/exoplayer2/source/ProgressiveMediaPeriodTest.java
@@ -15,7 +15,7 @@
*/
package com.google.android.exoplayer2.source;
-import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
+import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil;
import static com.google.common.truth.Truth.assertThat;
import android.net.Uri;
diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java
index 0400eeb640..fc7f697cca 100644
--- a/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java
+++ b/library/dash/src/test/java/com/google/android/exoplayer2/e2etest/DashPlaybackTest.java
@@ -26,9 +26,9 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.robolectric.PlaybackOutput;
import com.google.android.exoplayer2.robolectric.ShadowMediaCodecConfig;
+import com.google.android.exoplayer2.robolectric.TestPlayerRunHelper;
import com.google.android.exoplayer2.testutil.AutoAdvancingFakeClock;
import com.google.android.exoplayer2.testutil.DumpFileAsserts;
-import com.google.android.exoplayer2.testutil.TestPlayerRunHelper;
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
import org.junit.Rule;
import org.junit.Test;
diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
index 2993bb4442..6bdc84438b 100644
--- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
+++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadManagerDashTest.java
@@ -31,13 +31,13 @@ import com.google.android.exoplayer2.offline.DefaultDownloaderFactory;
import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadRequest;
import com.google.android.exoplayer2.offline.StreamKey;
+import com.google.android.exoplayer2.robolectric.TestDownloadManagerListener;
import com.google.android.exoplayer2.scheduler.Requirements;
import com.google.android.exoplayer2.testutil.CacheAsserts.RequestSet;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.DummyMainThread.TestRunnable;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource;
-import com.google.android.exoplayer2.testutil.TestDownloadManagerListener;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.DataSource.Factory;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
diff --git a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
index 6b528cdd82..98a7f6e887 100644
--- a/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
+++ b/library/dash/src/test/java/com/google/android/exoplayer2/source/dash/offline/DownloadServiceDashTest.java
@@ -34,11 +34,11 @@ import com.google.android.exoplayer2.offline.DownloadManager;
import com.google.android.exoplayer2.offline.DownloadRequest;
import com.google.android.exoplayer2.offline.DownloadService;
import com.google.android.exoplayer2.offline.StreamKey;
+import com.google.android.exoplayer2.robolectric.TestDownloadManagerListener;
import com.google.android.exoplayer2.scheduler.Scheduler;
import com.google.android.exoplayer2.testutil.DummyMainThread;
import com.google.android.exoplayer2.testutil.FakeDataSet;
import com.google.android.exoplayer2.testutil.FakeDataSource;
-import com.google.android.exoplayer2.testutil.TestDownloadManagerListener;
import com.google.android.exoplayer2.testutil.TestUtil;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.cache.CacheDataSource;
diff --git a/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/RobolectricUtil.java b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/RobolectricUtil.java
new file mode 100644
index 0000000000..0374559be9
--- /dev/null
+++ b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/RobolectricUtil.java
@@ -0,0 +1,90 @@
+/*
+ * 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.robolectric;
+
+import android.os.Looper;
+import com.google.android.exoplayer2.util.Clock;
+import com.google.android.exoplayer2.util.ConditionVariable;
+import com.google.android.exoplayer2.util.SystemClock;
+import com.google.common.base.Supplier;
+import java.util.concurrent.TimeoutException;
+import org.robolectric.shadows.ShadowLooper;
+
+/** Utility methods for Robolectric-based tests. */
+public final class RobolectricUtil {
+
+ private RobolectricUtil() {}
+
+ /**
+ * 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;
+
+ /**
+ * Creates a {@link ConditionVariable} whose {@link ConditionVariable#block(long)} method times
+ * out according to wallclock time when used in Robolectric tests.
+ */
+ public static ConditionVariable createRobolectricConditionVariable() {
+ return new ConditionVariable(
+ new SystemClock() {
+ @Override
+ public long elapsedRealtime() {
+ // elapsedRealtime() does not advance during Robolectric test execution, so use
+ // currentTimeMillis() instead. This is technically unsafe because this clock is not
+ // guaranteed to be monotonic, but in practice it will work provided the clock of the
+ // host machine does not change during test execution.
+ return Clock.DEFAULT.currentTimeMillis();
+ }
+ });
+ }
+
+ /**
+ * Runs tasks of the main Robolectric {@link Looper} until the {@code condition} returns {@code
+ * true}.
+ *
+ *
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 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 condition, long timeoutMs, Clock clock)
+ throws TimeoutException {
+ if (Looper.myLooper() != Looper.getMainLooper()) {
+ throw new IllegalStateException();
+ }
+ long timeoutTimeMs = clock.currentTimeMillis() + timeoutMs;
+ while (!condition.get()) {
+ if (clock.currentTimeMillis() >= timeoutTimeMs) {
+ throw new TimeoutException();
+ }
+ ShadowLooper.runMainLooperOneTask();
+ }
+ }
+}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestDownloadManagerListener.java
similarity index 93%
rename from testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
rename to robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestDownloadManagerListener.java
index 6fa7ebe741..493e95cb09 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestDownloadManagerListener.java
+++ b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestDownloadManagerListener.java
@@ -13,8 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.android.exoplayer2.testutil;
+package com.google.android.exoplayer2.robolectric;
+import static com.google.android.exoplayer2.robolectric.RobolectricUtil.createRobolectricConditionVariable;
import static com.google.common.truth.Truth.assertThat;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.junit.Assert.fail;
@@ -46,8 +47,8 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
public TestDownloadManagerListener(DownloadManager downloadManager) {
this.downloadManager = downloadManager;
downloadStates = new HashMap<>();
- initializedCondition = TestUtil.createRobolectricConditionVariable();
- idleCondition = TestUtil.createRobolectricConditionVariable();
+ initializedCondition = createRobolectricConditionVariable();
+ idleCondition = createRobolectricConditionVariable();
downloadManager.addListener(this);
}
@@ -61,7 +62,7 @@ public final class TestDownloadManagerListener implements DownloadManager.Listen
idleCondition.close();
// If the manager is already idle the condition will be opened by the code immediately below.
// Else it will be opened by onIdle().
- ConditionVariable checkedOnMainThread = TestUtil.createRobolectricConditionVariable();
+ ConditionVariable checkedOnMainThread = createRobolectricConditionVariable();
new Handler(downloadManager.getApplicationLooper())
.post(
() -> {
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestPlayerRunHelper.java b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java
similarity index 90%
rename from testutils/src/main/java/com/google/android/exoplayer2/testutil/TestPlayerRunHelper.java
rename to robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java
index 6a2be5e03a..55a55ab059 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestPlayerRunHelper.java
+++ b/robolectricutils/src/main/java/com/google/android/exoplayer2/robolectric/TestPlayerRunHelper.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.google.android.exoplayer2.testutil;
+package com.google.android.exoplayer2.robolectric;
-import static com.google.android.exoplayer2.testutil.TestUtil.runMainLooperUntil;
+import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runMainLooperUntil;
import android.os.Handler;
import android.os.Looper;
@@ -48,7 +48,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param expectedState The expected {@link Player.State}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilPlaybackState(Player player, @Player.State int expectedState)
@@ -78,7 +78,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param expectedPlayWhenReady The expected value for {@link Player#getPlayWhenReady()}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilPlayWhenReady(Player player, boolean expectedPlayWhenReady)
@@ -108,7 +108,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param expectedTimeline The expected {@link Timeline}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilTimelineChanged(Player player, Timeline expectedTimeline)
@@ -137,7 +137,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @return The new {@link Timeline}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static Timeline runUntilTimelineChanged(Player player) throws TimeoutException {
@@ -163,7 +163,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param expectedReason The expected {@link Player.DiscontinuityReason}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilPositionDiscontinuity(
@@ -189,7 +189,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @return The raised {@link ExoPlaybackException}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static ExoPlaybackException runUntilError(Player player) throws TimeoutException {
@@ -214,7 +214,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @return The new offloadSchedulingEnabled state.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static boolean runUntilReceiveOffloadSchedulingEnabledNewState(Player player)
@@ -241,7 +241,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param expectedSleepForOffload The expected sleep of offload state.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilSleepingForOffload(Player player, boolean expectedSleepForOffload)
@@ -266,7 +266,7 @@ public class TestPlayerRunHelper {
* callback has been called.
*
* @param player The {@link Player}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilRenderedFirstFrame(SimpleExoPlayer player) throws TimeoutException {
@@ -291,7 +291,7 @@ public class TestPlayerRunHelper {
* @param player The {@link Player}.
* @param windowIndex The window.
* @param positionMs The position within the window, in milliseconds.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void playUntilPosition(ExoPlayer player, int windowIndex, long positionMs)
@@ -329,7 +329,7 @@ public class TestPlayerRunHelper {
*
* @param player The {@link Player}.
* @param windowIndex The window.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void playUntilStartOfWindow(ExoPlayer player, int windowIndex)
@@ -342,7 +342,7 @@ public class TestPlayerRunHelper {
* commands on the internal playback thread.
*
* @param player The {@link Player}.
- * @throws TimeoutException If the {@link TestUtil#DEFAULT_TIMEOUT_MS default timeout} is
+ * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
* exceeded.
*/
public static void runUntilPendingCommandsAreFullyHandled(ExoPlayer player)
diff --git a/testutils/src/test/java/com/google/android/exoplayer2/testutil/TestUtilTest.java b/robolectricutils/src/test/java/com/google/android/exoplayer2/robolectric/RobolectricUtilTest.java
similarity index 82%
rename from testutils/src/test/java/com/google/android/exoplayer2/testutil/TestUtilTest.java
rename to robolectricutils/src/test/java/com/google/android/exoplayer2/robolectric/RobolectricUtilTest.java
index cc7df84375..08d1a2ae2b 100644
--- a/testutils/src/test/java/com/google/android/exoplayer2/testutil/TestUtilTest.java
+++ b/robolectricutils/src/test/java/com/google/android/exoplayer2/robolectric/RobolectricUtilTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.google.android.exoplayer2.testutil;
+package com.google.android.exoplayer2.robolectric;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
@@ -31,14 +31,13 @@ import java.util.concurrent.TimeoutException;
import org.junit.Test;
import org.junit.runner.RunWith;
-/** Unit test for {@link TestUtil}. */
+/** Unit test for {@link RobolectricUtil}. */
@RunWith(AndroidJUnit4.class)
-public class TestUtilTest {
-
+public class RobolectricUtilTest {
@Test
public void createRobolectricConditionVariable_blockWithTimeout_timesOut()
throws InterruptedException {
- ConditionVariable conditionVariable = TestUtil.createRobolectricConditionVariable();
+ ConditionVariable conditionVariable = RobolectricUtil.createRobolectricConditionVariable();
assertThat(conditionVariable.block(/* timeoutMs= */ 1)).isFalse();
assertThat(conditionVariable.isOpen()).isFalse();
}
@@ -46,7 +45,7 @@ public class TestUtilTest {
@Test
public void createRobolectricConditionVariable_blockWithTimeout_blocksForAtLeastTimeout()
throws InterruptedException {
- ConditionVariable conditionVariable = TestUtil.createRobolectricConditionVariable();
+ ConditionVariable conditionVariable = RobolectricUtil.createRobolectricConditionVariable();
long startTimeMs = System.currentTimeMillis();
assertThat(conditionVariable.block(/* timeoutMs= */ 500)).isFalse();
long endTimeMs = System.currentTimeMillis();
@@ -57,7 +56,7 @@ public class TestUtilTest {
public void runMainLooperUntil_withConditionAlreadyTrue_returnsImmediately() throws Exception {
Clock mockClock = mock(Clock.class);
- TestUtil.runMainLooperUntil(() -> true, /* timeoutMs= */ 0, mockClock);
+ RobolectricUtil.runMainLooperUntil(() -> true, /* timeoutMs= */ 0, mockClock);
verify(mockClock, atMost(1)).currentTimeMillis();
}
@@ -69,7 +68,7 @@ public class TestUtilTest {
assertThrows(
TimeoutException.class,
- () -> TestUtil.runMainLooperUntil(() -> false, /* timeoutMs= */ 42, mockClock));
+ () -> RobolectricUtil.runMainLooperUntil(() -> false, /* timeoutMs= */ 42, mockClock));
verify(mockClock, times(3)).currentTimeMillis();
}
@@ -87,7 +86,7 @@ public class TestUtilTest {
.thenReturn(false)
.thenReturn(true);
- TestUtil.runMainLooperUntil(mockCondition, /* timeoutMs= */ 5674, mock(Clock.class));
+ RobolectricUtil.runMainLooperUntil(mockCondition, /* timeoutMs= */ 5674, mock(Clock.class));
verify(mockCondition, times(5)).get();
}
diff --git a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java
index 7107c0b8a4..f52f4380cf 100644
--- a/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java
+++ b/testutils/src/main/java/com/google/android/exoplayer2/testutil/TestUtil.java
@@ -25,7 +25,6 @@ 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;
@@ -38,41 +37,21 @@ import com.google.android.exoplayer2.metadata.MetadataInputBuffer;
import com.google.android.exoplayer2.upstream.DataSource;
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.SystemClock;
import com.google.android.exoplayer2.util.Util;
-import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.primitives.Bytes;
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.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() {}
/**
@@ -457,81 +436,4 @@ public class TestUtil {
return buffer;
}
- /**
- * Creates a {@link ConditionVariable} whose {@link ConditionVariable#block(long)} method times
- * out according to wallclock time when used in Robolectric tests.
- */
- public static ConditionVariable createRobolectricConditionVariable() {
- return new ConditionVariable(
- new SystemClock() {
- @Override
- public long elapsedRealtime() {
- // elapsedRealtime() does not advance during Robolectric test execution, so use
- // currentTimeMillis() instead. This is technically unsafe because this clock is not
- // guaranteed to be monotonic, but in practice it will work provided the clock of the
- // host machine does not change during test execution.
- return Clock.DEFAULT.currentTimeMillis();
- }
- });
- }
-
- /**
- * Runs tasks of the main Robolectric {@link Looper} until the {@code condition} returns {@code
- * true}.
- *
- * 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 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 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);
- }
- }
}