Clover Coverage Report - Kuali Student 1.3.0-SNAPSHOT (Aggregated)
Coverage timestamp: Thu Apr 28 2011 05:03:32 EDT
../../../../img/srcFileCovDistChart0.png 2% of files have more coverage
54   192   23   6
24   111   0.43   9
9     2.56  
1    
 
  TestUtilities       Line # 33 54 0% 23 87 0% 0.0
 
No Tests
 
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    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  0 toggle public static void waitForExceptionRouting() {
46  0 waitForExceptionRouting(5*60*1000);
47    }
48   
 
49  0 toggle public static void waitForExceptionRouting(long milliseconds) {
50  0 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    } catch (InterruptedException e) {
57  0 Assert.fail("This thread was interuppted while waiting for exception routing.");
58    }
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    }
63   
 
64  0 toggle public static Thread getExceptionThreader() {
65  0 return exceptionThreader;
66    }
67   
 
68  0 toggle public static void setExceptionThreader(Thread exceptionThreader) {
69  0 TestUtilities.exceptionThreader = exceptionThreader;
70    }
71   
 
72  0 toggle 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  0 toggle 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  0 toggle 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  0 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  0 toggle protected static boolean annotationOverridesSuperClass(Annotation annotation) throws Exception {
158  0 boolean overrides = true; // default is to just override
159  0 Method m = null;;
160  0 try {
161  0 m = annotation.getClass().getMethod("overrideSuperClasses", null);
162    } catch (NoSuchMethodException nsme) {
163    // do nothing
164    }
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  0 toggle 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    }
190    }
191    }
192    }