@Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  for (String s : valuesToReturn) {
                    if (s == null) {
                      System.out.println("throwing exception");
                      try {
                        Thread.sleep(100);
                      } catch (Throwable e) {

                      }
                      observer.onError(new NullPointerException());
                      return;
                    } else {
                      observer.onNext(s);
                    }
                  }
                  System.out.println("subscription complete");
                  observer.onComplete();
                }
              });
      t.start();
    }
    @Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  observer.onNext("hello");
                  observer.onComplete();
                }
              });
      t.start();
    }
 @Override
 public void subscribe(Subscriber<? super String> observer) {
   observer.onSubscribe(EmptySubscription.INSTANCE);
   boolean errorThrown = false;
   for (String s : valuesToReturn) {
     if (s == null) {
       System.out.println("throwing exception");
       observer.onError(new NullPointerException());
       errorThrown = true;
       // purposefully not returning here so it will continue calling onNext
       // so that we also test that we handle bad sequences like this
     } else {
       observer.onNext(s);
     }
   }
   if (!errorThrown) {
     observer.onComplete();
   }
 }
    @Override
    public void subscribe(final Subscriber<? super String> observer) {
      observer.onSubscribe(EmptySubscription.INSTANCE);
      t =
          new Thread(
              new Runnable() {

                @Override
                public void run() {
                  try {
                    Thread.sleep(100);
                  } catch (InterruptedException e) {
                    observer.onError(e);
                  }
                  observer.onNext("hello");
                  observer.onComplete();
                }
              });
      t.start();
    }
  @Test
  public void testRequestFromChainedOperator() {
    TestSubscriber<String> s = new TestSubscriber<>();
    Operator<String, String> o =
        s1 ->
            new Subscriber<String>() {

              @Override
              public void onSubscribe(Subscription a) {
                s1.onSubscribe(a);
              }

              @Override
              public void onComplete() {}

              @Override
              public void onError(Throwable e) {}

              @Override
              public void onNext(String t) {}
            };
    s.request(10);
    Subscriber<? super String> ns = o.apply(s);

    final AtomicLong r = new AtomicLong();
    // set set the producer at the top of the chain (ns) and it should flow through the operator to
    // the (s) subscriber
    // and then it should request up with the value set on the final Subscriber (s)
    ns.onSubscribe(
        new Subscription() {

          @Override
          public void request(long n) {
            r.set(n);
          }

          @Override
          public void cancel() {}
        });
    assertEquals(10, r.get());
  }
  /**
   * Common method to take an Iterator as a source of values.
   *
   * @param s
   * @param it
   */
  static <T> void subscribe(Subscriber<? super T> s, Iterator<? extends T> it) {
    if (it == null) {
      EmptySubscription.error(s, new NullPointerException("The iterator is null"));
      return;
    }

    boolean b;

    try {
      b = it.hasNext();
    } catch (Throwable e) {
      EmptySubscription.error(s, e);
      return;
    }
    if (!b) {
      EmptySubscription.complete(s);
      return;
    }

    s.onSubscribe(new PublisherIterableSubscription<>(s, it));
  }
  @Test
  public void testRequestFromDecoupledOperatorThatRequestsN() {
    TestSubscriber<String> s = new TestSubscriber<>();
    final AtomicLong innerR = new AtomicLong();
    Operator<String, String> o =
        child -> {
          // we want to decouple the chain so set our own Producer on the child instead of it coming
          // from the parent
          child.onSubscribe(
              new Subscription() {

                @Override
                public void request(long n) {
                  innerR.set(n);
                }

                @Override
                public void cancel() {}
              });

          AsyncObserver<String> as =
              new AsyncObserver<String>() {

                @Override
                protected void onStart() {
                  // we request 99 up to the parent
                  request(99);
                }

                @Override
                public void onComplete() {}

                @Override
                public void onError(Throwable e) {}

                @Override
                public void onNext(String t) {}
              };
          return as;
        };
    s.request(10);
    Subscriber<? super String> ns = o.apply(s);

    final AtomicLong r = new AtomicLong();
    // set set the producer at the top of the chain (ns) and it should flow through the operator to
    // the (s) subscriber
    // and then it should request up with the value set on the final Subscriber (s)
    ns.onSubscribe(
        new Subscription() {

          @Override
          public void request(long n) {
            r.set(n);
          }

          @Override
          public void cancel() {}
        });
    assertEquals(99, r.get());
    assertEquals(10, innerR.get());
  }
 @Override
 public void subscribe(Subscriber<? super String> observer) {
   observer.onSubscribe(EmptySubscription.INSTANCE);
   observer.onNext("hello");
   observer.onComplete();
 }