/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * Created on Sep 8, 2010 */ package com.bigdata.io; import java.nio.ByteBuffer; import junit.framework.TestCase2; import com.bigdata.io.DirectBufferPoolAllocator.Allocation; import com.bigdata.io.DirectBufferPoolAllocator.IAllocation; import com.bigdata.io.DirectBufferPoolAllocator.IAllocationContext; /** * Test suite for {@link DirectBufferPoolAllocator}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestDirectBufferPoolAllocator extends TestCase2 { /** * */ public TestDirectBufferPoolAllocator() { } /** * @param name */ public TestDirectBufferPoolAllocator(String name) { super(name); } private final DirectBufferPool pool = DirectBufferPool.INSTANCE; @Override protected void tearDown() throws Exception { // Verify that all allocated buffers were released. DirectBufferPoolTestHelper.checkBufferPools(this); super.tearDown(); } /** * Opens and closes the allocator. */ public void test_close() { final DirectBufferPoolAllocator fixture = new DirectBufferPoolAllocator( pool); fixture.close(); } /** * Unit test verifies that {@link IAllocationContext}s created for different * keys are distinct. */ public void test_allocationContextsAreDistinct() { final DirectBufferPoolAllocator fixture = new DirectBufferPoolAllocator( pool); try { final Object key1 = "1"; final Object key2 = "2"; final IAllocationContext context1 = fixture .getAllocationContext(key1); assertNotNull(context1); final IAllocationContext context2 = fixture .getAllocationContext(key2); assertNotNull(context2); assertTrue(context1 != context2); } finally { fixture.close(); } } /** * Opens the allocator, creates an {@link IAllocationContext}, obtains an * {@link IAllocation} from that context, and then releases the * {@link IAllocationContext}. The test also verifies that the * {@link ByteBuffer} was released back to the {@link DirectBufferPool}. * * @throws InterruptedException */ public void test_allocateThenClose() throws InterruptedException { final DirectBufferPoolAllocator fixture = new DirectBufferPoolAllocator( pool); try { final Object key = getName(); final IAllocationContext context1 = fixture .getAllocationContext(key); /* * Note: We can not test the poolSize change because it may have * unallocated ByteBuffer's lying about which it can reuse without * allocating a new buffer. */ // final int poolSizeBefore = pool.getPoolSize(); final int maxSize = fixture.getMaxSlotSize(); // get a maximum size allocation. final IAllocation[] allocations = context1.alloc(maxSize); // assertEquals(poolSizeBefore + 1, pool.getPoolSize()); // should be a single allocation assertEquals(1, allocations.length); // the allocation. final IAllocation tmp = allocations[0]; // valid id. assertNotNull(tmp.getId()); // valid slice. { final ByteBuffer b = tmp.getSlice(); assertNotNull(b); assertEquals("position", 0, b.position()); assertEquals("limit", maxSize, b.limit()); assertEquals("capacity", maxSize, b.capacity()); assertTrue("isDirect", b.isDirect()); assertFalse("isReadOnly", b.isReadOnly()); } // release the allocation. context1.release(); /* * Note: while the buffer was released to the pool, the pool size * does not decrease so we can not check the post condition here. */ // assertEquals(poolSizeBefore, pool.getPoolSize()); try { tmp.getSlice(); fail("Expecting: " + IllegalStateException.class); } catch (IllegalStateException ex) { if (log.isInfoEnabled()) log.info("Ignoring expected exception: " + ex); } } finally { fixture.close(); } } // /** // * @todo Write a unit test to look for a memory leak in the backing // * {@link DirectBufferPool} as allocations are released from the // * {@link DirectBufferPoolAllocator}. However, not that the // * {@link DirectBufferPool} DOES NOT release buffers back to the JVM // * so the pool size will not decrease. Instead, what you have to do is // * look to see that alloc/free alloc/free patterns do not cause the // * #of allocated buffers on the {@link DirectBufferPool} to increase. // */ // public void test_memoryLeak() { // // fail("write test"); // // } /** * Unit tests for multiple allocations within the same. This verifies both * the the manner in which the position and limit are updated as we walk * through the buffer. * * @throws InterruptedException */ public void test_multipleBufferAllocation() throws InterruptedException { final DirectBufferPoolAllocator fixture = new DirectBufferPoolAllocator( pool); try { final IAllocationContext ctx = fixture.getAllocationContext("1"); final int allocSize = 10; final IAllocation[] a1 = ctx.alloc(allocSize); final IAllocation[] a2 = ctx.alloc(allocSize); assertEquals(1,a1.length); assertEquals(1,a2.length); assertEquals(allocSize,a1[0].getSlice().capacity()); assertEquals(allocSize,a2[0].getSlice().capacity()); final Allocation x0 = (Allocation)a1[0]; final Allocation x1 = (Allocation)a2[0]; // both allocations are slices onto the same backing buffer. assertTrue(x0.nativeBuffer == x1.nativeBuffer); // the position was advanced by the #of bytes allocated. assertEquals(allocSize * 2, x0.nativeBuffer.buffer().position()); // the limit on the native byte buffer has not been changed. assertEquals(x0.nativeBuffer.buffer().capacity(), x0.nativeBuffer.buffer().limit()); } finally { fixture.close(); } } // /** // * @todo write a unit test for // * {@link DirectBufferPoolAllocator#put(byte[], IAllocation[])}. // */ // public void test_put() { // fail("write tests"); // } }