Coverage Report - org.kuali.rice.test.TestUtilities
 
Classes in this File Line Coverage Branch Coverage Complexity
TestUtilities
0%
0/60
0%
0/34
3.444
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.test;
 17  
 
 18  
 import java.lang.annotation.Annotation;
 19  
 import java.lang.reflect.Method;
 20  
 import java.util.ArrayList;
 21  
 import java.util.List;
 22  
 import java.util.Map;
 23  
 import java.util.Set;
 24  
 
 25  
 import junit.framework.Assert;
 26  
 
 27  
 import org.kuali.rice.core.api.config.property.Config;
 28  
 import org.kuali.rice.core.api.config.property.ConfigContext;
 29  
 import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
 30  
 import org.kuali.rice.core.api.resourceloader.ResourceLoader;
 31  
 import org.mortbay.jetty.webapp.WebAppClassLoader;
 32  
 
 33  0
 public class TestUtilities {
 34  
         
 35  
         private static Thread exceptionThreader;
 36  
         
 37  
         /**
 38  
      * Waits "indefinately" for the exception routing thread to terminate.
 39  
      *
 40  
      * This actually doesn't wait forever but puts an upper bound of 5 minutes
 41  
      * on the time to wait for the exception routing thread to complete.  If a
 42  
      * document cannot go into exception routing within 5 minutes  then we got
 43  
      * problems.
 44  
      */
 45  
     public static void waitForExceptionRouting() {
 46  0
             waitForExceptionRouting(5*60*1000);
 47  0
     }
 48  
 
 49  
     public static void waitForExceptionRouting(long milliseconds) {
 50  
             try {
 51  0
                     Thread thread = getExceptionThreader();
 52  0
                     if (thread == null) {
 53  0
                             throw new IllegalStateException("No exception thread was established, likely message is not being processed for exception routing.");
 54  
                     }
 55  0
                     thread.join(milliseconds);
 56  0
             } catch (InterruptedException e) {
 57  0
                     Assert.fail("This thread was interuppted while waiting for exception routing.");
 58  0
             }
 59  0
             if (getExceptionThreader().isAlive()) {
 60  0
                     Assert.fail("Document was not put into exception routing within the specified amount of time " + milliseconds);
 61  
             }
 62  0
     }
 63  
 
 64  
     public static Thread getExceptionThreader() {
 65  0
         return exceptionThreader;
 66  
     }
 67  
 
 68  
     public static void setExceptionThreader(Thread exceptionThreader) {
 69  0
         TestUtilities.exceptionThreader = exceptionThreader;
 70  0
     }        
 71  
 
 72  
     protected List<Class> annotationsPresent(Class clazz, Class[] annotationClasses) {
 73  0
         List<Class> annotationsPresent = new ArrayList<Class>();
 74  0
         for (Class c: annotationClasses) {
 75  0
             if (clazz.isAnnotationPresent(c)) {
 76  0
                 annotationsPresent.add(c);
 77  
             }
 78  
         }
 79  0
         return annotationsPresent;
 80  
     }
 81  
 
 82  
     protected static boolean contains(Class[] list, Class target) {
 83  0
         for (Class c: list) {
 84  0
             if (c.getName().equals(target.getName())) {
 85  0
                 return true;
 86  
             }
 87  
         }
 88  0
         return false;
 89  
     }
 90  
 
 91  
     /**
 92  
      * This method facilitates using annotations in a unit test class hierarchy.  We walk up the class hierarchy
 93  
      * and on each class, looking for the presence of any of the specified annotation types.  If the particular class
 94  
      * defines one of the annotation types, it is marked for handling.  Once any single target annotation is found
 95  
      * on the class, it is marked and no further annotations are inspected.
 96  
      * 
 97  
      * If the annotation defines an 'overrideSuperClasses' method, and this method returns false, then processing
 98  
      * continues up the class hierarchy.  Otherwise processing stops when the first annotation is found.  Note that
 99  
      * this feature only makes sense when specifying a single annotation type.
 100  
      * 
 101  
      * After a list of classes in descending hierarchy order is compiled, the list is iterated over (again, in
 102  
      * descending hierarchy order) and if the class is not already present in the caller-supplied list of classes
 103  
      * already handled by the caller, the class is added to a list of classes that need to be handled by the caller,
 104  
      * which is then returned to the caller.
 105  
      * 
 106  
      * It is the caller's responsibility to handle the returned classes, and store them in some internal list which it may
 107  
      * give back to this method in the future.
 108  
      * 
 109  
      * @throws Exception if there is a problem in reflection on an Annotation object
 110  
      */
 111  
     public static List<Class> getHierarchyClassesToHandle(Class testClass, Class[] annotationClasses, Set<String> classesHandled) throws Exception {
 112  0
         List<Class> classesThatNeedHandling = new ArrayList<Class>();
 113  
         // get a list of all classes the current class extends from that use the PerSuiteUnitTestData annotation
 114  0
         List<Class> classesToCheck = new ArrayList<Class>();
 115  
         // here we get the list apart checking the annotations to support the perSuiteDataLoaderLifecycleNamesRun variable better
 116  
         {
 117  0
             Class clazz = testClass;
 118  0
             superClassLoop: while (!clazz.getName().equals(Object.class.getName())) {
 119  0
                 for (Annotation annotation : clazz.getDeclaredAnnotations()) {
 120  
                     // if this isn't one of the annotations we're interested in, move on
 121  0
                     if (!contains(annotationClasses, annotation.annotationType())) {
 122  0
                         continue;
 123  
                     }
 124  
 
 125  
                     // this class should be processed because it contains an annotation we are interested in
 126  0
                     classesToCheck.add(0, clazz);
 127  
                     
 128  
                     // now check to see if annotation overrides super class implementations
 129  0
                     if (annotationOverridesSuperClass(annotation)) {
 130  
                         // we're done here
 131  0
                         break superClassLoop;
 132  
                     }
 133  
                     // we just added the class to classes to check, we don't need to add it again
 134  
                     // so just stop looking at annotations in this particular class
 135  
                     break;
 136  
                 }
 137  0
                 clazz = clazz.getSuperclass();
 138  
             }
 139  
         }
 140  
         
 141  0
         for (Class clazz: classesToCheck) {
 142  0
             if (!classesHandled.contains(clazz.getName())) {
 143  0
                 classesThatNeedHandling.add(clazz);
 144  
             }
 145  
         }
 146  0
         return classesThatNeedHandling;
 147  
     }
 148  
     
 149  
     /**
 150  
      * Determines whether an annotation should override the same type of annotation on a superclass,
 151  
      * by using reflection to invoke the 'overrideSuperClasses' method on the annotation if it exists.
 152  
      * If the annotation does not supply this method, the default is true.
 153  
      * @param annotation the annotation to inspect
 154  
      * @return whether this annotation overrides any annotations of similar type in super classes
 155  
      * @throws Exception if an error occurs during reflection
 156  
      */
 157  
     protected static boolean annotationOverridesSuperClass(Annotation annotation) throws Exception {
 158  0
         boolean overrides = true; // default is to just override
 159  0
         Method m = null;;
 160  
         try {
 161  0
             m = annotation.getClass().getMethod("overrideSuperClasses", null);
 162  0
         } catch (NoSuchMethodException nsme) {
 163  
             // do nothing
 164  0
         }
 165  0
         if (m != null) {
 166  0
             Object result = m.invoke(annotation, (Object[]) null);
 167  0
             if (result instanceof Boolean) {
 168  0
                 overrides = (Boolean) result;
 169  
             } else {
 170  0
                 throw new RuntimeException("Annotation 'overrideSuperClasses' did not return Boolean value");
 171  
             }
 172  
         }
 173  0
         return overrides;
 174  
     }
 175  
     
 176  
     /**
 177  
      * Adds all ResourceLoaders registered to WebAppClassLoaders to the GlobalResourceLoader.
 178  
      * Overrides the current context config with the Config registered to the (last) WebAppClassLoader
 179  
      */
 180  
     public static void addWebappsToContext() {
 181  0
         for (Map.Entry<ClassLoader, Config> configEntry : ConfigContext.getConfigs()) {
 182  0
             if (configEntry.getKey() instanceof WebAppClassLoader) {
 183  0
                 ResourceLoader rl = GlobalResourceLoader.getResourceLoader(configEntry.getKey());
 184  0
                 if (rl == null) {
 185  0
                     Assert.fail("didn't find resource loader for workflow test harness web app");
 186  
                 }
 187  0
                 GlobalResourceLoader.addResourceLoader(rl);
 188  0
                 ConfigContext.overrideConfig(Thread.currentThread().getContextClassLoader(), configEntry.getValue());
 189  0
             }
 190  
         }
 191  0
     }
 192  
 }