public final class

RobolectricUtil

extends java.lang.Object

 java.lang.Object

↳androidx.media3.test.utils.robolectric.RobolectricUtil

Gradle dependencies

compile group: 'androidx.media3', name: 'media3-test-utils-robolectric', version: '1.0.0-alpha03'

  • groupId: androidx.media3
  • artifactId: media3-test-utils-robolectric
  • version: 1.0.0-alpha03

Artifact androidx.media3:media3-test-utils-robolectric:1.0.0-alpha03 it located at Google repository (https://maven.google.com/)

Overview

Utility methods for Robolectric-based tests.

Summary

Fields
public static final longDEFAULT_TIMEOUT_MS

The default timeout applied when calling RobolectricUtil.

Methods
public static ConditionVariablecreateRobolectricConditionVariable()

Creates a ConditionVariable whose ConditionVariable.block(long) method times out according to wallclock time when used in Robolectric tests.

public static voidrunLooperUntil(Looper looper, <any> condition)

Runs tasks of the looper until the condition returns true.

public static voidrunLooperUntil(Looper looper, <any> condition, long timeoutMs, Clock clock)

Runs tasks of the looper until the condition returns true.

public static voidrunMainLooperUntil(<any> condition)

Runs tasks of the main Robolectric until the condition returns true.

public static voidrunMainLooperUntil(<any> condition, long timeoutMs, Clock clock)

Runs tasks of the main Robolectric until the condition returns true.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

public static final long DEFAULT_TIMEOUT_MS

The default timeout applied when calling RobolectricUtil. This timeout should be sufficient for any condition using a Robolectric test.

Methods

public static ConditionVariable createRobolectricConditionVariable()

Creates a ConditionVariable whose ConditionVariable.block(long) method times out according to wallclock time when used in Robolectric tests.

public static void runMainLooperUntil(<any> condition)

Runs tasks of the main Robolectric until the condition returns true.

Must be called on the main test thread.

Parameters:

condition: The condition.

public static void runMainLooperUntil(<any> condition, long timeoutMs, Clock clock)

Runs tasks of the main Robolectric until the condition returns true.

Must be called on the main test thread.

Parameters:

condition: The condition.
timeoutMs: The timeout in milliseconds.
clock: The Clock to measure the timeout.

public static void runLooperUntil(Looper looper, <any> condition)

Runs tasks of the looper until the condition returns true.

Must be called on the thread corresponding to the looper.

Parameters:

looper: The .
condition: The condition.

public static void runLooperUntil(Looper looper, <any> condition, long timeoutMs, Clock clock)

Runs tasks of the looper until the condition returns true.

Must be called on the thread corresponding to the looper.

Parameters:

looper: The .
condition: The condition.
timeoutMs: The timeout in milliseconds.
clock: The Clock to measure the timeout.

Source

/*
 * 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 androidx.media3.test.utils.robolectric;

import static org.robolectric.Shadows.shadowOf;

import android.os.Looper;
import androidx.media3.common.util.Clock;
import androidx.media3.common.util.ConditionVariable;
import androidx.media3.common.util.SystemClock;
import androidx.media3.common.util.UnstableApi;
import com.google.common.base.Supplier;
import java.util.concurrent.TimeoutException;
import org.robolectric.shadows.ShadowLooper;

/** Utility methods for Robolectric-based tests. */
@UnstableApi
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}.
   *
   * <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}.
   *
   * <p>Must be called on the main test thread.
   *
   * @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 {
    runLooperUntil(Looper.getMainLooper(), condition, timeoutMs, clock);
  }

  /**
   * Runs tasks of the {@code looper} until the {@code condition} returns {@code true}.
   *
   * <p>Must be called on the thread corresponding to the {@code looper}.
   *
   * @param looper The {@link Looper}.
   * @param condition The condition.
   * @throws TimeoutException If the {@link #DEFAULT_TIMEOUT_MS} is exceeded.
   */
  public static void runLooperUntil(Looper looper, Supplier<Boolean> condition)
      throws TimeoutException {
    runLooperUntil(looper, condition, DEFAULT_TIMEOUT_MS * 1000000, Clock.DEFAULT);
  }

  /**
   * Runs tasks of the {@code looper} until the {@code condition} returns {@code true}.
   *
   * <p>Must be called on the thread corresponding to the {@code looper}.
   *
   * @param looper The {@link Looper}.
   * @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 runLooperUntil(
      Looper looper, Supplier<Boolean> condition, long timeoutMs, Clock clock)
      throws TimeoutException {
    if (Looper.myLooper() != looper) {
      throw new IllegalStateException();
    }
    ShadowLooper shadowLooper = shadowOf(looper);
    long timeoutTimeMs = clock.currentTimeMillis() + timeoutMs;
    while (!condition.get()) {
      if (clock.currentTimeMillis() >= timeoutTimeMs) {
        throw new TimeoutException();
      }
      shadowLooper.runOneTask();
    }
  }
}