1 package org.xerial.snappy.pool; 2 3 import static org.junit.Assert.assertEquals; 4 import static org.junit.Assert.assertNotEquals; 5 import static org.junit.Assert.assertNotNull; 6 import static org.junit.Assert.assertNotSame; 7 import static org.junit.Assert.assertNull; 8 import static org.junit.Assert.assertSame; 9 import static org.junit.Assert.assertTrue; 10 11 import java.lang.ref.Reference; 12 import java.lang.ref.WeakReference; 13 import java.nio.ByteBuffer; 14 import java.util.ArrayList; 15 import java.util.List; 16 17 import org.junit.Test; 18 19 20 public class CachingBufferPoolTest { 21 22 private static final int LIST_COUNT = 2048; 23 24 @Test testAdjustSize()25 public void testAdjustSize() { 26 assertEquals(4 * 1024, CachingBufferPool.adjustSize(2)); 27 assertEquals(4 * 1024, CachingBufferPool.adjustSize(1023)); 28 assertEquals(4 * 1024, CachingBufferPool.adjustSize(1024)); 29 assertEquals(4 * 1024, CachingBufferPool.adjustSize(1025)); 30 assertEquals(4 * 1024, CachingBufferPool.adjustSize(4 * 1024)); 31 assertEquals((4 + 2) * 1024, CachingBufferPool.adjustSize((4 * 1024) + 1)); 32 assertEquals(6 * 1024, CachingBufferPool.adjustSize(5 * 1024)); 33 assertEquals(6 * 1024, CachingBufferPool.adjustSize((5 * 1024) + 1)); 34 35 assertEquals(32 * 1024, CachingBufferPool.adjustSize(32 * 1024)); 36 assertEquals((32 + 16) * 1024, CachingBufferPool.adjustSize((32 * 1024) + 1)); 37 38 assertEquals(2 * 1024 * 1024, CachingBufferPool.adjustSize(2 * 1024 * 1024)); 39 assertEquals(((2 * 1024) + 512) * 1024, CachingBufferPool.adjustSize((2 * 1024 * 1024) + 1)); 40 41 assertEquals(16 * 1024 * 1024, CachingBufferPool.adjustSize(16 * 1024 * 1024)); 42 assertEquals((16 + 4) * 1024 * 1024, CachingBufferPool.adjustSize((16 * 1024 * 1024) + 1)); 43 44 assertEquals(128 * 1024 * 1024, CachingBufferPool.adjustSize(128 * 1024 * 1024)); 45 assertEquals((128 + 16) * 1024 * 1024, CachingBufferPool.adjustSize((128 * 1024 * 1024) + 1)); 46 47 assertEquals(512 * 1024 * 1024, CachingBufferPool.adjustSize(512 * 1024 * 1024)); 48 assertEquals((512 + 128) * 1024 * 1024, CachingBufferPool.adjustSize((512 * 1024 * 1024) + 1)); 49 assertEquals(0x6000_0000, CachingBufferPool.adjustSize(0x6000_0000)); 50 assertEquals(0x6000_0000, CachingBufferPool.adjustSize(0x6000_0000 - 1)); 51 assertEquals(Integer.MAX_VALUE, CachingBufferPool.adjustSize(0x6000_0001)); 52 assertEquals(Integer.MAX_VALUE, CachingBufferPool.adjustSize(Integer.MAX_VALUE)); 53 assertEquals(Integer.MAX_VALUE, CachingBufferPool.adjustSize(Integer.MAX_VALUE - 1)); 54 } 55 56 @Test testDirectByteBuffers()57 public void testDirectByteBuffers() throws Exception { 58 59 BufferPool pool = CachingBufferPool.getInstance(); 60 61 ByteBuffer bb1 = pool.allocateDirect(12 * 1024); 62 assertNotNull(bb1); 63 assertEquals(12 * 1024, bb1.limit()); 64 assertEquals(12 * 1024, bb1.capacity()); 65 assertEquals(0, bb1.position()); 66 67 ByteBuffer bb2 = pool.allocateDirect(12 * 1024); 68 assertNotNull(bb2); 69 assertEquals(12 * 1024, bb2.limit()); 70 assertEquals(12 * 1024, bb2.capacity()); 71 assertEquals(0, bb2.position()); 72 73 assertNotSame(bb1, bb2); 74 75 bb2.position(18); 76 pool.releaseDirect(bb2); 77 78 ByteBuffer bb3 = pool.allocateDirect(12 * 1024); 79 assertNotNull(bb3); 80 assertEquals(12 * 1024, bb3.limit()); 81 assertEquals(12 * 1024, bb3.capacity()); 82 assertEquals(0, bb3.position()); 83 84 assertNotSame(bb1, bb2); 85 assertSame(bb2, bb3); 86 87 pool.releaseDirect(bb1); 88 89 ByteBuffer bb4 = pool.allocateDirect((12 * 1024) - 1); 90 assertNotNull(bb4); 91 assertEquals(12 * 1024, bb4.limit()); 92 assertEquals(12 * 1024, bb4.capacity()); 93 assertEquals(0, bb4.position()); 94 95 assertSame(bb1, bb4); 96 } 97 98 @Test testArrays()99 public void testArrays() throws Exception { 100 101 BufferPool pool = CachingBufferPool.getInstance(); 102 103 byte[] bb1 = pool.allocateArray(12 * 1024); 104 assertNotNull(bb1); 105 assertEquals(12 * 1024, bb1.length); 106 107 byte[] bb2 = pool.allocateArray(12 * 1024); 108 assertNotNull(bb2); 109 assertEquals(12 * 1024, bb2.length); 110 111 assertNotSame(bb1, bb2); 112 113 pool.releaseArray(bb2); 114 115 byte[] bb3 = pool.allocateArray(12 * 1024); 116 assertNotNull(bb3); 117 assertEquals(12 * 1024, bb3.length); 118 119 assertNotSame(bb1, bb2); 120 assertSame(bb2, bb3); 121 122 pool.releaseArray(bb1); 123 124 byte[] bb4 = pool.allocateArray((12 * 1024) - 1); 125 assertNotNull(bb4); 126 assertEquals(12 * 1024, bb4.length); 127 128 assertSame(bb1, bb4); 129 } 130 131 @Test testSoftReferences()132 public void testSoftReferences() { 133 134 BufferPool pool = CachingBufferPool.getInstance(); 135 byte[] bb1 = pool.allocateArray(8 * 1024); 136 Reference<byte[]> ref = new WeakReference<byte[]>(bb1); 137 bb1[0] = 123; 138 bb1[8000] = -74; 139 int bb1HC = System.identityHashCode(bb1); 140 141 pool.releaseArray(bb1); 142 143 byte[] bb1_copy = pool.allocateArray(8 * 1024); 144 assertSame(bb1, bb1_copy); 145 assertEquals(123, bb1_copy[0]); 146 assertEquals(-74, bb1_copy[8000]); 147 assertEquals(bb1HC, System.identityHashCode(bb1_copy)); 148 149 //release back into pool (again) 150 pool.releaseArray(bb1); 151 152 //release strong references 153 bb1_copy = null; 154 bb1 = null; 155 assertNotNull(ref.get()); 156 157 //force an OOME to for SoftReferences to be collected 158 List<byte[]> vals = forceOOMEGC(LIST_COUNT); 159 assertTrue("count: " + vals.size(), vals.size() < LIST_COUNT); 160 161 //assert that our test reference has been cleared 162 assertNull(ref.get()); 163 164 //get another value from the pool 165 byte[] bb2 = pool.allocateArray(8 * 1024); 166 //assert that it is indeed a new value, and not same from previous 167 assertNotEquals(123, bb2[0]); 168 assertNotEquals(-74, bb2[8000]); 169 assertNotEquals(bb1HC, System.identityHashCode(bb2)); 170 } 171 forceOOMEGC(int count)172 private static List<byte[]> forceOOMEGC(int count) { 173 final List<byte[]> vals = new ArrayList<>(count); 174 175 try { 176 for (int i=0; i<count; ++i) { 177 vals.add(new byte[10 * 1024 * 1024]); 178 } 179 } catch(Error e) { 180 181 } 182 return vals; 183 } 184 } 185