package net.yadan.banana.memory.block; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import junit.framework.TestSuite; import net.yadan.banana.memory.IBlockAllocator; import net.yadan.banana.memory.MemInitializer; import net.yadan.banana.memory.OutOfMemoryException; import net.yadan.banana.memory.initializers.MemSetInitializer; import net.yadan.banana.memory.initializers.PrototypeInitializer; import org.junit.After; import org.junit.Test; public abstract class AbstractBlockAllocatorTest extends TestSuite { IBlockAllocator a; private IBlockAllocator create(int numBlocks, int blockSize) { return create(numBlocks, blockSize, 0, new MemSetInitializer(-1)); } public abstract IBlockAllocator create(int numBlocks, int blockSize, double growthFactor, MemInitializer initializer); @After public void postTest() { if (a != null) { assertEquals("Test leaks memory", 0, a.usedBlocks()); } a = null; } @Test public void testConstructor() { a = create(20, 10); assertEquals(20, a.maxBlocks()); assertEquals(10, a.blockSize()); } @Test public void testAllocationsAndFreeBlocks_1() { testAllocationsAndFreeBlocks(1); } @Test public void testAllocationsAndFreeBlocks_2() { testAllocationsAndFreeBlocks(2); } @Test public void testAllocationsAndFreeBlocks_10() { testAllocationsAndFreeBlocks(10); } public void testAllocationsAndFreeBlocks(int size) { IBlockAllocator a = create(3, size); assertEquals(3, a.freeBlocks()); a.malloc(); assertEquals(2, a.freeBlocks()); a.malloc(); assertEquals(1, a.freeBlocks()); a.malloc(); assertEquals(0, a.freeBlocks()); try { a.malloc(); fail("Did not throw an OutOfMemoryException"); } catch (OutOfMemoryException e) { } } @Test public void testFree() { a = create(2, 1); int p = a.malloc(); assertEquals(1, a.freeBlocks()); a.free(p); assertEquals(2, a.freeBlocks()); } @Test public void testSetGetInt() { a = create(3, 1); int p1 = a.malloc(); int p2 = a.malloc(); int p3 = a.malloc(); assertEquals(0, a.freeBlocks()); a.setInt(p1, 0, 1); a.setInt(p2, 0, 2); a.setInt(p3, 0, 3); assertEquals(1, a.getInt(p1, 0)); assertEquals(2, a.getInt(p2, 0)); assertEquals(3, a.getInt(p3, 0)); a.free(p1); a.free(p2); a.free(p3); } @Test public void testSetGetFloat() { a = create(3, 2); int p1 = a.malloc(); int p2 = a.malloc(); int p3 = a.malloc(); assertEquals(0, a.freeBlocks()); a.setFloat(p1, 0, 1); a.setFloat(p1, 1, 2); a.setFloat(p2, 0, Float.MIN_NORMAL); a.setFloat(p2, 1, Float.MAX_VALUE); a.setFloat(p3, 0, Float.NEGATIVE_INFINITY); a.setFloat(p3, 1, Float.POSITIVE_INFINITY); assertEquals(1, a.getFloat(p1, 0), Float.MIN_VALUE); assertEquals(2, a.getFloat(p1, 1), Float.MIN_VALUE); assertEquals(Float.MIN_NORMAL, a.getFloat(p2, 0), Float.MIN_VALUE); assertEquals(Float.MAX_VALUE, a.getFloat(p2, 1), Float.MIN_VALUE); assertEquals(Float.NEGATIVE_INFINITY, a.getFloat(p3, 0), Float.MIN_VALUE); assertEquals(Float.POSITIVE_INFINITY, a.getFloat(p3, 1), Float.MIN_VALUE); a.free(p1); a.free(p2); a.free(p3); } @Test public void testSetGetDouble() { a = create(3, 4); int p1 = a.malloc(); int p2 = a.malloc(); int p3 = a.malloc(); assertEquals(0, a.freeBlocks()); a.setDouble(p1, 0, 1); a.setDouble(p1, 2, 2); a.setDouble(p2, 0, Double.MIN_NORMAL); a.setDouble(p2, 2, Double.MAX_VALUE); a.setDouble(p3, 0, Double.NEGATIVE_INFINITY); a.setDouble(p3, 2, Double.POSITIVE_INFINITY); assertEquals(1, a.getDouble(p1, 0), Double.MIN_VALUE); assertEquals(2, a.getDouble(p1, 2), Double.MIN_VALUE); assertEquals(Double.MIN_NORMAL, a.getDouble(p2, 0), Double.MIN_VALUE); assertEquals(Double.MAX_VALUE, a.getDouble(p2, 2), Double.MIN_VALUE); assertEquals(Double.NEGATIVE_INFINITY, a.getDouble(p3, 0), Double.MIN_VALUE); assertEquals(Double.POSITIVE_INFINITY, a.getDouble(p3, 2), Double.MIN_VALUE); a.free(p1); a.free(p2); a.free(p3); } @Test public void testUpperShort() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, 0); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.setUpperShort(p, 0, 99); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(99, a.getUpperShort(p, 0)); a.free(p); } @Test public void testLowerShort() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, 0); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.setLowerShort(p, 0, 99); assertEquals(99, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.free(p); } @Test public void testUpperShortNeg() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, 0); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.setUpperShort(p, 0, -1); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(-1, a.getUpperShort(p, 0)); a.free(p); } @Test public void testLowerShortNeg() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, 0); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.setLowerShort(p, 0, -1); assertEquals(-1, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.free(p); } @Test public void testUpperShort_initialNeg() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, -1); assertEquals(-1, a.getLowerShort(p, 0)); assertEquals(-1, a.getUpperShort(p, 0)); a.setUpperShort(p, 0, 0); assertEquals(-1, a.getLowerShort(p, 0)); assertEquals(0, a.getUpperShort(p, 0)); a.free(p); } @Test public void testLowerShort_initialNeg() { a = create(3, 1); int p = a.malloc(); a.setInt(p, 0, -1); assertEquals(-1, a.getLowerShort(p, 0)); assertEquals(-1, a.getUpperShort(p, 0)); a.setLowerShort(p, 0, 0); assertEquals(0, a.getLowerShort(p, 0)); assertEquals(-1, a.getUpperShort(p, 0)); a.free(p); } @Test public void testCharsAccessFullBlock() { a = create(3, 2); int p = a.malloc(); char chars[] = new char[4]; char out[] = new char[4]; for (char a = 'a'; a - 'a' < 4; a++) { chars[a - 'a'] = a; } a.setChars(p, 0, chars, 0, 4); a.getChars(p, 0, out, 0, 4); assertArrayEquals(chars, out); a.free(p); } @Test public void testCharsSetPartialBlock() { a = create(3, 20); // new blocks will be initialized with -1 a.setInitializer(new MemSetInitializer(-1)); int p = a.malloc(); // 20 ints char chars[] = new char[20]; char out[] = new char[20]; for (char a = 'a'; a - 'a' < 20; a++) { chars[a - 'a'] = a; } a.setChars(p, 5, chars, 0, 20); a.getChars(p, 5, out, 0, 20); assertArrayEquals(chars, out); for (int i = 0; i < 5; i++) { assertEquals(-1, a.getInt(p, i)); } for (int i = 15; i < 20; i++) { assertEquals(-1, a.getInt(p, i)); } a.free(p); } @Test public void testCharsAccessFullBlock_even() { a = create(1, 2); // new blocks will be initialized with -1 a.setInitializer(new MemSetInitializer(-1)); // set 19 chars, last int should be partial int p = a.malloc(); int n = 3; char chars[] = new char[n]; char out[] = new char[n]; for (char a = 'a'; a - 'a' < n; a++) { chars[a - 'a'] = a; } a.setChars(p, 0, chars, 0, n); a.getChars(p, 0, out, 0, n); assertArrayEquals(chars, out); assertEquals(-1, a.getLowerShort(p, 1)); a.free(p); } @Test public void testLong() { a = create(10, 5); int p = a.malloc(); a.setLong(p, 0, Long.MAX_VALUE); assertEquals(Long.MAX_VALUE, a.getLong(p, 0)); a.free(p); } @Test public void testInitializer() { int[] prototype = new int[] { 1, 2, 3 }; a = create(5, 3, 0, new PrototypeInitializer(prototype)); for (int i = 0; i < 5; i++) { int n = a.malloc(); int[] data = new int[3]; a.getInts(n, 0, data, 0, 3); assertArrayEquals(prototype, data); a.free(n); } } @Test public void testGrowth() { a = create(2, 1, 2.0, null); int p1 = a.malloc(); int p2 = a.malloc(); a.setInt(p1, 0, 1); a.setInt(p2, 0, 2); assertEquals(2, a.maxBlocks()); assertEquals(2, a.usedBlocks()); assertEquals(0, a.freeBlocks()); int p3 = a.malloc(); // growth! a.setInt(p3, 0, 3); assertEquals(4, a.maxBlocks()); assertEquals(3, a.usedBlocks()); assertEquals(1, a.freeBlocks()); int p4 = a.malloc(); a.setInt(p4, 0, 4); assertEquals(4, a.maxBlocks()); assertEquals(4, a.usedBlocks()); assertEquals(0, a.freeBlocks()); a.free(p1); a.free(p2); a.free(p3); a.free(p4); } @Test public void testMemCopy_fullblock() { a = create(2, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] out = new int[5]; int p1 = a.malloc(); int p2 = a.malloc(); a.setInts(p1, 0, data, 0, a.blockSize()); a.memCopy(p1, 0, p2, 0, a.blockSize()); a.getInts(p2, 0, out, 0, a.blockSize()); assertArrayEquals(data, out); a.free(p1); a.free(p2); } @Test public void testMemCopy_same_offset() { a = create(2, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 0, 2, 3, 4, 5 }; int[] out = new int[5]; int p1 = a.malloc(); int p2 = a.malloc(); a.setInts(p1, 0, data, 0, a.blockSize()); a.memCopy(p1, 1, p2, 1, a.blockSize() - 1); a.getInts(p2, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.free(p1); a.free(p2); } @Test public void testMemCopy_diff_offset() { a = create(2, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 0, 1, 2, 3, 4 }; int[] out = new int[5]; int p1 = a.malloc(); int p2 = a.malloc(); a.setInts(p1, 0, data, 0, a.blockSize()); a.memCopy(p1, 0, p2, 1, a.blockSize() - 1); a.getInts(p2, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.free(p1); a.free(p2); } @Test public void testMemSet_fullblock() { a = create(2, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 9, 9, 9, 9, 9 }; int[] out = new int[5]; int p1 = a.malloc(); a.setInts(p1, 0, data, 0, a.blockSize()); a.memSet(p1, 0, 5, 9); a.getInts(p1, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.free(p1); } @Test public void testMemSet_partialBlock() { a = create(2, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 1, 9, 9, 9, 5 }; int[] out = new int[5]; int p1 = a.malloc(); a.setInts(p1, 0, data, 0, a.blockSize()); a.memSet(p1, 1, 3, 9); a.getInts(p1, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.free(p1); } @Test public void testInitialize() { int[] prototype = new int[] { 1, 2, 3 }; a = create(5, 3, 0, new PrototypeInitializer(prototype)); int p = a.malloc(); try { a.memSet(p, 0, 3, 0); int out[] = new int[3]; a.getInts(p, 0, out, 0, 3); assertArrayEquals(new int[] { 0, 0, 0 }, out); a.initialize(p); a.getInts(p, 0, out, 0, 3); assertArrayEquals(prototype, out); } finally { a.free(p); } } @Override public String toString() { return a.toString(); } @Test public void testMemCopy_fullblock_diffArrays() { a = create(8, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 1, 2, 3, 4, 5 }; int[] out = new int[5]; int a1_1 = a.malloc(); a.malloc(); a.malloc(); a.malloc(); int a2_1 = a.malloc(); a.setInts(a1_1, 0, data, 0, a.blockSize()); a.memCopy(a1_1, 0, a2_1, 0, a.blockSize()); a.getInts(a2_1, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.clear(); } @Test public void testMemCopy_same_offset_diffArrays() { a = create(8, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 0, 2, 3, 4, 5 }; int[] out = new int[5]; int a1_1 = a.malloc(); a.malloc(); a.malloc(); a.malloc(); int a2_1 = a.malloc(); a.setInts(a1_1, 0, data, 0, a.blockSize()); a.memCopy(a1_1, 1, a2_1, 1, a.blockSize() - 1); a.getInts(a2_1, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.clear(); } @Test public void testMemCopy_diff_offset_diffArrays() { a = create(8, 5, 0, null); int[] data = new int[] { 1, 2, 3, 4, 5 }; int[] expected = new int[] { 0, 1, 2, 3, 4 }; int[] out = new int[5]; int a1_1 = a.malloc(); a.malloc(); a.malloc(); a.malloc(); int a2_1 = a.malloc(); a.setInts(a1_1, 0, data, 0, a.blockSize()); a.memCopy(a1_1, 0, a2_1, 1, a.blockSize() - 1); a.getInts(a2_1, 0, out, 0, a.blockSize()); assertArrayEquals(expected, out); a.clear(); } }