/* * Copyright 2014-2017 Real Logic Ltd. * * 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.aeron.logbuffer; import io.aeron.protocol.DataHeaderFlyweight; import org.agrona.ErrorHandler; import org.agrona.concurrent.UnsafeBuffer; import org.agrona.concurrent.status.Position; import org.junit.*; import org.mockito.InOrder; import static io.aeron.logbuffer.FrameDescriptor.*; import static io.aeron.protocol.HeaderFlyweight.HDR_TYPE_DATA; import static org.agrona.BitUtil.align; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.*; public class TermReaderTest { private static final int TERM_BUFFER_CAPACITY = LogBufferDescriptor.TERM_MIN_LENGTH; private static final int HEADER_LENGTH = DataHeaderFlyweight.HEADER_LENGTH; private static final int INITIAL_TERM_ID = 7; private final Header header = new Header(INITIAL_TERM_ID, TERM_BUFFER_CAPACITY); private final UnsafeBuffer termBuffer = mock(UnsafeBuffer.class); private final ErrorHandler errorHandler = mock(ErrorHandler.class); private final FragmentHandler handler = mock(FragmentHandler.class); private final Position subscriberPosition = mock(Position.class); @Before public void setUp() { when(termBuffer.capacity()).thenReturn(TERM_BUFFER_CAPACITY); } @Test public void shouldReadFirstMessage() { final int msgLength = 1; final int frameLength = HEADER_LENGTH + msgLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int termOffset = 0; when(termBuffer.getIntVolatile(0)).thenReturn(frameLength); when(termBuffer.getShort(typeOffset(0))).thenReturn((short)HDR_TYPE_DATA); final int readOutcome = TermReader.read( termBuffer, termOffset, handler, Integer.MAX_VALUE, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(1)); final InOrder inOrder = inOrder(termBuffer, handler, subscriberPosition); inOrder.verify(termBuffer).getIntVolatile(0); inOrder.verify(handler).onFragment(eq(termBuffer), eq(HEADER_LENGTH), eq(msgLength), any(Header.class)); inOrder.verify(subscriberPosition).setOrdered(alignedFrameLength); } @Test public void shouldNotReadPastTail() { final int termOffset = 0; final int readOutcome = TermReader.read( termBuffer, termOffset, handler, Integer.MAX_VALUE, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(0)); verify(subscriberPosition, never()).setOrdered(anyLong()); verify(termBuffer).getIntVolatile(0); verify(handler, never()).onFragment(any(), anyInt(), anyInt(), any()); } @Test public void shouldReadOneLimitedMessage() { final int msgLength = 1; final int frameLength = HEADER_LENGTH + msgLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int termOffset = 0; when(termBuffer.getIntVolatile(anyInt())).thenReturn(frameLength); when(termBuffer.getShort(anyInt())).thenReturn((short)HDR_TYPE_DATA); final int readOutcome = TermReader.read( termBuffer, termOffset, handler, 1, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(1)); final InOrder inOrder = inOrder(termBuffer, handler, subscriberPosition); inOrder.verify(termBuffer).getIntVolatile(0); inOrder.verify(handler).onFragment(eq(termBuffer), eq(HEADER_LENGTH), eq(msgLength), any(Header.class)); inOrder.verify(subscriberPosition).setOrdered(alignedFrameLength); inOrder.verifyNoMoreInteractions(); } @Test public void shouldReadMultipleMessages() { final int msgLength = 1; final int frameLength = HEADER_LENGTH + msgLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int termOffset = 0; when(termBuffer.getIntVolatile(0)).thenReturn(frameLength); when(termBuffer.getIntVolatile(alignedFrameLength)).thenReturn(frameLength); when(termBuffer.getShort(anyInt())).thenReturn((short)HDR_TYPE_DATA); final int readOutcome = TermReader.read( termBuffer, termOffset, handler, Integer.MAX_VALUE, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(2)); final InOrder inOrder = inOrder(termBuffer, handler, subscriberPosition); inOrder.verify(termBuffer).getIntVolatile(0); inOrder.verify(handler).onFragment(eq(termBuffer), eq(HEADER_LENGTH), eq(msgLength), any(Header.class)); inOrder.verify(termBuffer).getIntVolatile(alignedFrameLength); inOrder .verify(handler) .onFragment(eq(termBuffer), eq(alignedFrameLength + HEADER_LENGTH), eq(msgLength), any(Header.class)); inOrder.verify(subscriberPosition).setOrdered(alignedFrameLength * 2); } @Test public void shouldReadLastMessage() { final int msgLength = 1; final int frameLength = HEADER_LENGTH + msgLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int frameOffset = TERM_BUFFER_CAPACITY - alignedFrameLength; when(termBuffer.getIntVolatile(frameOffset)).thenReturn(frameLength); when(termBuffer.getShort(typeOffset(frameOffset))).thenReturn((short)HDR_TYPE_DATA); final int readOutcome = TermReader.read( termBuffer, frameOffset, handler, Integer.MAX_VALUE, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(1)); final InOrder inOrder = inOrder(termBuffer, handler, subscriberPosition); inOrder.verify(termBuffer).getIntVolatile(frameOffset); inOrder.verify(handler).onFragment( eq(termBuffer), eq(frameOffset + HEADER_LENGTH), eq(msgLength), any(Header.class)); inOrder.verify(subscriberPosition).setOrdered(alignedFrameLength); } @Test public void shouldNotReadLastMessageWhenPadding() { final int msgLength = 1; final int frameLength = HEADER_LENGTH + msgLength; final int alignedFrameLength = align(frameLength, FRAME_ALIGNMENT); final int frameOffset = TERM_BUFFER_CAPACITY - alignedFrameLength; when(termBuffer.getIntVolatile(frameOffset)).thenReturn(frameLength); when(termBuffer.getShort(typeOffset(frameOffset))).thenReturn((short)PADDING_FRAME_TYPE); final int readOutcome = TermReader.read( termBuffer, frameOffset, handler, Integer.MAX_VALUE, header, errorHandler, 0, subscriberPosition); assertThat(readOutcome, is(0)); final InOrder inOrder = inOrder(termBuffer, subscriberPosition); inOrder.verify(termBuffer).getIntVolatile(frameOffset); verify(handler, never()).onFragment(any(), anyInt(), anyInt(), any()); inOrder.verify(subscriberPosition).setOrdered(alignedFrameLength); } }