1 16 17 package org.apache.commons.beanutils.locale; 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 import org.apache.commons.beanutils.ContextClassLoaderLocal; 32 import org.apache.commons.beanutils.PrimitiveBean; 33 34 44 45 public class LocaleBeanificationTestCase extends TestCase { 46 47 49 50 public static final int MAX_GC_ITERATIONS = 50; 51 52 54 55 57 58 63 public LocaleBeanificationTestCase(String name) { 64 super(name); 65 } 66 67 68 70 71 74 public void setUp() { 75 76 LocaleConvertUtils.deregister(); 77 78 } 79 80 81 84 public static Test suite() { 85 return (new TestSuite(LocaleBeanificationTestCase.class)); 86 } 87 88 89 92 public void tearDown() { 93 ; } 95 96 97 99 100 public void testMemoryTestMethodology() throws Exception { 101 ClassLoader loader = new ClassLoader () {}; 104 WeakReference reference = new WeakReference (loader); 105 Class myClass = loader.loadClass("org.apache.commons.beanutils.BetaBean"); 106 107 assertNotNull("Weak reference released early", reference.get()); 108 109 loader = null; 111 myClass = null; 112 113 int iterations = 0; 114 int bytz = 2; 115 while(true) { 116 System.gc(); 117 if(iterations++ > MAX_GC_ITERATIONS){ 118 fail("Max iterations reached before resource released."); 119 } 120 if( reference.get() == null ) { 121 break; 122 123 } else { 124 byte[] b = new byte[bytz]; 126 bytz = bytz * 2; 127 } 128 } 129 } 130 131 132 public void testMemoryLeak2() throws Exception { 133 135 if (isPre14JVM()) { 136 System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM"); 137 return; 138 } 139 140 TestClassLoader loader = new TestClassLoader(); 142 ReferenceQueue queue = new ReferenceQueue (); 143 WeakReference loaderReference = new WeakReference (loader, queue); 144 Integer test = new Integer (1); 145 146 WeakReference testReference = new WeakReference (test, queue); 147 Map map = new WeakHashMap(); 149 map.put(loader, test); 150 151 assertEquals("In map", test, map.get(loader)); 152 assertNotNull("Weak reference released early (1)", loaderReference.get()); 153 assertNotNull("Weak reference released early (2)", testReference.get()); 154 155 loader = null; 157 test = null; 158 159 int iterations = 0; 160 int bytz = 2; 161 while(true) { 162 System.gc(); 163 if(iterations++ > MAX_GC_ITERATIONS){ 164 fail("Max iterations reached before resource released."); 165 } 166 map.isEmpty(); 167 168 if( 169 loaderReference.get() == null && 170 testReference.get() == null) { 171 break; 172 173 } else { 174 byte[] b = new byte[bytz]; 176 bytz = bytz * 2; 177 } 178 } 179 } 180 181 182 public void testMemoryLeak() throws Exception { 183 if (isPre14JVM()) { 184 System.out.println("WARNING: CANNOT TEST MEMORY LEAK ON PRE1.4 JVM"); 185 return; 186 } 187 188 TestClassLoader loader = new TestClassLoader(); 190 WeakReference loaderReference = new WeakReference (loader); 191 LocaleBeanUtilsBean.getLocaleBeanUtilsInstance(); 192 193 class GetBeanUtilsBeanThread extends Thread { 194 195 LocaleBeanUtilsBean beanUtils; 196 LocaleConvertUtilsBean convertUtils; 197 198 GetBeanUtilsBeanThread() {} 199 200 public void run() { 201 beanUtils = LocaleBeanUtilsBean.getLocaleBeanUtilsInstance(); 202 convertUtils = LocaleConvertUtilsBean.getInstance(); 203 LogFactory.releaseAll(); 205 } 206 207 public String toString() { 208 return "GetBeanUtilsBeanThread"; 209 } 210 } 211 212 213 GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(); 214 WeakReference threadWeakReference = new WeakReference (thread); 215 thread.setContextClassLoader(loader); 216 217 thread.start(); 218 thread.join(); 219 220 WeakReference beanUtilsReference = new WeakReference (thread.beanUtils); 221 WeakReference convertUtilsReference = new WeakReference (thread.convertUtils); 222 223 assertNotNull("Weak reference released early (1)", loaderReference.get()); 224 assertNotNull("Weak reference released early (2)", beanUtilsReference.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 LocaleBeanUtilsBean.getLocaleBeanUtilsInstance(); 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 convertUtilsReference.get() == null) { 245 break; 246 247 } else { 248 byte[] b = new byte[bytz]; 250 bytz = bytz * 2; 251 } 252 } 253 } 254 255 259 public void testGetByContextClassLoader() throws Exception { 260 261 class GetBeanUtilsBeanThread extends Thread { 262 263 private Signal signal; 264 265 GetBeanUtilsBeanThread(Signal signal) { 266 this.signal = signal; 267 } 268 269 public void run() { 270 signal.setSignal(2); 271 signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance()); 272 signal.setConvertUtils(LocaleConvertUtilsBean.getInstance()); 273 } 274 275 public String toString() { 276 return "GetBeanUtilsBeanThread"; 277 } 278 } 279 280 Signal signal = new Signal(); 281 signal.setSignal(1); 282 283 GetBeanUtilsBeanThread thread = new GetBeanUtilsBeanThread(signal); 284 thread.setContextClassLoader(new TestClassLoader()); 285 286 thread.start(); 287 thread.join(); 288 289 assertEquals("Signal not set by test thread", 2, signal.getSignal()); 290 assertTrue( 291 "Different LocaleBeanUtilsBean instances per context classloader", 292 LocaleBeanUtilsBean.getInstance() != signal.getBean()); 293 assertTrue( 294 "Different LocaleConvertUtilsBean instances per context classloader", 295 LocaleConvertUtilsBean.getInstance() != signal.getConvertUtils()); 296 } 297 298 299 303 public void testContextClassLoaderLocal() throws Exception { 304 305 class CCLLTesterThread extends Thread { 306 307 private Signal signal; 308 private ContextClassLoaderLocal ccll; 309 310 CCLLTesterThread(Signal signal, ContextClassLoaderLocal ccll) { 311 this.signal = signal; 312 this.ccll = ccll; 313 } 314 315 public void run() { 316 ccll.set(new Integer (1789)); 317 signal.setSignal(2); 318 signal.setMarkerObject(ccll.get()); 319 } 320 321 public String toString() { 322 return "CCLLTesterThread"; 323 } 324 } 325 326 ContextClassLoaderLocal ccll = new ContextClassLoaderLocal(); 327 ccll.set(new Integer (1776)); 328 assertEquals("Start thread sets value", new Integer (1776), ccll.get()); 329 330 Signal signal = new Signal(); 331 signal.setSignal(1); 332 333 CCLLTesterThread thread = new CCLLTesterThread(signal, ccll); 334 thread.setContextClassLoader(new TestClassLoader()); 335 336 thread.start(); 337 thread.join(); 338 339 assertEquals("Signal not set by test thread", 2, signal.getSignal()); 340 assertEquals("Second thread preserves value", new Integer (1776), ccll.get()); 341 assertEquals("Second thread gets value it set", new Integer (1789), signal.getMarkerObject()); 342 } 343 344 345 public void testContextClassloaderIndependence() throws Exception { 346 347 class TestIndependenceThread extends Thread { 348 private Signal signal; 349 private PrimitiveBean bean; 350 351 TestIndependenceThread(Signal signal, PrimitiveBean bean) { 352 this.signal = signal; 353 this.bean = bean; 354 } 355 356 public void run() { 357 try { 358 signal.setSignal(3); 359 LocaleConvertUtils.register(new LocaleConverter() { 360 public Object convert(Class type, Object value) { 361 return new Integer (9); 362 } 363 public Object convert(Class type, Object value, String pattern) { 364 return new Integer (9); 365 } 366 }, Integer.TYPE, Locale.getDefault()); 367 LocaleBeanUtils.setProperty(bean, "int", "1"); 368 } catch (Exception e) { 369 e.printStackTrace(); 370 signal.setException(e); 371 } 372 } 373 374 public String toString() { 375 return "TestIndependenceThread"; 376 } 377 } 378 379 PrimitiveBean bean = new PrimitiveBean(); 380 LocaleBeanUtils.setProperty(bean, "int", new Integer (1)); 381 assertEquals("Wrong property value (1)", 1, bean.getInt()); 382 383 LocaleConvertUtils.register(new LocaleConverter() { 384 public Object convert(Class type, Object value) { 385 return new Integer (5); 386 } 387 public Object convert(Class type, Object value, String pattern) { 388 return new Integer (5); 389 } 390 }, Integer.TYPE, Locale.getDefault()); 391 LocaleBeanUtils.setProperty(bean, "int", "1"); 392 assertEquals("Wrong property value(2)", 5, bean.getInt()); 393 394 Signal signal = new Signal(); 395 signal.setSignal(1); 396 TestIndependenceThread thread = new TestIndependenceThread(signal, bean); 397 thread.setContextClassLoader(new TestClassLoader()); 398 399 thread.start(); 400 thread.join(); 401 402 assertNull("Exception thrown by test thread:" + signal.getException(), signal.getException()); 403 assertEquals("Signal not set by test thread", 3, signal.getSignal()); 404 assertEquals("Wrong property value(3)", 9, bean.getInt()); 405 406 } 407 408 409 public void testBeanUtilsBeanSetInstance() throws Exception { 410 411 class SetInstanceTesterThread extends Thread { 412 413 private Signal signal; 414 private LocaleBeanUtilsBean bean; 415 416 SetInstanceTesterThread(Signal signal, LocaleBeanUtilsBean bean) { 417 this.signal = signal; 418 this.bean = bean; 419 } 420 421 public void run() { 422 LocaleBeanUtilsBean.setInstance(bean); 423 signal.setSignal(21); 424 signal.setBean(LocaleBeanUtilsBean.getLocaleBeanUtilsInstance()); 425 } 426 427 public String toString() { 428 return "SetInstanceTesterThread"; 429 } 430 } 431 432 Signal signal = new Signal(); 433 signal.setSignal(1); 434 435 LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean(); 436 LocaleBeanUtilsBean beanTwo = new LocaleBeanUtilsBean(); 437 438 SetInstanceTesterThread thread = new SetInstanceTesterThread(signal, beanTwo); 439 thread.setContextClassLoader(new TestClassLoader()); 440 441 LocaleBeanUtilsBean.setInstance(beanOne); 442 assertEquals("Start thread gets right instance", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance()); 443 444 thread.start(); 445 thread.join(); 446 447 assertEquals("Signal not set by test thread", 21, signal.getSignal()); 448 assertEquals("Second thread preserves value", beanOne, LocaleBeanUtilsBean.getLocaleBeanUtilsInstance()); 449 assertEquals("Second thread gets value it set", beanTwo, signal.getBean()); 450 } 451 452 453 public void testContextClassLoaderUnset() throws Exception { 454 LocaleBeanUtilsBean beanOne = new LocaleBeanUtilsBean(); 455 ContextClassLoaderLocal ccll = new ContextClassLoaderLocal(); 456 ccll.set(beanOne); 457 assertEquals("Start thread gets right instance", beanOne, ccll.get()); 458 ccll.unset(); 459 assertTrue("Unset works", !beanOne.equals(ccll.get())); 460 } 461 462 private boolean isPre14JVM() { 463 String version = System.getProperty("java.specification.version"); 466 StringTokenizer tokenizer = new StringTokenizer(version,"."); 467 if (tokenizer.nextToken().equals("1")) { 468 String minorVersion = tokenizer.nextToken(); 469 if (minorVersion.equals("0")) return true; 470 if (minorVersion.equals("1")) return true; 471 if (minorVersion.equals("2")) return true; 472 if (minorVersion.equals("3")) return true; 473 } 474 return false; 475 } 476 477 479 class TestClassLoader extends ClassLoader { 480 public String toString() { 481 return "TestClassLoader"; 482 } 483 } 484 485 class Signal { 486 private Exception e; 487 private int signal = 0; 488 private LocaleBeanUtilsBean bean; 489 private LocaleConvertUtilsBean 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 LocaleBeanUtilsBean getBean() { 517 return bean; 518 } 519 520 public void setBean(LocaleBeanUtilsBean bean) { 521 this.bean = bean; 522 } 523 524 public LocaleConvertUtilsBean getConvertUtils() { 525 return convertUtils; 526 } 527 528 public void setConvertUtils(LocaleConvertUtilsBean convertUtils) { 529 this.convertUtils = convertUtils; 530 } 531 } 532 } 533 534 | Popular Tags |