@Test
  public void bufferStopsWhenStopped() throws IOException, InterruptedException {
    CountDownLatch latch = new CountDownLatch(1);
    Pair<InputStream, List<byte[]>> stream = TestUtils.generateStream(100);

    MJpegStreamBufferer buffer = new MJpegStreamBufferer(5);

    buffer.start(
        new MJpegStreamBufferListener() {
          @Override
          public void stopped() {
            latch.countDown();
          }

          @Override
          public void streamBuffered(byte[] stream) {
            try {
              Thread.sleep(1000);
            } catch (InterruptedException e) {
              throw new RuntimeException(e);
            }
          }

          @Override
          public void streamDiscarded(byte[] stream) {}
        },
        new MJpegStreamIterator(stream.getLeft()));

    buffer.stop();
    latch.await();
  }
  @Test
  public void bufferDiscardsStreamWhenFull() throws IOException, InterruptedException {
    CountDownLatch latch = new CountDownLatch(1);
    Pair<InputStream, List<byte[]>> stream = TestUtils.generateStream(100);

    MJpegStreamBufferer buffer = new MJpegStreamBufferer(5);

    AtomicInteger discardedCount = new AtomicInteger(0);

    buffer.start(
        new MJpegStreamBufferListener() {
          @Override
          public void stopped() {
            latch.countDown();
          }

          @Override
          public void streamBuffered(byte[] stream) {}

          @Override
          public void streamDiscarded(byte[] stream) {
            discardedCount.incrementAndGet();
          }
        },
        new MJpegStreamIterator(stream.getLeft()));

    latch.await();

    for (int x = 0; x < 5; ++x) {
      assertThat(buffer.get(), is(stream.getRight().get(x + 95)));
    }

    assertNull(buffer.get());
    assertThat(discardedCount.get(), is(95));
  }
  @Test
  public void bufferBuffersAllData() throws IOException, InterruptedException {
    CountDownLatch stopLatch = new CountDownLatch(1);
    int size = 100;

    Pair<InputStream, List<byte[]>> stream = TestUtils.generateStream(size);

    MJpegStreamBufferer buffer = new MJpegStreamBufferer(200);

    buffer.start(
        new MJpegStreamBufferListener() {
          @Override
          public void stopped() {
            stopLatch.countDown();
          }

          @Override
          public void streamBuffered(byte[] stream) {
            try {
              Thread.sleep(10);
            } catch (InterruptedException e) {
              throw new RuntimeException(e);
            }
          }

          @Override
          public void streamDiscarded(byte[] stream) {}
        },
        new MJpegStreamIterator(stream.getLeft()));

    List<byte[]> streams = Lists.newArrayList();
    CountDownLatch readLatchGet = new CountDownLatch(1);
    Thread t =
        new Thread(
            () -> {
              while (true) {
                if (buffer.isStopped()) {
                  break;
                }

                byte[] data = buffer.get();

                if (data != null) {
                  streams.add(data);
                }
              }

              readLatchGet.countDown();
            });

    t.start();

    readLatchGet.await();
    assertThat(streams.size(), is(size));

    for (int x = 0; x < size; ++x) {
      assertThat(streams.get(x), is(stream.getRight().get(x)));
    }

    stopLatch.await();
  }