code: /*
   * Copyright (c) 2016-present, RxJava Contributors.
   *
   * 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 io.reactivex.rxjava3.internal.util;
  
  import static org.junit.Assert.*;
  
  import java.util.List;
  
  import io.reactivex.rxjava3.disposables.Disposable;
  import org.junit.Test;
  
  import io.reactivex.rxjava3.core.*;
  import io.reactivex.rxjava3.exceptions.TestException;
  import io.reactivex.rxjava3.internal.subscriptions.BooleanSubscription;
  import io.reactivex.rxjava3.observers.TestObserver;
  import io.reactivex.rxjava3.plugins.RxJavaPlugins;
  import io.reactivex.rxjava3.subscribers.TestSubscriber;
  import io.reactivex.rxjava3.testsupport.TestHelper;
  
  public class AtomicThrowableTest extends RxJavaTest {
  
      @Test
      public void isTerminated() {
          AtomicThrowable ex = new AtomicThrowable();
  
          assertFalse(ex.isTerminated());
  
          assertNull(ex.terminate());
  
          assertTrue(ex.isTerminated());
      }
  
      @Test
      public void tryTerminateAndReportNull() {
          List<Throwable> errors = TestHelper.trackPluginErrors();
          try {
  
              AtomicThrowable ex = new AtomicThrowable();
              ex.tryTerminateAndReport();
  
              assertTrue("" + errors, errors.isEmpty());
          } finally {
              RxJavaPlugins.reset();
          }
      }
  
      @Test
      public void tryTerminateAndReportAlreadyTerminated() {
          List<Throwable> errors = TestHelper.trackPluginErrors();
          try {
  
              AtomicThrowable ex = new AtomicThrowable();
              ex.terminate();
  
              ex.tryTerminateAndReport();
  
              assertTrue("" + errors, errors.isEmpty());
          } finally {
              RxJavaPlugins.reset();
          }
      }
  
      @Test
      public void tryTerminateAndReportHasError() {
          List<Throwable> errors = TestHelper.trackPluginErrors();
          try {
  
              AtomicThrowable ex = new AtomicThrowable();
              ex.set(new TestException());
  
              ex.tryTerminateAndReport();
  
              TestHelper.assertUndeliverable(errors, 0, TestException.class);
  
              assertEquals(1, errors.size());
          } finally {
              RxJavaPlugins.reset();
          }
      }
  
      @Test
      public void tryTerminateConsumerSubscriberNoError() {
          TestSubscriber<Object> ts = new TestSubscriber<>();
          ts.onSubscribe(new BooleanSubscription());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer(ts);
          ts.assertResult();
      }
  
      @Test
      public void tryTerminateConsumerSubscriberError() {
          TestSubscriber<Object> ts = new TestSubscriber<>();
          ts.onSubscribe(new BooleanSubscription());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer(ts);
          ts.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerSubscriberTerminated() {
          TestSubscriber<Object> ts = new TestSubscriber<>();
          ts.onSubscribe(new BooleanSubscription());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer(ts);
          ts.assertEmpty();
      }
  
      @Test
      public void tryTerminateConsumerObserverNoError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer((Observer<Object>)to);
          to.assertResult();
      }
  
      @Test
      public void tryTerminateConsumerObserverError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer((Observer<Object>)to);
          to.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerObserverTerminated() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer((Observer<Object>)to);
          to.assertEmpty();
      }
  
      @Test
      public void tryTerminateConsumerMaybeObserverNoError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer((MaybeObserver<Object>)to);
          to.assertResult();
      }
  
      @Test
      public void tryTerminateConsumerMaybeObserverError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer((MaybeObserver<Object>)to);
          to.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerMaybeObserverTerminated() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer((MaybeObserver<Object>)to);
          to.assertEmpty();
      }
  
      @Test
      public void tryTerminateConsumerSingleNoError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer((SingleObserver<Object>)to);
          to.assertEmpty();
      }
  
      @Test
      public void tryTerminateConsumerSingleError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer((SingleObserver<Object>)to);
          to.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerSingleTerminated() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer((SingleObserver<Object>)to);
          to.assertEmpty();
      }
  
      @Test
      public void tryTerminateConsumerCompletableObserverNoError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer((CompletableObserver)to);
          to.assertResult();
      }
  
      @Test
      public void tryTerminateConsumerCompletableObserverError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer((CompletableObserver)to);
          to.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerCompletableObserverTerminated() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer((CompletableObserver)to);
          to.assertEmpty();
      }
  
      static <T> Emitter<T> wrapToEmitter(final Observer<T> observer) {
          return new Emitter<T>() {
              @Override
              public void onNext(T value) {
                  observer.onNext(value);
              }
  
              @Override
              public void onError(Throwable error) {
                  observer.onError(error);
              }
  
              @Override
              public void onComplete() {
                  observer.onComplete();
              }
          };
      }
  
      @Test
      public void tryTerminateConsumerEmitterNoError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.tryTerminateConsumer(wrapToEmitter(to));
          to.assertResult();
      }
  
      @Test
      public void tryTerminateConsumerEmitterError() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.set(new TestException());
          ex.tryTerminateConsumer(wrapToEmitter(to));
          to.assertFailure(TestException.class);
      }
  
      @Test
      public void tryTerminateConsumerEmitterTerminated() {
          TestObserver<Object> to = new TestObserver<>();
          to.onSubscribe(Disposable.empty());
  
          AtomicThrowable ex = new AtomicThrowable();
          ex.terminate();
          ex.tryTerminateConsumer(wrapToEmitter(to));
          to.assertEmpty();
      }
  
      @Test
      public void tryAddThrowableOrReportNull() {
          List<Throwable> errors = TestHelper.trackPluginErrors();
          try {
  
              AtomicThrowable ex = new AtomicThrowable();
              ex.tryAddThrowableOrReport(new TestException());
  
              assertTrue("" + errors, errors.isEmpty());
          } finally {
              RxJavaPlugins.reset();
          }
      }
  
      @Test
      public void tryAddThrowableOrReportTerminated() {
          List<Throwable> errors = TestHelper.trackPluginErrors();
          try {
  
              AtomicThrowable ex = new AtomicThrowable();
              ex.terminate();
  
              assertFalse(ex.tryAddThrowableOrReport(new TestException()));
  
              assertFalse("" + errors, errors.isEmpty());
              TestHelper.assertUndeliverable(errors, 0, TestException.class);
          } finally {
              RxJavaPlugins.reset();
          }
      }
  }
  