1 16 17 package org.apache.commons.beanutils; 18 19 import java.util.*; 20 21 import java.lang.ref.WeakReference ; 22 import java.lang.ref.ReferenceQueue ; 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 40 41 public class BeanificationTestCase extends TestCase { 42 43 45 46 public static final int MAX_GC_ITERATIONS = 50; 47 48 50 51 53 54 59 public BeanificationTestCase(String name) { 60 super(name); 61 } 62 63 64 66 67 70 public void setUp() { 71 72 ConvertUtils.deregister(); 73 74 } 75 76 77 80 public static Test suite() { 81 return (new TestSuite(BeanificationTestCase.class)); 82 } 83 84 85 88 public void tearDown() { 89 ; } 91 92 93 95 96 public void testMemoryTestMethodology() throws Exception { 97 ClassLoader loader = new ClassLoader () {}; 100 WeakReference reference = new WeakReference (loader); 101 Class myClass = loader.loadClass("org.apache.commons.beanutils.BetaBean"); 102 103 assertNotNull("Weak reference released early", reference.get()); 104 105 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 byte[] b = new byte[bytz]; 122 bytz = bytz * 2; 123 } 124 } 125 } 126 127 128 public void testMemoryLeak2() throws Exception { 129 131 if (isPre14JVM()) { 132 System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM"); 133 return; 134 } 135 136 TestClassLoader loader = new TestClassLoader(); 138 ReferenceQueue queue = new ReferenceQueue (); 139 WeakReference loaderReference = new WeakReference (loader, queue); 140 Integer test = new Integer (1); 141 142 WeakReference testReference = new WeakReference (test, queue); 143 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 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 byte[] b = new byte[bytz]; 172 bytz = bytz * 2; 173 } 174 } 175 } 176 177 178 public void testMemoryLeak() throws Exception { 179 if (isPre14JVM()) { 180 System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM"); 181 return; 182 } 183 184 TestClassLoader loader = new TestClassLoader(); 186 WeakReference loaderReference = new WeakReference (loader); 187 BeanUtilsBean.getInstance(); 188 189 class GetBeanUtilsBeanThread extends Thread { 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 LogFactory.releaseAll(); 203 } 204 205 public String toString() { 206 return "GetBeanUtilsBeanThread"; 207 } 208 } 209 210 211 GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(); 212 WeakReference threadWeakReference = new WeakReference (thread); 213 thread.setContextClassLoader(loader); 214 215 thread.start(); 216 thread.join(); 217 218 WeakReference beanUtilsReference = new WeakReference (thread.beanUtils); 219 WeakReference propertyUtilsReference = new WeakReference (thread.propertyUtils); 220 WeakReference convertUtilsReference = new WeakReference (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 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 byte[] b = new byte[bytz]; 251 bytz = bytz * 2; 252 } 253 } 254 } 255 256 260 public void testGetByContextClassLoader() throws Exception { 261 262 class GetBeanUtilsBeanThread extends Thread { 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 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 308 public void testContextClassLoaderLocal() throws Exception { 309 310 class CCLLTesterThread extends Thread { 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 (1789)); 322 signal.setSignal(2); 323 signal.setMarkerObject(ccll.get()); 324 } 325 326 public String toString() { 327 return "CCLLTesterThread"; 328 } 329 } 330 331 ContextClassLoaderLocal ccll = new ContextClassLoaderLocal(); 332 ccll.set(new Integer (1776)); 333 assertEquals("Start thread sets value", new Integer (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 (1776), ccll.get()); 346 assertEquals("Second thread gets value it set", new Integer (1789), signal.getMarkerObject()); 347 } 348 349 350 public void testContextClassloaderIndependence() throws Exception { 351 352 class TestIndependenceThread extends Thread { 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 convert(Class type, Object value) { 366 return new Integer (9); 367 } 368 }, Integer.TYPE); 369 BeanUtils.setProperty(bean, "int", new Integer (1)); 370 } catch (Exception e) { 371 e.printStackTrace(); 372 signal.setException(e); 373 } 374 } 375 376 public String toString() { 377 return "TestIndependenceThread"; 378 } 379 } 380 381 PrimitiveBean bean = new PrimitiveBean(); 382 BeanUtils.setProperty(bean, "int", new Integer (1)); 383 assertEquals("Wrong property value (1)", 1, bean.getInt()); 384 385 ConvertUtils.register(new Converter() { 386 public Object convert(Class type, Object value) { 387 return new Integer (5); 388 } 389 }, Integer.TYPE); 390 BeanUtils.setProperty(bean, "int", new Integer (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 408 public void testBeanUtilsBeanSetInstance() throws Exception { 409 410 class SetInstanceTesterThread extends Thread { 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 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 452 public void testContextClassLoaderUnset() throws Exception { 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 String version = System.getProperty("java.specification.version"); 465 StringTokenizer tokenizer = new StringTokenizer(version,"."); 466 if (tokenizer.nextToken().equals("1")) { 467 String 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 478 class TestClassLoader extends ClassLoader { 479 public String toString() { 480 return "TestClassLoader"; 481 } 482 } 483 484 class Signal { 485 private Exception e; 486 private int signal = 0; 487 private BeanUtilsBean bean; 488 private PropertyUtilsBean propertyUtils; 489 private ConvertUtilsBean convertUtils; 490 private Object marker; 491 492 public Exception getException() { 493 return e; 494 } 495 496 public void setException(Exception 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 getMarkerObject() { 509 return marker; 510 } 511 512 public void setMarkerObject(Object 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 |