/* * Copyright 2014-2020 Real Logic Limited. * * 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 * * https://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.aeron; import io.aeron.logbuffer.*; import io.aeron.logbuffer.ControlledFragmentHandler.Action; import io.aeron.protocol.DataHeaderFlyweight; import io.aeron.protocol.HeaderFlyweight; import org.agrona.DirectBuffer; import org.agrona.ErrorHandler; import org.agrona.concurrent.UnsafeBuffer; import org.agrona.concurrent.status.AtomicLongPosition; import org.agrona.concurrent.status.Position; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InOrder; import org.mockito.Mockito; import static io.aeron.logbuffer.LogBufferDescriptor.*; import static io.aeron.protocol.DataHeaderFlyweight.HEADER_LENGTH; import static java.nio.ByteBuffer.allocateDirect; import static org.agrona.BitUtil.align; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.*; public class ImageTest { private static final int TERM_BUFFER_LENGTH = LogBufferDescriptor.TERM_MIN_LENGTH; private static final int POSITION_BITS_TO_SHIFT = LogBufferDescriptor.positionBitsToShift(TERM_BUFFER_LENGTH); private static final byte[] DATA = new byte[36]; static { for (int i = 0; i < DATA.length; i++) { DATA[i] = (byte)i; } } private static final long CORRELATION_ID = 0xC044E1AL; private static final int SESSION_ID = 0x5E55101D; private static final int STREAM_ID = 0xC400E; private static final String SOURCE_IDENTITY = "ipc"; private static final int INITIAL_TERM_ID = 0xEE81D; private static final int MESSAGE_LENGTH = HEADER_LENGTH + DATA.length; private static final int ALIGNED_FRAME_LENGTH = align(MESSAGE_LENGTH, FrameDescriptor.FRAME_ALIGNMENT); private final UnsafeBuffer rcvBuffer = new UnsafeBuffer(allocateDirect(ALIGNED_FRAME_LENGTH)); private final DataHeaderFlyweight dataHeader = new DataHeaderFlyweight(); private final FragmentHandler mockFragmentHandler = mock(FragmentHandler.class); private final ControlledFragmentHandler mockControlledFragmentHandler = mock(ControlledFragmentHandler.class); private final Position position = spy(new AtomicLongPosition()); private final LogBuffers logBuffers = mock(LogBuffers.class); private final ErrorHandler errorHandler = mock(ErrorHandler.class); private final Subscription subscription = mock(Subscription.class); private final UnsafeBuffer[] termBuffers = new UnsafeBuffer[PARTITION_COUNT]; @BeforeEach public void setUp() { dataHeader.wrap(rcvBuffer); for (int i = 0; i < PARTITION_COUNT; i++) { termBuffers[i] = new UnsafeBuffer(allocateDirect(TERM_BUFFER_LENGTH)); } final UnsafeBuffer logMetaDataBuffer = new UnsafeBuffer(allocateDirect(LOG_META_DATA_LENGTH)); when(logBuffers.duplicateTermBuffers()).thenReturn(termBuffers); when(logBuffers.termLength()).thenReturn(TERM_BUFFER_LENGTH); when(logBuffers.metaDataBuffer()).thenReturn(logMetaDataBuffer); } @Test public void shouldHandleClosedImage() { final Image image = createImage(); image.close(); assertTrue(image.isClosed()); assertThat(image.poll(mockFragmentHandler, Integer.MAX_VALUE), is(0)); assertThat(image.position(), is(0L)); } @Test public void shouldAllowValidPosition() { final Image image = createImage(); final long expectedPosition = TERM_BUFFER_LENGTH - 32; position.setOrdered(expectedPosition); assertThat(image.position(), is(expectedPosition)); image.position(TERM_BUFFER_LENGTH); assertThat(image.position(), is((long)TERM_BUFFER_LENGTH)); } @Test public void shouldNotAdvancePastEndOfTerm() { final Image image = createImage(); final long expectedPosition = TERM_BUFFER_LENGTH - 32; position.setOrdered(expectedPosition); assertThat(image.position(), is(expectedPosition)); assertThrows(IllegalArgumentException.class, () -> image.position(TERM_BUFFER_LENGTH + 32)); } @Test public void shouldReportCorrectPositionOnReception() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); final int messages = image.poll(mockFragmentHandler, Integer.MAX_VALUE); assertThat(messages, is(1)); verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); final InOrder inOrder = Mockito.inOrder(position); inOrder.verify(position).setOrdered(initialPosition); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldReportCorrectPositionOnReceptionWithNonZeroPositionInInitialTermId() { final int initialMessageIndex = 5; final int initialTermOffset = offsetForFrame(initialMessageIndex); final long initialPosition = computePosition( INITIAL_TERM_ID, initialTermOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(initialMessageIndex)); final int messages = image.poll(mockFragmentHandler, Integer.MAX_VALUE); assertThat(messages, is(1)); verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(initialTermOffset + HEADER_LENGTH), eq(DATA.length), any(Header.class)); final InOrder inOrder = Mockito.inOrder(position); inOrder.verify(position).setOrdered(initialPosition); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldReportCorrectPositionOnReceptionWithNonZeroPositionInNonInitialTermId() { final int activeTermId = INITIAL_TERM_ID + 1; final int initialMessageIndex = 5; final int initialTermOffset = offsetForFrame(initialMessageIndex); final long initialPosition = computePosition(activeTermId, initialTermOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(activeTermId, offsetForFrame(initialMessageIndex)); final int messages = image.poll(mockFragmentHandler, Integer.MAX_VALUE); assertThat(messages, is(1)); verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(initialTermOffset + HEADER_LENGTH), eq(DATA.length), any(Header.class)); final InOrder inOrder = Mockito.inOrder(position); inOrder.verify(position).setOrdered(initialPosition); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldPollNoFragmentsToControlledFragmentHandler() { final Image image = createImage(); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(0)); verify(position, never()).setOrdered(anyLong()); verify(mockControlledFragmentHandler, never()).onFragment( any(UnsafeBuffer.class), anyInt(), anyInt(), any(Header.class)); } @Test public void shouldPollOneFragmentToControlledFragmentHandlerOnContinue() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldUpdatePositionOnRethrownExceptionInControlledPoll() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenThrow(new RuntimeException()); doThrow(new RuntimeException()).when(errorHandler).onError(any()); boolean thrown = false; try { image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); } catch (final Exception ignore) { thrown = true; } assertTrue(thrown); assertThat(image.position(), is(initialPosition + ALIGNED_FRAME_LENGTH)); verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); } @Test public void shouldUpdatePositionOnRethrownExceptionInPoll() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); doThrow(new RuntimeException()).when(mockFragmentHandler) .onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class)); doThrow(new RuntimeException()).when(errorHandler).onError(any()); boolean thrown = false; try { image.poll(mockFragmentHandler, Integer.MAX_VALUE); } catch (final Exception ignore) { thrown = true; } assertTrue(thrown); assertThat(image.position(), is(initialPosition + ALIGNED_FRAME_LENGTH)); verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); } @Test public void shouldNotPollOneFragmentToControlledFragmentHandlerOnAbort() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.ABORT); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(0)); assertThat(image.position(), is(initialPosition)); verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); } @Test public void shouldPollOneFragmentToControlledFragmentHandlerOnBreak() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.BREAK); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldPollFragmentsToControlledFragmentHandlerOnCommit() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.COMMIT); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(2)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(ALIGNED_FRAME_LENGTH + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + (ALIGNED_FRAME_LENGTH * 2)); } @Test public void shouldUpdatePositionToEndOfCommittedFragmentOnCommit() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(2)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE, Action.COMMIT, Action.CONTINUE); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(3)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); // first fragment, continue inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); // second fragment, commit inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(ALIGNED_FRAME_LENGTH + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + (ALIGNED_FRAME_LENGTH * 2)); // third fragment, continue, but position is updated because last inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(2 * ALIGNED_FRAME_LENGTH + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + (ALIGNED_FRAME_LENGTH * 3)); } @Test public void shouldPollFragmentsToControlledFragmentHandlerOnContinue() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.controlledPoll(mockControlledFragmentHandler, Integer.MAX_VALUE); assertThat(fragmentsRead, is(2)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(ALIGNED_FRAME_LENGTH + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + (ALIGNED_FRAME_LENGTH * 2)); } @Test public void shouldPollNoFragmentsToBoundedControlledFragmentHandlerWithMaxPositionBeforeInitialPosition() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = initialPosition - HEADER_LENGTH; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.boundedControlledPoll( mockControlledFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(0)); assertThat(position.get(), is(initialPosition)); verify(mockControlledFragmentHandler, never()).onFragment( any(UnsafeBuffer.class), anyInt(), anyInt(), any(Header.class)); } @Test public void shouldPollFragmentsToBoundedControlledFragmentHandlerWithInitialOffsetNotZero() { final long initialPosition = computePosition( INITIAL_TERM_ID, offsetForFrame(1), POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = initialPosition + ALIGNED_FRAME_LENGTH; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(2)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.boundedControlledPoll( mockControlledFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); assertThat(position.get(), is(maxPosition)); verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), anyInt(), anyInt(), any(Header.class)); } @Test public void shouldPollFragmentsToBoundedControlledFragmentHandlerWithMaxPositionBeforeNextMessage() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = initialPosition + ALIGNED_FRAME_LENGTH; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.boundedControlledPoll( mockControlledFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldPollFragmentsToBoundedFragmentHandlerWithMaxPositionBeforeNextMessage() { final long initialPosition = computePosition(INITIAL_TERM_ID, 0, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = initialPosition + ALIGNED_FRAME_LENGTH; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(0)); insertDataFrame(INITIAL_TERM_ID, offsetForFrame(1)); final int fragmentsRead = image.boundedPoll(mockFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockFragmentHandler); inOrder.verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(initialPosition + ALIGNED_FRAME_LENGTH); } @Test public void shouldPollFragmentsToBoundedControlledFragmentHandlerWithMaxPositionAfterEndOfTerm() { final int initialOffset = TERM_BUFFER_LENGTH - (ALIGNED_FRAME_LENGTH * 2); final long initialPosition = computePosition( INITIAL_TERM_ID, initialOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = initialPosition + TERM_BUFFER_LENGTH; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, initialOffset); insertPaddingFrame(INITIAL_TERM_ID, initialOffset + ALIGNED_FRAME_LENGTH); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.boundedControlledPoll( mockControlledFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(initialOffset + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(TERM_BUFFER_LENGTH); } @Test public void shouldPollFragmentsToBoundedControlledFragmentHandlerWithMaxPositionAboveIntMaxValue() { final int initialOffset = TERM_BUFFER_LENGTH - (ALIGNED_FRAME_LENGTH * 2); final long initialPosition = computePosition( INITIAL_TERM_ID, initialOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = (long)Integer.MAX_VALUE + 1000; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, initialOffset); insertPaddingFrame(INITIAL_TERM_ID, initialOffset + ALIGNED_FRAME_LENGTH); when(mockControlledFragmentHandler.onFragment(any(DirectBuffer.class), anyInt(), anyInt(), any(Header.class))) .thenReturn(Action.CONTINUE); final int fragmentsRead = image.boundedControlledPoll( mockControlledFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockControlledFragmentHandler); inOrder.verify(mockControlledFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(initialOffset + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(TERM_BUFFER_LENGTH); } @Test public void shouldPollFragmentsToBoundedFragmentHandlerWithMaxPositionAboveIntMaxValue() { final int initialOffset = TERM_BUFFER_LENGTH - (ALIGNED_FRAME_LENGTH * 2); final long initialPosition = computePosition( INITIAL_TERM_ID, initialOffset, POSITION_BITS_TO_SHIFT, INITIAL_TERM_ID); final long maxPosition = (long)Integer.MAX_VALUE + 1000; position.setOrdered(initialPosition); final Image image = createImage(); insertDataFrame(INITIAL_TERM_ID, initialOffset); insertPaddingFrame(INITIAL_TERM_ID, initialOffset + ALIGNED_FRAME_LENGTH); final int fragmentsRead = image.boundedPoll( mockFragmentHandler, maxPosition, Integer.MAX_VALUE); assertThat(fragmentsRead, is(1)); final InOrder inOrder = Mockito.inOrder(position, mockFragmentHandler); inOrder.verify(mockFragmentHandler).onFragment( any(UnsafeBuffer.class), eq(initialOffset + HEADER_LENGTH), eq(DATA.length), any(Header.class)); inOrder.verify(position).setOrdered(TERM_BUFFER_LENGTH); } private Image createImage() { return new Image(subscription, SESSION_ID, position, logBuffers, errorHandler, SOURCE_IDENTITY, CORRELATION_ID); } private void insertDataFrame(final int activeTermId, final int termOffset) { dataHeader .termId(INITIAL_TERM_ID) .streamId(STREAM_ID) .sessionId(SESSION_ID) .termOffset(termOffset) .frameLength(DATA.length + HEADER_LENGTH) .headerType(HeaderFlyweight.HDR_TYPE_DATA) .flags(DataHeaderFlyweight.BEGIN_AND_END_FLAGS) .version(HeaderFlyweight.CURRENT_VERSION); rcvBuffer.putBytes(dataHeader.dataOffset(), DATA); final int activeIndex = indexByTerm(INITIAL_TERM_ID, activeTermId); TermRebuilder.insert(termBuffers[activeIndex], termOffset, rcvBuffer, ALIGNED_FRAME_LENGTH); } private void insertPaddingFrame(final int activeTermId, final int termOffset) { dataHeader .termId(INITIAL_TERM_ID) .streamId(STREAM_ID) .sessionId(SESSION_ID) .frameLength(TERM_BUFFER_LENGTH - termOffset) .headerType(HeaderFlyweight.HDR_TYPE_PAD) .flags(DataHeaderFlyweight.BEGIN_AND_END_FLAGS) .version(HeaderFlyweight.CURRENT_VERSION); final int activeIndex = indexByTerm(INITIAL_TERM_ID, activeTermId); TermRebuilder.insert(termBuffers[activeIndex], termOffset, rcvBuffer, TERM_BUFFER_LENGTH - termOffset); } private static int offsetForFrame(final int index) { return index * ALIGNED_FRAME_LENGTH; } }