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
21 import java.util.List;
22 import java.util.ArrayList;
23 import java.util.NoSuchElementException;
24
25 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
26 import org.apache.commons.pool.impl.StackKeyedObjectPool;
27
28 /***
29 * Abstract {@link TestCase} for {@link ObjectPool} implementations.
30 * @author Rodney Waldhoff
31 * @author Sandy McArthur
32 * @version $Revision: 607154 $ $Date: 2007-12-27 18:37:53 -0700 (Thu, 27 Dec 2007) $
33 */
34 public abstract class TestKeyedObjectPool extends TestCase {
35 public TestKeyedObjectPool(String testName) {
36 super(testName);
37 }
38
39 /***
40 * Create an <code>KeyedObjectPool</code> with the specified factory.
41 * The pool should be in a default configuration and conform to the expected
42 * behaviors described in {@link KeyedObjectPool}.
43 * Generally speaking there should be no limits on the various object counts.
44 */
45 protected abstract KeyedObjectPool makeEmptyPool(KeyedPoolableObjectFactory factory);
46
47 protected final String KEY = "key";
48
49 public void testClosedPoolBehavior() throws Exception {
50 final KeyedObjectPool pool;
51 try {
52 pool = makeEmptyPool(new BaseKeyedPoolableObjectFactory() {
53 public Object makeObject(final Object key) throws Exception {
54 return new Object();
55 }
56 });
57 } catch(UnsupportedOperationException uoe) {
58 return;
59 }
60
61 Object o1 = pool.borrowObject(KEY);
62 Object o2 = pool.borrowObject(KEY);
63
64 pool.close();
65
66 try {
67 pool.addObject(KEY);
68 fail("A closed pool must throw an IllegalStateException when addObject is called.");
69 } catch (IllegalStateException ise) {
70
71 }
72
73 try {
74 pool.borrowObject(KEY);
75 fail("A closed pool must throw an IllegalStateException when borrowObject is called.");
76 } catch (IllegalStateException ise) {
77
78 }
79
80
81 assertEquals("A closed pool shouldn't have any idle objects.", 0, pool.getNumIdle(KEY));
82 assertEquals("A closed pool shouldn't have any idle objects.", 0, pool.getNumIdle());
83 pool.getNumActive();
84 pool.getNumActive(KEY);
85 pool.returnObject(KEY, o1);
86 assertEquals("returnObject should not add items back into the idle object pool for a closed pool.", 0, pool.getNumIdle(KEY));
87 assertEquals("returnObject should not add items back into the idle object pool for a closed pool.", 0, pool.getNumIdle());
88 pool.invalidateObject(KEY, o2);
89 pool.clear(KEY);
90 pool.clear();
91 pool.close();
92 }
93
94 private final Integer ZERO = new Integer(0);
95 private final Integer ONE = new Integer(1);
96
97 public void testKPOFAddObjectUsage() throws Exception {
98 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
99 final KeyedObjectPool pool;
100 try {
101 pool = makeEmptyPool(factory);
102 } catch(UnsupportedOperationException uoe) {
103 return;
104 }
105 final List expectedMethods = new ArrayList();
106
107
108 pool.addObject(KEY);
109 expectedMethods.add(new MethodCall("makeObject", KEY).returned(ZERO));
110 if (pool instanceof StackKeyedObjectPool) {
111 expectedMethods.add(new MethodCall(
112 "validateObject", KEY, ZERO).returned(Boolean.TRUE));
113 }
114 expectedMethods.add(new MethodCall("passivateObject", KEY, ZERO));
115 assertEquals(expectedMethods, factory.getMethodCalls());
116
117
118 reset(pool, factory, expectedMethods);
119
120
121 factory.setMakeObjectFail(true);
122 try {
123 pool.addObject(KEY);
124 fail("Expected addObject to propagate makeObject exception.");
125 } catch (PrivateException pe) {
126
127 }
128 expectedMethods.add(new MethodCall("makeObject", KEY));
129 assertEquals(expectedMethods, factory.getMethodCalls());
130
131 clear(factory, expectedMethods);
132
133
134 factory.setMakeObjectFail(false);
135 factory.setPassivateObjectFail(true);
136 try {
137 pool.addObject(KEY);
138 fail("Expected addObject to propagate passivateObject exception.");
139 } catch (PrivateException pe) {
140
141 }
142 expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE));
143 if (pool instanceof StackKeyedObjectPool) {
144 expectedMethods.add(new MethodCall(
145 "validateObject", KEY, ONE).returned(Boolean.TRUE));
146 }
147 expectedMethods.add(new MethodCall("passivateObject", KEY, ONE));
148 assertEquals(expectedMethods, factory.getMethodCalls());
149 }
150
151 public void testKPOFBorrowObjectUsages() throws Exception {
152 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
153 final KeyedObjectPool pool;
154 try {
155 pool = makeEmptyPool(factory);
156 } catch(UnsupportedOperationException uoe) {
157 return;
158 }
159 final List expectedMethods = new ArrayList();
160 Object obj;
161
162 if (pool instanceof GenericKeyedObjectPool) {
163 ((GenericKeyedObjectPool) pool).setTestOnBorrow(true);
164 }
165
166
167
168
169 pool.addObject(KEY);
170 clear(factory, expectedMethods);
171 obj = pool.borrowObject(KEY);
172 expectedMethods.add(new MethodCall("activateObject", KEY, ZERO));
173 expectedMethods.add(new MethodCall("validateObject", KEY, ZERO).returned(Boolean.TRUE));
174 assertEquals(expectedMethods, factory.getMethodCalls());
175 pool.returnObject(KEY, obj);
176
177
178 reset(pool, factory, expectedMethods);
179
180
181 factory.setMakeObjectFail(true);
182 try {
183 obj = pool.borrowObject(KEY);
184 fail("Expected borrowObject to propagate makeObject exception.");
185 } catch (PrivateException pe) {
186
187 }
188 expectedMethods.add(new MethodCall("makeObject", KEY));
189 assertEquals(expectedMethods, factory.getMethodCalls());
190
191
192
193 reset(pool, factory, expectedMethods);
194 pool.addObject(KEY);
195 clear(factory, expectedMethods);
196
197 factory.setActivateObjectFail(true);
198 expectedMethods.add(new MethodCall("activateObject", KEY, obj));
199 try {
200 obj = pool.borrowObject(KEY);
201 fail("Expecting NoSuchElementException");
202 } catch (NoSuchElementException e) {
203
204 }
205
206
207 expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE));
208 expectedMethods.add(new MethodCall("activateObject", KEY, ONE));
209 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
210 assertEquals(expectedMethods, factory.getMethodCalls());
211
212
213 reset(pool, factory, expectedMethods);
214 pool.addObject(KEY);
215 clear(factory, expectedMethods);
216
217 factory.setValidateObjectFail(true);
218
219
220 try {
221 obj = pool.borrowObject(KEY);
222 fail("Expecting NoSuchElementException");
223 } catch (NoSuchElementException ex) {
224
225 }
226
227 expectedMethods.add(new MethodCall("activateObject", KEY, ZERO));
228 expectedMethods.add(new MethodCall("validateObject", KEY, ZERO));
229
230 expectedMethods.add(new MethodCall("makeObject", KEY).returned(ONE));
231 expectedMethods.add(new MethodCall("activateObject", KEY, ONE));
232 expectedMethods.add(new MethodCall("validateObject", KEY, ONE));
233 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
234 assertEquals(expectedMethods, factory.getMethodCalls());
235 }
236
237 public void testKPOFReturnObjectUsages() throws Exception {
238 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
239 final KeyedObjectPool pool;
240 try {
241 pool = makeEmptyPool(factory);
242 } catch(UnsupportedOperationException uoe) {
243 return;
244 }
245 final List expectedMethods = new ArrayList();
246 Object obj;
247 int idleCount;
248
249
250 obj = pool.borrowObject(KEY);
251 clear(factory, expectedMethods);
252
253
254 pool.returnObject(KEY, obj);
255 if (pool instanceof StackKeyedObjectPool) {
256 expectedMethods.add(new MethodCall(
257 "validateObject", KEY, obj).returned(Boolean.TRUE));
258 }
259 expectedMethods.add(new MethodCall("passivateObject", KEY, obj));
260 assertEquals(expectedMethods, factory.getMethodCalls());
261
262
263 reset(pool, factory, expectedMethods);
264
265
266 pool.addObject(KEY);
267 pool.addObject(KEY);
268 pool.addObject(KEY);
269 assertEquals(3, pool.getNumIdle(KEY));
270 obj = pool.borrowObject(KEY);
271 obj = pool.borrowObject(KEY);
272 assertEquals(1, pool.getNumIdle(KEY));
273 assertEquals(2, pool.getNumActive(KEY));
274 clear(factory, expectedMethods);
275 factory.setPassivateObjectFail(true);
276 pool.returnObject(KEY, obj);
277 if (pool instanceof StackKeyedObjectPool) {
278 expectedMethods.add(new MethodCall(
279 "validateObject", KEY, obj).returned(Boolean.TRUE));
280 }
281 expectedMethods.add(new MethodCall("passivateObject", KEY, obj));
282 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
283 assertEquals(expectedMethods, factory.getMethodCalls());
284 assertEquals(1, pool.getNumIdle(KEY));
285 assertEquals(1, pool.getNumActive(KEY));
286
287 reset(pool, factory, expectedMethods);
288 obj = pool.borrowObject(KEY);
289 clear(factory, expectedMethods);
290 factory.setPassivateObjectFail(true);
291 factory.setDestroyObjectFail(true);
292 try {
293 pool.returnObject(KEY, obj);
294 if (!(pool instanceof GenericKeyedObjectPool)) {
295 fail("Expecting destroyObject exception to be propagated");
296 }
297 } catch (PrivateException ex) {
298
299 }
300 }
301
302 public void testKPOFInvalidateObjectUsages() throws Exception {
303 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
304 final KeyedObjectPool pool;
305 try {
306 pool = makeEmptyPool(factory);
307 } catch(UnsupportedOperationException uoe) {
308 return;
309 }
310 final List expectedMethods = new ArrayList();
311 Object obj;
312
313
314
315 obj = pool.borrowObject(KEY);
316 clear(factory, expectedMethods);
317
318
319 pool.invalidateObject(KEY, obj);
320 expectedMethods.add(new MethodCall("destroyObject", KEY, obj));
321 assertEquals(expectedMethods, factory.getMethodCalls());
322
323
324 reset(pool, factory, expectedMethods);
325 obj = pool.borrowObject(KEY);
326 clear(factory, expectedMethods);
327 factory.setDestroyObjectFail(true);
328 try {
329 pool.invalidateObject(KEY, obj);
330 fail("Expecting destroy exception to propagate");
331 } catch (PrivateException ex) {
332
333 }
334 Thread.sleep(250);
335 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
336 assertEquals(expectedMethods, factory.getMethodCalls());
337 }
338
339 public void testKPOFClearUsages() throws Exception {
340 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
341 final KeyedObjectPool pool;
342 try {
343 pool = makeEmptyPool(factory);
344 } catch(UnsupportedOperationException uoe) {
345 return;
346 }
347 final List expectedMethods = new ArrayList();
348
349
350 PoolUtils.prefill(pool, KEY, 5);
351 pool.clear();
352
353
354 reset(pool, factory, expectedMethods);
355 factory.setDestroyObjectFail(true);
356 PoolUtils.prefill(pool, KEY, 5);
357 pool.clear();
358 }
359
360 public void testKPOFCloseUsages() throws Exception {
361 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
362 KeyedObjectPool pool;
363 try {
364 pool = makeEmptyPool(factory);
365 } catch(UnsupportedOperationException uoe) {
366 return;
367 }
368 final List expectedMethods = new ArrayList();
369
370
371 PoolUtils.prefill(pool, KEY, 5);
372 pool.close();
373
374
375
376 pool = makeEmptyPool(factory);
377 reset(pool, factory, expectedMethods);
378 factory.setDestroyObjectFail(true);
379 PoolUtils.prefill(pool, KEY, 5);
380 pool.close();
381 }
382
383 public void testToString() throws Exception {
384 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
385 try {
386 makeEmptyPool(factory).toString();
387 } catch(UnsupportedOperationException uoe) {
388 return;
389 }
390 }
391
392 private void reset(final KeyedObjectPool pool, final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) throws Exception {
393 pool.clear();
394 clear(factory, expectedMethods);
395 factory.reset();
396 }
397
398 private void clear(final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) {
399 factory.getMethodCalls().clear();
400 expectedMethods.clear();
401 }
402
403 protected static class FailingKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
404 private final List methodCalls = new ArrayList();
405 private int count = 0;
406 private boolean makeObjectFail;
407 private boolean activateObjectFail;
408 private boolean validateObjectFail;
409 private boolean passivateObjectFail;
410 private boolean destroyObjectFail;
411
412 public FailingKeyedPoolableObjectFactory() {
413 }
414
415 public void reset() {
416 count = 0;
417 getMethodCalls().clear();
418 setMakeObjectFail(false);
419 setActivateObjectFail(false);
420 setValidateObjectFail(false);
421 setPassivateObjectFail(false);
422 setDestroyObjectFail(false);
423 }
424
425 public List getMethodCalls() {
426 return methodCalls;
427 }
428
429 public int getCurrentCount() {
430 return count;
431 }
432
433 public void setCurrentCount(final int count) {
434 this.count = count;
435 }
436
437 public boolean isMakeObjectFail() {
438 return makeObjectFail;
439 }
440
441 public void setMakeObjectFail(boolean makeObjectFail) {
442 this.makeObjectFail = makeObjectFail;
443 }
444
445 public boolean isDestroyObjectFail() {
446 return destroyObjectFail;
447 }
448
449 public void setDestroyObjectFail(boolean destroyObjectFail) {
450 this.destroyObjectFail = destroyObjectFail;
451 }
452
453 public boolean isValidateObjectFail() {
454 return validateObjectFail;
455 }
456
457 public void setValidateObjectFail(boolean validateObjectFail) {
458 this.validateObjectFail = validateObjectFail;
459 }
460
461 public boolean isActivateObjectFail() {
462 return activateObjectFail;
463 }
464
465 public void setActivateObjectFail(boolean activateObjectFail) {
466 this.activateObjectFail = activateObjectFail;
467 }
468
469 public boolean isPassivateObjectFail() {
470 return passivateObjectFail;
471 }
472
473 public void setPassivateObjectFail(boolean passivateObjectFail) {
474 this.passivateObjectFail = passivateObjectFail;
475 }
476
477 public Object makeObject(final Object key) throws Exception {
478 final MethodCall call = new MethodCall("makeObject", key);
479 methodCalls.add(call);
480 int count = this.count++;
481 if (makeObjectFail) {
482 throw new PrivateException("makeObject");
483 }
484 final Integer obj = new Integer(count);
485 call.setReturned(obj);
486 return obj;
487 }
488
489 public void activateObject(final Object key, final Object obj) throws Exception {
490 methodCalls.add(new MethodCall("activateObject", key, obj));
491 if (activateObjectFail) {
492 throw new PrivateException("activateObject");
493 }
494 }
495
496 public boolean validateObject(final Object key, final Object obj) {
497 final MethodCall call = new MethodCall("validateObject", key, obj);
498 methodCalls.add(call);
499 if (validateObjectFail) {
500 throw new PrivateException("validateObject");
501 }
502 final boolean r = true;
503 call.returned(new Boolean(r));
504 return r;
505 }
506
507 public void passivateObject(final Object key, final Object obj) throws Exception {
508 methodCalls.add(new MethodCall("passivateObject", key, obj));
509 if (passivateObjectFail) {
510 throw new PrivateException("passivateObject");
511 }
512 }
513
514 public void destroyObject(final Object key, final Object obj) throws Exception {
515 methodCalls.add(new MethodCall("destroyObject", key, obj));
516 if (destroyObjectFail) {
517 throw new PrivateException("destroyObject");
518 }
519 }
520 }
521 }