package net.yadan.banana.map; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import net.yadan.banana.DebugLevel; import net.yadan.banana.memory.Buffer; import net.yadan.banana.memory.IBuffer; import net.yadan.banana.memory.IMemAllocator; import net.yadan.banana.memory.OutOfMemoryException; import net.yadan.banana.memory.initializers.MemSetInitializer; import net.yadan.banana.memory.malloc.ChainedAllocator; import org.junit.Test; public class VarKeyHashMapTest { private static final String PREFIX = "hello "; private static final int BLOCK_SIZE = 10; protected IVarKeyHashMap create(int initialCapacity, double loadFactor) { IMemAllocator valuesAllocator = new ChainedAllocator(100, VarKeyHashMap.RESERVED_SIZE + BLOCK_SIZE, 2.0); IMemAllocator keysAllocator = new ChainedAllocator(100, BLOCK_SIZE, 2.0); valuesAllocator.setDebug(true); valuesAllocator.setInitializer(new MemSetInitializer(-1)); keysAllocator.setDebug(true); keysAllocator.setInitializer(new MemSetInitializer(-1)); IVarKeyHashMap map = new VarKeyHashMap(valuesAllocator, keysAllocator, initialCapacity, loadFactor); map.setDebug(DebugLevel.DEBUG_STRUCTURE); return map; } @Test public void testHashMapIntFloat() { IVarKeyHashMap h = create(10, 0.75f); assertEquals(10, h.getCapacity()); assertEquals(0.75f, h.getLoadFactor(), Float.MIN_VALUE); } @Test public void testSizeAfterAdd() { IVarKeyHashMap h = create(20, 1.0); IBuffer key = new Buffer(10); for (int i = 1; i <= 20; i++) { key.appendChars((PREFIX + i).toCharArray()); h.createRecord(key, BLOCK_SIZE); assertEquals(i, h.size()); key.reset(); } } @Test public void testSizeAfterRemove() { IBuffer key = new Buffer(10); IVarKeyHashMap h = create(20, 1.0); for (int i = 1; i <= 20; i++) { key.appendChars((PREFIX + i).toCharArray()); h.createRecord(key, BLOCK_SIZE); key.reset(); } assertEquals(20, h.size()); for (int i = 1; i <= 20; i++) { key.appendChars((PREFIX + i).toCharArray()); h.remove(key); assertEquals(20 - i, h.size()); key.reset(); } } @Test public void testPutRecord() { IBuffer key = new Buffer(10); IBuffer key2 = new Buffer(10); IVarKeyHashMap h = create(10, 0.75f); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); key2.appendChars((PREFIX + 100).toCharArray()); assertEquals(-1, h.findRecord(key2)); assertEquals(pointer, h.findRecord(key)); } @Test public void testPutRecordWithSameKey() { IVarKeyHashMap h = create(10, 0.75f); IMemAllocator keys = h.keysMemory(); IMemAllocator values = h.valueMemory(); values.setInitializer(new MemSetInitializer(0)); assertEquals(0, keys.usedBlocks()); assertEquals(0, values.usedBlocks()); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer1 = h.createRecord(key, BLOCK_SIZE); assertEquals(pointer1, h.findRecord(key)); assertEquals(1, keys.usedBlocks()); assertEquals(1, values.usedBlocks()); h.setInt(pointer1, 0, 19); int pointer2 = h.createRecord(key, BLOCK_SIZE); assertEquals(0, h.getInt(pointer2, 0)); assertEquals(1, keys.usedBlocks()); assertEquals(1, values.usedBlocks()); h.setInt(pointer2, 0, 29); assertEquals(pointer2, h.findRecord(key)); assertEquals(1, keys.usedBlocks()); assertEquals(1, h.size()); } @Test public void testIsEmpty() { IBuffer key = new Buffer(10); key.appendChars((PREFIX + 10).toCharArray()); IVarKeyHashMap h = create(10, 0.75f); assertTrue(h.isEmpty()); h.createRecord(key, BLOCK_SIZE); assertFalse(h.isEmpty()); } @Test public void testContainsKey() { IBuffer key = new Buffer(10); key.appendChars((PREFIX + 100).toCharArray()); IVarKeyHashMap h = create(10, 0.75f); assertFalse(h.containsKey(key)); h.createRecord(key, BLOCK_SIZE); assertTrue(h.containsKey(key)); } @Test public void testLongData() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); h.setLong(pointer, 0, Long.MAX_VALUE); assertEquals(Long.MAX_VALUE, h.getLong(pointer, 0)); h.setLong(pointer, 0, 800); assertEquals(800, h.getLong(pointer, 0)); } @Test public void testIntData() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); h.setInt(pointer, 0, Integer.MAX_VALUE); assertEquals(Integer.MAX_VALUE, h.getInt(pointer, 0)); h.setInt(pointer, 1, 800); assertEquals(800, h.getInt(pointer, 1)); } @Test public void testFloatData() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); h.setFloat(pointer, 0, Integer.MAX_VALUE); assertEquals(Integer.MAX_VALUE, h.getFloat(pointer, 0), Float.MIN_VALUE); h.setInt(pointer, 1, 800); assertEquals(800, h.getInt(pointer, 1)); } @Test public void testDoubleData() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); h.setDouble(pointer, 0, 9999); assertEquals(9999, h.getDouble(pointer, 0), Double.MIN_VALUE); h.setDouble(pointer, 2, 800); assertEquals(800, h.getDouble(pointer, 2), Double.MIN_VALUE); } @Test public void testRemove() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); key.appendChars((PREFIX + 1000).toCharArray()); int pointer = h.createRecord(key, BLOCK_SIZE); assertEquals(pointer, h.findRecord(key)); assertEquals(1, h.size()); h.remove(key); assertEquals(0, h.size()); } @Test public void testClear() { IVarKeyHashMap h = create(10, 0.75f); IBuffer key = new Buffer(10); assertEquals(0, h.size()); for (int i = 1; i <= 20; i++) { key.appendChars((PREFIX + i).toCharArray()); h.createRecord(key, BLOCK_SIZE); key.reset(); } h.clear(); assertEquals(0, h.size()); } @Test public void testHashKeyOverflow() { IVarKeyHashMap h = create(100000, 0.75f); IBuffer key = new Buffer(20); key.appendChars("1234567890123456789012345678901234567890".toCharArray()); h.createRecord(key, BLOCK_SIZE); } @Test public void testGrowth() { IVarKeyHashMap h = create(10, 0.5); IBuffer key = new Buffer(10); for (int i = 0; i < 5; i++) { key.appendChars((PREFIX + (i * i * i)).toCharArray()); int n = h.createRecord(key, BLOCK_SIZE); h.setInt(n, 0, i); key.reset(); } key.appendChars((PREFIX + (5 * 5 * 5)).toCharArray()); int n = h.createRecord(key, BLOCK_SIZE); h.setInt(n, 0, 5); key.reset(); assertEquals(6, h.size()); for (int i = 0; i < h.size(); i++) { key.appendChars((PREFIX + (i * i * i)).toCharArray()); assertEquals(i, h.getInt(h.findRecord(key), 0)); key.reset(); } } @Test public void testOutOfMemory() { IMemAllocator valuesAllocator = new ChainedAllocator(5, VarKeyHashMap.RESERVED_SIZE + BLOCK_SIZE, 0); IMemAllocator keysAllocator = new ChainedAllocator(5, BLOCK_SIZE, 0); valuesAllocator.setDebug(true); valuesAllocator.setInitializer(new MemSetInitializer(-1)); keysAllocator.setDebug(true); keysAllocator.setInitializer(new MemSetInitializer(-1)); IVarKeyHashMap h = new VarKeyHashMap(keysAllocator, valuesAllocator, 10, 1); IBuffer key = new Buffer(5 * BLOCK_SIZE); for (int i = 0; i < key.capacity(); i++) { key.appendInt(i); } IBuffer value = new Buffer(5 * BLOCK_SIZE); value.setUsed(5 * BLOCK_SIZE); try { h.createRecord(key, value); fail(); } catch (OutOfMemoryException e) { } assertEquals(0, valuesAllocator.usedBlocks()); assertEquals(0, keysAllocator.usedBlocks()); } @Test public void testReallocRecord() { IBuffer key = new Buffer(5 * BLOCK_SIZE); IVarKeyHashMap h = create(10, 0.8); for (int i = 0; i < 10; i++) { key.appendInt(i * i); int r = h.createRecord(key, 1); // System.out.println(h.valueMemory().pointerDebugString(r)); h.setInt(r, 0, i); key.reset(); } for (int i = 0; i < 10; i++) { key.appendInt(i * i); int r = h.reallocRecord(key, 15); h.setInt(r, 10, i); // System.out.println(h.valueMemory().pointerDebugString(r)); key.reset(); } } @Test public void testFindMissingVarKey() { IBuffer key = new Buffer(10); IBuffer key2 = new Buffer(20); key.appendChars((PREFIX + 100).toCharArray()); key2.setUsed(15); IVarKeyHashMap h = create(10, 0.75f); assertFalse(h.containsKey(key)); h.createRecord(key, BLOCK_SIZE); assertTrue(h.containsKey(key)); assertEquals(-1, h.findRecord(key2)); } @Test public void testCreateSameRecordDifferentSize() { IVarKeyHashMap h = create(10, 0.8); IBuffer key = new Buffer(10); key.appendInts(new int[]{1,2,3}); h.createRecord(key, BLOCK_SIZE); int size = BLOCK_SIZE * 2; int r = h.createRecord(key, size); h.setInts(r, 0, new int[size], 0, size); } @Test public void testGetKeyData() { final IVarKeyHashMap h = create(10, 0.8); final IBuffer key = new Buffer(10); key.appendInts(new int[]{1,2,3}); h.createRecord(key, BLOCK_SIZE); h.visitRecords(new VarKeyHashMapVisitorAdapter() { @Override public void visit(IVarKeyHashMap map, int keyPtr, int valuePtr, long num, long total) { IBuffer out = new Buffer(1); h.getKeyData(keyPtr, out); assertEquals(key, out); } }); } }