1   /*
2    * Copyright 2006 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.commons.pool;
18  
19  import junit.framework.TestCase;
20  import junit.framework.AssertionFailedError;
21  import junit.framework.Test;
22  import junit.framework.TestSuite;
23  
24  import java.lang.reflect.Proxy;
25  import java.lang.reflect.InvocationHandler;
26  import java.lang.reflect.Method;
27  import java.util.List;
28  import java.util.ArrayList;
29  import java.util.Set;
30  import java.util.HashSet;
31  import java.util.TimerTask;
32  import java.util.Collection;
33  import java.util.Map;
34  import java.util.Iterator;
35  import java.util.Arrays;
36  
37  /***
38   * Unit tests for {@link PoolUtils}.
39   *
40   * @author Sandy McArthur
41   * @version $Revision: 384433 $ $Date: 2006-03-09 00:19:21 -0500 (Thu, 09 Mar 2006) $
42   */
43  public class TestPoolUtils extends TestCase {
44  
45      /*** Period between checks for minIdle tests. Increase this if you happen to get too many false failures. */
46      private static final int CHECK_PERIOD = 300;
47  
48      /*** Times to let the minIdle check run. */
49      private static final int CHECK_COUNT = 4;
50  
51      /*** Sleep time to let the minIdle tests run CHECK_COUNT times. */
52      private static final int CHECK_SLEEP_PERIOD = CHECK_PERIOD * (CHECK_COUNT - 1) + CHECK_PERIOD / 2;
53  
54      public static Test suite() {
55          return new TestSuite(TestPoolUtils.class);
56      }
57  
58      public void testJavaBeanInstantiation() {
59          new PoolUtils();
60      }
61  
62      public void testAdaptKeyedPoolableObjectFactory() throws Exception {
63          try {
64              PoolUtils.adapt((KeyedPoolableObjectFactory)null);
65              fail("PoolUtils.adapt(KeyedPoolableObjectFactory) must not allow null factory.");
66          } catch (IllegalArgumentException iae) {
67              // expected
68          }
69      }
70  
71      public void testAdaptKeyedPoolableObjectFactoryKey() throws Exception {
72          try {
73              PoolUtils.adapt((KeyedPoolableObjectFactory)null, new Object());
74              fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null factory.");
75          } catch (IllegalArgumentException iae) {
76              // expected
77          }
78          try {
79              PoolUtils.adapt((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, null), null);
80              fail("PoolUtils.adapt(KeyedPoolableObjectFactory, key) must not allow null key.");
81          } catch (IllegalArgumentException iae) {
82              // expected
83          }
84  
85          final List calledMethods = new ArrayList();
86          final KeyedPoolableObjectFactory kpof =
87                  (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods);
88  
89          final PoolableObjectFactory pof = PoolUtils.adapt(kpof);
90          final List expectedMethods = invokeEveryMethod(pof);
91          assertEquals(expectedMethods, calledMethods);
92      }
93  
94      public void testAdaptPoolableObjectFactory() throws Exception {
95          try {
96              PoolUtils.adapt((PoolableObjectFactory)null);
97              fail("PoolUtils.adapt(PoolableObjectFactory) must not allow null factory.");
98          } catch (IllegalArgumentException iae) {
99              // expected
100         }
101 
102         final List calledMethods = new ArrayList();
103         final PoolableObjectFactory pof =
104                 (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods);
105 
106         final KeyedPoolableObjectFactory kpof = PoolUtils.adapt(pof);
107         final List expectedMethods = invokeEveryMethod(kpof);
108         assertEquals(expectedMethods, calledMethods);
109     }
110 
111     public void testAdaptKeyedObjectPool() throws Exception {
112         try {
113             PoolUtils.adapt((KeyedObjectPool)null);
114             fail("PoolUtils.adapt(KeyedObjectPool) must not allow a null pool.");
115         } catch(IllegalArgumentException iae) {
116             // expected
117         }
118     }
119 
120     public void testAdaptKeyedObjectPoolKey() throws Exception {
121         try {
122             PoolUtils.adapt((KeyedObjectPool)null, new Object());
123             fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null pool.");
124         } catch(IllegalArgumentException iae) {
125             // expected
126         }
127         try {
128             PoolUtils.adapt((KeyedObjectPool)createProxy(KeyedObjectPool.class, null), null);
129             fail("PoolUtils.adapt(KeyedObjectPool, key) must not allow a null key.");
130         } catch(IllegalArgumentException iae) {
131             // expected
132         }
133 
134         final List calledMethods = new ArrayList();
135         final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
136 
137         final ObjectPool op = PoolUtils.adapt(kop, new Object());
138         final List expectedMethods = invokeEveryMethod(op);
139         assertEquals(expectedMethods, calledMethods);
140     }
141 
142     public void testAdaptObjectPool() throws Exception {
143         try {
144             PoolUtils.adapt((ObjectPool)null);
145             fail("PoolUtils.adapt(ObjectPool) must not allow a null pool.");
146         } catch(IllegalArgumentException iae) {
147             // expected
148         }
149 
150         final List calledMethods = new ArrayList();
151         final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
152 
153         final KeyedObjectPool kop = PoolUtils.adapt(op);
154         final List expectedMethods = invokeEveryMethod(kop);
155         assertEquals(expectedMethods, calledMethods);
156     }
157 
158     public void testCheckedPoolObjectPool() throws Exception {
159         try {
160             PoolUtils.checkedPool((ObjectPool)null, Object.class);
161             fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null pool.");
162         } catch(IllegalArgumentException iae) {
163             // expected
164         }
165         try {
166             PoolUtils.checkedPool((ObjectPool)createProxy(ObjectPool.class, null), null);
167             fail("PoolUtils.checkedPool(ObjectPool, Class) must not allow a null type.");
168         } catch(IllegalArgumentException iae) {
169             // expected
170         }
171 
172         final List calledMethods = new ArrayList();
173         ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
174 
175         ObjectPool cop = PoolUtils.checkedPool(op, Object.class);
176         final List expectedMethods = invokeEveryMethod(cop);
177         assertEquals(expectedMethods, calledMethods);
178 
179         op = new BaseObjectPool() {
180             public Object borrowObject() throws Exception {
181                 return new Integer(0);
182             }
183             public void returnObject(Object obj) {}
184             public void invalidateObject(Object obj) {}
185         };
186         cop = PoolUtils.checkedPool(op, String.class);
187 
188         try {
189             cop.borrowObject();
190             fail("borrowObject should have failed as Integer !instanceof String.");
191         } catch (ClassCastException cce) {
192             // expected
193         }
194         try {
195             cop.returnObject(new Integer(1));
196             fail("returnObject should have failed as Integer !instanceof String.");
197         } catch (ClassCastException cce) {
198             // expected
199         }
200         try {
201             cop.invalidateObject(new Integer(2));
202             fail("invalidateObject should have failed as Integer !instanceof String.");
203         } catch (ClassCastException cce) {
204             // expected
205         }
206     }
207 
208     public void testCheckedPoolKeyedObjectPool() throws Exception {
209         try {
210             PoolUtils.checkedPool((KeyedObjectPool)null, Object.class);
211             fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null pool.");
212         } catch(IllegalArgumentException iae) {
213             // expected
214         }
215         try {
216             PoolUtils.checkedPool((KeyedObjectPool)createProxy(KeyedObjectPool.class, null), null);
217             fail("PoolUtils.checkedPool(KeyedObjectPool, Class) must not allow a null type.");
218         } catch(IllegalArgumentException iae) {
219             // expected
220         }
221 
222         final List calledMethods = new ArrayList();
223         KeyedObjectPool op = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
224 
225         KeyedObjectPool cop = PoolUtils.checkedPool(op, Object.class);
226         final List expectedMethods = invokeEveryMethod(cop);
227         assertEquals(expectedMethods, calledMethods);
228 
229 
230         op = new BaseKeyedObjectPool() {
231             public Object borrowObject(Object key) {
232                 return new Integer(0);
233             }
234 
235             public void returnObject(Object key, Object obj) {}
236 
237             public void invalidateObject(Object key, Object obj) {}
238         };
239         cop = PoolUtils.checkedPool(op, String.class);
240 
241         try {
242             cop.borrowObject(null);
243             fail("borrowObject should have failed as Integer !instanceof String.");
244         } catch (ClassCastException cce) {
245             // expected
246         }
247         try {
248             cop.returnObject(null, new Integer(1));
249             fail("returnObject should have failed as Integer !instanceof String.");
250         } catch (ClassCastException cce) {
251             // expected
252         }
253         try {
254             cop.invalidateObject(null, new Integer(2));
255             fail("invalidateObject should have failed as Integer !instanceof String.");
256         } catch (ClassCastException cce) {
257             // expected
258         }
259     }
260 
261     public void testCheckMinIdleObjectPool() throws Exception {
262         try {
263             PoolUtils.checkMinIdle(null, 1, 1);
264             fail("PoolUtils.checkMinIdle(ObjectPool,,) must not allow null pool.");
265         } catch (IllegalArgumentException iae) {
266             // expected
267         }
268         try {
269             final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, null);
270             PoolUtils.checkMinIdle(pool, -1, 1);
271             fail("PoolUtils.checkMinIdle(ObjectPool,,) must not accept negative min idle values.");
272         } catch (IllegalArgumentException iae) {
273             // expected
274         }
275 
276         // Because this isn't determinist and you can get false failures, try more than once.
277         AssertionFailedError afe = null;
278         int triesLeft = 3;
279         do {
280             afe = null;
281             try {
282                 final List calledMethods = new ArrayList();
283                 final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
284                 final TimerTask task = PoolUtils.checkMinIdle(pool, 1, CHECK_PERIOD); // checks minIdle immediately
285 
286                 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
287                 task.cancel();
288                 task.toString();
289 
290                 final List expectedMethods = new ArrayList();
291                 for (int i=0; i < CHECK_COUNT; i++) {
292                     expectedMethods.add("getNumIdle");
293                     expectedMethods.add("addObject");
294                 }
295                 expectedMethods.add("toString");
296                 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
297             } catch (AssertionFailedError e) {
298                 afe = e;
299             }
300         } while (--triesLeft > 0 && afe != null);
301         if (afe != null) {
302             throw afe;
303         }
304     }
305 
306     public void testCheckMinIdleKeyedObjectPool() throws Exception {
307         try {
308             PoolUtils.checkMinIdle(null, new Object(), 1, 1);
309             fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not allow null pool.");
310         } catch (IllegalArgumentException iae) {
311             // expected
312         }
313         try {
314             final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
315             PoolUtils.checkMinIdle(pool, (Object)null, 1, 1);
316             fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept null keys.");
317         } catch (IllegalArgumentException iae) {
318             // expected
319         }
320         try {
321             final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
322             PoolUtils.checkMinIdle(pool, new Object(), -1, 1);
323             fail("PoolUtils.checkMinIdle(KeyedObjectPool,Object,int,long) must not accept negative min idle values.");
324         } catch (IllegalArgumentException iae) {
325             // expected
326         }
327 
328         // Because this isn't determinist and you can get false failures, try more than once.
329         AssertionFailedError afe = null;
330         int triesLeft = 3;
331         do {
332             afe = null;
333             try {
334                 final List calledMethods = new ArrayList();
335                 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
336                 final Object key = new Object();
337                 final TimerTask task = PoolUtils.checkMinIdle(pool, key, 1, CHECK_PERIOD); // checks minIdle immediately
338 
339                 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
340                 task.cancel();
341                 task.toString();
342 
343                 final List expectedMethods = new ArrayList();
344                 for (int i=0; i < CHECK_COUNT; i++) {
345                     expectedMethods.add("getNumIdle");
346                     expectedMethods.add("addObject");
347                 }
348                 expectedMethods.add("toString");
349                 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
350             } catch (AssertionFailedError e) {
351                 afe = e;
352             }
353         } while (--triesLeft > 0 && afe != null);
354         if (afe != null) {
355             throw afe;
356         }
357     }
358 
359     public void testCheckMinIdleKeyedObjectPoolKeys() throws Exception {
360         try {
361             final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
362             PoolUtils.checkMinIdle(pool, null, 1, 1);
363             fail("PoolUtils.checkMinIdle(KeyedObjectPool,Collection,int,long) must not accept null keys.");
364         } catch (IllegalArgumentException iae) {
365             // expected
366         }
367 
368         // Because this isn't determinist and you can get false failures, try more than once.
369         AssertionFailedError afe = null;
370         int triesLeft = 3;
371         do {
372             afe = null;
373             try {
374                 final List calledMethods = new ArrayList();
375                 final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
376                 final Collection keys = new ArrayList(2);
377                 keys.add("one");
378                 keys.add("two");
379                 final Map tasks = PoolUtils.checkMinIdle(pool, keys, 1, CHECK_PERIOD); // checks minIdle immediately
380 
381                 Thread.sleep(CHECK_SLEEP_PERIOD); // will check CHECK_COUNT more times.
382                 final Iterator iter = tasks.values().iterator();
383                 while (iter.hasNext()) {
384                     final TimerTask task = (TimerTask)iter.next();
385                     task.cancel();
386                 }
387 
388                 final List expectedMethods = new ArrayList();
389                 for (int i=0; i < CHECK_COUNT * keys.size(); i++) {
390                     expectedMethods.add("getNumIdle");
391                     expectedMethods.add("addObject");
392                 }
393                 assertEquals(expectedMethods, calledMethods); // may fail because of the thread scheduler
394             } catch (AssertionFailedError e) {
395                 afe = e;
396             }
397         } while (--triesLeft > 0 && afe != null);
398         if (afe != null) {
399             throw afe;
400         }
401     }
402 
403     public void testPrefillObjectPool() throws Exception {
404         try {
405             PoolUtils.prefill(null, 1);
406             fail("PoolUtils.prefill(ObjectPool,int) must not allow null pool.");
407         } catch (IllegalArgumentException iae) {
408             // expected
409         }
410 
411         final List calledMethods = new ArrayList();
412         final ObjectPool pool = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
413 
414         PoolUtils.prefill(pool, 0);
415         final List expectedMethods = new ArrayList();
416         assertEquals(expectedMethods, calledMethods);
417 
418         calledMethods.clear();
419         PoolUtils.prefill(pool, 3);
420         for (int i=0; i < 3; i++) {
421             expectedMethods.add("addObject");
422         }
423         assertEquals(expectedMethods, calledMethods);
424     }
425 
426     public void testPrefillKeyedObjectPool() throws Exception {
427         try {
428             PoolUtils.prefill(null, new Object(), 1);
429             fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null pool.");
430         } catch (IllegalArgumentException iae) {
431             // expected
432         }
433         try {
434             final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
435             PoolUtils.prefill(pool, (Object)null, 1);
436             fail("PoolUtils.prefill(KeyedObjectPool,Object,int) must not accept null key.");
437         } catch (IllegalArgumentException iae) {
438             // expected
439         }
440 
441         final List calledMethods = new ArrayList();
442         final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
443 
444         PoolUtils.prefill(pool, new Object(), 0);
445         final List expectedMethods = new ArrayList();
446         assertEquals(expectedMethods, calledMethods);
447 
448         calledMethods.clear();
449         PoolUtils.prefill(pool, new Object(), 3);
450         for (int i=0; i < 3; i++) {
451             expectedMethods.add("addObject");
452         }
453         assertEquals(expectedMethods, calledMethods);
454     }
455 
456     public void testPrefillKeyedObjectPoolCollection() throws Exception {
457         try {
458             final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, null);
459             PoolUtils.prefill(pool, null, 1);
460             fail("PoolUtils.prefill(KeyedObjectPool,Collection,int) must not accept null keys.");
461         } catch (IllegalArgumentException iae) {
462             // expected
463         }
464 
465         final List calledMethods = new ArrayList();
466         final KeyedObjectPool pool = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
467 
468         final Set keys = new HashSet();
469         PoolUtils.prefill(pool, keys, 0);
470         final List expectedMethods = new ArrayList();
471         assertEquals(expectedMethods, calledMethods);
472 
473         calledMethods.clear();
474         keys.add(new Integer(1));
475         keys.add("two");
476         keys.add(new Double(3.1415926));
477         PoolUtils.prefill(pool, keys, 3);
478         for (int i=0; i < keys.size() * 3; i++) {
479             expectedMethods.add("addObject");
480         }
481         assertEquals(expectedMethods, calledMethods);
482     }
483 
484     public void testSynchronizedPoolObjectPool() throws Exception {
485         try {
486             PoolUtils.synchronizedPool((ObjectPool)null);
487             fail("PoolUtils.synchronizedPool(ObjectPool) must not allow a null pool.");
488         } catch(IllegalArgumentException iae) {
489             // expected
490         }
491 
492         final List calledMethods = new ArrayList();
493         final ObjectPool op = (ObjectPool)createProxy(ObjectPool.class, calledMethods);
494 
495         final ObjectPool sop = PoolUtils.synchronizedPool(op);
496         final List expectedMethods = invokeEveryMethod(sop);
497         assertEquals(expectedMethods, calledMethods);
498 
499         // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
500     }
501 
502     public void testSynchronizedPoolKeyedObjectPool() throws Exception {
503         try {
504             PoolUtils.synchronizedPool((KeyedObjectPool)null);
505             fail("PoolUtils.synchronizedPool(KeyedObjectPool) must not allow a null pool.");
506         } catch(IllegalArgumentException iae) {
507             // expected
508         }
509 
510         final List calledMethods = new ArrayList();
511         final KeyedObjectPool kop = (KeyedObjectPool)createProxy(KeyedObjectPool.class, calledMethods);
512 
513         final KeyedObjectPool skop = PoolUtils.synchronizedPool(kop);
514         final List expectedMethods = invokeEveryMethod(skop);
515         assertEquals(expectedMethods, calledMethods);
516 
517         // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
518     }
519 
520     public void testSynchronizedPoolableFactoryPoolableObjectFactory() throws Exception {
521         try {
522             PoolUtils.synchronizedPoolableFactory((PoolableObjectFactory)null);
523             fail("PoolUtils.synchronizedPoolableFactory(PoolableObjectFactory) must not allow a null factory.");
524         } catch(IllegalArgumentException iae) {
525             // expected
526         }
527 
528         final List calledMethods = new ArrayList();
529         final PoolableObjectFactory pof =
530                 (PoolableObjectFactory)createProxy(PoolableObjectFactory.class, calledMethods);
531 
532         final PoolableObjectFactory spof = PoolUtils.synchronizedPoolableFactory(pof);
533         final List expectedMethods = invokeEveryMethod(spof);
534         assertEquals(expectedMethods, calledMethods);
535 
536         // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
537     }
538 
539     public void testSynchronizedPoolableFactoryKeyedPoolableObjectFactory() throws Exception {
540         try {
541             PoolUtils.synchronizedPoolableFactory((KeyedPoolableObjectFactory)null);
542             fail("PoolUtils.synchronizedPoolableFactory(KeyedPoolableObjectFactory) must not allow a null factory.");
543         } catch(IllegalArgumentException iae) {
544             // expected
545         }
546 
547         final List calledMethods = new ArrayList();
548         final KeyedPoolableObjectFactory kpof =
549                 (KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, calledMethods);
550 
551         final KeyedPoolableObjectFactory skpof = PoolUtils.synchronizedPoolableFactory(kpof);
552         final List expectedMethods = invokeEveryMethod(skpof);
553         assertEquals(expectedMethods, calledMethods);
554 
555         // TODO: Anyone feel motivated to construct a test that verifies proper synchronization?
556     }
557 
558     private static List invokeEveryMethod(ObjectPool op) throws Exception {
559         op.addObject();
560         op.borrowObject();
561         op.clear();
562         op.close();
563         op.getNumActive();
564         op.getNumIdle();
565         op.invalidateObject(new Object());
566         op.returnObject(new Object());
567         op.setFactory((PoolableObjectFactory)createProxy(PoolableObjectFactory.class, null));
568         op.toString();
569 
570         final List expectedMethods = Arrays.asList(new String[] {
571                 "addObject", "borrowObject", "clear", "close",
572                 "getNumActive", "getNumIdle", "invalidateObject",
573                 "returnObject", "setFactory", "toString"
574         });
575         return expectedMethods;
576     }
577 
578     private static List invokeEveryMethod(KeyedObjectPool kop) throws Exception {
579         kop.addObject(null);
580         kop.borrowObject(null);
581         kop.clear();
582         kop.clear(null);
583         kop.close();
584         kop.getNumActive();
585         kop.getNumActive(null);
586         kop.getNumIdle();
587         kop.getNumIdle(null);
588         kop.invalidateObject(null, new Object());
589         kop.returnObject(null, new Object());
590         kop.setFactory((KeyedPoolableObjectFactory)createProxy(KeyedPoolableObjectFactory.class, null));
591         kop.toString();
592 
593         final List expectedMethods = Arrays.asList(new String[] {
594                 "addObject", "borrowObject", "clear", "clear", "close",
595                 "getNumActive", "getNumActive", "getNumIdle", "getNumIdle", "invalidateObject",
596                 "returnObject", "setFactory", "toString"
597         });
598         return expectedMethods;
599     }
600 
601     private static List invokeEveryMethod(PoolableObjectFactory pof) throws Exception {
602         pof.activateObject(null);
603         pof.destroyObject(null);
604         pof.makeObject();
605         pof.passivateObject(null);
606         pof.validateObject(null);
607         pof.toString();
608 
609         final List expectedMethods = Arrays.asList(new String[] {
610                 "activateObject", "destroyObject", "makeObject",
611                 "passivateObject", "validateObject", "toString",
612         });
613         return expectedMethods;
614     }
615 
616     private static List invokeEveryMethod(KeyedPoolableObjectFactory kpof) throws Exception {
617         kpof.activateObject(null, null);
618         kpof.destroyObject(null, null);
619         kpof.makeObject(null);
620         kpof.passivateObject(null, null);
621         kpof.validateObject(null, null);
622         kpof.toString();
623 
624         final List expectedMethods = Arrays.asList(new String[] {
625                 "activateObject", "destroyObject", "makeObject",
626                 "passivateObject", "validateObject", "toString",
627         });
628         return expectedMethods;
629     }
630 
631     private static Object createProxy(final Class clazz, final List logger) {
632         return Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz },
633                 new MethodCallLogger(logger));
634     }
635 
636     private static class MethodCallLogger implements InvocationHandler {
637         private final List calledMethods;
638 
639         MethodCallLogger(final List calledMethods) {
640             this.calledMethods = calledMethods;
641         }
642 
643         public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
644             calledMethods.add(method.getName());
645             if (boolean.class.equals(method.getReturnType())) {
646                 return Boolean.FALSE;
647             } else if (int.class.equals(method.getReturnType())) {
648                 return new Integer(0);
649             } else if (long.class.equals(method.getReturnType())) {
650                 return new Long(0);
651             } else if (Object.class.equals(method.getReturnType())) {
652                 return new Object();
653             } else {
654                 return null;
655             }
656         }
657     }
658 }