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