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