You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2007/12/04 00:38:53 UTC

svn commit: r600729 - in /directory/apacheds/branches/bigbang/core-integ/src: main/java/org/apache/directory/server/core/integ/ main/java/org/apache/directory/server/core/integ/annotations/ main/java/org/apache/directory/server/core/integ/state/ test/j...

Author: akarasulu
Date: Mon Dec  3 15:38:50 2007
New Revision: 600729

URL: http://svn.apache.org/viewvc?rev=600729&view=rev
Log:
changes to integration framework ...

 o introduced state pattern to get rid of some serious complexity in the CiRunner
 o removed sample suite and same test classes since people can just look at doco and or
   the existing tests for now
 o added all the logic needed to get integration tests working again reusing the same
   service across tests in the same suite or across test runs even - highely configurable
 o removed some unneeded annotations
 o made the methods on the context static so static imports can be used: this works because
   of the ThreadLocal for thread specific context lookups
 o using inheritable settings class now to manage inheritance of properties from suites to
   classes to methods
 o new scope annotation created for the "intended scope" of a service: the intended scope
   is what is used to force a cleanup at that level. 
 o the default service factory now turns on the changelog by default
 

Added:
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Scope.java
      - copied, changed from r600253, directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java
Removed:
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/ForceCleanup.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleITest.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/integ/SampleSuite.java
Modified:
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/InheritableSettings.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/ServiceScope.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/NonExistentState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedDirtyState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedPristineState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedRevertedState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedDirtyState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedPristineState.java
    directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/TestServiceContext.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/StockCoreISuite.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java
    directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/collective/CollectiveAttributeServiceIT.java

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiRunner.java Mon Dec  3 15:38:50 2007
@@ -19,26 +19,15 @@
 package org.apache.directory.server.core.integ;
 
 
-import org.apache.directory.server.core.DirectoryService;
-import org.apache.directory.server.core.changelog.Tag;
-import static org.apache.directory.server.core.integ.AnnotationUtils.getMode;
-import static org.apache.directory.server.core.integ.AnnotationUtils.newFactory;
-import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
-import org.apache.directory.server.core.integ.annotations.Factory;
-import org.apache.directory.server.core.integ.annotations.ForceCleanup;
-import org.apache.directory.server.core.integ.annotations.Mode;
+import static org.apache.directory.server.core.integ.state.TestServiceContext.*;
 import org.junit.internal.runners.InitializationError;
 import org.junit.internal.runners.JUnit4ClassRunner;
-import org.junit.internal.runners.MethodRoadie;
-import org.junit.internal.runners.TestMethod;
 import org.junit.runner.Description;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-import javax.naming.NamingException;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 
@@ -50,126 +39,47 @@
  */
 public class CiRunner extends JUnit4ClassRunner
 {
-    /**
-     * The default setup mode to use is ROLLBACK.  Why you might ask
-     * is it not NOSERVICE?  The user shown us their intentions and has
-     * made a conscious decision to conduct tests with a running core
-     * service by selecting this Runner in the first place via the
-     * \@RunWith JUnit annotation.  So by default it makes sense to
-     * just give them that if they decide to use it in any of the tests
-     * contained which is most likely the case otherwise why would
-     * they bother to use this runner.  The thing is some tests may
-     * need the service and some might not even use it.  If the ROLLBACK
-     * mode is used then there is no cost incurred for having a running
-     * server in the background.  The server will be used anyway at some
-     * point by some tests.  When not used by some tests there are no
-     * rollbacks and so the service just sits waiting for tests to use
-     * it.
-     *
-     * <ul>
-     *   <li>
-     *     If the default was NOSERVICE the user would have to do more
-     *     work specify a mode on each test method that needs the core
-     *     service running.
-     *   </li>
-     *   <li>
-     *     If the default was PRISTINE then those tests not needing a
-     *     service up would shutdown existing servers, clean up,
-     *     create a new one and start the new service.  This process
-     *     costs about 2-3 seconds churns the disk and costs memory.
-     *     Turning off this default would require more effort on the
-     *     user when we already know their intensions.
-     *   </li>
-     *   <li>
-     *     If the default was RESTART then the impact would be similar
-     *     to the pristine case with perhaps much less waste but still
-     *     it would be very inefficient.
-     *   </li>
-     *   <li>
-     *     If the default was CUMULATIVE then some test that may delete
-     *     and create the same entries, often not worrying about cleanup
-     *     would collide causing false negatives.
-     *   </li>
-     * </ul>
-     *
-     * As you can see the best option for the default is the ROLLBACK mode.
-     * When a suite is present however mode inheritance can be utilized to
-     * override this default.
-     */
-    public static final SetupMode DEFAULT_MODE = SetupMode.ROLLBACK;
-
-    private Class<?> clazz;
+    private static final Logger LOG = LoggerFactory.getLogger( CiRunner.class );
     private CiSuite suite;
-    private SetupMode setupMode;
-    private DirectoryService service;
-    private DirectoryServiceFactory factory;
-    private boolean cleanup;
+    private InheritableSettings settings;
 
 
     public CiRunner( Class<?> clazz ) throws InitializationError
     {
         super( clazz );
-        this.clazz = clazz;
     }
 
 
-    @Override
-    public void run( final RunNotifier notifier )
+    protected InheritableSettings getSettings()
     {
-        if ( suite == null )
-        {
-            setupMode = getMode( clazz.getAnnotation( Mode.class ), DEFAULT_MODE );
-            factory = newFactory( clazz.getAnnotation( Factory.class ), DirectoryServiceFactory.DEFAULT );
-        }
-        else
-        {
-            service = suite.getService();
-            setupMode = getMode( clazz.getAnnotation( Mode.class ), suite.getSetupMode() );
-            factory = newFactory( clazz.getAnnotation( Factory.class ), suite.getFactory() );
-        }
-
-        if ( clazz.getAnnotation( ForceCleanup.class ) != null )
+        if ( settings != null )
         {
-            cleanup = true;
+            return settings;
         }
 
-        // if the suite is null that means it's up to this class to cleanup
-        if ( suite == null || cleanup )
+        if ( suite == null )
         {
-            cleanup( notifier );
+            settings = new InheritableSettings( getDescription(), null );
         }
 
-        super.run( notifier );
-
-        // if the suite is null that means it's up to this class to cleanup
-        if ( suite == null || cleanup )
-        {
-            cleanup( notifier );
-            service = null;
-        }
+        return settings;
     }
 
 
-    private void cleanup( final RunNotifier notifier )
+    @Override
+    public void run( final RunNotifier notifier )
     {
-        if ( service != null && service.isStarted() )
-        {
-            try
-            {
-                service.shutdown();
-            }
-            catch ( NamingException e )
-            {
-                notifier.fireTestFailure( new Failure( getDescription(), e ) );
-            }
-        }
-        else if ( service != null )
+        super.run( notifier );
+        ServiceScope scope = getSettings().getScope();
+        if ( scope == ServiceScope.TESTCLASS )
         {
             try
             {
-                doDelete( service.getWorkingDirectory() );
+                shutdown();
+                cleanup();
+                destroy();
             }
-            catch ( IOException e )
+            catch ( Exception e )
             {
                 notifier.fireTestFailure( new Failure( getDescription(), e ) );
             }
@@ -177,297 +87,24 @@
     }
 
 
-    public static final String INVALID_SERVICE_FIELD_MSG =
-            "You must create a static DirectoryService field named service in your test class: ";
-
-
     @Override
     protected void invokeTestMethod( Method method, final RunNotifier notifier )
     {
+        LOG.debug( "About to invoke test method {}", method.getName() );
         Description description = methodDescription( method );
-        Object test;
-
-        try
-        {
-            test = createTest();
-        }
-        catch ( InvocationTargetException e )
-        {
-            notifier.testAborted( description, e.getCause() );
-            return;
-        }
-        catch ( Exception e )
-        {
-            notifier.testAborted( description, e );
-            return;
-        }
-
-        TestMethod testMethod = wrapMethod( method );
-
-        if ( ! testMethod.isIgnored() )
-        {
-            SetupMode methodMode = getMode( method.getAnnotation( Mode.class ), setupMode );
-            DirectoryServiceFactory methodFactory = newFactory( method.getAnnotation( Factory.class ), factory );
-
-            if ( method.getAnnotation( ForceCleanup.class ) != null )
-            {
-                if ( service != null && service.isStarted() )
-                {
-                    try
-                    {
-                        service.shutdown();
-                    }
-                    catch ( NamingException e )
-                    {
-                        notifier.testAborted( description, e );
-                    }
-                }
-
-                if ( service != null )
-                {
-                    cleanup( notifier );
-                    service = null;
-                }
-            }
-
-            switch( methodMode.ordinal )
-            {
-                case( SetupMode.NOSERVICE_ORDINAL ):
-                case( SetupMode.CUMULATIVE_ORDINAL ):
-                    if ( service == null )
-                    {
-                        service = factory.newInstance();
-
-                        try
-                        {
-                            service.startup();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-
-                    if ( service != null )
-                    {
-                        try
-                        {
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    break;
-                case( SetupMode.ROLLBACK_ORDINAL ):
-                    // if the service is null instantiate it w/ factory
-                    if ( service == null )
-                    {
-                        service = methodFactory.newInstance();
-                        cleanup( notifier );
-                        service.getChangeLog().setEnabled( true );
-                        
-                        try
-                        {
-                            service.startup();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // if the service is not null but is stopped then we need to cleanup and start
-                    else if ( ! service.isStarted() )
-                    {
-                        cleanup( notifier );
-                        try
-                        {
-                            service.startup();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // server is up and running so we just need to revert it to the last tag
-                    else
-                    {
-                        Tag latest;
-
-                        try
-                        {
-                            latest = service.getChangeLog().getLatest();
-                            if ( latest == null && ! ( service.getChangeLog().getCurrentRevision() <= 0 ) )
-                            {
-                                service.revert( 0 );
-                            }
-                            else if ( latest != null && 
-                                ! ( service.getChangeLog().getCurrentRevision() <= latest.getRevision() ) )
-                            {
-                                service.revert( latest.getRevision() );
-                            }
-
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    break;
-                case( SetupMode.RESTART_ORDINAL ):
-                    // if the service is null instantiate it w/ factory
-                    if ( service == null )
-                    {
-                        service = methodFactory.newInstance();
-                        service.getChangeLog().setEnabled( true );
-
-                        try
-                        {
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // if the service is not null but is stopped then we need to just start
-                    else if ( ! service.isStarted() )
-                    {
-                        try
-                        {
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // server is up and running so we just need to restart it
-                    else
-                    {
-                        try
-                        {
-                            service.shutdown();
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    break;
-                case( SetupMode.PRISTINE_ORDINAL ):
-                    // if the service is null instantiate it w/ factory
-                    if ( service == null )
-                    {
-                        service = methodFactory.newInstance();
-                        service.getChangeLog().setEnabled( true );
-
-                        try
-                        {
-                            doDelete( service.getWorkingDirectory() );
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( Exception e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // if the service is not null but is stopped then we need to cleanup and start
-                    else if ( ! service.isStarted() )
-                    {
-                        cleanup( notifier );
-                        service = methodFactory.newInstance();
-                        service.getChangeLog().setEnabled( true );
-                        cleanup( notifier );
-                        try
-                        {
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    // server is up and running so we just need to revert it to the last tag
-                    else
-                    {
-                        try
-                        {
-                            service.shutdown();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                        cleanup( notifier );
-                        service = methodFactory.newInstance();
-                        service.getChangeLog().setEnabled( true );
-                        cleanup( notifier );
-                        try
-                        {
-                            service.startup();
-                            service.getChangeLog().tag();
-                        }
-                        catch ( NamingException e )
-                        {
-                            notifier.testAborted( description, e );
-                        }
-                    }
-                    break;
-                default:
-                    throw new IllegalStateException( "Unidentified method mode: " + methodMode );
-            }
-
-            try
-            {
-                Field field = test.getClass().getDeclaredField( "service" );
-                if ( ! DirectoryService.class.isAssignableFrom( field.getType() ) )
-                {
-                    //noinspection ThrowableInstanceNeverThrown
-                    notifier.testAborted( description,
-                            new RuntimeException( INVALID_SERVICE_FIELD_MSG ).fillInStackTrace() );
-                }
-
-                field.set( test.getClass(), service );
-            }
-            catch ( Exception e )
-            {
-                notifier.testAborted( description, e );
-            }
-        }
-
-        new MethodRoadie( test, testMethod, notifier, description ).run();
+        test( getTestClass(), wrapMethod( method ), notifier, new InheritableSettings( description, getSettings() ) );
     }
 
 
     public void setSuite( CiSuite suite )
     {
         this.suite = suite;
+        this.settings = new InheritableSettings( getDescription(), suite.getSettings() );
     }
 
 
-    public SetupMode getSetupMode()
-    {
-        return setupMode;
-    }
-
-
-    public DirectoryServiceFactory getFactory()
-    {
-        return factory;
-    }
-
-
-    public DirectoryService getService()
+    public CiSuite getSuite()
     {
-        return service;
+        return suite;
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/CiSuite.java Mon Dec  3 15:38:50 2007
@@ -19,20 +19,17 @@
 package org.apache.directory.server.core.integ;
 
 
-import org.apache.directory.server.core.DirectoryService;
-import static org.apache.directory.server.core.integ.AnnotationUtils.getMode;
-import static org.apache.directory.server.core.integ.AnnotationUtils.newFactory;
-import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
-import org.apache.directory.server.core.integ.annotations.Factory;
-import org.apache.directory.server.core.integ.annotations.Mode;
 import org.junit.internal.runners.InitializationError;
 import org.junit.runner.Runner;
 import org.junit.runner.notification.Failure;
 import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.Suite;
 
-import java.io.File;
-import java.util.Collections;
+import static org.apache.directory.server.core.integ.state.TestServiceContext.shutdown;
+import static org.apache.directory.server.core.integ.state.TestServiceContext.cleanup;
+
+import javax.naming.NamingException;
+import java.io.IOException;
 import java.util.List;
 
 
@@ -46,60 +43,17 @@
  */
 public class CiSuite extends Suite
 {
-    /**
-     * Must be ROLLBACK to not through inheritence impact the
-     * reasoning for these decisions that are made clear in
-     * {@Link CiRunner#DEFAULT_MODE}.
-     */
-    public static final SetupMode DEFAULT_MODE = SetupMode.ROLLBACK;
-
-    /**
-     * The suite level setup mode.  This is the mode that is inherited
-     * by test classes included in this suite.  It determines the life
-     * cycle of a directory service as tests are run against it.
-     */
-    private SetupMode mode = DEFAULT_MODE;
-
-    /**
-     * The suite level service factory. This is the factory that is
-     * inherited by test classes included in this suite.  It is used
-     * to instantiate services for suite's, test clases, and test
-     * cases depending on the setup mode utilized.
-     */
-    private DirectoryServiceFactory factory = DirectoryServiceFactory.DEFAULT;
-
-    /**
-     * The suite level reference to the directory service.  This
-     * service object may be used as a shared service across all tests.
-     * Sometimes each test may create it's own service and be run in
-     * parallel.  Likewise for tests.  It all depends on the threading
-     * model and on the lifecycle of the tested service.
-     */
-    private DirectoryService service;
-
-    /**
-     * List of ldifFiles to be loaded before conducting a test at
-     * various stages and based on the mode of the setup.    
-      */
-    private List<File> ldifFiles = Collections.emptyList();
+    private InheritableSettings settings;
 
 
     public CiSuite( Class<?> clazz ) throws InitializationError
     {
         super( clazz );
-        factory = newFactory( clazz.getAnnotation( Factory.class ), factory );
-        mode = getMode( clazz.getAnnotation( Mode.class ), mode );
+        settings = new InheritableSettings( getDescription() );
     }
 
 
-    protected CiSuite( Class<?> clazz, Class<?>[] classes ) throws InitializationError
-    {
-        super( clazz, classes );
-    }
-
-
-    @Override
-    public void run( final RunNotifier notifier )
+    public void addAll( List<? extends Runner> runners )
     {
         for ( Runner runner : getRunners() )
         {
@@ -108,29 +62,61 @@
                 CiRunner cir = ( CiRunner) runner;
                 cir.setSuite( this );
             }
+            else
+            {
+                throw new IllegalArgumentException( String.format( "Unexpected runner type \"%s\".  " +
+                        "Test classes within CiSuites must use CiRunners.", runner ) );
+            }
         }
 
+        super.addAll( runners );
+    }
+
+
+    public void add( Runner runner )
+    {
+        if ( runner instanceof CiRunner )
+        {
+            CiRunner cir = ( CiRunner) runner;
+            cir.setSuite( this );
+            super.add( runner );
+        }
+        else
+        {
+            throw new IllegalArgumentException( String.format( "Unexpected runner type \"%s\".  " +
+                    "Test classes within CiSuites must use CiRunners.", runner ) );
+        }
+    }
+
+
+    @Override
+    public void run( final RunNotifier notifier )
+    {
         super.run( notifier );
 
-        if ( service != null && service.isStarted() )
+        /*
+         * For any service scope other than test system scope, we must have to
+         * shutdown the sevice and cleanup the working directory.  Failures to
+         * do this without exception shows that something is wrong with the
+         * server and so the entire test should be marked as failed.  So we
+         * presume that tests have failed in the suite if the fixture is in an
+         * inconsistent state.  Who knows if this inconsistent state of the
+         * service could have made it so false results were acquired while
+         * running tests.
+         */
+
+        if ( settings.getScope() != ServiceScope.TESTSYSTEM )
         {
             try
             {
-                service.shutdown();
+                shutdown();
+                cleanup();
             }
-            catch ( Exception e )
+            catch ( NamingException e )
             {
                 notifier.fireTestFailure( new Failure( getDescription(), e ) );
             }
-        }
-
-        if ( service != null )
-        {
-            try
-            {
-                doDelete( service.getWorkingDirectory() );
-            }
-            catch ( Exception e )
+            catch ( IOException e )
             {
                 notifier.fireTestFailure( new Failure( getDescription(), e ) );
             }
@@ -138,38 +124,8 @@
     }
 
 
-    public SetupMode getSetupMode()
-    {
-        return mode;
-    }
-
-
-    public void setSetupMode( SetupMode mode )
-    {
-        this.mode = mode;
-    }
-
-
-    public DirectoryServiceFactory getFactory()
-    {
-        return factory;
-    }
-
-
-    public void setFactory( DirectoryServiceFactory factory )
-    {
-        this.factory = factory;
-    }
-
-
-    public DirectoryService getService()
-    {
-        return service;
-    }
-
-
-    public void setService( DirectoryService service )
+    public InheritableSettings getSettings()
     {
-        this.service = service;
+        return settings;
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/DirectoryServiceFactory.java Mon Dec  3 15:38:50 2007
@@ -42,7 +42,14 @@
     {
         public DirectoryService newInstance()
         {
-            return new DefaultDirectoryService();
+            DirectoryService service = new DefaultDirectoryService();
+            service.getChangeLog().setEnabled( true );
+
+            // change the working directory to something that is unique
+            // on the system and somewhere either under target directory
+            // or somewhere in a temp area of the machine.
+
+            return service;
         }
     };
 

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/InheritableSettings.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/InheritableSettings.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/InheritableSettings.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/InheritableSettings.java Mon Dec  3 15:38:50 2007
@@ -19,11 +19,7 @@
 package org.apache.directory.server.core.integ;
 
 
-import org.apache.directory.server.core.integ.annotations.Mode;
-import org.apache.directory.server.core.integ.annotations.Factory;
-import org.apache.directory.server.core.integ.annotations.ApplyLdifs;
-import org.apache.directory.server.core.integ.annotations.ApplyLdifFiles;
-
+import org.apache.directory.server.core.integ.annotations.*;
 import org.junit.runner.Description;
 
 import java.util.ArrayList;
@@ -48,6 +44,8 @@
     private final InheritableSettings parent;
     /** junit test description containing all annotations queried */
     private final Description description;
+    /** default scope of a service */
+    private static final ServiceScope DEFAULT_SCOPE = ServiceScope.TESTSUITE;
 
 
     /**
@@ -60,11 +58,11 @@
         this.description = description;
         this.parent = null;
 
-        if ( ! description.isSuite() )
-        {
-            throw new IllegalStateException( String.format( "%s is not a suite! It requires parent settings.",
-                    description.getDisplayName() ) );
-        }
+//        if ( ! description.isSuite() )
+//        {
+//            throw new IllegalStateException( String.format( "%s is not a suite! It requires parent settings.",
+//                    description.getDisplayName() ) );
+//        }
     }
 
 
@@ -199,5 +197,25 @@
         }
 
         return ldifFiles;
+    }
+
+
+    public ServiceScope getScope()
+    {
+        ServiceScope parentScope = DEFAULT_SCOPE;
+        if ( parent != null )
+        {
+            parentScope = parent.getScope();
+        }
+
+        Scope annotation = description.getAnnotation( Scope.class );
+        if ( annotation == null )
+        {
+            return parentScope;
+        }
+        else
+        {
+            return annotation.value();
+        }
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/ServiceScope.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/ServiceScope.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/ServiceScope.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/ServiceScope.java Mon Dec  3 15:38:50 2007
@@ -29,16 +29,14 @@
 {
     TESTSUITE( 0, "service has test suite level scope" ),
     TESTCLASS( 1, "service has test class level scope" ),
-    TESTMETHOD( 2, "service has test method level scope" ),
-    TESTSYSTEM( 3, "service has test system level scope" );
+    TESTSYSTEM( 2, "service has test system level scope" );
 
     public final int ordinal;
     public final String description;
 
     public static final int TESTSUITE_ORDINAL = 0;
     public static final int TESTCLASS_ORDINAL = 1;
-    public static final int TESTMETHOD_ORDINAL = 2;
-    public static final int TESTSYSTEM_ORDINAL = 3;
+    public static final int TESTSYSTEM_ORDINAL = 2;
 
 
     ServiceScope( int ordinal, String description )

Copied: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Scope.java (from r600253, directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java)
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Scope.java?p2=directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Scope.java&p1=directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java&r1=600253&r2=600729&rev=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Mode.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/annotations/Scope.java Mon Dec  3 15:38:50 2007
@@ -19,7 +19,7 @@
  */
 package org.apache.directory.server.core.integ.annotations;
 
-import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.server.core.integ.ServiceScope;
 
 import java.lang.annotation.*;
 
@@ -34,7 +34,7 @@
 @Inherited
 @Retention ( RetentionPolicy.RUNTIME )
 @Target ( { ElementType.METHOD, ElementType.TYPE } )
-public @interface Mode
+public @interface Scope
 {
-     SetupMode value();
-}
+     ServiceScope value();
+}
\ No newline at end of file

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/NonExistentState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/NonExistentState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/NonExistentState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/NonExistentState.java Mon Dec  3 15:38:50 2007
@@ -20,19 +20,27 @@
 
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
+import org.apache.directory.server.core.integ.SetupMode;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
+import org.junit.internal.runners.MethodRoadie;
 import org.junit.runner.notification.RunNotifier;
+import org.junit.runner.Description;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.InvocationTargetException;
 
 
 /**
- * Document me!
+ * The state of a test service when it has not yet been created.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class NonExistentState implements TestServiceState
 {
+    private static final Logger LOG = LoggerFactory.getLogger( NonExistentState.class );
     private final TestServiceContext context;
 
 
@@ -51,36 +59,93 @@
 
     public void destroy()
     {
-        // do nothing!
+        throw new IllegalStateException( "Cannot destroy when service is in NonExistant state" );
     }
 
 
     public void cleanup()
     {
-        // do nothing
+        throw new IllegalStateException( "Cannot cleanup when service is in NonExistant state" );
     }
 
 
     public void startup()
     {
-        throw new IllegalStateException( "Attempting to start up a test service that does not exist." );
+        throw new IllegalStateException( "Cannot startup when service is in NonExistant state" );
     }
 
 
     public void shutdown()
     {
-        throw new IllegalStateException( "Attempting to shut down a test service that does not exist." );
+        throw new IllegalStateException( "Cannot shutdown service in NonExistant state." );
     }
 
 
+    /**
+     * This method is a bit different.  Consider this method to hold the logic
+     * which is needed to shift the context state from the present state to a
+     * started state so we can call test on the current state of the context.
+     *
+     * Basically if the service is not needed or the test is ignored, then we
+     * just invoke the test: if ignored the test is not dealt with by the
+     * MethodRoadie run method.
+     *
+     * In tests not ignored requiring setup modes RESTART and CUMULATIVE we
+     * simply create the service and start it up without a cleanup.  In the
+     * PRISTINE and ROLLBACK modes we do the same but cleanup() before a
+     * restart.
+     *
+     *
+     * @param testClass
+     * @param testMethod
+     * @param notifier
+     * @param settings
+     */
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
-        throw new IllegalStateException( "Attempting to run integration tests on a service that does not exist." );
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.RESTART || settings.getMode() == SetupMode.CUMULATIVE )
+        {
+            try
+            {
+                context.getState().create( settings.getFactory() );
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+        }
+
+        if ( settings.getMode() == SetupMode.PRISTINE || settings.getMode() == SetupMode.ROLLBACK )
+        {
+            try
+            {
+                context.getState().create( settings.getFactory() );
+                context.getState().cleanup();
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+        }
+
+        // state object what ever it is will change state so we just return
+        context.getState().test( testClass, testMethod, notifier, settings );
     }
 
 
     public void revert()
     {
-        throw new IllegalStateException( "Attempting to revert a test service that does not exist." );
+        throw new IllegalStateException( "Cannot revert when service is in NonExistant state" );
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedDirtyState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedDirtyState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedDirtyState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedDirtyState.java Mon Dec  3 15:38:50 2007
@@ -18,13 +18,13 @@
  */
 package org.apache.directory.server.core.integ.state;
 
-import org.apache.directory.server.core.integ.SetupMode;
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
-import org.junit.runner.notification.Failure;
-import org.junit.runner.notification.RunNotifier;
+import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.shared.ldap.NotImplementedException;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
+import org.junit.runner.notification.RunNotifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -32,7 +32,8 @@
 
 
 /**
- * The state of the service where it has been started and is dirty.
+ * The state of a test service where it has been started and has been used for
+ * integration tests which has changed it's contents.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
@@ -51,46 +52,151 @@
 
     public void create( DirectoryServiceFactory factory )
     {
-        throw new IllegalStateException( "The running service must be shutdown before creating a new one." );
+        throw new IllegalStateException( "Cannot create new instance while service is running.");
     }
 
 
     public void destroy()
     {
-        throw new IllegalStateException( "The running service must be shutdown before destroying it." );
+        throw new IllegalStateException( "Cannot destroy started service." );
     }
 
 
     public void cleanup()
     {
-        throw new IllegalStateException( "The running service must be shutdown before cleaning it." );
+        throw new IllegalStateException( "Cannot cleanup started service." );
     }
 
 
     public void startup()
     {
-        throw new IllegalStateException( "The running service must be shutdown before starting it." );
+        throw new IllegalStateException( "Cannot startup started service." );
     }
 
 
-    public void shutdown()
+    public void shutdown() throws NamingException
     {
+        context.getService().shutdown();
+        context.setState( context.getStoppedDirtyState() );
     }
 
 
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
-
-    }
-
-
-    public void test()
-    {
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.PRISTINE )
+        {
+            try
+            {
+                context.getState().shutdown();
+                context.getState().cleanup();
+
+                // @todo check if the factory changed here
+                if ( true ) // change this to check if factory changed since the last run
+                {
+                     context.getState().destroy();
+                     context.getState().create( settings.getFactory() );
+                }
+
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+
+            // state object what ever it is will handle tagging before test method
+            // invocation and it will also change the state so we can just return
+            context.getState().test( testClass, testMethod, notifier, settings );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.RESTART )
+        {
+            try
+            {
+                context.getState().shutdown();
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+
+            // right now the state has cycled back to started dirty so we cannot
+            // call test() on the state or we'll loop forever shutting down and
+            // starting the service so we simply invoke the method directly and
+            // and don't mess with the state because it will still be dirty.
+
+            // @TODO a restart will whipe the in memory changelog so we will not
+            // know what revision we are at.  The changelog needs to persist the
+            // current revision across restarts even if it uses an inmemory store.
+            // So this means if there is are the following order of test runs
+            // with respective modes:
+            //
+            // test0 -> ! ( NOSERVICE )         # tagged at t0 then changed
+            // test1 -> RESTART                 # shutdown/startup no cleanup
+            // test2 -> ROLLBACK                # no t0 to rollback to
+            //
+            // To prevent this tags should be persisted across restarts really.
+            // This is easy to do and can be implemented quickly.  We can
+            // perstist both the current revision and tags.
+            //
+            // This basically makes the premis that a cleanup is required after
+            // a shutdown not needed in how we handle rollbacks.
+
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.ROLLBACK )
+        {
+            try
+            {
+//                // @todo check if the factory changed here
+//                if ( true ) // change this to check if factory changed since the last run
+//                {
+//                     context.getState().shutdown();
+//                     context.getState().cleanup();
+//                     context.getState().destroy();
+//                     context.getState().create( settings.getFactory() );
+//                     context.getState().test( testClass, testMethod, notifier, settings );
+//                     return;
+//                }
+//                else
+//                {
+                    context.getState().revert();
+//                }
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+
+            // state object what ever it is will handle tagging before test method
+            // invocation and it will also change the state so we can just return
+            context.getState().test( testClass, testMethod, notifier, settings );
+            return;
+        }
+
+        // at this point only CUMULATIVE tests get to here and they don't care
+        // what we do so we can just invoke the test and the state stays same
+        TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
     }
 
 
-    public void revert()
+    public void revert() throws NamingException
     {
-
+        context.getService().revert();
+        context.setState( context.getStartedRevertedState() );
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedPristineState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedPristineState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedPristineState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedPristineState.java Mon Dec  3 15:38:50 2007
@@ -21,22 +21,27 @@
 
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
+import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.shared.ldap.NotImplementedException;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
 import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
-import java.io.IOException;
 
 
 /**
- * Document me!
+ * A test service state where the server is running and has not been used for
+ * any integration test since it was created.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class StartedPristineState implements TestServiceState
 {
+    private static final Logger LOG = LoggerFactory.getLogger( StartedPristineState.class );
     private final TestServiceContext context;
 
 
@@ -48,42 +53,70 @@
 
     public void create( DirectoryServiceFactory factory )
     {
-
+        throw new IllegalStateException( "Cannot create new instance while service is running." );
     }
 
 
     public void destroy()
     {
-
+        throw new IllegalStateException( "Cannot destroy started service." );
     }
 
 
-    public void cleanup() throws IOException
+    public void cleanup()
     {
-
+        throw new IllegalStateException( "Cannot cleanup started service." );
     }
 
 
-    public void startup() throws NamingException
+    public void startup()
     {
-
+        throw new IllegalStateException( "Cannot startup started service." );
     }
 
 
     public void shutdown() throws NamingException
     {
-
+        context.getService().shutdown();
+        context.setState( context.getStoppedPristineState() );
     }
 
 
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
-
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        try
+        {
+            context.getService().getChangeLog().tag();
+        }
+        catch ( NamingException e )
+        {
+            // @TODO - we might want to check the revision of the service before
+            // we presume that it has been soiled.  Some tests may simply peform
+            // some read operations or checks on the service and may not alter it
+            context.setState( context.getStartedDirtyState() );
+
+            notifier.testAborted( settings.getDescription(), e );
+            return;
+        }
+
+        TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+
+        // @TODO - we might want to check the revision of the service before
+        // we presume that it has been soiled.  Some tests may simply peform
+        // some read operations or checks on the service and may not alter it
+        context.setState( context.getStartedDirtyState() );
     }
 
 
     public void revert() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot revert already pristine service." );
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedRevertedState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedRevertedState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedRevertedState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StartedRevertedState.java Mon Dec  3 15:38:50 2007
@@ -21,22 +21,30 @@
 
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
+import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.shared.ldap.NotImplementedException;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
 import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
-import java.io.IOException;
 
 
 /**
- * Document me!
+ * The state of a running test service which has been used for running
+ * integration tests and has been reverted to contain the same content as it
+ * did when created and started.  It is not really pristine however for all
+ * practical purposes of integration testing it appears to be the same as
+ * when first started.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class StartedRevertedState implements TestServiceState
 {
+    private static final Logger LOG = LoggerFactory.getLogger( StartedRevertedState.class );
     private final TestServiceContext context;
 
 
@@ -48,42 +56,98 @@
 
     public void create( DirectoryServiceFactory factory )
     {
-
+        throw new IllegalStateException( "Cannot create new instance while service is running." );
     }
 
 
     public void destroy()
     {
-
+        throw new IllegalStateException( "Cannot destroy started service." );
     }
 
 
-    public void cleanup() throws IOException
+    public void cleanup()
     {
-
+        throw new IllegalStateException( "Cannot cleanup started service." );
     }
 
 
-    public void startup() throws NamingException
+    public void startup()
     {
-
+        throw new IllegalStateException( "Cannot startup started service." );
     }
 
 
     public void shutdown() throws NamingException
     {
-
+        context.getService().shutdown();
+        context.setState( context.getStoppedDirtyState() );
     }
 
 
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
-
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.PRISTINE )
+        {
+            try
+            {
+                context.getState().shutdown();
+                context.getState().cleanup();
+
+                // @todo check if the factory changed here
+                if ( true ) // change this to check if factory changed since the last run
+                {
+                     context.getState().destroy();
+                     context.getState().create( settings.getFactory() );
+                }
+
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+
+            // state object what ever it is will handle tagging before test method
+            // invocation and it will also change the state so we can just return
+            context.getState().test( testClass, testMethod, notifier, settings );
+            return;
+        }
+
+        try
+        {
+            context.getService().getChangeLog().tag();
+        }
+        catch ( NamingException e )
+        {
+            // @TODO - we might want to check the revision of the service before
+            // we presume that it has been soiled.  Some tests may simply peform
+            // some read operations or checks on the service and may not alter it
+            context.setState( context.getStartedDirtyState() );
+
+            notifier.testAborted( settings.getDescription(), e );
+            return;
+        }
+
+        TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+
+        // @TODO - we might want to check the revision of the service before
+        // we presume that it has been soiled.  Some tests may simply peform
+        // some read operations or checks on the service and may not alter it
+        context.setState( context.getStartedDirtyState() );
     }
 
 
     public void revert() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot revert already reverted service." );
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedDirtyState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedDirtyState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedDirtyState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedDirtyState.java Mon Dec  3 15:38:50 2007
@@ -21,22 +21,29 @@
 
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
+import org.apache.directory.server.core.integ.SetupMode;
+import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
+import org.apache.directory.shared.ldap.NotImplementedException;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
 import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
 import java.io.IOException;
 
 
 /**
- * Document me!
+ * The test service state where it has been stopped after having been used for
+ * tests.  Reverted test services are considered dirty when they are stopped.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class StoppedDirtyState implements TestServiceState
 {
+    private static final Logger LOG = LoggerFactory.getLogger( StoppedDirtyState.class );
     private final TestServiceContext context;
 
 
@@ -48,42 +55,89 @@
 
     public void create( DirectoryServiceFactory factory )
     {
-
+        throw new IllegalStateException( "Cannot create existing service." );
     }
 
 
     public void destroy()
     {
-
+        context.setService( null );
+        context.setState( context.getNonExistentState() );
+        System.gc();
     }
 
 
     public void cleanup() throws IOException
     {
-
+        doDelete( context.getService().getWorkingDirectory() );
+        context.setState( context.getStoppedPristineState() );
     }
 
 
     public void startup() throws NamingException
     {
-
+        context.getService().startup();
+        context.setState( context.getStartedDirtyState() );
     }
 
 
     public void shutdown() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot shutdown stopped service." );
     }
 
 
+    /**
+     * @TODO you're not figuring in changes in the factory and not reinstantiating the service
+     *
+     * @param testClass
+     * @param testMethod
+     * @param notifier
+     * @param settings
+     */
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        if ( settings.getMode() == SetupMode.CUMULATIVE || settings.getMode() == SetupMode.RESTART )
+        {
+            try
+            {
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+        }
+
+        if ( settings.getMode() == SetupMode.PRISTINE || settings.getMode() == SetupMode.ROLLBACK )
+        {
+            try
+            {
+                context.getState().cleanup();
+                context.getState().startup();
+            }
+            catch ( Exception e )
+            {
+                notifier.testAborted( settings.getDescription(), e );
+                return;
+            }
+        }
 
+        // state object what ever it is will change state so we just return
+        context.getState().test( testClass, testMethod, notifier, settings );
     }
 
 
     public void revert() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot revert stopped service." );
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedPristineState.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedPristineState.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedPristineState.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/StoppedPristineState.java Mon Dec  3 15:38:50 2007
@@ -21,22 +21,29 @@
 
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
 import org.apache.directory.server.core.integ.InheritableSettings;
+import org.apache.directory.server.core.integ.SetupMode;
+import static org.apache.directory.server.core.integ.IntegrationUtils.doDelete;
+import org.apache.directory.shared.ldap.NotImplementedException;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
 import org.junit.runner.notification.RunNotifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.naming.NamingException;
 import java.io.IOException;
 
 
 /**
- * Document me!
+ * A state representing a test service that has either just been created,
+ * or a running pristine instance has been stopped.
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
 public class StoppedPristineState implements TestServiceState
 {
+    private static final Logger LOG = LoggerFactory.getLogger( StoppedPristineState.class );
     private final TestServiceContext context;
 
 
@@ -48,42 +55,69 @@
 
     public void create( DirectoryServiceFactory factory )
     {
-
+        throw new IllegalStateException( "Cannot create a stopped instance." );
     }
 
 
     public void destroy()
     {
-
+        context.setService( null );
+        context.setState( context.getNonExistentState() );
+        System.gc();
     }
 
 
+    /**
+     * Even though this method should ignore the call it will attempt to delete any
+     * working directory if at all present.
+     *
+     * @see TestServiceState#cleanup()
+     */
     public void cleanup() throws IOException
     {
-
+        doDelete( context.getService().getWorkingDirectory() );
     }
 
 
     public void startup() throws NamingException
     {
-
+        context.getService().startup();
+        context.setState( context.getStartedPristineState() );
     }
 
 
     public void shutdown() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot shutdown stopped pristine service." );
     }
 
 
     public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
     {
+        if ( settings.getMode() == SetupMode.NOSERVICE || testMethod.isIgnored() )
+        {
+            // no state change here
+            TestServiceContext.invokeTest( testClass, testMethod, notifier, settings.getDescription() );
+            return;
+        }
+
+        try
+        {
+            context.getState().startup();
+        }
+        catch ( Exception e )
+        {
+            notifier.testAborted( settings.getDescription(), e );
+            return;
+        }
 
+        // state object what ever it is will change state so we just return
+        context.getState().test( testClass, testMethod, notifier, settings );
     }
 
 
     public void revert() throws NamingException
     {
-
+        throw new IllegalStateException( "Cannot revert stopped service." );        
     }
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/TestServiceContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/TestServiceContext.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/TestServiceContext.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/main/java/org/apache/directory/server/core/integ/state/TestServiceContext.java Mon Dec  3 15:38:50 2007
@@ -21,14 +21,17 @@
 
 import org.apache.directory.server.core.DirectoryService;
 import org.apache.directory.server.core.integ.DirectoryServiceFactory;
-import org.apache.directory.server.core.integ.ServiceScope;
 import org.apache.directory.server.core.integ.InheritableSettings;
-import org.junit.runner.notification.RunNotifier;
+import org.junit.internal.runners.MethodRoadie;
 import org.junit.internal.runners.TestClass;
 import org.junit.internal.runners.TestMethod;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
 
 import javax.naming.NamingException;
 import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
 
 
 /**
@@ -51,41 +54,26 @@
     private final TestServiceState stoppedPristineState = new StoppedPristineState( this );
 
 
-    /**
-     * the level at which the service was started and where it will be 
-     * shutdown, cleaned and destroyed if it is still present
-     */
-    private final ServiceScope scope;
-
     /** current service state with respect to the testing life cycle */
-    private TestServiceState state;
+    private TestServiceState state = nonExistentState;
 
     /** the core directory service managed by this context */
     private DirectoryService service;
 
 
-    public TestServiceContext( ServiceScope scope )
-    {
-        this.scope = scope;
-    }
-
-
     /**
      * Gets the TestServiceContext associated with the current thread of
-     * execution.  If one does not yet exist it will be created using the
-     * provided scope parameter.  If the scope is null a null pointer
-     * exception may result.
+     * execution.  If one does not yet exist it will be created.
      *
-     * @param scope the level at which the service was started
      * @return the context associated with the calling thread
      */
-    public static TestServiceContext get( ServiceScope scope )
+    public static TestServiceContext get()
     {
         TestServiceContext context = CONTEXTS.get();
 
         if ( context == null )
         {
-            context = new TestServiceContext( scope );
+            context = new TestServiceContext();
             CONTEXTS.set( context );
         }
 
@@ -112,9 +100,9 @@
      *
      * @param factory the factory to use for creating a configured service
      */
-    public void create( DirectoryServiceFactory factory )
+    public static void create( DirectoryServiceFactory factory )
     {
-        state.create( factory );
+        get().state.create( factory );
     }
 
 
@@ -123,9 +111,9 @@
      * entails nulling out reference to it and triggering garbage
      * collection.
      */
-    public void destroy()
+    public static void destroy()
     {
-        state.destroy();
+        get().state.destroy();
     }
 
 
@@ -136,9 +124,9 @@
      *
      * @throws IOException on errors while deleting the working directory
      */
-    public void cleanup() throws IOException
+    public static void cleanup() throws IOException
     {
-        state.cleanup();
+        get().state.cleanup();
     }
 
 
@@ -147,9 +135,9 @@
      *
      * @throws NamingException on failures to start the core directory service
      */
-    public void startup() throws NamingException
+    public static void startup() throws NamingException
     {
-        state.startup();
+        get().state.startup();
     }
 
 
@@ -158,28 +146,25 @@
      *
      * @throws NamingException on failures to stop the core directory service
      */
-    public void shutdown() throws NamingException
+    public static void shutdown() throws NamingException
     {
-        state.shutdown();
+        get().state.shutdown();
     }
 
 
     /**
      * Action where an attempt is made to run a test against the service.
      *
-     * All annotations should have already been processed for
-     * InheritableSettings yet they and others can be processed since we have
-     * access to the method annotations below
-     *
      * @param testClass the class whose test method is to be run
      * @param testMethod the test method which is to be run
      * @param notifier a notifier to report failures to
      * @param settings the inherited settings and annotations associated with
      * the test method
      */
-    public void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier, InheritableSettings settings )
+    public static void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier,
+                             InheritableSettings settings )
     {
-        state.test( testClass, testMethod, notifier, settings );
+        get().getState().test( testClass, testMethod, notifier, settings );
     }
 
 
@@ -190,12 +175,42 @@
      * @throws NamingException on failures to revert the state of the core
      * directory service
      */
-    public void revert() throws NamingException
+    public static void revert() throws NamingException
     {
-        state.revert();
+        get().state.revert();
     }
 
 
+    static void invokeTest( TestClass testClass, TestMethod testMethod, RunNotifier notifier, Description description )
+    {
+        Object test;
+        
+        try
+        {
+            test = testClass.getConstructor().newInstance();
+            Field field = testClass.getJavaClass().getDeclaredField( "service" );
+            field.set( testClass.getJavaClass(), get().getService() );
+        }
+        catch ( InvocationTargetException e )
+        {
+            notifier.testAborted( description, e.getCause() );
+            return;
+        }
+        catch ( Exception e )
+        {
+            notifier.testAborted( description, e );
+            return;
+        }
+
+        new MethodRoadie( test, testMethod, notifier, description ).run();
+    }
+
+
+    // -----------------------------------------------------------------------
+    // Package Friendly Instance Methods
+    // -----------------------------------------------------------------------
+
+
     void setState( TestServiceState state )
     {
         this.state = state;
@@ -241,12 +256,6 @@
     TestServiceState getStoppedPristineState()
     {
         return stoppedPristineState;
-    }
-
-
-    ServiceScope getScope()
-    {
-        return scope;
     }
 
 

Modified: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/StockCoreISuite.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/StockCoreISuite.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/StockCoreISuite.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/StockCoreISuite.java Mon Dec  3 15:38:50 2007
@@ -21,6 +21,10 @@
 import org.apache.directory.server.core.authn.SimpleAuthenticationIT;
 import org.apache.directory.server.core.collective.CollectiveAttributeServiceIT;
 import org.apache.directory.server.core.integ.CiSuite;
+import org.apache.directory.server.core.integ.ServiceScope;
+import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.server.core.integ.annotations.Scope;
+import org.apache.directory.server.core.integ.annotations.Mode;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 
@@ -36,6 +40,8 @@
         SimpleAuthenticationIT.class,
         CollectiveAttributeServiceIT.class
         } )
+@Scope ( ServiceScope.TESTSUITE )
+@Mode ( SetupMode.ROLLBACK )
 public class StockCoreISuite
 {
 }

Modified: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/authn/SimpleAuthenticationIT.java Mon Dec  3 15:38:50 2007
@@ -24,9 +24,6 @@
 import org.apache.directory.server.core.integ.CiRunner;
 import static org.apache.directory.server.core.integ.IntegrationUtils.apply;
 import static org.apache.directory.server.core.integ.IntegrationUtils.getUserAddLdif;
-import org.apache.directory.server.core.integ.SetupMode;
-import org.apache.directory.server.core.integ.annotations.ForceCleanup;
-import org.apache.directory.server.core.integ.annotations.Mode;
 import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.ModificationItemImpl;
@@ -51,8 +48,6 @@
  * @version $Rev$
  */
 @RunWith( CiRunner.class )
-@Mode ( SetupMode.ROLLBACK )
-@ForceCleanup
 public class SimpleAuthenticationIT
 {
     public static DirectoryService service;

Modified: directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/collective/CollectiveAttributeServiceIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/collective/CollectiveAttributeServiceIT.java?rev=600729&r1=600728&r2=600729&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/collective/CollectiveAttributeServiceIT.java (original)
+++ directory/apacheds/branches/bigbang/core-integ/src/test/java/org/apache/directory/server/core/collective/CollectiveAttributeServiceIT.java Mon Dec  3 15:38:50 2007
@@ -22,7 +22,10 @@
 
 import org.apache.directory.server.core.DirectoryService;
 import org.apache.directory.server.core.integ.CiRunner;
-import org.apache.directory.server.core.integ.annotations.ForceCleanup;
+import org.apache.directory.server.core.integ.ServiceScope;
+import org.apache.directory.server.core.integ.SetupMode;
+import org.apache.directory.server.core.integ.annotations.Scope;
+import org.apache.directory.server.core.integ.annotations.Mode;
 import static org.apache.directory.server.core.integ.IntegrationUtils.getSystemContext;
 import org.apache.directory.shared.ldap.message.AttributeImpl;
 import org.apache.directory.shared.ldap.message.AttributesImpl;
@@ -45,7 +48,8 @@
  * @version $Rev$
  */
 @RunWith ( CiRunner.class )
-@ForceCleanup
+@Scope ( ServiceScope.TESTSUITE )
+@Mode ( SetupMode.ROLLBACK )
 public class CollectiveAttributeServiceIT
 {
     public static DirectoryService service;