content: /**
   * 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.flowable.internal.operators;
  
  import static org.junit.Assert.*;
  
  import java.util.*;
  import java.util.concurrent.TimeUnit;
  import java.util.concurrent.atomic.*;
  
  import org.junit.*;
  import org.reactivestreams.*;
  
  import io.reactivex.common.*;
  import io.reactivex.common.exceptions.*;
  import io.reactivex.common.functions.*;
  import io.reactivex.common.internal.functions.Functions;
  import io.reactivex.flowable.*;
  import io.reactivex.flowable.internal.subscriptions.BooleanSubscription;
  import io.reactivex.flowable.processors.*;
  import io.reactivex.flowable.subscribers.*;
  
  
  public class FlowableWindowWithTimeTest {
  
      private TestScheduler scheduler;
      private Scheduler.Worker innerScheduler;
  
      @Before
      public void before() {
          scheduler = new TestScheduler();
          innerScheduler = scheduler.createWorker();
      }
  
      @Test
      public void testTimedAndCount() {
          final List<String> list = new ArrayList<String>();
          final List<List<String>> lists = new ArrayList<List<String>>();
  
          Flowable<String> source = Flowable.unsafeCreate(new Publisher<String>() {
              @Override
              public void subscribe(Subscriber<? super String> observer) {
                  observer.onSubscribe(new BooleanSubscription());
                  push(observer, "one", 10);
                  push(observer, "two", 90);
                  push(observer, "three", 110);
                  push(observer, "four", 190);
                  push(observer, "five", 210);
                  complete(observer, 250);
              }
          });
  
          Flowable<Flowable<String>> windowed = source.window(100, TimeUnit.MILLISECONDS, scheduler, 2);
          windowed.subscribe(observeWindow(list, lists));
  
          scheduler.advanceTimeTo(100, TimeUnit.MILLISECONDS);
          assertEquals(1, lists.size());
          assertEquals(lists.get(0), list("one", "two"));
  
          scheduler.advanceTimeTo(200, TimeUnit.MILLISECONDS);
          assertEquals(2, lists.size());
          assertEquals(lists.get(1), list("three", "four"));
  
          scheduler.advanceTimeTo(300, TimeUnit.MILLISECONDS);
          assertEquals(3, lists.size());
          assertEquals(lists.get(2), list("five"));
      }
  
      @Test
      public void testTimed() {
          final List<String> list = new ArrayList<String>();
          final List<List<String>> lists = new ArrayList<List<String>>();
  
          Flowable<String> source = Flowable.unsafeCreate(new Publisher<String>() {
              @Override
              public void subscribe(Subscriber<? super String> observer) {
                  observer.onSubscribe(new BooleanSubscription());
                  push(observer, "one", 98);
                  push(observer, "two", 99);
                  push(observer, "three", 99); // FIXME happens after the window is open
                  push(observer, "four", 101);
                  push(observer, "five", 102);
                  complete(observer, 150);
              }
          });
  
          Flowable<Flowable<String>> windowed = source.window(100, TimeUnit.MILLISECONDS, scheduler);
          windowed.subscribe(observeWindow(list, lists));
  
          scheduler.advanceTimeTo(101, TimeUnit.MILLISECONDS);
          assertEquals(1, lists.size());
          assertEquals(lists.get(0), list("one", "two", "three"));
  
          scheduler.advanceTimeTo(201, TimeUnit.MILLISECONDS);
          assertEquals(2, lists.size());
          assertEquals(lists.get(1), list("four", "five"));
      }
  
      private List<String> list(String... args) {
          List<String> list = new ArrayList<String>();
          for (String arg : args) {
              list.add(arg);
          }
          return list;
      }
  
      private <T> void push(final Subscriber<T> observer, final T value, int delay) {
          innerScheduler.schedule(new Runnable() {
              @Override
              public void run() {
                  observer.onNext(value);
              }
          }, delay, TimeUnit.MILLISECONDS);
      }
  
      private void complete(final Subscriber<?> observer, int delay) {
          innerScheduler.schedule(new Runnable() {
              @Override
              public void run() {
                  observer.onComplete();
              }
          }, delay, TimeUnit.MILLISECONDS);
      }
  
      private <T> Consumer<Flowable<T>> observeWindow(final List<T> list, final List<List<T>> lists) {
          return new Consumer<Flowable<T>>() {
              @Override
              public void accept(Flowable<T> stringFlowable) {
                  stringFlowable.subscribe(new DefaultSubscriber<T>() {
                      @Override
                      public void onComplete() {
                          lists.add(new ArrayList<T>(list));
                          list.clear();
                      }
  
                      @Override
                      public void onError(Throwable e) {
                          Assert.fail(e.getMessage());
                      }
  
                      @Override
                      public void onNext(T args) {
                          list.add(args);
                      }
                  });
              }
          };
      }
      @Test
      public void testExactWindowSize() {
          Flowable<Flowable<Integer>> source = Flowable.range(1, 10)
                  .window(1, TimeUnit.MINUTES, scheduler, 3);
  
          final List<Integer> list = new ArrayList<Integer>();
          final List<List<Integer>> lists = new ArrayList<List<Integer>>();
  
          source.subscribe(observeWindow(list, lists));
  
          assertEquals(4, lists.size());
          assertEquals(3, lists.get(0).size());
          assertEquals(Arrays.asList(1, 2, 3), lists.get(0));
          assertEquals(3, lists.get(1).size());
          assertEquals(Arrays.asList(4, 5, 6), lists.get(1));
          assertEquals(3, lists.get(2).size());
          assertEquals(Arrays.asList(7, 8, 9), lists.get(2));
          assertEquals(1, lists.get(3).size());
          assertEquals(Arrays.asList(10), lists.get(3));
      }
  
      @Test
      public void testTakeFlatMapCompletes() {
          TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
  
          final AtomicInteger wip = new AtomicInteger();
  
          final int indicator = 999999999;
  
          FlowableWindowWithSizeTest.hotStream()
          .window(300, TimeUnit.MILLISECONDS)
          .take(10)
          .doOnComplete(new Action() {
              @Override
              public void run() {
                  System.out.println("Main done!");
              }
          })
          .flatMap(new Function<Flowable<Integer>, Flowable<Integer>>() {
              @Override
              public Flowable<Integer> apply(Flowable<Integer> w) {
                  return w.startWith(indicator)
                          .doOnComplete(new Action() {
                              @Override
                              public void run() {
                                  System.out.println("inner done: " + wip.incrementAndGet());
                              }
                          })
                          ;
              }
          })
          .doOnNext(new Consumer<Integer>() {
              @Override
              public void accept(Integer pv) {
                  System.out.println(pv);
              }
          })
          .subscribe(ts);
  
          ts.awaitTerminalEvent(5, TimeUnit.SECONDS);
          ts.assertComplete();
          Assert.assertTrue(ts.valueCount() != 0);
      }
  
  
      @Test
      public void timespanTimeskipCustomSchedulerBufferSize() {
          Flowable.range(1, 10)
          .window(1, 1, TimeUnit.MINUTES, Schedulers.io(), 2)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
      }
  
      @Test
      public void timespanDefaultSchedulerSize() {
          Flowable.range(1, 10)
          .window(1, TimeUnit.MINUTES, 20)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
      }
  
      @Test
      public void timespanDefaultSchedulerSizeRestart() {
          Flowable.range(1, 10)
          .window(1, TimeUnit.MINUTES, 20, true)
          .flatMap(Functions.<Flowable<Integer>>identity(), true)
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
      }
  
      @Test
      public void invalidSpan() {
          try {
              Flowable.just(1).window(-99, 1, TimeUnit.SECONDS);
              fail("Should have thrown!");
          } catch (IllegalArgumentException ex) {
              assertEquals("timespan > 0 required but it was -99", ex.getMessage());
          }
      }
  
      @Test
      public void timespanTimeskipDefaultScheduler() {
          Flowable.just(1)
          .window(1, 1, TimeUnit.MINUTES)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1);
      }
  
      @Test
      public void timespanTimeskipCustomScheduler() {
          Flowable.just(1)
          .window(1, 1, TimeUnit.MINUTES, Schedulers.io())
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1);
      }
  
      @Test
      public void timeskipJustOverlap() {
          Flowable.just(1)
          .window(2, 1, TimeUnit.MINUTES, Schedulers.single())
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1);
      }
  
      @Test
      public void timeskipJustSkip() {
          Flowable.just(1)
          .window(1, 2, TimeUnit.MINUTES, Schedulers.single())
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertResult(1);
      }
  
      @Test
      public void timeskipSkipping() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Integer> ts = pp.window(1, 2, TimeUnit.SECONDS, scheduler)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test();
  
          pp.onNext(1);
          pp.onNext(2);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(3);
          pp.onNext(4);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(5);
          pp.onNext(6);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(7);
          pp.onComplete();
  
          ts.assertResult(1, 2, 5, 6);
      }
  
      @Test
      public void timeskipOverlapping() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Integer> ts = pp.window(2, 1, TimeUnit.SECONDS, scheduler)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test();
  
          pp.onNext(1);
          pp.onNext(2);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(3);
          pp.onNext(4);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(5);
          pp.onNext(6);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          pp.onNext(7);
          pp.onComplete();
  
          ts.assertResult(1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7);
      }
  
      @Test
      public void exactOnError() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Integer> ts = pp.window(1, 1, TimeUnit.SECONDS, scheduler)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test();
  
          pp.onError(new TestException());
  
          ts.assertFailure(TestException.class);
      }
  
      @Test
      public void overlappingOnError() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Integer> ts = pp.window(2, 1, TimeUnit.SECONDS, scheduler)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test();
  
          pp.onError(new TestException());
  
          ts.assertFailure(TestException.class);
      }
  
      @Test
      public void skipOnError() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Integer> ts = pp.window(1, 2, TimeUnit.SECONDS, scheduler)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test();
  
          pp.onError(new TestException());
  
          ts.assertFailure(TestException.class);
      }
  
      @Test
      @SuppressWarnings("unchecked")
      public void exactBackpressure() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(1, 1, TimeUnit.SECONDS, scheduler)
          .test(0L);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          ts.assertFailure(MissingBackpressureException.class);
      }
  
      @Test
      @SuppressWarnings("unchecked")
      public void skipBackpressure() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(1, 2, TimeUnit.SECONDS, scheduler)
          .test(0L);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          ts.assertFailure(MissingBackpressureException.class);
      }
  
      @Test
      @SuppressWarnings("unchecked")
      public void overlapBackpressure() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(2, 1, TimeUnit.SECONDS, scheduler)
          .test(0L);
  
          scheduler.advanceTimeBy(1, TimeUnit.SECONDS);
  
          ts.assertFailure(MissingBackpressureException.class);
      }
  
      @Test
      public void exactBackpressure2() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(1, 1, TimeUnit.SECONDS, scheduler)
          .test(1L);
  
          scheduler.advanceTimeBy(2, TimeUnit.SECONDS);
  
          ts.assertError(MissingBackpressureException.class);
      }
  
      @Test
      public void skipBackpressure2() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(1, 2, TimeUnit.SECONDS, scheduler)
          .test(1L);
  
          scheduler.advanceTimeBy(2, TimeUnit.SECONDS);
  
          ts.assertError(MissingBackpressureException.class);
      }
  
      @Test
      public void overlapBackpressure2() {
          TestScheduler scheduler = new TestScheduler();
  
          PublishProcessor<Integer> pp = PublishProcessor.create();
  
          TestSubscriber<Flowable<Integer>> ts = pp.window(2, 1, TimeUnit.SECONDS, scheduler)
          .test(1L);
  
          scheduler.advanceTimeBy(2, TimeUnit.SECONDS);
  
          ts.assertError(MissingBackpressureException.class);
      }
  
      @Test
      public void dispose() {
          TestHelper.checkDisposed(Flowable.range(1, 5).window(1, TimeUnit.DAYS, Schedulers.single()).onBackpressureDrop());
  
          TestHelper.checkDisposed(Flowable.range(1, 5).window(2, 1, TimeUnit.DAYS, Schedulers.single()).onBackpressureDrop());
  
          TestHelper.checkDisposed(Flowable.range(1, 5).window(1, 2, TimeUnit.DAYS, Schedulers.single()).onBackpressureDrop());
  
          TestHelper.checkDisposed(Flowable.never()
                  .window(1, TimeUnit.DAYS, Schedulers.single(), 2, true).onBackpressureDrop());
      }
  
      @Test
      public void restartTimer() {
          Flowable.range(1, 5)
          .window(1, TimeUnit.DAYS, Schedulers.single(), 2, true)
          .flatMap(Functions.<Flowable<Integer>>identity())
          .test()
          .assertResult(1, 2, 3, 4, 5);
      }
  
      @Test
      public void exactBoundaryError() {
          Flowable.error(new TestException())
          .window(1, TimeUnit.DAYS, Schedulers.single(), 2, true)
          .test()
          .assertSubscribed()
          .assertError(TestException.class)
          .assertNotComplete();
      }
  
      @Test
      public void restartTimerMany() throws Exception {
          final AtomicBoolean cancel1 = new AtomicBoolean();
          Flowable.intervalRange(1, 1000, 1, 1, TimeUnit.MILLISECONDS)
          .doOnCancel(new Action() {
              @Override
              public void run() throws Exception {
                  cancel1.set(true);
              }
          })
          .window(1, TimeUnit.MILLISECONDS, Schedulers.single(), 2, true)
          .flatMap(Functions.<Flowable<Long>>identity())
          .take(500)
          .test()
          .awaitDone(5, TimeUnit.SECONDS)
          .assertSubscribed()
          .assertValueCount(500)
          .assertNoErrors()
          .assertComplete();
  
          int timeout = 20;
          while (timeout-- > 0 && !cancel1.get()) {
              Thread.sleep(100);
          }
  
          assertTrue("intervalRange was not cancelled!", cancel1.get());
      }
  
      @Test
      public void exactUnboundedReentrant() {
          TestScheduler scheduler = new TestScheduler();
  
          final FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
              @Override
              public void onNext(Integer t) {
                  super.onNext(t);
                  if (t == 1) {
                      ps.onNext(2);
                      ps.onComplete();
                  }
              }
          };
  
          ps.window(1, TimeUnit.MILLISECONDS, scheduler)
          .flatMap(new Function<Flowable<Integer>, Flowable<Integer>>() {
              @Override
              public Flowable<Integer> apply(Flowable<Integer> v) throws Exception {
                  return v;
              }
          })
          .subscribe(to);
  
          ps.onNext(1);
  
          to
          .awaitDone(1, TimeUnit.SECONDS)
          .assertResult(1, 2);
      }
  
      @Test
      public void exactBoundedReentrant() {
          TestScheduler scheduler = new TestScheduler();
  
          final FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
              @Override
              public void onNext(Integer t) {
                  super.onNext(t);
                  if (t == 1) {
                      ps.onNext(2);
                      ps.onComplete();
                  }
              }
          };
  
          ps.window(1, TimeUnit.MILLISECONDS, scheduler, 10, true)
          .flatMap(new Function<Flowable<Integer>, Flowable<Integer>>() {
              @Override
              public Flowable<Integer> apply(Flowable<Integer> v) throws Exception {
                  return v;
              }
          })
          .subscribe(to);
  
          ps.onNext(1);
  
          to
          .awaitDone(1, TimeUnit.SECONDS)
          .assertResult(1, 2);
      }
  
      @Test
      public void exactBoundedReentrant2() {
          TestScheduler scheduler = new TestScheduler();
  
          final FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
              @Override
              public void onNext(Integer t) {
                  super.onNext(t);
                  if (t == 1) {
                      ps.onNext(2);
                      ps.onComplete();
                  }
              }
          };
  
          ps.window(1, TimeUnit.MILLISECONDS, scheduler, 2, true)
          .flatMap(new Function<Flowable<Integer>, Flowable<Integer>>() {
              @Override
              public Flowable<Integer> apply(Flowable<Integer> v) throws Exception {
                  return v;
              }
          })
          .subscribe(to);
  
          ps.onNext(1);
  
          to
          .awaitDone(1, TimeUnit.SECONDS)
          .assertResult(1, 2);
      }
  
      @Test
      public void skipReentrant() {
          TestScheduler scheduler = new TestScheduler();
  
          final FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Integer> to = new TestSubscriber<Integer>() {
              @Override
              public void onNext(Integer t) {
                  super.onNext(t);
                  if (t == 1) {
                      ps.onNext(2);
                      ps.onComplete();
                  }
              }
          };
  
          ps.window(1, 2, TimeUnit.MILLISECONDS, scheduler)
          .flatMap(new Function<Flowable<Integer>, Flowable<Integer>>() {
              @Override
              public Flowable<Integer> apply(Flowable<Integer> v) throws Exception {
                  return v;
              }
          })
          .subscribe(to);
  
          ps.onNext(1);
  
          to
          .awaitDone(1, TimeUnit.SECONDS)
          .assertResult(1, 2);
      }
  
      @Test
      public void sizeTimeTimeout() {
          TestScheduler scheduler = new TestScheduler();
          PublishProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, 100)
          .test()
          .assertValueCount(1);
  
          scheduler.advanceTimeBy(5, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(2)
          .assertNoErrors()
          .assertNotComplete();
  
          ts.values().get(0).test().assertResult();
      }
  
      @Test
      public void periodicWindowCompletion() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, Long.MAX_VALUE, false)
          .test();
  
          scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(21)
          .assertNoErrors()
          .assertNotComplete();
      }
  
      @Test
      public void periodicWindowCompletionRestartTimer() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, Long.MAX_VALUE, true)
          .test();
  
          scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(21)
          .assertNoErrors()
          .assertNotComplete();
      }
  
      @Test
      public void periodicWindowCompletionBounded() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, 5, false)
          .test();
  
          scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(21)
          .assertNoErrors()
          .assertNotComplete();
      }
  
      @Test
      public void periodicWindowCompletionRestartTimerBounded() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, 5, true)
          .test();
  
          scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(21)
          .assertNoErrors()
          .assertNotComplete();
      }
  
      @Test
      public void periodicWindowCompletionRestartTimerBoundedSomeData() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, 2, true)
          .test();
  
          ps.onNext(1);
          ps.onNext(2);
  
          scheduler.advanceTimeBy(100, TimeUnit.MILLISECONDS);
  
          ts.assertValueCount(22)
          .assertNoErrors()
          .assertNotComplete();
      }
      @Test
      public void countRestartsOnTimeTick() {
          TestScheduler scheduler = new TestScheduler();
          FlowableProcessor<Integer> ps = PublishProcessor.<Integer>create();
  
          TestSubscriber<Flowable<Integer>> ts = ps.window(5, TimeUnit.MILLISECONDS, scheduler, 5, true)
          .test();
  
          // window #1
          ps.onNext(1);
          ps.onNext(2);
  
          scheduler.advanceTimeBy(5, TimeUnit.MILLISECONDS);
  
          // window #2
          ps.onNext(3);
          ps.onNext(4);
          ps.onNext(5);
          ps.onNext(6);
  
          ts.assertValueCount(2)
          .assertNoErrors()
          .assertNotComplete();
      }
  }
  
  