1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool2;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertThrows;
21 import static org.junit.jupiter.api.Assertions.assertTrue;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.NoSuchElementException;
26
27 import org.apache.commons.pool2.impl.GenericObjectPool;
28 import org.apache.commons.pool2.impl.SoftReferenceObjectPool;
29 import org.junit.jupiter.api.Test;
30
31
32
33
34 public abstract class AbstractTestObjectPool {
35
36 private static void clear(final MethodCallPoolableObjectFactory factory, final List<MethodCall> expectedMethods) {
37 factory.getMethodCalls().clear();
38 expectedMethods.clear();
39 }
40
41 static void removeDestroyObjectCall(final List<MethodCall> calls) {
42 calls.removeIf(call -> "destroyObject".equals(call.getName()));
43 }
44
45 private static void reset(final ObjectPool<Object> pool, final MethodCallPoolableObjectFactory factory, final List<MethodCall> expectedMethods) throws Exception {
46 pool.clear();
47 clear(factory, expectedMethods);
48 factory.reset();
49 }
50
51
52 private final Integer ZERO = Integer.valueOf(0);
53
54 private final Integer ONE = Integer.valueOf(1);
55
56
57
58
59
60
61
62
63
64
65
66
67
68 protected abstract <E extends Exception> ObjectPool<Object> makeEmptyPool(PooledObjectFactory<Object> factory) throws UnsupportedOperationException;
69
70 @Test
71 public void testClosedPoolBehavior() throws Exception {
72 final ObjectPool<Object> pool;
73 try {
74 pool = makeEmptyPool(new MethodCallPoolableObjectFactory());
75 } catch (final UnsupportedOperationException uoe) {
76 return;
77 }
78 final Object o1 = pool.borrowObject();
79 final Object o2 = pool.borrowObject();
80
81 pool.close();
82
83 assertThrows(IllegalStateException.class, pool::addObject, "A closed pool must throw an IllegalStateException when addObject is called.");
84
85 assertThrows(IllegalStateException.class, pool::borrowObject, "A closed pool must throw an IllegalStateException when borrowObject is called.");
86
87
88 if (pool.getNumIdle() >= 0) {
89 assertEquals(0, pool.getNumIdle(), "A closed pool shouldn't have any idle objects.");
90 }
91 if (pool.getNumActive() >= 0) {
92 assertEquals(2, pool.getNumActive(), "A closed pool should still keep count of active objects.");
93 }
94 pool.returnObject(o1);
95 if (pool.getNumIdle() >= 0) {
96 assertEquals(0, pool.getNumIdle(), "returnObject should not add items back into the idle object pool for a closed pool.");
97 }
98 if (pool.getNumActive() >= 0) {
99 assertEquals(1, pool.getNumActive(), "A closed pool should still keep count of active objects.");
100 }
101 pool.invalidateObject(o2);
102 if (pool.getNumIdle() >= 0) {
103 assertEquals(0, pool.getNumIdle(), "invalidateObject must not add items back into the idle object pool.");
104 }
105 if (pool.getNumActive() >= 0) {
106 assertEquals(0, pool.getNumActive(), "A closed pool should still keep count of active objects.");
107 }
108 pool.clear();
109 pool.close();
110 }
111
112 @Test
113 public void testPOFAddObjectUsage() throws Exception {
114 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
115 final ObjectPool<Object> pool;
116 try {
117 pool = makeEmptyPool(factory);
118 } catch (final UnsupportedOperationException uoe) {
119 return;
120 }
121 final List<MethodCall> expectedMethods = new ArrayList<>();
122
123 assertEquals(0, pool.getNumActive());
124 assertEquals(0, pool.getNumIdle());
125
126 pool.addObject();
127 assertEquals(0, pool.getNumActive());
128 assertEquals(1, pool.getNumIdle());
129 expectedMethods.add(new MethodCall("makeObject").returned(ZERO));
130
131 if (pool instanceof SoftReferenceObjectPool) {
132 expectedMethods.add(new MethodCall(
133 "validateObject", ZERO).returned(Boolean.TRUE));
134 }
135 expectedMethods.add(new MethodCall("passivateObject", ZERO));
136 assertEquals(expectedMethods, factory.getMethodCalls());
137
138
139 reset(pool, factory, expectedMethods);
140
141
142 factory.setMakeObjectFail(true);
143 assertThrows(PrivateException.class, pool::addObject, "Expected addObject to propagate makeObject exception.");
144 expectedMethods.add(new MethodCall("makeObject"));
145 assertEquals(expectedMethods, factory.getMethodCalls());
146
147 clear(factory, expectedMethods);
148
149
150 factory.setMakeObjectFail(false);
151 factory.setPassivateObjectFail(true);
152 assertThrows(PrivateException.class, pool::addObject, "Expected addObject to propagate passivateObject exception.");
153 expectedMethods.add(new MethodCall("makeObject").returned(ONE));
154
155 if (pool instanceof SoftReferenceObjectPool) {
156 expectedMethods.add(new MethodCall("validateObject", ONE).returned(Boolean.TRUE));
157 }
158 expectedMethods.add(new MethodCall("passivateObject", ONE));
159 assertEquals(expectedMethods, factory.getMethodCalls());
160 pool.close();
161 }
162
163 @Test
164 public void testPOFBorrowObjectUsages() throws Exception {
165 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
166 final ObjectPool<Object> pool;
167 try {
168 pool = makeEmptyPool(factory);
169 } catch (final UnsupportedOperationException uoe) {
170 return;
171 }
172 if (pool instanceof GenericObjectPool) {
173 ((GenericObjectPool<Object>) pool).setTestOnBorrow(true);
174 }
175 final List<MethodCall> expectedMethods = new ArrayList<>();
176 Object obj;
177
178
179
180
181 pool.addObject();
182 clear(factory, expectedMethods);
183 obj = pool.borrowObject();
184 expectedMethods.add(new MethodCall("activateObject", ZERO));
185 expectedMethods.add(new MethodCall("validateObject", ZERO).returned(Boolean.TRUE));
186 assertEquals(expectedMethods, factory.getMethodCalls());
187 pool.returnObject(obj);
188
189
190 reset(pool, factory, expectedMethods);
191
192
193 factory.setMakeObjectFail(true);
194 assertThrows(PrivateException.class, pool::borrowObject, "Expected borrowObject to propagate makeObject exception.");
195 expectedMethods.add(new MethodCall("makeObject"));
196 assertEquals(expectedMethods, factory.getMethodCalls());
197
198
199 reset(pool, factory, expectedMethods);
200 pool.addObject();
201 clear(factory, expectedMethods);
202
203 factory.setActivateObjectFail(true);
204 expectedMethods.add(new MethodCall("activateObject", obj));
205
206 assertThrows(NoSuchElementException.class, pool::borrowObject, "Expecting NoSuchElementException");
207
208 expectedMethods.add(new MethodCall("makeObject").returned(ONE));
209 expectedMethods.add(new MethodCall("activateObject", ONE));
210 removeDestroyObjectCall(factory.getMethodCalls());
211 assertEquals(expectedMethods, factory.getMethodCalls());
212
213
214 reset(pool, factory, expectedMethods);
215 pool.addObject();
216 clear(factory, expectedMethods);
217
218 factory.setValidateObjectFail(true);
219 expectedMethods.add(new MethodCall("activateObject", ZERO));
220 expectedMethods.add(new MethodCall("validateObject", ZERO));
221
222 assertThrows(NoSuchElementException.class, pool::borrowObject, "Expecting NoSuchElementException");
223
224
225 expectedMethods.add(new MethodCall("makeObject").returned(ONE));
226 expectedMethods.add(new MethodCall("activateObject", ONE));
227 expectedMethods.add(new MethodCall("validateObject", ONE));
228 removeDestroyObjectCall(factory.getMethodCalls());
229
230 assertTrue(factory.getMethodCalls().containsAll(expectedMethods));
231 pool.close();
232 }
233
234 @Test
235 public void testPOFClearUsages() throws Exception {
236 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
237 final ObjectPool<Object> pool;
238 try {
239 pool = makeEmptyPool(factory);
240 } catch (final UnsupportedOperationException uoe) {
241 return;
242 }
243 final List<MethodCall> expectedMethods = new ArrayList<>();
244
245
246 pool.addObjects(5);
247 pool.clear();
248
249
250 reset(pool, factory, expectedMethods);
251 factory.setDestroyObjectFail(true);
252 pool.addObjects(5);
253 pool.clear();
254 pool.close();
255 }
256
257 @Test
258 public void testPOFCloseUsages() throws Exception {
259 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
260 ObjectPool<Object> pool;
261 try {
262 pool = makeEmptyPool(factory);
263 } catch (final UnsupportedOperationException uoe) {
264 return;
265 }
266 final List<MethodCall> expectedMethods = new ArrayList<>();
267
268
269 pool.addObjects(5);
270 pool.close();
271
272
273 try {
274 pool = makeEmptyPool(factory);
275 } catch (final UnsupportedOperationException uoe) {
276 return;
277 }
278 reset(pool, factory, expectedMethods);
279 factory.setDestroyObjectFail(true);
280 pool.addObjects(5);
281 pool.close();
282 }
283
284 @Test
285 public void testPOFInvalidateObjectUsages() throws Exception {
286 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
287 final ObjectPool<Object> pool;
288 try {
289 pool = makeEmptyPool(factory);
290 } catch (final UnsupportedOperationException uoe) {
291 return;
292 }
293 final List<MethodCall> expectedMethods = new ArrayList<>();
294 Object obj;
295
296
297
298 obj = pool.borrowObject();
299 clear(factory, expectedMethods);
300
301
302 pool.invalidateObject(obj);
303 expectedMethods.add(new MethodCall("destroyObject", obj));
304 assertEquals(expectedMethods, factory.getMethodCalls());
305
306
307 reset(pool, factory, expectedMethods);
308 final Object obj2 = pool.borrowObject();
309 clear(factory, expectedMethods);
310 factory.setDestroyObjectFail(true);
311 assertThrows(PrivateException.class, () -> pool.invalidateObject(obj2));
312 Thread.sleep(250);
313 removeDestroyObjectCall(factory.getMethodCalls());
314 assertEquals(expectedMethods, factory.getMethodCalls());
315 pool.close();
316 }
317
318 @Test
319 public void testPOFReturnObjectUsages() throws Exception {
320 final MethodCallPoolableObjectFactory factory = new MethodCallPoolableObjectFactory();
321 final ObjectPool<Object> pool;
322 try {
323 pool = makeEmptyPool(factory);
324 } catch (final UnsupportedOperationException uoe) {
325 return;
326 }
327 final List<MethodCall> expectedMethods = new ArrayList<>();
328 Object obj;
329
330
331 obj = pool.borrowObject();
332 clear(factory, expectedMethods);
333
334
335 pool.returnObject(obj);
336
337 if (pool instanceof SoftReferenceObjectPool) {
338 expectedMethods.add(new MethodCall(
339 "validateObject", obj).returned(Boolean.TRUE));
340 }
341 expectedMethods.add(new MethodCall("passivateObject", obj));
342 assertEquals(expectedMethods, factory.getMethodCalls());
343
344
345 reset(pool, factory, expectedMethods);
346 pool.addObject();
347 pool.addObject();
348 pool.addObject();
349 assertEquals(3, pool.getNumIdle());
350
351 obj = pool.borrowObject();
352 pool.borrowObject();
353 assertEquals(1, pool.getNumIdle());
354 assertEquals(2, pool.getNumActive());
355 clear(factory, expectedMethods);
356 factory.setPassivateObjectFail(true);
357 pool.returnObject(obj);
358
359 if (pool instanceof SoftReferenceObjectPool) {
360 expectedMethods.add(new MethodCall("validateObject", obj).returned(Boolean.TRUE));
361 }
362 expectedMethods.add(new MethodCall("passivateObject", obj));
363 removeDestroyObjectCall(factory.getMethodCalls());
364 assertEquals(expectedMethods, factory.getMethodCalls());
365 assertEquals(1, pool.getNumIdle());
366 assertEquals(1, pool.getNumActive());
367
368
369 reset(pool, factory, expectedMethods);
370 obj = pool.borrowObject();
371 clear(factory, expectedMethods);
372 factory.setPassivateObjectFail(true);
373 factory.setDestroyObjectFail(true);
374 pool.returnObject(obj);
375 pool.close();
376 }
377
378 @Test
379 public void testToString() {
380 final ObjectPool<Object> pool;
381 try {
382 pool = makeEmptyPool(new MethodCallPoolableObjectFactory());
383 } catch (final UnsupportedOperationException uoe) {
384 return;
385 }
386 pool.toString();
387 pool.close();
388 }
389 }