From c62d3800e6b2e322320b69117f450fafe9b44224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Thu, 17 Sep 2015 23:41:21 +0200 Subject: [PATCH] Component state - Tests for the "driver" code --- TODO | 1 - .../info/ebenoit/ebul/cmp/ComponentState.java | 4 + .../ebenoit/ebul/cmp/TestComponentState.java | 279 +++++++++++++++++- 3 files changed, 272 insertions(+), 12 deletions(-) diff --git a/TODO b/TODO index 5b98d17..4e72dec 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ To Do: - * Tests for driver-related stuff in ComponentState * Registry tests * Registry doc * General usage documentation diff --git a/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java b/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java index a124dad..c4ad981 100644 --- a/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java +++ b/src/main/java/info/ebenoit/ebul/cmp/ComponentState.java @@ -352,6 +352,10 @@ public final class ComponentState * This method attempts to initialise a component. It makes sure that all of the component's dependencies have been * initialised, then executes the lifecycle action for the {@link LifecycleStage#INITIALISE INITIALISE} stage. Then, * if the component has drivers, it initialises them. + *

+ * Note: unlike the {@link #start()} method, which can be called from anywhere, this method is always called in + * "the right order" by the registry. Because of that, no attempts at protecting from a second execution of the + * initialisation action are made. * * @throws ComponentInitialisationException * if an error occurs while executing an initialisation action diff --git a/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java b/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java index cd24c91..34c4cc2 100644 --- a/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java +++ b/src/test/java/info/ebenoit/ebul/cmp/TestComponentState.java @@ -73,7 +73,7 @@ public class TestComponentState @Override - public void setComponentRegistry( ComponentRegistry registry ) + public void setComponentRegistry( final ComponentRegistry registry ) { this.registry = registry; } @@ -118,12 +118,12 @@ public class TestComponentState final ComponentState cs = new ComponentState( reg , ci ); try { if ( initialised ) { - Field f = ComponentState.class.getDeclaredField( "initialised" ); + final Field f = ComponentState.class.getDeclaredField( "initialised" ); f.setAccessible( true ); f.setBoolean( cs , true ); } if ( active ) { - Field f = ComponentState.class.getDeclaredField( "active" ); + final Field f = ComponentState.class.getDeclaredField( "active" ); f.setAccessible( true ); f.setBoolean( cs , true ); } @@ -310,7 +310,7 @@ public class TestComponentState public void testInitNoAction( ) { final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( new Object( ) ); - final ComponentState cs = makeState( ci , reg , false , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , false , false ); cs.init( ); Assert.assertTrue( cs.isInitialised( ) ); } @@ -325,7 +325,7 @@ public class TestComponentState .setLifecycleAction( LifecycleStage.INITIALISE , ( o ) -> { o.stage = LifecycleStage.INITIALISE; } ); - final ComponentState cs = makeState( ci , reg , false , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , false , false ); cs.init( ); Assert.assertSame( LifecycleStage.INITIALISE , lcaTest.stage ); Assert.assertTrue( cs.isInitialised( ) ); @@ -341,7 +341,7 @@ public class TestComponentState .setLifecycleAction( LifecycleStage.INITIALISE , ( o ) -> { o.stage = LifecycleStage.INITIALISE; } ); - final ComponentState cs = makeState( ci , reg , true , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , true , false ); cs.init( ); Assert.assertNull( lcaTest.stage ); } @@ -411,6 +411,72 @@ public class TestComponentState } + /** Test: {@link ComponentState#init()} initialises the component's drivers */ + @Test + public void testInitDrivers( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , false , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , false , false ); + cs2.setDriverFor( cs1 ); + + cs1.init( ); + Assert.assertTrue( cs2.isInitialised( ) ); + } + + + /** + * Test: {@link ComponentState#init()} initialises the component's drivers after the component + */ + @Test + public void testInitDriversOrder( ) + { + final LCATest lcaTest = new LCATest( ); + final NewComponentInfo< LCATest > ci1 = new NewComponentInfo< LCATest >( lcaTest ) // + .setLifecycleAction( LifecycleStage.INITIALISE , ( o ) -> { + o.stage = LifecycleStage.INITIALISE; + } ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , false , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.INITIALISE , ( o ) -> { + Assert.assertSame( LifecycleStage.INITIALISE , lcaTest.stage ); + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , false , false ); + cs2.setDriverFor( cs1 ); + + cs1.init( ); + } + + + /** + * Test: {@link ComponentState#init()} initialises the component even if the drivers fail to initialise + */ + @Test + public void testInitDriverFailure( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , false , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.INITIALISE , ( o ) -> { + throw new ComponentInitialisationException( ); + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , false , false ); + cs2.setDriverFor( cs1 ); + + try { + cs1.init( ); + } catch ( final ComponentInitialisationException e ) { + Assert.assertTrue( cs1.isInitialised( ) ); + return; + } + Assert.fail( "no ComponentInitialisationException" ); + } + + /** Test: {@link ComponentState#destroy()} throws {@link IllegalStateException} if the component is active */ @Test( expected = IllegalStateException.class ) public void testDestroyActive( ) @@ -509,6 +575,52 @@ public class TestComponentState } + /** Test: {@link ComponentState#destroy()} destroys the component's drivers */ + @Test + public void testDestroyDrivers( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + + cs1.destroy( ); + Assert.assertFalse( cs2.isInitialised( ) ); + } + + + /** + * Test: {@link ComponentState#destroy()} destroys the component's drivers after the component's other reverse + * dependencies + */ + @Test + public void testDestroyDriversOrder( ) + { + final LCATest lcaTest = new LCATest( ); + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci3 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.DESTROY , ( o ) -> { + Assert.assertNull( lcaTest.stage ); + } ); + final ComponentState cs3 = TestComponentState.makeState( ci3 , this.reg , true , false ); + cs3.addDependency( cs1 ); + + final NewComponentInfo< LCATest > ci2 = new NewComponentInfo< LCATest >( lcaTest ) // + .setLifecycleAction( LifecycleStage.DESTROY , ( o ) -> { + o.stage = LifecycleStage.DESTROY; + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + cs1.destroy( ); + } + + /** Test: {@link ComponentState#start()} on uninitialised components throws {@link IllegalStateException} */ @Test( expected = IllegalStateException.class ) public void testStartUninitialised( ) @@ -525,7 +637,7 @@ public class TestComponentState public void testStartFailedRegistry( ) { final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( new Object( ) ); - final ComponentState cs = makeState( ci , reg , true , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , true , false ); this.reg.failed = true; cs.start( ); } @@ -536,7 +648,7 @@ public class TestComponentState public void testStartInactiveRegistry( ) { final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( new Object( ) ); - final ComponentState cs = makeState( ci , reg , true , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , true , false ); cs.start( ); } @@ -546,7 +658,7 @@ public class TestComponentState public void testStartNoAction( ) { final NewComponentInfo< Object > ci = new NewComponentInfo< Object >( new Object( ) ); - final ComponentState cs = makeState( ci , reg , true , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , true , false ); this.reg.active = true; cs.start( ); Assert.assertTrue( cs.isActive( ) ); @@ -562,7 +674,7 @@ public class TestComponentState .setLifecycleAction( LifecycleStage.START , ( o ) -> { o.stage = LifecycleStage.START; } ); - final ComponentState cs = makeState( ci , reg , true , false ); + final ComponentState cs = TestComponentState.makeState( ci , this.reg , true , false ); this.reg.active = true; cs.start( ); Assert.assertSame( LifecycleStage.START , lcaTest.stage ); @@ -651,6 +763,103 @@ public class TestComponentState } + /** Test: {@link ComponentState#start()} starts the component's drivers */ + @Test + public void testStartDrivers( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + this.reg.active = true; + cs1.start( ); + Assert.assertTrue( cs2.isActive( ) ); + } + + + /** + * Test: {@link ComponentState#start()} starts the component's drivers after the component + */ + @Test + public void testStartDriversOrder( ) + { + final LCATest lcaTest = new LCATest( ); + final NewComponentInfo< LCATest > ci1 = new NewComponentInfo< LCATest >( lcaTest ) // + .setLifecycleAction( LifecycleStage.START , ( o ) -> { + o.stage = LifecycleStage.START; + } ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.START , ( o ) -> { + Assert.assertSame( LifecycleStage.START , lcaTest.stage ); + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + this.reg.active = true; + cs1.start( ); + } + + + /** + * Test: {@link ComponentState#start()} starts the component even if the drivers fail to start + */ + @Test + public void testStartDriverFailure( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.START , ( o ) -> { + throw new ComponentStartupException( ); + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + this.reg.active = true; + try { + cs1.start( ); + } catch ( final ComponentStartupException e ) { + Assert.assertTrue( cs1.isActive( ) ); + return; + } + Assert.fail( "no ComponentStartupException" ); + } + + + /** Test: {@link ComponentState#start()} on a driver starts the component and the drivers */ + @Test + public void testStartDriverDirectly( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , false ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , false ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + final NewComponentInfo< Object > ci3 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs3 = TestComponentState.makeState( ci3 , this.reg , true , false ); + cs3.setDriverFor( cs1 ); + cs3.addDependency( cs1 ); + + this.reg.active = true; + cs2.start( ); + Assert.assertTrue( cs1.isActive( ) ); + Assert.assertTrue( cs2.isActive( ) ); + Assert.assertTrue( cs3.isActive( ) ); + } + + /** Test: {@link ComponentState#stop()} with a failed registry throws {@link IllegalStateException} */ @Test( expected = IllegalStateException.class ) public void testStopFailedRegistry( ) @@ -704,7 +913,7 @@ public class TestComponentState this.reg.active = true; try { cs.stop( ); - } catch ( ComponentShutdownException e ) { + } catch ( final ComponentShutdownException e ) { Assert.assertSame( failure , e ); Assert.assertTrue( cs.isActive( ) ); return; @@ -730,6 +939,54 @@ public class TestComponentState } + /** Test: {@link ComponentState#stop()} stops the component's drivers */ + @Test + public void testStopDrivers( ) + { + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , true ); + + final NewComponentInfo< Object > ci2 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , true ); + cs2.setDriverFor( cs1 ); + + this.reg.active = true; + cs1.stop( ); + Assert.assertFalse( cs2.isActive( ) ); + } + + + /** + * Test: {@link ComponentState#stop()} stops the component's drivers after the component's other reverse + * dependencies + */ + @Test + public void testStopDriversOrder( ) + { + final LCATest lcaTest = new LCATest( ); + final NewComponentInfo< Object > ci1 = new NewComponentInfo< Object >( new Object( ) ); + final ComponentState cs1 = TestComponentState.makeState( ci1 , this.reg , true , true ); + + final NewComponentInfo< Object > ci3 = new NewComponentInfo< Object >( new Object( ) ) // + .setLifecycleAction( LifecycleStage.STOP , ( o ) -> { + Assert.assertNull( lcaTest.stage ); + } ); + final ComponentState cs3 = TestComponentState.makeState( ci3 , this.reg , true , true ); + cs3.addDependency( cs1 ); + + final NewComponentInfo< LCATest > ci2 = new NewComponentInfo< LCATest >( lcaTest ) // + .setLifecycleAction( LifecycleStage.STOP , ( o ) -> { + o.stage = LifecycleStage.STOP; + } ); + final ComponentState cs2 = TestComponentState.makeState( ci2 , this.reg , true , true ); + cs2.setDriverFor( cs1 ); + cs2.addDependency( cs1 ); + + this.reg.active = true; + cs1.stop( ); + } + + /** Test: {@link ComponentState#restart()} with a failed registry throws {@link IllegalStateException} */ @Test( expected = IllegalStateException.class ) public void testRestartFailedRegistry( )