@Test
public void innerLimitReasons() throws ExecutionException, InterruptedException {

    // One hits limit ; one has not yet returned anything
    List<FirableCursor<Integer>> cursors = Arrays.asList(
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1)).limitRowsTo(1)),
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(3, 4)))
    );
    RecordCursorIterator<Integer> cursor = UnorderedUnionCursor.create(functionsFromCursors(cursors), null, null).asIterator();
    cursors.get(0).fireAll();
    assertEquals(0, (int)cursor.next());
    cursors.get(1).fire();
    assertEquals(3, (int)cursor.next());
    cursors.get(1).fire();
    assertEquals(4, (int)cursor.next());
    cursors.get(1).fire();
    assertThat(cursor.hasNext(), is(false));
    assertEquals(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED, cursor.getNoNextReason());
    // One hits limit ; one has fired exactly once
    cursors = Arrays.asList(
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1)).limitRowsTo(1)),
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(3, 4)))
    );
    cursor = UnorderedUnionCursor.create(functionsFromCursors(cursors), null, null).asIterator();
    cursors.get(1).fire();
    assertEquals(3, (int)cursor.next());
    cursors.get(0).fireAll();
    assertEquals(0, (int)cursor.next());
    cursors.get(1).fire();
    assertEquals(4, (int)cursor.next());
    cursors.get(1).fire();
    assertThat(cursor.hasNext(), is(false));
    assertEquals(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED, cursor.getNoNextReason());
    // One hits limit ; one is exhausted
    cursors = Arrays.asList(
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1)).limitRowsTo(1)),
            new FirableCursor<>(RecordCursor.fromList(Collections.singletonList(3)))
    );
    cursor = UnorderedUnionCursor.create(functionsFromCursors(cursors), null, null).asIterator();
    cursors.get(1).fire();
    assertEquals(3, (int)cursor.next());
    cursors.get(0).fireAll();
    cursors.get(1).fireAll();
    assertEquals(0, (int)cursor.next());
    assertThat(cursor.hasNext(), is(false));
    assertEquals(RecordCursor.NoNextReason.RETURN_LIMIT_REACHED, cursor.getNoNextReason());
    // One hits return limit ; one hits scan limit exhausted
    cursors = Arrays.asList(
            new FirableCursor<>(RecordCursor.fromList(Arrays.asList(0, 1)).limitRowsTo(1)),
            new FirableCursor<>(new RecordCursorTest.FakeOutOfBandCursor<>(RecordCursor.fromList(Arrays.asList(3, 4)), 1, RecordCursor.NoNextReason.SCAN_LIMIT_REACHED))
    );
    cursor = UnorderedUnionCursor.create(functionsFromCursors(cursors), null, null).asIterator();
    cursors.get(1).fire();
    assertEquals(3, (int)cursor.next());
    cursors.get(0).fireAll();
    assertEquals(0, (int)cursor.next());
    cursors.get(1).fireAll();
    assertThat(cursor.hasNext(), is(false));
    assertEquals(RecordCursor.NoNextReason.SCAN_LIMIT_REACHED, cursor.getNoNextReason());
}