public NativeReader.Progress getProgress() {
    return progress.get();
  }
@Test
  public void testGetProgress() throws Exception {
    MockReaderIterator iterator = new MockReaderIterator(0, 5);
    MockOutputReceiver receiver = new MockOutputReceiver();

    ManualScheduler scheduler = new ManualScheduler();
    final ReadOperation readOperation =
        ReadOperation.forTest(new MockReader(iterator), receiver, scheduler.getExecutor(), context);

    Thread thread = runReadLoopInThread(readOperation);
    for (int i = 0; i < 5; ++i) {
      // Reader currently blocked in start()/advance().
      // Ensure that getProgress() doesn't block while the reader advances.
      ApproximateReportedProgress progress =
          readerProgressToCloudProgress(readOperation.getProgress());
      Long observedIndex =
          (progress == null) ? null : progress.getPosition().getRecordIndex().longValue();
      assertTrue(
          "Actual: " + observedIndex + " instead of " + i,
          (i == 0 && progress == null) || i == observedIndex || i == observedIndex + 1);
      iterator.offerNext(i);
      // Now the reader is not blocked (instead the receiver is blocked): progress can be
      // updated. Wait for it to be updated.
      scheduler.runOnce();

      receiver.unblockProcess();
    }
    thread.join();
  }