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