dedc70251e5a87a2c681fd12c5d1563726d4e29b
[appc.git] / appc-common / src / test / java / org / openecomp / appc / pool / PoolTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright (C) 2017 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
21  */
22
23
24
25 package org.openecomp.appc.pool;
26
27 import static org.junit.Assert.assertEquals;
28 import static org.junit.Assert.assertFalse;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertNull;
31 import static org.junit.Assert.assertTrue;
32
33 import java.io.IOException;
34 import java.lang.reflect.InvocationTargetException;
35 import java.lang.reflect.Method;
36 import java.lang.reflect.Proxy;
37
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.openecomp.appc.pool.Allocator;
41 import org.openecomp.appc.pool.Destructor;
42 import org.openecomp.appc.pool.Pool;
43 import org.openecomp.appc.pool.PoolDrainedException;
44 import org.openecomp.appc.pool.PoolExtensionException;
45 import org.openecomp.appc.pool.PoolSpecificationException;
46 import org.openecomp.appc.pool.*;
47
48
49 public class PoolTest implements Allocator<Testable>, Destructor<Testable> {
50
51     private Pool<Testable> pool;
52     private static final int MIN = 10;
53     private static final int MAX = 100;
54     private int index = 0;
55     private int destroyCount = 0;
56
57     /**
58      * Set up the test by allocating a pool with MIN-MAX size (bounded pool)
59      *
60      * @throws PoolSpecificationException
61      *             If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
62      */
63     @Before
64     public void setup() throws PoolSpecificationException {
65         pool = new Pool<>(MIN, MAX);
66         index = 0;
67         destroyCount = 0;
68     }
69
70     /**
71      * Test that trying to construct a pool with a bad minimum throws an exception
72      *
73      * @throws PoolSpecificationException
74      *             If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
75      */
76     @Test(expected = PoolSpecificationException.class)
77     public void testInvalidMinSize() throws PoolSpecificationException {
78         pool = new Pool<>(-1, MAX);
79     }
80
81     /**
82      * Test that trying to construct a pool with a bad maximum throws an exception
83      *
84      * @throws PoolSpecificationException
85      *             If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
86      */
87     @Test(expected = PoolSpecificationException.class)
88     public void testInvalidMaxSize() throws PoolSpecificationException {
89         pool = new Pool<>(MIN, -1);
90     }
91
92     /**
93      * Test creation of a pool where max is less than min fails
94      *
95      * @throws PoolSpecificationException
96      *             If the minimum size is less than 0, or if the max size is non-zero and less than the min size.
97      */
98     @Test(expected = PoolSpecificationException.class)
99     public void testInvalidSizeRange() throws PoolSpecificationException {
100         pool = new Pool<>(MAX, MIN);
101     }
102
103     /**
104      * Test state
105      */
106     @Test
107     public void testMinPool() {
108         assertEquals(MIN, pool.getMinPool());
109     }
110
111     /**
112      * Test state
113      */
114     @Test
115     public void testMaxPool() {
116         assertEquals(MAX, pool.getMaxPool());
117     }
118
119     /**
120      * Test state
121      */
122     @Test
123     public void testAllocator() {
124         assertNull(pool.getAllocator());
125         pool.setAllocator(this);
126         assertNotNull(pool.getAllocator());
127     }
128
129     /**
130      * Test state
131      */
132     @Test
133     public void testDestructor() {
134         assertNull(pool.getDestructor());
135         pool.setDestructor(this);
136         assertNotNull(pool.getDestructor());
137     }
138
139     /**
140      * Test that we can allocate and release elements and that the pool maintains them in MRU order
141      *
142      * @throws PoolExtensionException
143      *             If the pool cannot be extended
144      * @throws PoolDrainedException
145      *             If the caller is trying to reserve an element from a drained pool
146      */
147     @Test
148     public void testAllocateAndRelease() throws PoolExtensionException, PoolDrainedException {
149         pool.setAllocator(this);
150
151         assertFalse(pool.isDrained());
152
153         /*
154          * Allocate three elements
155          */
156         Testable value1 = pool.reserve();
157         assertNotNull(value1);
158         assertEquals(Integer.valueOf(MIN - 1), value1.getId());
159         assertEquals(1, pool.getAllocatedSize());
160         assertEquals(MIN - 1, pool.getFreeSize());
161         assertEquals(1, pool.getAllocatedSize());
162
163         Testable value2 = pool.reserve();
164         assertNotNull(value2);
165         assertEquals(Integer.valueOf(MIN - 2), value2.getId());
166         assertEquals(2, pool.getAllocatedSize());
167         assertEquals(MIN - 2, pool.getFreeSize());
168         assertEquals(2, pool.getAllocatedSize());
169
170         Testable value3 = pool.reserve();
171         assertNotNull(value3);
172         assertEquals(Integer.valueOf(MIN - 3), value3.getId());
173         assertEquals(3, pool.getAllocatedSize());
174         assertEquals(MIN - 3, pool.getFreeSize());
175         assertEquals(3, pool.getAllocatedSize());
176
177         /*
178          * Now, release them in the order obtained
179          */
180         pool.release(value1);
181         pool.release(value2);
182         pool.release(value3);
183
184         assertEquals(0, pool.getAllocatedSize());
185         assertEquals(MIN, pool.getFreeSize());
186
187         /*
188          * Now, allocate them again, but their values should be reversed (3, 2, 1) representing the most recently used
189          * to the least recently used.
190          */
191         value1 = pool.reserve();
192         assertNotNull(value1);
193         assertEquals(Integer.valueOf(MIN - 3), value1.getId());
194
195         value2 = pool.reserve();
196         assertNotNull(value2);
197         assertEquals(Integer.valueOf(MIN - 2), value2.getId());
198
199         value3 = pool.reserve();
200         assertNotNull(value3);
201         assertEquals(Integer.valueOf(MIN - 1), value3.getId());
202     }
203
204     /**
205      * Test that we can trim the pool to a desired size
206      *
207      * @throws PoolExtensionException
208      *             If the pool cannot be extended
209      * @throws NoSuchMethodException
210      *             if a matching method is not found.
211      * @throws SecurityException
212      *             if the request is denied.
213      * @throws IllegalAccessException
214      *             if this Method object is enforcing Java language access control and the underlying method is
215      *             inaccessible.
216      * @throws IllegalArgumentException
217      *             if the method is an instance method and the specified object argument is not an instance of the class
218      *             or interface declaring the underlying method (or of a subclass or implementor thereof); if the number
219      *             of actual and formal parameters differ; if an unwrapping conversion for primitive arguments fails; or
220      *             if, after possible unwrapping, a parameter value cannot be converted to the corresponding formal
221      *             parameter type by a method invocation conversion.
222      * @throws InvocationTargetException
223      *             if the underlying method throws an exception.
224      * @throws PoolDrainedException
225      *             If the caller is trying to reserve an element from a drained pool
226      */
227     @SuppressWarnings("nls")
228     @Test
229     public void testTrim() throws PoolExtensionException, NoSuchMethodException, SecurityException,
230         IllegalAccessException, IllegalArgumentException, InvocationTargetException, PoolDrainedException {
231         pool.setAllocator(this);
232         int SIZE = 50;
233         Proxy[] array = new Proxy[SIZE];
234
235         assertEquals(0, pool.getAllocatedSize());
236         for (int i = 0; i < SIZE; i++) {
237             array[i] = (Proxy) pool.reserve();
238         }
239         assertEquals(SIZE, pool.getAllocatedSize());
240
241         for (int i = 0; i < SIZE; i++) {
242             pool.release((Testable) array[i]);
243         }
244         assertEquals(0, pool.getAllocatedSize());
245
246         assertEquals(SIZE, pool.getFreeSize());
247
248         Method trimMethod = Pool.class.getDeclaredMethod("trim", new Class[] {
249             Integer.TYPE
250         });
251         trimMethod.setAccessible(true);
252         trimMethod.invoke(pool, new Object[] {
253             SIZE - MIN
254         });
255
256         assertEquals(MIN, pool.getFreeSize());
257     }
258
259     /**
260      * Test that we can drain a pool containing a mix of free and allocated elements
261      *
262      * @throws PoolExtensionException
263      *             If the pool cannot be extended
264      * @throws PoolDrainedException
265      *             If the caller is trying to reserve an element from a drained pool
266      */
267     @Test
268     public void testDrain() throws PoolExtensionException, PoolDrainedException {
269         int SIZE = 50;
270         int FREE = 20;
271         int ALLOC = SIZE - FREE;
272
273         Proxy[] array = new Proxy[SIZE];
274         pool.setAllocator(this);
275         pool.setDestructor(this);
276
277         assertFalse(pool.isDrained());
278
279         assertEquals(0, pool.getAllocatedSize());
280         for (int i = 0; i < SIZE; i++) {
281             array[i] = (Proxy) pool.reserve();
282         }
283         assertEquals(SIZE, pool.getAllocatedSize());
284
285         for (int i = 0; i < FREE; i++) {
286             pool.release((Testable) array[i]);
287         }
288         assertEquals(ALLOC, pool.getAllocatedSize());
289         assertEquals(FREE, pool.getFreeSize());
290
291         pool.drain();
292         assertEquals(0, pool.getFreeSize());
293         assertEquals(0, pool.getAllocatedSize());
294         assertTrue(pool.isDrained());
295
296         assertEquals(SIZE, destroyCount);
297     }
298
299     /**
300      * @see org.openecomp.appc.pool.Destructor#destroy(java.io.Closeable, org.openecomp.appc.pool.Pool)
301      */
302     @Override
303     public void destroy(Testable obj, Pool<Testable> pool) {
304         destroyCount++;
305         try {
306             obj.close();
307         } catch (IOException e) {
308             e.printStackTrace();
309         }
310     }
311
312     /**
313      * @see org.openecomp.appc.pool.Allocator#allocate(org.openecomp.appc.pool.Pool)
314      */
315     @Override
316     public Testable allocate(Pool<Testable> pool) {
317         Testable e = new Element(index++);
318
319         return e;
320     }
321 }