/**
   * Can receive timeout if subscribe never receives an onError/onCompleted ... which reveals a race
   * condition.
   */
  @Test(timeout = 10000)
  public void testSubscribeCompletionRaceCondition() {
    for (int i = 0; i < 50; i++) {
      final ReplaySubject<String> subject = ReplaySubject.create();
      final AtomicReference<String> value1 = new AtomicReference<String>();

      subject.subscribe(
          new Action1<String>() {

            @Override
            public void call(String t1) {
              try {
                // simulate a slow observer
                Thread.sleep(50);
              } catch (InterruptedException e) {
                e.printStackTrace();
              }
              value1.set(t1);
            }
          });

      Thread t1 =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  subject.onNext("value");
                  subject.onCompleted();
                }
              });

      SubjectObserverThread t2 = new SubjectObserverThread(subject);
      SubjectObserverThread t3 = new SubjectObserverThread(subject);
      SubjectObserverThread t4 = new SubjectObserverThread(subject);
      SubjectObserverThread t5 = new SubjectObserverThread(subject);

      t2.start();
      t3.start();
      t1.start();
      t4.start();
      t5.start();
      try {
        t1.join();
        t2.join();
        t3.join();
        t4.join();
        t5.join();
      } catch (InterruptedException e) {
        throw new RuntimeException(e);
      }

      assertEquals("value", value1.get());
      assertEquals("value", t2.value.get());
      assertEquals("value", t3.value.get());
      assertEquals("value", t4.value.get());
      assertEquals("value", t5.value.get());
    }
  }