/* * 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 org.junit.Before; import org.junit.Test; import io.aeron.protocol.DataHeaderFlyweight; import org.agrona.concurrent.UnsafeBuffer; import static io.aeron.logbuffer.FrameDescriptor.FRAME_ALIGNMENT; import static org.agrona.BitUtil.align; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; import static org.mockito.Mockito.*; public class TermGapScannerTest { private static final int LOG_BUFFER_CAPACITY = LogBufferDescriptor.TERM_MIN_LENGTH; private static final int TERM_ID = 1; private static final int HEADER_LENGTH = DataHeaderFlyweight.HEADER_LENGTH; private final UnsafeBuffer termBuffer = mock(UnsafeBuffer.class); private final TermGapScanner.GapHandler gapHandler = mock(TermGapScanner.GapHandler.class); @Before public void setUp() { when(termBuffer.capacity()).thenReturn(LOG_BUFFER_CAPACITY); } @Test public void shouldReportGapAtBeginningOfBuffer() { final int frameOffset = align(HEADER_LENGTH * 3, FRAME_ALIGNMENT); final int highWaterMark = frameOffset + align(HEADER_LENGTH, FRAME_ALIGNMENT); when(termBuffer.getIntVolatile(frameOffset)).thenReturn(HEADER_LENGTH); assertThat(TermGapScanner.scanForGap(termBuffer, TERM_ID, 0, highWaterMark, gapHandler), is(0)); verify(gapHandler).onGap(TERM_ID, 0, frameOffset); } @Test public void shouldReportSingleGapWhenBufferNotFull() { final int tail = align(HEADER_LENGTH, FRAME_ALIGNMENT); final int highWaterMark = FRAME_ALIGNMENT * 3; when(termBuffer.getIntVolatile(tail - align(HEADER_LENGTH, FRAME_ALIGNMENT))).thenReturn(HEADER_LENGTH); when(termBuffer.getIntVolatile(tail)).thenReturn(0); when(termBuffer.getIntVolatile(highWaterMark - align(HEADER_LENGTH, FRAME_ALIGNMENT))) .thenReturn(HEADER_LENGTH); assertThat(TermGapScanner.scanForGap(termBuffer, TERM_ID, tail, highWaterMark, gapHandler), is(tail)); verify(gapHandler).onGap(TERM_ID, tail, align(HEADER_LENGTH, FRAME_ALIGNMENT)); } @Test public void shouldReportSingleGapWhenBufferIsFull() { final int tail = LOG_BUFFER_CAPACITY - (align(HEADER_LENGTH, FRAME_ALIGNMENT) * 2); final int highWaterMark = LOG_BUFFER_CAPACITY; when(termBuffer.getIntVolatile(tail - align(HEADER_LENGTH, FRAME_ALIGNMENT))).thenReturn(HEADER_LENGTH); when(termBuffer.getIntVolatile(tail)).thenReturn(0); when(termBuffer.getIntVolatile(highWaterMark - align(HEADER_LENGTH, FRAME_ALIGNMENT))) .thenReturn(HEADER_LENGTH); assertThat(TermGapScanner.scanForGap(termBuffer, TERM_ID, tail, highWaterMark, gapHandler), is(tail)); verify(gapHandler).onGap(TERM_ID, tail, align(HEADER_LENGTH, FRAME_ALIGNMENT)); } @Test public void shouldReportNoGapWhenHwmIsInPadding() { final int paddingLength = align(HEADER_LENGTH, FRAME_ALIGNMENT) * 2; final int tail = LOG_BUFFER_CAPACITY - paddingLength; final int highWaterMark = LOG_BUFFER_CAPACITY - paddingLength + HEADER_LENGTH; when(termBuffer.getIntVolatile(tail)).thenReturn(paddingLength); when(termBuffer.getIntVolatile(tail + HEADER_LENGTH)).thenReturn(0); assertThat(TermGapScanner.scanForGap(termBuffer, TERM_ID, tail, highWaterMark, gapHandler), is(LOG_BUFFER_CAPACITY)); verifyZeroInteractions(gapHandler); } }