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
30
31
32
33
34 public abstract class TestKeyedObjectPool extends TestCase {
35 public TestKeyedObjectPool(String testName) {
36 super(testName);
37 }
38
39
40
41
42
43
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
248
249 obj = pool.borrowObject(KEY);
250 clear(factory, expectedMethods);
251
252
253 pool.returnObject(KEY, obj);
254 if (pool instanceof StackKeyedObjectPool) {
255 expectedMethods.add(new MethodCall(
256 "validateObject", KEY, obj).returned(Boolean.TRUE));
257 }
258 expectedMethods.add(new MethodCall("passivateObject", KEY, obj));
259 assertEquals(expectedMethods, factory.getMethodCalls());
260
261
262 reset(pool, factory, expectedMethods);
263
264
265 pool.addObject(KEY);
266 pool.addObject(KEY);
267 pool.addObject(KEY);
268 assertEquals(3, pool.getNumIdle(KEY));
269 obj = pool.borrowObject(KEY);
270 obj = pool.borrowObject(KEY);
271 assertEquals(1, pool.getNumIdle(KEY));
272 assertEquals(2, pool.getNumActive(KEY));
273 clear(factory, expectedMethods);
274 factory.setPassivateObjectFail(true);
275 pool.returnObject(KEY, obj);
276 if (pool instanceof StackKeyedObjectPool) {
277 expectedMethods.add(new MethodCall(
278 "validateObject", KEY, obj).returned(Boolean.TRUE));
279 }
280 expectedMethods.add(new MethodCall("passivateObject", KEY, obj));
281 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
282 assertEquals(expectedMethods, factory.getMethodCalls());
283 assertEquals(1, pool.getNumIdle(KEY));
284 assertEquals(1, pool.getNumActive(KEY));
285
286 reset(pool, factory, expectedMethods);
287 obj = pool.borrowObject(KEY);
288 clear(factory, expectedMethods);
289 factory.setPassivateObjectFail(true);
290 factory.setDestroyObjectFail(true);
291 try {
292 pool.returnObject(KEY, obj);
293 if (!(pool instanceof GenericKeyedObjectPool)) {
294 fail("Expecting destroyObject exception to be propagated");
295 }
296 } catch (PrivateException ex) {
297
298 }
299 }
300
301 public void testKPOFInvalidateObjectUsages() throws Exception {
302 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
303 final KeyedObjectPool pool;
304 try {
305 pool = makeEmptyPool(factory);
306 } catch(UnsupportedOperationException uoe) {
307 return;
308 }
309 final List expectedMethods = new ArrayList();
310 Object obj;
311
312
313
314 obj = pool.borrowObject(KEY);
315 clear(factory, expectedMethods);
316
317
318 pool.invalidateObject(KEY, obj);
319 expectedMethods.add(new MethodCall("destroyObject", KEY, obj));
320 assertEquals(expectedMethods, factory.getMethodCalls());
321
322
323 reset(pool, factory, expectedMethods);
324 obj = pool.borrowObject(KEY);
325 clear(factory, expectedMethods);
326 factory.setDestroyObjectFail(true);
327 try {
328 pool.invalidateObject(KEY, obj);
329 fail("Expecting destroy exception to propagate");
330 } catch (PrivateException ex) {
331
332 }
333 Thread.sleep(250);
334 TestObjectPool.removeDestroyObjectCall(factory.getMethodCalls());
335 assertEquals(expectedMethods, factory.getMethodCalls());
336 }
337
338 public void testKPOFClearUsages() throws Exception {
339 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
340 final KeyedObjectPool pool;
341 try {
342 pool = makeEmptyPool(factory);
343 } catch(UnsupportedOperationException uoe) {
344 return;
345 }
346 final List expectedMethods = new ArrayList();
347
348
349 PoolUtils.prefill(pool, KEY, 5);
350 pool.clear();
351
352
353 reset(pool, factory, expectedMethods);
354 factory.setDestroyObjectFail(true);
355 PoolUtils.prefill(pool, KEY, 5);
356 pool.clear();
357 }
358
359 public void testKPOFCloseUsages() throws Exception {
360 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
361 KeyedObjectPool pool;
362 try {
363 pool = makeEmptyPool(factory);
364 } catch(UnsupportedOperationException uoe) {
365 return;
366 }
367 final List expectedMethods = new ArrayList();
368
369
370 PoolUtils.prefill(pool, KEY, 5);
371 pool.close();
372
373
374
375 pool = makeEmptyPool(factory);
376 reset(pool, factory, expectedMethods);
377 factory.setDestroyObjectFail(true);
378 PoolUtils.prefill(pool, KEY, 5);
379 pool.close();
380 }
381
382 public void testToString() throws Exception {
383 final FailingKeyedPoolableObjectFactory factory = new FailingKeyedPoolableObjectFactory();
384 try {
385 makeEmptyPool(factory).toString();
386 } catch(UnsupportedOperationException uoe) {
387 return;
388 }
389 }
390
391 private void reset(final KeyedObjectPool pool, final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) throws Exception {
392 pool.clear();
393 clear(factory, expectedMethods);
394 factory.reset();
395 }
396
397 private void clear(final FailingKeyedPoolableObjectFactory factory, final List expectedMethods) {
398 factory.getMethodCalls().clear();
399 expectedMethods.clear();
400 }
401
402 protected static class FailingKeyedPoolableObjectFactory implements KeyedPoolableObjectFactory {
403 private final List methodCalls = new ArrayList();
404 private int count = 0;
405 private boolean makeObjectFail;
406 private boolean activateObjectFail;
407 private boolean validateObjectFail;
408 private boolean passivateObjectFail;
409 private boolean destroyObjectFail;
410
411 public FailingKeyedPoolableObjectFactory() {
412 }
413
414 public void reset() {
415 count = 0;
416 getMethodCalls().clear();
417 setMakeObjectFail(false);
418 setActivateObjectFail(false);
419 setValidateObjectFail(false);
420 setPassivateObjectFail(false);
421 setDestroyObjectFail(false);
422 }
423
424 public List getMethodCalls() {
425 return methodCalls;
426 }
427
428 public int getCurrentCount() {
429 return count;
430 }
431
432 public void setCurrentCount(final int count) {
433 this.count = count;
434 }
435
436 public boolean isMakeObjectFail() {
437 return makeObjectFail;
438 }
439
440 public void setMakeObjectFail(boolean makeObjectFail) {
441 this.makeObjectFail = makeObjectFail;
442 }
443
444 public boolean isDestroyObjectFail() {
445 return destroyObjectFail;
446 }
447
448 public void setDestroyObjectFail(boolean destroyObjectFail) {
449 this.destroyObjectFail = destroyObjectFail;
450 }
451
452 public boolean isValidateObjectFail() {
453 return validateObjectFail;
454 }
455
456 public void setValidateObjectFail(boolean validateObjectFail) {
457 this.validateObjectFail = validateObjectFail;
458 }
459
460 public boolean isActivateObjectFail() {
461 return activateObjectFail;
462 }
463
464 public void setActivateObjectFail(boolean activateObjectFail) {
465 this.activateObjectFail = activateObjectFail;
466 }
467
468 public boolean isPassivateObjectFail() {
469 return passivateObjectFail;
470 }
471
472 public void setPassivateObjectFail(boolean passivateObjectFail) {
473 this.passivateObjectFail = passivateObjectFail;
474 }
475
476 public Object makeObject(final Object key) throws Exception {
477 final MethodCall call = new MethodCall("makeObject", key);
478 methodCalls.add(call);
479 int count = this.count++;
480 if (makeObjectFail) {
481 throw new PrivateException("makeObject");
482 }
483 final Integer obj = new Integer(count);
484 call.setReturned(obj);
485 return obj;
486 }
487
488 public void activateObject(final Object key, final Object obj) throws Exception {
489 methodCalls.add(new MethodCall("activateObject", key, obj));
490 if (activateObjectFail) {
491 throw new PrivateException("activateObject");
492 }
493 }
494
495 public boolean validateObject(final Object key, final Object obj) {
496 final MethodCall call = new MethodCall("validateObject", key, obj);
497 methodCalls.add(call);
498 if (validateObjectFail) {
499 throw new PrivateException("validateObject");
500 }
501 final boolean r = true;
502 call.returned(new Boolean(r));
503 return r;
504 }
505
506 public void passivateObject(final Object key, final Object obj) throws Exception {
507 methodCalls.add(new MethodCall("passivateObject", key, obj));
508 if (passivateObjectFail) {
509 throw new PrivateException("passivateObject");
510 }
511 }
512
513 public void destroyObject(final Object key, final Object obj) throws Exception {
514 methodCalls.add(new MethodCall("destroyObject", key, obj));
515 if (destroyObjectFail) {
516 throw new PrivateException("destroyObject");
517 }
518 }
519 }
520 }