KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > beanutils > BeanificationTestCase


1 /*
2  * Copyright 2001-2004 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.beanutils;
18
19 import java.util.*;
20
21 import java.lang.ref.WeakReference JavaDoc;
22 import java.lang.ref.ReferenceQueue JavaDoc;
23
24 import junit.framework.TestCase;
25 import junit.framework.Test;
26 import junit.framework.TestSuite;
27
28 import org.apache.commons.collections.ReferenceMap;
29 import org.apache.commons.logging.LogFactory;
30
31 /**
32  * <p>
33  * Test Case for changes made during Beanutils Beanification
34  * </p>
35  *
36  * @author Robert Burrell Donkin
37  * @author Juozas Baliuka
38  * @version $Revision: 1.5 $ $Date: 2004/02/28 13:18:36 $
39  */

40
41 public class BeanificationTestCase extends TestCase {
42     
43     // ---------------------------------------------------- Constants
44

45     /** Maximum number of iterations before our test fails */
46     public static final int MAX_GC_ITERATIONS = 50;
47     
48     // ---------------------------------------------------- Instance Variables
49

50
51     // ---------------------------------------------------------- Constructors
52

53
54     /**
55      * Construct a new instance of this test case.
56      *
57      * @param name Name of the test case
58      */

59     public BeanificationTestCase(String JavaDoc name) {
60         super(name);
61     }
62
63
64     // -------------------------------------------------- Overall Test Methods
65

66
67     /**
68      * Set up instance variables required by this test case.
69      */

70     public void setUp() {
71
72         ConvertUtils.deregister();
73
74     }
75
76
77     /**
78      * Return the tests included in this test suite.
79      */

80     public static Test suite() {
81         return (new TestSuite(BeanificationTestCase.class));
82     }
83
84
85     /**
86      * Tear down instance variables required by this test case.
87      */

88     public void tearDown() {
89         ; // No action required
90
}
91
92
93     // ------------------------------------------------ Individual Test Methods
94

95     /** Test of the methodology we'll use for some of the later tests */
96     public void testMemoryTestMethodology() throws Exception JavaDoc {
97         // test methodology
98
// many thanks to Juozas Baliuka for suggesting this method
99
ClassLoader JavaDoc loader = new ClassLoader JavaDoc() {};
100         WeakReference JavaDoc reference = new WeakReference JavaDoc(loader);
101         Class JavaDoc myClass = loader.loadClass("org.apache.commons.beanutils.BetaBean");
102         
103         assertNotNull("Weak reference released early", reference.get());
104         
105         // dereference class loader and class:
106
loader = null;
107         myClass = null;
108         
109         int iterations = 0;
110         int bytz = 2;
111         while(true) {
112             System.gc();
113             if(iterations++ > MAX_GC_ITERATIONS){
114                 fail("Max iterations reached before resource released.");
115             }
116             if( reference.get() == null ) {
117                 break;
118                 
119             } else {
120                 // create garbage:
121
byte[] b = new byte[bytz];
122                 bytz = bytz * 2;
123             }
124         }
125     }
126     
127     /** Tests whether classloaders and beans are released from memory by the map used by beanutils */
128     public void testMemoryLeak2() throws Exception JavaDoc {
129         // tests when the map used by beanutils has the right behaviour
130

131         if (isPre14JVM()) {
132             System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
133             return;
134         }
135         
136         // many thanks to Juozas Baliuka for suggesting this methodology
137
TestClassLoader loader = new TestClassLoader();
138         ReferenceQueue JavaDoc queue = new ReferenceQueue JavaDoc();
139         WeakReference JavaDoc loaderReference = new WeakReference JavaDoc(loader, queue);
140         Integer JavaDoc test = new Integer JavaDoc(1);
141         
142         WeakReference JavaDoc testReference = new WeakReference JavaDoc(test, queue);
143         //Map map = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD, true);
144
Map map = new WeakHashMap();
145         map.put(loader, test);
146         
147         assertEquals("In map", test, map.get(loader));
148         assertNotNull("Weak reference released early (1)", loaderReference.get());
149         assertNotNull("Weak reference released early (2)", testReference.get());
150         
151         // dereference strong references
152
loader = null;
153         test = null;
154         
155         int iterations = 0;
156         int bytz = 2;
157         while(true) {
158             System.gc();
159             if(iterations++ > MAX_GC_ITERATIONS){
160                 fail("Max iterations reached before resource released.");
161             }
162             map.isEmpty();
163             
164             if(
165                 loaderReference.get() == null &&
166                 testReference.get() == null) {
167                 break;
168                 
169             } else {
170                 // create garbage:
171
byte[] b = new byte[bytz];
172                 bytz = bytz * 2;
173             }
174         }
175     }
176     
177     /** Tests whether classloaders and beans are released from memory */
178     public void testMemoryLeak() throws Exception JavaDoc {
179         if (isPre14JVM()) {
180             System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM");
181             return;
182         }
183         
184         // many thanks to Juozas Baliuka for suggesting this methodology
185
TestClassLoader loader = new TestClassLoader();
186         WeakReference JavaDoc loaderReference = new WeakReference JavaDoc(loader);
187         BeanUtilsBean.getInstance();
188
189         class GetBeanUtilsBeanThread extends Thread JavaDoc {
190             
191             BeanUtilsBean beanUtils;
192             ConvertUtilsBean convertUtils;
193             PropertyUtilsBean propertyUtils;
194         
195             GetBeanUtilsBeanThread() {}
196             
197             public void run() {
198                 beanUtils = BeanUtilsBean.getInstance();
199                 convertUtils = ConvertUtilsBean.getInstance();
200                 propertyUtils = PropertyUtilsBean.getInstance();
201                 // XXX Log keeps a reference around!
202
LogFactory.releaseAll();
203             }
204             
205             public String JavaDoc toString() {
206                 return "GetBeanUtilsBeanThread";
207             }
208         }
209         
210     
211         GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread();
212         WeakReference JavaDoc threadWeakReference = new WeakReference JavaDoc(thread);
213         thread.setContextClassLoader(loader);
214
215         thread.start();
216         thread.join();
217         
218         WeakReference JavaDoc beanUtilsReference = new WeakReference JavaDoc(thread.beanUtils);
219         WeakReference JavaDoc propertyUtilsReference = new WeakReference JavaDoc(thread.propertyUtils);
220         WeakReference JavaDoc convertUtilsReference = new WeakReference JavaDoc(thread.convertUtils);
221         
222         assertNotNull("Weak reference released early (1)", loaderReference.get());
223         assertNotNull("Weak reference released early (2)", beanUtilsReference.get());
224         assertNotNull("Weak reference released early (3)", propertyUtilsReference.get());
225         assertNotNull("Weak reference released early (4)", convertUtilsReference.get());
226         
227         // dereference strong references
228
loader = null;
229         thread.setContextClassLoader(null);
230         thread = null;
231         
232         int iterations = 0;
233         int bytz = 2;
234         while(true) {
235             BeanUtilsBean.getInstance();
236             System.gc();
237             if(iterations++ > MAX_GC_ITERATIONS){
238                 fail("Max iterations reached before resource released.");
239             }
240
241             if(
242                 loaderReference.get() == null &&
243                 beanUtilsReference.get() == null &&
244                 propertyUtilsReference.get() == null &&
245                 convertUtilsReference.get() == null) {
246                 break;
247                 
248             } else {
249                 // create garbage:
250
byte[] b = new byte[bytz];
251                 bytz = bytz * 2;
252             }
253         }
254     }
255     
256     /**
257      * Tests whether difference instances are loaded by different
258      * context classloaders.
259      */

260     public void testGetByContextClassLoader() throws Exception JavaDoc {
261             
262         class GetBeanUtilsBeanThread extends Thread JavaDoc {
263             
264             private Signal signal;
265         
266             GetBeanUtilsBeanThread(Signal signal) {
267                 this.signal = signal;
268             }
269             
270             public void run() {
271                 signal.setSignal(2);
272                 signal.setBean(BeanUtilsBean.getInstance());
273                 signal.setConvertUtils(ConvertUtilsBean.getInstance());
274                 signal.setPropertyUtils(PropertyUtilsBean.getInstance());
275             }
276             
277             public String JavaDoc toString() {
278                 return "GetBeanUtilsBeanThread";
279             }
280         }
281             
282         Signal signal = new Signal();
283         signal.setSignal(1);
284         
285         GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal);
286         thread.setContextClassLoader(new TestClassLoader());
287         
288         thread.start();
289         thread.join();
290         
291         assertEquals("Signal not set by test thread", 2, signal.getSignal());
292         assertTrue(
293                     "Different BeanUtilsBean instances per context classloader",
294                     BeanUtilsBean.getInstance() != signal.getBean());
295         assertTrue(
296                     "Different ConvertUtilsBean instances per context classloader",
297                     ConvertUtilsBean.getInstance() != signal.getConvertUtils());
298         assertTrue(
299                     "Different PropertyUtilsBean instances per context classloader",
300                     PropertyUtilsBean.getInstance() != signal.getPropertyUtils());
301     }
302     
303     
304     /**
305      * Tests whether difference instances are loaded by different
306      * context classloaders.
307      */

308     public void testContextClassLoaderLocal() throws Exception JavaDoc {
309             
310         class CCLLTesterThread extends Thread JavaDoc {
311             
312             private Signal signal;
313             private ContextClassLoaderLocal ccll;
314         
315             CCLLTesterThread(Signal signal, ContextClassLoaderLocal ccll) {
316                 this.signal = signal;
317                 this.ccll = ccll;
318             }
319             
320             public void run() {
321                 ccll.set(new Integer JavaDoc(1789));
322                 signal.setSignal(2);
323                 signal.setMarkerObject(ccll.get());
324             }
325             
326             public String JavaDoc toString() {
327                 return "CCLLTesterThread";
328             }
329         }
330             
331         ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
332         ccll.set(new Integer JavaDoc(1776));
333         assertEquals("Start thread sets value", new Integer JavaDoc(1776), ccll.get());
334         
335         Signal signal = new Signal();
336         signal.setSignal(1);
337         
338         CCLLTesterThread thread = new CCLLTesterThread(signal, ccll);
339         thread.setContextClassLoader(new TestClassLoader());
340         
341         thread.start();
342         thread.join();
343         
344         assertEquals("Signal not set by test thread", 2, signal.getSignal());
345         assertEquals("Second thread preserves value", new Integer JavaDoc(1776), ccll.get());
346         assertEquals("Second thread gets value it set", new Integer JavaDoc(1789), signal.getMarkerObject());
347     }
348     
349     /** Tests whether calls are independent for different classloaders */
350     public void testContextClassloaderIndependence() throws Exception JavaDoc {
351     
352         class TestIndependenceThread extends Thread JavaDoc {
353             private Signal signal;
354             private PrimitiveBean bean;
355         
356             TestIndependenceThread(Signal signal, PrimitiveBean bean) {
357                 this.signal = signal;
358                 this.bean = bean;
359             }
360             
361             public void run() {
362                 try {
363                     signal.setSignal(3);
364                     ConvertUtils.register(new Converter() {
365                                             public Object JavaDoc convert(Class JavaDoc type, Object JavaDoc value) {
366                                                 return new Integer JavaDoc(9);
367                                             }
368                                                 }, Integer.TYPE);
369                     BeanUtils.setProperty(bean, "int", new Integer JavaDoc(1));
370                 } catch (Exception JavaDoc e) {
371                     e.printStackTrace();
372                     signal.setException(e);
373                 }
374             }
375             
376             public String JavaDoc toString() {
377                 return "TestIndependenceThread";
378             }
379         }
380         
381         PrimitiveBean bean = new PrimitiveBean();
382         BeanUtils.setProperty(bean, "int", new Integer JavaDoc(1));
383         assertEquals("Wrong property value (1)", 1, bean.getInt());
384
385         ConvertUtils.register(new Converter() {
386                                 public Object JavaDoc convert(Class JavaDoc type, Object JavaDoc value) {
387                                     return new Integer JavaDoc(5);
388                                 }
389                                     }, Integer.TYPE);
390         BeanUtils.setProperty(bean, "int", new Integer JavaDoc(1));
391         assertEquals("Wrong property value(2)", 5, bean.getInt());
392     
393         Signal signal = new Signal();
394         signal.setSignal(1);
395         TestIndependenceThread thread = new TestIndependenceThread(signal, bean);
396         thread.setContextClassLoader(new TestClassLoader());
397         
398         thread.start();
399         thread.join();
400         
401         assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException());
402         assertEquals("Signal not set by test thread", 3, signal.getSignal());
403         assertEquals("Wrong property value(3)", 9, bean.getInt());
404         
405     }
406     
407     /** Tests whether different threads can set beanutils instances correctly */
408     public void testBeanUtilsBeanSetInstance() throws Exception JavaDoc {
409             
410         class SetInstanceTesterThread extends Thread JavaDoc {
411             
412             private Signal signal;
413             private BeanUtilsBean bean;
414         
415             SetInstanceTesterThread(Signal signal, BeanUtilsBean bean) {
416                 this.signal = signal;
417                 this.bean = bean;
418             }
419             
420             public void run() {
421                 BeanUtilsBean.setInstance(bean);
422                 signal.setSignal(21);
423                 signal.setBean(BeanUtilsBean.getInstance());
424             }
425             
426             public String JavaDoc toString() {
427                 return "SetInstanceTesterThread";
428             }
429         }
430         
431         Signal signal = new Signal();
432         signal.setSignal(1);
433
434         BeanUtilsBean beanOne = new BeanUtilsBean();
435         BeanUtilsBean beanTwo = new BeanUtilsBean();
436         
437         SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo);
438         thread.setContextClassLoader(new TestClassLoader());
439         
440         BeanUtilsBean.setInstance(beanOne);
441         assertEquals("Start thread gets right instance", beanOne, BeanUtilsBean.getInstance());
442         
443         thread.start();
444         thread.join();
445         
446         assertEquals("Signal not set by test thread", 21, signal.getSignal());
447         assertEquals("Second thread preserves value", beanOne, BeanUtilsBean.getInstance());
448         assertEquals("Second thread gets value it set", beanTwo, signal.getBean());
449     }
450     
451     /** Tests whether the unset method works*/
452     public void testContextClassLoaderUnset() throws Exception JavaDoc {
453         BeanUtilsBean beanOne = new BeanUtilsBean();
454         ContextClassLoaderLocal ccll = new ContextClassLoaderLocal();
455         ccll.set(beanOne);
456         assertEquals("Start thread gets right instance", beanOne, ccll.get());
457         ccll.unset();
458         assertTrue("Unset works", !beanOne.equals(ccll.get()));
459     }
460     
461     private boolean isPre14JVM() {
462         // some pre 1.4 JVM have buggy WeakHashMap implementations
463
// this is used to test for those JVM
464
String JavaDoc version = System.getProperty("java.specification.version");
465         StringTokenizer tokenizer = new StringTokenizer(version,".");
466         if (tokenizer.nextToken().equals("1")) {
467             String JavaDoc minorVersion = tokenizer.nextToken();
468             if (minorVersion.equals("0")) return true;
469             if (minorVersion.equals("1")) return true;
470             if (minorVersion.equals("2")) return true;
471             if (minorVersion.equals("3")) return true;
472         }
473         return false;
474     }
475     
476     // ---- Auxillary classes
477

478     class TestClassLoader extends ClassLoader JavaDoc {
479         public String JavaDoc toString() {
480             return "TestClassLoader";
481         }
482     }
483     
484     class Signal {
485         private Exception JavaDoc e;
486         private int signal = 0;
487         private BeanUtilsBean bean;
488         private PropertyUtilsBean propertyUtils;
489         private ConvertUtilsBean convertUtils;
490         private Object JavaDoc marker;
491         
492         public Exception JavaDoc getException() {
493             return e;
494         }
495         
496         public void setException(Exception JavaDoc e) {
497             this.e = e;
498         }
499         
500         public int getSignal() {
501             return signal;
502         }
503         
504         public void setSignal(int signal) {
505             this.signal = signal;
506         }
507         
508         public Object JavaDoc getMarkerObject() {
509             return marker;
510         }
511         
512         public void setMarkerObject(Object JavaDoc marker) {
513             this.marker = marker;
514         }
515         
516         public BeanUtilsBean getBean() {
517             return bean;
518         }
519         
520         public void setBean(BeanUtilsBean bean) {
521             this.bean = bean;
522         }
523         
524         public PropertyUtilsBean getPropertyUtils() {
525             return propertyUtils;
526         }
527         
528         public void setPropertyUtils(PropertyUtilsBean propertyUtils) {
529             this.propertyUtils = propertyUtils;
530         }
531         
532         public ConvertUtilsBean getConvertUtils() {
533             return convertUtils;
534         }
535         
536         public void setConvertUtils(ConvertUtilsBean convertUtils) {
537             this.convertUtils = convertUtils;
538         }
539     }
540 }
541
542
Popular Tags