/* * sulky-modules - several general-purpose modules. * Copyright (C) 2007-2011 Joern Huxhorn * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* * Copyright 2007-2011 Joern Huxhorn * * 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 de.huxhorn.sulky.buffers; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class OverwritingCircularBufferTest { private final Logger logger = LoggerFactory.getLogger(OverwritingCircularBufferTest.class); private static final int TEST_BUFFER_SIZE = 5; private OverwritingCircularBuffer<Long> instance; @Before public void setUp() throws Exception { instance = new OverwritingCircularBuffer<>(TEST_BUFFER_SIZE); } @Test public void empty() { assertTrue("Instance is not empty!", instance.isEmpty()); assertTrue("Instance is full!", !instance.isFull()); assertEquals("Size doesn't match!", 0, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); assertEquals("overflowCounter doesn't match!", 0, instance.getOverflowCounter()); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator has next!", !iterator.hasNext()); } @Test public void one() { instance.add((long) 1); assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance is full!", !instance.isFull()); assertEquals("Size doesn't match!", 1, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); assertEquals("overflowCounter doesn't match!", 0, instance.getOverflowCounter()); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); Long element = iterator.next(); Long getRelativeValue = instance.getRelative(0); Long getValue = instance.get(0); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}, getValue={}", new Object[]{0, element, getRelativeValue, getValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) 1, element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } @Test public void nearlyFull() { for(int i = 0; i < TEST_BUFFER_SIZE - 1; i++) { instance.add((long) i); } assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance is full!", !instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE - 1, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); assertEquals("overflowCounter doesn't match!", 0, instance.getOverflowCounter()); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE - 1; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) i, element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void full() { for(int i = 0; i < TEST_BUFFER_SIZE; i++) { instance.add((long) i); } assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance isn't full!", instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); assertEquals("overflowCounter doesn't match!", 0, instance.getOverflowCounter()); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) i, element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void overflowOne() { for(int i = 0; i < TEST_BUFFER_SIZE; i++) { instance.add((long) i); } instance.add((long) TEST_BUFFER_SIZE); assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance isn't full!", instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); long overflowCounter = instance.getOverflowCounter(); assertEquals("overflowCounter doesn't match!", 1, overflowCounter); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i + overflowCounter); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) (i + 1), element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void overflowDouble() { for(int i = 0; i < TEST_BUFFER_SIZE * 2; i++) { instance.add((long) i); } assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance isn't full!", instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); long overflowCounter = instance.getOverflowCounter(); assertEquals("overflowCounter doesn't match!", TEST_BUFFER_SIZE, overflowCounter); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i + overflowCounter); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) (i + TEST_BUFFER_SIZE), element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void addAllList() { List<Long> values = new ArrayList<>(); for(int i = 0; i < 4 * TEST_BUFFER_SIZE; i++) { values.add((long) i); } if(logger.isInfoEnabled()) logger.info("Adding values: {}", values); instance.addAll(values); if(logger.isInfoEnabled()) logger.info("Buffer after adding: {}", instance); assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance isn't full!", instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); long overflowCounter = instance.getOverflowCounter(); assertEquals("overflowCounter doesn't match!", 3 * TEST_BUFFER_SIZE, overflowCounter); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i + overflowCounter); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) (i + 3 * TEST_BUFFER_SIZE), element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void addAllArray() { Long[] values = new Long[4 * TEST_BUFFER_SIZE]; for(int i = 0; i < 4 * TEST_BUFFER_SIZE; i++) { values[i] = (long) i; } if(logger.isInfoEnabled()) logger.info("Adding values: {}", (Object)values); instance.addAll(values); if(logger.isInfoEnabled()) logger.info("Buffer after adding: {}", instance); assertTrue("Instance is empty!", !instance.isEmpty()); assertTrue("Instance isn't full!", instance.isFull()); assertEquals("Size doesn't match!", TEST_BUFFER_SIZE, instance.getAvailableElements()); assertEquals("getBufferSize doesn't match!", TEST_BUFFER_SIZE, instance.getBufferSize()); long overflowCounter = instance.getOverflowCounter(); assertEquals("overflowCounter doesn't match!", 3 * TEST_BUFFER_SIZE, overflowCounter); Iterator<Long> iterator = instance.iterator(); assertTrue("iterator doesn't have next!", iterator.hasNext()); for(int i = 0; i < TEST_BUFFER_SIZE; i++) { Long element = iterator.next(); Long getRelativeValue = instance.getRelative(i); Long getValue = instance.get(i + overflowCounter); if(logger.isInfoEnabled()) { logger .info("Element #{}: iterValue={}, getRelativeValue={}", new Object[]{i, element, getRelativeValue}); } assertEquals("Unexpected value returned by iterator!", (Long) (long) (i + 3 * TEST_BUFFER_SIZE), element); assertEquals("Iterator and getRelative values differ!", element, getRelativeValue); assertEquals("Iterator and get values differ!", element, getValue); } } @Test public void addRemove() { internalTestRemove(instance, 0); internalTestRemove(instance, 3); internalTestRemove(instance, 7); internalTestRemove(instance, 17); internalTestRemove(instance, 4 * TEST_BUFFER_SIZE); instance = new OverwritingCircularBuffer<>(17); internalTestRemove(instance, 23); // absurd... instance = new OverwritingCircularBuffer<>(1); internalTestRemove(instance, 17); } @Test public void addRemoveAll() { internalTestRemoveAll(instance, 0); internalTestRemoveAll(instance, 3); internalTestRemoveAll(instance, 7); internalTestRemoveAll(instance, 17); internalTestRemoveAll(instance, 4 * TEST_BUFFER_SIZE); instance = new OverwritingCircularBuffer<>(17); internalTestRemoveAll(instance, 23); // absurd... instance = new OverwritingCircularBuffer<>(1); internalTestRemoveAll(instance, 17); } public void internalTestRemove(OverwritingCircularBuffer<Long> impl, int valueCount) { long bufferSize = impl.getBufferSize(); if(logger.isInfoEnabled()) { logger .info("Executing add-remove-reset test with valueCount={} and buffer.getBufferSize={}.", valueCount, bufferSize); } List<Long> values = new ArrayList<>(valueCount); for(int i = 0; i < valueCount; i++) { values.add((long) i); } if(logger.isInfoEnabled()) logger.info("Adding values: {}", values); impl.addAll(values); if(logger.isInfoEnabled()) logger.info("Buffer after adding: {}", impl); if(valueCount == 0) { assertTrue("Instance isn't empty!", impl.isEmpty()); } else { assertTrue("Instance is empty!", !impl.isEmpty()); } long expectedElementCount = valueCount; long expectedOverflowCount = 0; if(valueCount > bufferSize) { expectedElementCount = bufferSize; expectedOverflowCount = valueCount - bufferSize; assertTrue("Instance isn't full!", impl.isFull()); } else { assertTrue("Instance is full!", !impl.isFull()); } assertEquals("Available doesn't match!", expectedElementCount, impl.getAvailableElements()); long overflowCounter = instance.getOverflowCounter(); assertEquals("overflowCounter doesn't match!", expectedOverflowCount, overflowCounter); assertEquals("Size doesn't match!", valueCount, impl.getSize()); for(int i = 0; i < expectedElementCount; i++) { assertTrue("Instance is empty!", !impl.isEmpty()); assertEquals("Size doesn't match!", expectedElementCount - i, impl.getAvailableElements()); if(logger.isDebugEnabled()) { logger.debug("Size before removal of element #{}: {}", i, impl.getAvailableElements()); } Long removeValue = impl.removeFirst(); if(logger.isDebugEnabled()) { logger.debug("Size after removal of element #{}: {}", i, impl.getAvailableElements()); } if(logger.isInfoEnabled()) logger.info("Element #{}: removeValue={}", new Object[]{i, removeValue}); assertEquals("Unexpected value returned by remove!", (Long) (expectedOverflowCount + i), removeValue); assertTrue("Instance is full!", !impl.isFull()); assertEquals("Size doesn't match!", expectedElementCount - i - 1, impl.getAvailableElements()); } assertTrue("Instance isn't empty!", impl.isEmpty()); Long removeValue = impl.removeFirst(); if(logger.isInfoEnabled()) { logger.info("Element #{}: removeValue={}", new Object[]{expectedElementCount, removeValue}); } assertNull("Remove after last element returned a value: " + removeValue, removeValue); assertEquals("overflowCounter doesn't match!", expectedOverflowCount, impl.getOverflowCounter()); assertEquals("getSize doesn't match!", valueCount, impl.getSize()); impl.reset(); assertEquals("overflowCounter doesn't match!", 0, impl.getOverflowCounter()); assertEquals("getSize doesn't match!", 0, impl.getSize()); assertTrue("Instance isn't empty!", impl.isEmpty()); assertTrue("Instance is full!", !impl.isFull()); } public void internalTestRemoveAll(OverwritingCircularBuffer<Long> impl, int valueCount) { long bufferSize = impl.getBufferSize(); if(logger.isInfoEnabled()) { logger .info("Executing add-remove-reset test with valueCount={} and buffer.getBufferSize={}.", valueCount, bufferSize); } List<Long> values = new ArrayList<>(valueCount); for(int i = 0; i < valueCount; i++) { values.add((long) i); } if(logger.isInfoEnabled()) logger.info("Adding values: {}", values); impl.addAll(values); if(logger.isInfoEnabled()) logger.info("Buffer after adding: {}", impl); if(valueCount == 0) { assertTrue("Instance isn't empty!", impl.isEmpty()); } else { assertTrue("Instance is empty!", !impl.isEmpty()); } long expectedElementCount = valueCount; long expectedOverflowCount = 0; if(valueCount > bufferSize) { expectedElementCount = bufferSize; expectedOverflowCount = valueCount - bufferSize; assertTrue("Instance isn't full!", impl.isFull()); } else { assertTrue("Instance is full!", !impl.isFull()); } assertEquals("Size doesn't match!", expectedElementCount, impl.getAvailableElements()); assertEquals("overflowCounter doesn't match!", expectedOverflowCount, impl.getOverflowCounter()); assertEquals("getSize doesn't match!", valueCount, impl.getSize()); List<Long> removedList = impl.removeAll(); assertTrue("Instance isn't empty!", impl.isEmpty()); assertEquals("overflowCounter doesn't match!", expectedOverflowCount, impl.getOverflowCounter()); assertEquals("getSize doesn't match!", valueCount, impl.getSize()); for(int i = 0; i < expectedElementCount; i++) { Long removeValue = removedList.get(i); if(logger.isInfoEnabled()) logger.info("Element #{}: removeValue={}", new Object[]{i, removeValue}); assertEquals("Unexpected value returned by remove!", (Long) (expectedOverflowCount + i), removeValue); } impl.reset(); assertEquals("overflowCounter doesn't match!", 0, impl.getOverflowCounter()); assertEquals("getSize doesn't match!", 0, impl.getSize()); assertTrue("Instance isn't empty!", impl.isEmpty()); assertTrue("Instance is full!", !impl.isFull()); } }