View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.directory.server.integ.state;
20  
21  
22  import java.io.IOException;
23  import java.lang.reflect.Field;
24  import java.lang.reflect.InvocationTargetException;
25  
26  import javax.naming.NamingException;
27  
28  import org.apache.directory.server.integ.InheritableServerSettings;
29  import org.apache.directory.server.ldap.LdapService;
30  import org.junit.internal.runners.MethodRoadie;
31  import org.junit.internal.runners.TestClass;
32  import org.junit.internal.runners.TestMethod;
33  import org.junit.runner.Description;
34  import org.junit.runner.notification.RunNotifier;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  
39  /**
40   * The context for managing the state of an integration test service.
41   * Each thread of execution driving tests manages it's own service context.
42   * Hence parallelism can be achieved while running integration tests.
43   *
44   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
45   * @version $Rev$, $Date$
46   */
47  public class TestServerContext
48  {
49      /** The logger */
50      private static final Logger LOG = LoggerFactory.getLogger( TestServerContext.class );
51      
52      /** The ThreadLocal containing the contexts */
53      private static final ThreadLocal<TestServerContext> CONTEXTS = new ThreadLocal<TestServerContext>();
54  
55      /** The NonExistant state instance */
56      private final TestServerState nonExistentState = new NonExistentState( this );
57  
58      /** The StartedPristine state instance */
59      private final TestServerState startedPristineState = new StartedPristineState( this );
60      
61      /** The StartedNormal state instance */
62      private final TestServerState startedNormalState = new StartedNormalState( this );
63  
64  
65      /** current service state with respect to the testing life cycle */
66      private TestServerState state = nonExistentState;
67  
68      /** the ldap server managed by this context */
69      private LdapService ldapService;
70  
71  
72      /**
73       * A private constructor, the clas contains only static methods, 
74       * no need to construct an instance.
75       */
76      private TestServerContext()
77      {
78          
79      }
80  
81  
82      /**
83       * Gets the TestServerContext associated with the current thread of
84       * execution.  If one does not yet exist it will be created.
85       *
86       * @return the context associated with the calling thread
87       */
88      public static TestServerContext get()
89      {
90          TestServerContext context = CONTEXTS.get();
91  
92          if ( context == null )
93          {
94              context = new TestServerContext();
95              CONTEXTS.set( context );
96          }
97  
98          return context;
99      }
100     
101 
102     /**
103      * Sets the TestServerContext for this current thread
104      *
105      * @param context the context associated with the calling thread
106      */
107     public static void set( TestServerContext context )
108     {
109         CONTEXTS.set( context );
110     }
111 
112 
113     /**
114      * Action where an attempt is made to create the service.  Service
115      * creation in this system is the combined instantiation and
116      * configuration which takes place when the factory is used to get
117      * a new instance of the service.
118      *
119      * @param settings the settings for this test
120      * @throws NamingException if we can't create the service
121      */
122     public static void create( InheritableServerSettings settings ) throws NamingException
123     {
124         get().state.create( settings );
125     }
126 
127 
128     /**
129      * Action where an attempt is made to destroy the service.  This
130      * entails nulling out reference to it and triggering garbage
131      * collection.
132      */
133     public static void destroy()
134     {
135         get().state.destroy();
136     }
137 
138 
139     /**
140      * Action where an attempt is made to erase the contents of the
141      * working directory used by the service for various files including
142      * partition database files.
143      *
144      * @throws IOException on errors while deleting the working directory
145      */
146     public static void cleanup() throws IOException
147     {
148         get().state.cleanup();
149     }
150 
151 
152     /**
153      * Action where an attempt is made to start up the service.
154      *
155      * @throws Exception on failures to start the core directory service
156      */
157     public static void startup() throws Exception
158     {
159         get().state.startup();
160     }
161 
162 
163     /**
164      * Action where an attempt is made to shutdown the service.
165      *
166      * @throws Exception on failures to stop the core directory service
167      */
168     public static void shutdown() throws Exception
169     {
170         get().state.shutdown();
171     }
172 
173 
174     /**
175      * Action where an attempt is made to run a test against the service.
176      *
177      * @param testClass the class whose test method is to be run
178      * @param testMethod the test method which is to be run
179      * @param notifier a notifier to report failures to
180      * @param settings the inherited settings and annotations associated with
181      * the test method
182      */
183     public static void test( TestClass testClass, TestMethod testMethod, RunNotifier notifier,
184                              InheritableServerSettings settings )
185     {
186         LOG.debug( "calling test(): {}", settings.getDescription().getDisplayName() );
187         get().getState().test( testClass, testMethod, notifier, settings );
188     }
189 
190 
191     /**
192      * Action where an attempt is made to revert the service to it's
193      * initial start up state by using a previous snapshot.
194      *
195      * @throws Exception on failures to revert the state of the core
196      * directory service
197      */
198     public static void revert() throws Exception
199     {
200         get().state.revert();
201     }
202 
203 
204     static void invokeTest( TestClass testClass, TestMethod testMethod, RunNotifier notifier, Description description )
205     {
206         try
207         {
208             Object test = testClass.getConstructor().newInstance();
209             Field field = testClass.getJavaClass().getDeclaredField( "ldapService" );
210             field.set( testClass.getJavaClass(), get().getLdapServer() );
211             new MethodRoadie( test, testMethod, notifier, description ).run();
212         }
213         catch ( InvocationTargetException e )
214         {
215             LOG.error( "Failed to invoke test method: " + description.getDisplayName(), e.getCause() );
216             notifier.testAborted( description, e.getCause() );
217             return;
218         }
219         catch ( InstantiationException ie )
220         {
221             LOG.error( "Failed to invoke test method: " + description.getDisplayName(), ie );
222             notifier.testAborted( description, ie );
223             return;
224         }
225         catch ( IllegalAccessException iae )
226         {
227             LOG.error( "Failed to invoke test method: " + description.getDisplayName(), iae );
228             notifier.testAborted( description, iae );
229             return;
230         }
231         catch ( NoSuchMethodException nsme )
232         {
233             LOG.error( "Failed to invoke test method: " + description.getDisplayName(), nsme );
234             notifier.testAborted( description, nsme );
235             return;
236         }
237         catch ( NoSuchFieldException nsfe )
238         {
239             LOG.error( "Failed to invoke test method: " + description.getDisplayName(), nsfe );
240             notifier.testAborted( description, nsfe );
241             return;
242         }
243     }
244 
245 
246     // -----------------------------------------------------------------------
247     // Package Friendly Instance Methods
248     // -----------------------------------------------------------------------
249 
250 
251     void setState( TestServerState state )
252     {
253         this.state = state;
254     }
255 
256 
257     TestServerState getState()
258     {
259         return state;
260     }
261 
262 
263     TestServerState getNonExistentState()
264     {
265         return nonExistentState;
266     }
267 
268 
269     TestServerState getStartedPristineState()
270     {
271         return startedPristineState;
272     }
273 
274 
275     TestServerState getStartedNormalState()
276     {
277         return startedNormalState;
278     }
279 
280 
281     LdapService getLdapServer()
282     {
283         return ldapService;
284     }
285 
286 
287     void setLdapServer( LdapService ldapService )
288     {
289         this.ldapService = ldapService;
290     }
291 }