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