/*
 * Copyright 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.transformer;

import static com.google.android.exoplayer2.robolectric.RobolectricUtil.runLooperUntil;

import androidx.annotation.Nullable;
import com.google.android.exoplayer2.MediaItem;
import com.google.android.exoplayer2.robolectric.RobolectricUtil;
import java.util.concurrent.TimeoutException;

/** Helper class to run a {@link Transformer} test. */
public final class TransformerTestRunner {

  private TransformerTestRunner() {}

  /**
   * Runs tasks of the {@link Transformer#getApplicationLooper() transformer Looper} until the
   * current {@link Transformer transformation} completes.
   *
   * @param transformer The {@link Transformer}.
   * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
   *     exceeded.
   * @throws IllegalStateException If the method is not called from the main thread, or if the
   *     transformation completes with error.
   */
  public static void runUntilCompleted(Transformer transformer) throws TimeoutException {
    @Nullable Exception exception = runUntilListenerCalled(transformer);
    if (exception != null) {
      throw new IllegalStateException(exception);
    }
  }

  /**
   * Runs tasks of the {@link Transformer#getApplicationLooper() transformer Looper} until a {@link
   * Transformer} error occurs.
   *
   * @param transformer The {@link Transformer}.
   * @return The raised exception.
   * @throws TimeoutException If the {@link RobolectricUtil#DEFAULT_TIMEOUT_MS default timeout} is
   *     exceeded.
   * @throws IllegalStateException If the method is not called from the main thread, or if the
   *     transformation completes without error.
   */
  public static TransformationException runUntilError(Transformer transformer)
      throws TimeoutException {
    @Nullable TransformationException exception = runUntilListenerCalled(transformer);
    if (exception == null) {
      throw new IllegalStateException("The transformation completed without error.");
    }
    return exception;
  }

  @Nullable
  private static TransformationException runUntilListenerCalled(Transformer transformer)
      throws TimeoutException {
    TransformationResult transformationResult = new TransformationResult();
    transformer.addListener(
        new Transformer.Listener() {
          @Override
          public void onTransformationCompleted(MediaItem inputMediaItem) {
            transformationResult.isCompleted = true;
          }

          @Override
          public void onTransformationError(
              MediaItem inputMediaItem, TransformationException exception) {
            transformationResult.exception = exception;
          }
        });
    runLooperUntil(
        transformer.getApplicationLooper(),
        () -> transformationResult.isCompleted || transformationResult.exception != null);
    return transformationResult.exception;
  }

  private static class TransformationResult {
    public boolean isCompleted;
    @Nullable public TransformationException exception;
  }
}

@@ -947,16 +947,188 @@
 ception;
+%0Aimport java.util.concurrent.atomic.AtomicBoolean;%0Aimport java.util.concurrent.atomic.AtomicReference;%0Aimport org.checkerframework.checker.nullness.compatqual.NullableType;
 %0A%0A/** He
@@ -2972,80 +2972,188 @@
     
-TransformationResult transformationResult = new TransformationResult
+AtomicBoolean transformationCompleted = new AtomicBoolean();%0A    AtomicReference%3C@NullableType TransformationException%3E transformationException =%0A        new AtomicReference%3C%3E
 ();%0A
+%0A
     
@@ -3332,33 +3332,24 @@
 ansformation
-Result.is
 Completed = 
@@ -3349,15 +3349,18 @@
 eted
- = 
+.set(
 true
+)
 ;%0A  
@@ -3538,32 +3538,25 @@
 ormation
-Result.e
+E
 xception
  = excep
@@ -3547,19 +3547,21 @@
 xception
- = 
+.set(
 exceptio
@@ -3557,24 +3557,25 @@
 et(exception
+)
 ;%0A          
@@ -3684,17 +3684,8 @@
 tion
-Result.is
 Comp
@@ -3689,16 +3689,22 @@
 ompleted
+.get()
  %7C%7C tran
@@ -3713,32 +3713,25 @@
 ormation
-Result.e
+E
 xception
  != null
@@ -3714,32 +3714,38 @@
 rmationException
+.get()
  != null);%0A    r
@@ -3739,16 +3739,17 @@
  null);%0A
+%0A
     retu
@@ -3769,163 +3769,23 @@
 tion
-Result.exception;%0A  %7D%0A%0A  private static class TransformationResult %7B%0A    public boolean isCompleted;%0A    @Nullable public TransformationException exception
+Exception.get()
 ;%0A  

Remove the need for a test runner TransformationResult.