1 17 package org.apache.avalon.excalibur.component.test; 18 19 import junit.framework.TestCase; 20 import junit.framework.TestSuite; 21 22 import org.apache.avalon.excalibur.component.DefaultComponentPool; 23 import org.apache.avalon.excalibur.component.ExcaliburComponentManager; 24 import org.apache.avalon.excalibur.pool.Poolable; 25 import org.apache.avalon.framework.activity.Disposable; 26 import org.apache.avalon.framework.component.Component; 27 import org.apache.avalon.framework.component.ComponentException; 28 import org.apache.avalon.framework.component.ComponentManager; 29 import org.apache.avalon.framework.component.Composable; 30 import org.apache.avalon.framework.configuration.Configuration; 31 import org.apache.avalon.framework.configuration.DefaultConfiguration; 32 import org.apache.avalon.framework.context.DefaultContext; 33 import org.apache.avalon.framework.logger.AbstractLogEnabled; 34 import org.apache.avalon.framework.logger.LogKitLogger; 35 import org.apache.avalon.framework.logger.Logger; 36 import org.apache.avalon.framework.thread.SingleThreaded; 37 import org.apache.avalon.framework.thread.ThreadSafe; 38 import org.apache.avalon.excalibur.testcase.ComponentStateValidator; 39 import org.apache.log.Hierarchy; 40 import org.apache.log.LogTarget; 41 import org.apache.log.Priority; 42 import org.apache.log.format.PatternFormatter; 43 import org.apache.log.output.io.StreamTarget; 44 45 54 public class ExcaliburComponentManagerTestCase extends TestCase 55 { 56 72 public static TestSuite suite() 73 { 74 TestSuite suite = new TestSuite(); 75 76 String [] behaviors = {"Bad", "Good"}; 77 String [] kidTypes = {""}; String [] lifestyles = {"SingleThreaded", "ThreadSafe", "Poolable"}; 79 80 for( int mb = 0; mb < behaviors.length; mb++ ) 81 { 82 for( int db = 0; db < behaviors.length; db++ ) 83 { 84 for( int kt = 0; kt < kidTypes.length; kt++ ) 85 { 86 for( int ml = 0; ml < lifestyles.length; ml++ ) 87 { 88 for( int dl = 0; dl < lifestyles.length; dl++ ) 89 { 90 for( int kl = 0; kl < lifestyles.length; kl++ ) 91 { 92 final String momClassName = 93 lifestyles[ ml ] + behaviors[ mb ] + "Mom"; 94 final String dadClassName = 95 lifestyles[ dl ] + behaviors[ db ] + "Dad"; 96 final String kidClassName = 97 lifestyles[ kl ] + kidTypes[ kt ] + "Kid"; 98 99 final String prefix = 100 ExcaliburComponentManagerTestCase.class.getName() + "$"; 101 102 suite.addTest 103 ( new ExcaliburComponentManagerTestCase( momClassName + 104 dadClassName + 105 kidClassName ) 106 { 107 public void runTest() throws Exception 108 { 109 managerLifecycle( Class.forName 110 ( prefix + momClassName ), 111 Class.forName 112 ( prefix + dadClassName ), 113 Class.forName 114 ( prefix + kidClassName ) ); 115 } 116 } 117 ); 118 } 119 } 120 } 121 } 122 } 123 } 124 125 return suite; 126 } 127 128 protected void managerLifecycle( Class momClass, Class dadClass, Class kidClass ) 129 throws Exception 130 { 131 Configuration emptyConfig = new DefaultConfiguration( "", "" ); 132 133 m_manager.addComponent( Mom.ROLE, momClass, emptyConfig ); 134 m_manager.addComponent( Dad.ROLE, dadClass, emptyConfig ); 135 m_manager.addComponent( Kid.ROLE, kidClass, emptyConfig ); 136 137 m_manager.initialize(); 138 139 Component mom = m_manager.lookup( Mom.ROLE ); 140 Component dad = m_manager.lookup( Dad.ROLE ); 141 142 m_manager.release( mom ); 143 m_manager.release( dad ); 144 145 m_manager.dispose(); 146 147 if( momClass.getName().indexOf( "Good" ) > -1 && 150 dadClass.getName().indexOf( "Good" ) > -1 ) 151 { 152 checkNumberOfDisposals( momClass, dadClass, kidClass ); 153 } 154 } 155 156 private void checkNumberOfDisposals( Class momClass, Class dadClass, Class kidClass ) 157 { 158 int momInstances = 1, dadInstances = 1; 159 160 int kidInstances = determineNumberOfKidInstances( kidClass, momInstances, dadInstances ); 161 162 int expectedDisposals = momInstances + dadInstances + kidInstances; 163 164 assertEquals( expectedDisposals, m_disposals ); 165 } 166 167 private int determineNumberOfKidInstances( Class kidClass, int momInstances, int dadInstances ) 168 { 169 int parentInstances = ( momInstances + dadInstances ); 170 171 if( ThreadSafe.class.isAssignableFrom( kidClass ) ) 172 { 173 return 1; 175 } 176 else if( Poolable.class.isAssignableFrom( kidClass ) ) 177 { 178 int poolGrowParameter = DefaultComponentPool.DEFAULT_POOL_SIZE / 4; 179 180 int extraKidsNeeded = parentInstances % poolGrowParameter; 181 182 if( extraKidsNeeded > 0 ) 183 { 184 return parentInstances + ( poolGrowParameter - extraKidsNeeded ); 186 } 187 } 188 189 return parentInstances; 191 } 192 193 196 197 public static abstract class AbstractBadParent extends AbstractLogEnabled 198 implements Component, Composable, Disposable 199 { 200 private final ComponentStateValidator m_validator = new ComponentStateValidator( this ); 201 202 protected ComponentManager m_innerManager; 203 protected Kid m_kid; 204 205 public void enableLogging( Logger logger ) 206 { 207 m_validator.checkLogEnabled(); 208 209 super.enableLogging( logger ); 210 } 211 212 public void compose( ComponentManager manager ) throws ComponentException 213 { 214 m_validator.checkComposed(); 215 216 m_innerManager = manager; 217 218 m_kid = (Kid)m_innerManager.lookup( Kid.ROLE ); 219 } 220 221 public void dispose() 222 { 223 m_validator.checkDisposed(); 224 225 try 226 { 227 m_kid.getName(); 228 } 229 catch( IllegalStateException ise ) 230 { 231 fail( ise.getMessage() ); 232 } 233 234 m_disposals++; 235 } 236 } 237 238 public static abstract class AbstractGoodParent extends AbstractBadParent 239 { 240 public void dispose() 241 { 242 super.dispose(); 243 m_innerManager.release( m_kid ); 244 } 245 } 246 247 public interface Mom extends Component 248 { 249 String ROLE = "Mom"; 250 } 251 252 public static class SingleThreadedBadMom extends AbstractBadParent 253 implements Mom, SingleThreaded 254 { 255 } 256 public static class SingleThreadedGoodMom extends AbstractGoodParent 257 implements Mom, SingleThreaded 258 { 259 } 260 public static class ThreadSafeBadMom extends AbstractBadParent 261 implements Mom, ThreadSafe 262 { 263 } 264 public static class ThreadSafeGoodMom extends AbstractGoodParent 265 implements Mom, ThreadSafe 266 { 267 } 268 public static class PoolableBadMom extends AbstractBadParent 269 implements Mom, Poolable 270 { 271 } 272 public static class PoolableGoodMom extends AbstractGoodParent 273 implements Mom, Poolable 274 { 275 } 276 277 public interface Dad extends Component 278 { 279 String ROLE = "Dad"; 280 } 281 282 public static class SingleThreadedBadDad extends AbstractBadParent 283 implements Dad, SingleThreaded 284 { 285 } 286 public static class SingleThreadedGoodDad extends AbstractGoodParent 287 implements Dad, SingleThreaded 288 { 289 } 290 public static class ThreadSafeBadDad extends AbstractBadParent 291 implements Dad, ThreadSafe 292 { 293 } 294 public static class ThreadSafeGoodDad extends AbstractGoodParent 295 implements Dad, ThreadSafe 296 { 297 } 298 public static class PoolableBadDad extends AbstractBadParent 299 implements Dad, Poolable 300 { 301 } 302 public static class PoolableGoodDad extends AbstractGoodParent 303 implements Dad, Poolable 304 { 305 } 306 307 public interface Kid extends Component 308 { 309 String ROLE = "Kid"; 310 311 String getName(); 312 } 313 314 public static abstract class AbstractKid extends AbstractLogEnabled 315 implements Kid, Disposable 316 { 317 public static final String ROLE = "Kid"; 318 319 protected final ComponentStateValidator m_validator = new ComponentStateValidator( this ); 320 321 public void enableLogging( Logger logger ) 322 { 323 m_validator.checkLogEnabled(); 324 325 super.enableLogging( logger ); 326 } 327 328 public void dispose() 329 { 330 m_validator.checkDisposed(); 331 332 m_disposals++; 333 } 334 335 public String getName() 336 { 337 m_validator.checkActive(); 338 339 return "Kid"; 340 } 341 } 342 343 public static class SingleThreadedKid extends AbstractKid 344 implements SingleThreaded 345 { 346 } 347 public static class ThreadSafeKid extends AbstractKid 348 implements ThreadSafe 349 { 350 } 351 public static class PoolableKid extends AbstractKid 352 implements Poolable 353 { 354 } 355 356 public static abstract class AbstractBadCircularKid extends AbstractKid 357 implements Composable 358 { 359 protected ComponentManager m_innerManager; 360 protected Mom m_mom; 361 protected Dad m_dad; 362 363 public void compose( ComponentManager manager ) throws ComponentException 364 { 365 m_validator.checkComposed(); 366 367 m_innerManager = manager; 368 } 369 370 public String getName() 371 { 372 String name = super.getName(); 373 374 try 375 { 376 m_mom = (Mom)m_innerManager.lookup( Mom.ROLE ); 377 m_dad = (Dad)m_innerManager.lookup( Dad.ROLE ); 378 } 379 catch( ComponentException ce ) 380 { 381 fail( ce.getMessage() ); 382 } 383 384 return ( name + " belongs to " + m_mom + " and " + m_dad ); 385 } 386 } 387 388 public static abstract class AbstractGoodCircularKid extends AbstractBadCircularKid 389 { 390 public void dispose() 391 { 392 super.dispose(); 393 394 m_innerManager.release( m_mom ); 395 m_innerManager.release( m_dad ); 396 } 397 } 398 399 public static class SingleThreadedBadCircularKid extends AbstractBadCircularKid 400 implements SingleThreaded 401 { 402 } 403 public static class ThreadSafeBadCircularKid extends AbstractBadCircularKid 404 implements ThreadSafe 405 { 406 } 407 public static class PoolableBadCircularKid extends AbstractBadCircularKid 408 implements Poolable 409 { 410 } 411 public static class SingleThreadedGoodCircularKid extends AbstractGoodCircularKid 412 implements SingleThreaded 413 { 414 } 415 public static class ThreadSafeGoodCircularKid extends AbstractGoodCircularKid 416 implements ThreadSafe 417 { 418 } 419 public static class PoolableGoodCircularKid extends AbstractGoodCircularKid 420 implements Poolable 421 { 422 } 423 424 427 428 private static int m_disposals; 429 430 private ExcaliburComponentManager m_manager; 431 432 private Logger m_logger; 433 434 public ExcaliburComponentManagerTestCase( String name ) 435 { 436 super( name ); 437 } 438 439 public void setUp() throws Exception 440 { 441 m_disposals = 0; 442 443 m_manager = new ExcaliburComponentManager(); 444 445 final String pattern = 446 ( "%5.5{priority} [%40.40{category}]: %{message}\n%{throwable}" ); 447 448 org.apache.log.Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor( getName() ); 449 logger.setLogTargets 450 ( new LogTarget[] 451 {new StreamTarget( System.out, new PatternFormatter( pattern ) )} ); 452 logger.setPriority( Priority.INFO ); 453 454 m_manager.enableLogging( new LogKitLogger( logger ) ); 455 m_manager.contextualize( new DefaultContext() ); 456 m_manager.configure( new DefaultConfiguration( "", "" ) ); 457 458 m_logger = new LogKitLogger( logger ); 459 } 460 461 public void tearDown() 462 { 463 m_manager = null; 464 } 465 466 } 467 | Popular Tags |