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