/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander 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. * * muCommander 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/>. */ package com.mucommander.commons.io; import org.testng.annotations.Test; /** * This class is a TestNG test case for {@link BufferPool}. * * @author Maxence Bernard, Nicolas Rinaudo */ public class BufferPoolTest { public final static int TEST_BUFFER_SIZE_1 = 27; public final static int TEST_BUFFER_SIZE_2 = 28; public final static int TEST_MAX_POOL_SIZE = 1000; /** * Tests <code>BufferPool</code> with byte array (<code>byte[]</code>) buffers. * * <p>This method invokes {@link #testBuffer(com.mucommander.commons.io.BufferPool.BufferFactory)} with a * {@link BufferPool.ByteArrayFactory} instance.</p> */ @Test public void testByteArrayBuffer() { testBuffer(new BufferPool.ByteArrayFactory()); } /** * Tests <code>BufferPool</code> with char array (<code>char[]</code>) buffers. * * <p>This method invokes {@link #testBuffer(com.mucommander.commons.io.BufferPool.BufferFactory)} with a * {@link BufferPool.CharArrayFactory} instance.</p> */ @Test public void testCharArrayBuffer() { testBuffer(new BufferPool.CharArrayFactory()); } /** * Tests <code>BufferPool</code> with <code>ByteBuffer</code> buffers. * * <p>This method invokes {@link #testBuffer(com.mucommander.commons.io.BufferPool.BufferFactory)} with a * {@link BufferPool.ByteBufferFactory} instance.</p> */ @Test public void testByteBuffer() { testBuffer(new BufferPool.ByteBufferFactory()); } /** * Tests <code>BufferPool</code> with <code>CharBuffer</code> buffers. * * <p>This method invokes {@link #testBuffer(com.mucommander.commons.io.BufferPool.BufferFactory)} with a * {@link BufferPool.CharBufferFactory} instance.</p> */ @Test public void testCharBuffer() { testBuffer(new BufferPool.CharBufferFactory()); } /** * Tests <code>BufferPool</code> with <code>ByteBuffer</code> buffers. * * <p>This test assumes that no buffer with size=={@link #TEST_BUFFER_SIZE_1} or size=={@link #TEST_BUFFER_SIZE_2} * exist in the pool when the test starts. It also assumes that no other thread uses <code>BufferPool</code> while * the test is being performed. <code>BufferPool</code> will be left in the same state as it was right before the * test.</p> * * @param factory the factory corresponding to the kind of buffer to test */ public void testBuffer(BufferPool.BufferFactory factory) { // Number of array buffers before we started the test int originalBufferCount = BufferPool.getBufferCount(factory); long originalPoolSize = BufferPool.getPoolSize(); // Create a new buffer with size=TEST_BUFFER_SIZE_1 Object buffer1 = BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1); assertBufferSize(buffer1, factory, TEST_BUFFER_SIZE_1); // Create a new buffer with size=TEST_BUFFER_SIZE_1, assert that it is different from the first one Object buffer2 = BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1); assertBufferSize(buffer2, factory, TEST_BUFFER_SIZE_1); assert buffer2!=buffer1; // Create a new buffer with size=TEST_BUFFER_SIZE_2 Object buffer3 = BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_2); assertBufferSize(buffer3, factory, TEST_BUFFER_SIZE_2); // Assert that the number of buffers in the pool and the pool size in bytes haven't changed assertBufferCount(originalBufferCount, factory); assert originalPoolSize == BufferPool.getPoolSize(); // Assert that none of the buffers we created are in the pool assert !BufferPool.containsBuffer(buffer1, factory); assert !BufferPool.containsBuffer(buffer2, factory); assert !BufferPool.containsBuffer(buffer3, factory); // Assert that releasing buffer3 and requesting a buffer with size=TEST_BUFFER_SIZE_2 brings back buffer3 BufferPool.releaseBuffer(buffer3, factory); assertBufferCount(originalBufferCount+1, factory); assert BufferPool.containsBuffer(buffer3, factory); assert buffer3==BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_2); assertBufferCount(originalBufferCount, factory); assert !BufferPool.containsBuffer(buffer3, factory); // Release all buffer instances and assert that the buffer count grows accordingly Object[] buffers = new Object[]{buffer2, buffer3, buffer1}; for(int b=0; b<buffers.length; b++) { // Call releaseBuffer twice and assert that the buffer is added to the pool only the first time assert BufferPool.releaseBuffer(buffers[b], factory); assert BufferPool.containsBuffer(buffers[b], factory); assertBufferCount(originalBufferCount+(b+1), factory); assert !BufferPool.releaseBuffer(buffers[b], factory); assert BufferPool.containsBuffer(buffers[b], factory); assertBufferCount(originalBufferCount+(b+1), factory); } // Retrieve all the buffers we created to leave BufferPool as it was before the test // and assert that the buffer count diminishes accordingly buffers = new Object[]{buffer3, buffer1, buffer2}; for(int b=0; b<buffers.length; b++) { BufferPool.getBuffer(factory, getBufferLength(buffers[b], factory)); assertBufferCount(originalBufferCount+(3-b-1), factory); } // Test the initial default buffer size assert BufferPool.INITIAL_DEFAULT_BUFFER_SIZE == BufferPool.getDefaultBufferSize(); assertBufferSize(BufferPool.getBuffer(factory), factory, BufferPool.INITIAL_DEFAULT_BUFFER_SIZE); // Test a custom default buffer size BufferPool.setDefaultBufferSize(TEST_BUFFER_SIZE_1); assert TEST_BUFFER_SIZE_1 == BufferPool.getDefaultBufferSize(); assertBufferSize(BufferPool.getBuffer(factory), factory, TEST_BUFFER_SIZE_1); // Reset the default buffer size to the initial value BufferPool.setDefaultBufferSize(BufferPool.INITIAL_DEFAULT_BUFFER_SIZE); // Test max pool size: max out the pool and verify that releaseBuffer fails (returns false) when trying // to add an extra buffer assert BufferPool.INITIAL_POOL_LIMIT == BufferPool.getMaxPoolSize(); BufferPool.setMaxPoolSize(TEST_MAX_POOL_SIZE); assert TEST_MAX_POOL_SIZE == BufferPool.getMaxPoolSize(); long bufferSize = getBufferSize(BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1), factory); // in bytes int nbBuffers = (int)(TEST_MAX_POOL_SIZE/bufferSize); buffers = new Object[nbBuffers]; for(int i=0; i<nbBuffers; i++) buffers[i] = BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1); Object extraBuffer = BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1); assert originalPoolSize == BufferPool.getPoolSize(); long lastPoolSize = originalPoolSize; long newPoolSize; for(int i=0; i<nbBuffers; i++) { assert BufferPool.releaseBuffer(buffers[i], factory); newPoolSize = BufferPool.getPoolSize(); assert lastPoolSize+bufferSize == newPoolSize; lastPoolSize = newPoolSize; } // At this point, the BufferPool should be maxed out, try adding one more buffer and assert that this fails assert !BufferPool.releaseBuffer(extraBuffer, factory); // Retrieve all the buffers we created to leave BufferPool as it was before the test // and assert that the pool returns to its original size for(int i=0; i<nbBuffers; i++) BufferPool.getBuffer(factory, TEST_BUFFER_SIZE_1); assert originalPoolSize == BufferPool.getPoolSize(); BufferPool.setMaxPoolSize(BufferPool.INITIAL_POOL_LIMIT); } /** * Asserts that the given buffer's size matches the specified one. * * @param buffer the buffer to test * @param factory the factory that was used to create the buffer * @param expectedSize the expected buffer size */ private void assertBufferSize(Object buffer, BufferPool.BufferFactory factory, int expectedSize) { assert expectedSize == getBufferLength(buffer, factory); } /** * Returns the length of the given buffer, as defined by {@link com.mucommander.commons.io.BufferPool.BufferContainer#getLength()}. * * @param buffer the buffer for which to return the length * @param factory the factory that was used to create the buffer * @return the length of the given buffer */ private int getBufferLength(Object buffer, BufferPool.BufferFactory factory) { return factory.newBufferContainer(buffer).getLength(); } /** * Returns the size in bytes of the given buffer, as defined by {@link com.mucommander.commons.io.BufferPool.BufferContainer#getSize()}. * * @param buffer the buffer for which to return the size * @param factory the factory that was used to create the buffer * @return the size in bytes of the given buffer */ private int getBufferSize(Object buffer, BufferPool.BufferFactory factory) { return factory.newBufferContainer(buffer).getSize(); } /** * Asserts that BufferPool contains <code>expectedCount</code> buffers of the kind corresponding to the factory. * * @param expectedCount the expected number of buffers * @param factory the factory corresponding to the kind of buffer to count */ private void assertBufferCount(int expectedCount, BufferPool.BufferFactory factory) { assert expectedCount == BufferPool.getBufferCount(factory); } }