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
124   409   47   4.13
26   255   0.38   30
30     1.57  
1    
 
  RiceTestCase       Line # 52 124 0% 47 180 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"); you may not use this file except in
5    * compliance with the License. You may obtain a copy of the License at
6    *
7    * http://www.opensource.org/licenses/ecl2.php
8    *
9    * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS
10    * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
11    * language governing permissions and limitations under the License.
12    */
13    package org.kuali.rice.test;
14   
15    import java.io.IOException;
16    import java.util.ArrayList;
17    import java.util.HashSet;
18    import java.util.LinkedList;
19    import java.util.List;
20    import java.util.ListIterator;
21    import java.util.Properties;
22    import java.util.Set;
23   
24    import javax.xml.namespace.QName;
25   
26    import org.apache.commons.lang.StringUtils;
27    import org.apache.log4j.Logger;
28    import org.apache.log4j.PropertyConfigurator;
29    import org.junit.After;
30    import org.junit.Before;
31    import org.kuali.rice.core.api.config.property.Config;
32    import org.kuali.rice.core.api.config.property.ConfigContext;
33    import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
34    import org.kuali.rice.core.api.lifecycle.Lifecycle;
35    import org.kuali.rice.core.impl.config.property.JAXBConfigImpl;
36    import org.kuali.rice.core.impl.resourceloader.SpringResourceLoader;
37    import org.kuali.rice.test.data.PerSuiteUnitTestData;
38    import org.kuali.rice.test.lifecycles.PerSuiteDataLoaderLifecycle;
39    import org.springframework.core.io.FileSystemResourceLoader;
40    import org.springframework.core.io.Resource;
41    import org.springframework.core.io.ResourceLoader;
42   
43    /**
44    * Useful superclass for all Rice test cases. Handles setup of test utilities and a test environment. Configures the
45    * Spring test environment providing a template method for custom context files in test mode. Also provides a template method
46    * for running custom transactional setUp. Tear down handles automatic tear down of objects created inside the test
47    * environment.
48    *
49    * @author Kuali Rice Team (rice.collab@kuali.org)
50    * @since 0.9
51    */
 
52    public abstract class RiceTestCase extends BaseRiceTestCase {
53   
54    private static final Logger LOG = Logger.getLogger(RiceTestCase.class);
55   
56    private static final String ALT_LOG4J_CONFIG_LOCATION_PROP = "alt.log4j.config.location";
57    private static final String DEFAULT_LOG4J_CONFIG = "classpath:rice-testharness-default-log4j.properties";
58    protected static final String DEFAULT_TEST_HARNESS_SPRING_BEANS = "classpath:TestHarnessSpringBeans.xml";
59    protected static boolean SUITE_LIFE_CYCLES_RAN = false;
60    protected static boolean SUITE_LIFE_CYCLES_FAILED = false;
61    protected static String failedSuiteTestName;
62   
63    protected List<Lifecycle> perTestLifeCycles = new LinkedList<Lifecycle>();
64   
65    protected List<Lifecycle> suiteLifeCycles = new LinkedList<Lifecycle>();
66   
67    private static Set<String> perSuiteDataLoaderLifecycleNamesRun = new HashSet<String>();
68   
69    private List<String> reports = new ArrayList<String>();
70   
71    private SpringResourceLoader testHarnessSpringResourceLoader;
72   
 
73  0 toggle @Before
74    public void setUp() throws Exception {
75  0 try {
76  0 configureLogging();
77  0 logBeforeRun();
78   
79  0 final long initTime = System.currentTimeMillis();
80   
81  0 setUpInternal();
82   
83  0 report("Time to start all Lifecycles: " + (System.currentTimeMillis() - initTime));
84    } catch (Throwable e) {
85  0 e.printStackTrace();
86  0 tearDown();
87  0 throw new RuntimeException(e);
88    }
89    }
90   
91    /**
92    * Internal setUp() implementation which is invoked by the main setUp() and wrapped
93    * with exception handling. Subclasses should override this method if they want to
94    * add set up steps that should occur in the standard set up process, wrapped by
95    * exception handling.
96    */
 
97  0 toggle protected void setUpInternal() throws Exception {
98  0 assertNotNull(getModuleName());
99  0 setModuleName(getModuleName());
100  0 setBaseDirSystemProperty(getModuleName());
101   
102  0 this.perTestLifeCycles = getPerTestLifecycles();
103  0 this.suiteLifeCycles = getSuiteLifecycles();
104   
105  0 if (SUITE_LIFE_CYCLES_FAILED) {
106  0 fail("Suite Lifecycles startup failed on test " + failedSuiteTestName + "!!! Please see logs for details.");
107    }
108  0 if (!SUITE_LIFE_CYCLES_RAN) {
109  0 try {
110  0 startLifecycles(this.suiteLifeCycles);
111  0 SUITE_LIFE_CYCLES_RAN = true;
112    } catch (Throwable e) {
113  0 e.printStackTrace();
114  0 SUITE_LIFE_CYCLES_RAN = false;
115  0 SUITE_LIFE_CYCLES_FAILED = true;
116  0 failedSuiteTestName = getFullTestName();
117  0 tearDown();
118  0 stopLifecycles(this.suiteLifeCycles);
119  0 throw new RuntimeException(e);
120    }
121    }
122   
123  0 startSuiteDataLoaderLifecycles();
124   
125  0 startLifecycles(this.perTestLifeCycles);
126   
127    }
128   
129    /**
130    * This block is walking up the class hierarchy of the current unit test looking for PerSuiteUnitTestData annotations. If it finds one,
131    * it will run it once, then add it to a set so that it does not get run again. This is needed so that multiple
132    * tests can extend from the same suite and so that there can be multiple suites throughout the test source branch.
133    *
134    * @throws Exception if a PerSuiteDataLoaderLifecycle is unable to be started
135    */
 
136  0 toggle protected void startSuiteDataLoaderLifecycles() throws Exception {
137  0 List<Class> classes = TestUtilities.getHierarchyClassesToHandle(getClass(), new Class[] { PerSuiteUnitTestData.class }, perSuiteDataLoaderLifecycleNamesRun);
138  0 for (Class c: classes) {
139  0 new PerSuiteDataLoaderLifecycle(c).start();
140  0 perSuiteDataLoaderLifecycleNamesRun.add(c.getName());
141    }
142    }
143   
144    /**
145    * maven will set this property and find resources from the config based on it. This makes eclipse testing work because
146    * we have to put the basedir in our config files in order to find things when testing from maven
147    */
 
148  0 toggle protected void setBaseDirSystemProperty(String moduleBaseDir) {
149  0 if (System.getProperty("basedir") == null) {
150  0 System.setProperty("basedir", System.getProperty("user.dir") + "/" + moduleBaseDir);
151    }
152    }
153   
154    /**
155    * Returns the basedir for the module under which the tests are currently executing.
156    */
 
157  0 toggle protected String getBaseDir() {
158  0 return System.getProperty("basedir");
159    }
160   
 
161  0 toggle protected void setModuleName(String moduleName) {
162  0 if (System.getProperty("module.name") == null) {
163  0 System.setProperty("module.name", moduleName);
164    }
165    }
166   
 
167  0 toggle @After
168    public void tearDown() throws Exception {
169    // wait for outstanding threads to complete for 1 minute
170  0 ThreadMonitor.tearDown(60000);
171  0 stopLifecycles(this.perTestLifeCycles);
172  0 logAfterRun();
173    }
174   
 
175  0 toggle protected void logBeforeRun() {
176  0 LOG.info("##############################################################");
177  0 LOG.info("# Starting test " + getFullTestName() + "...");
178  0 LOG.info("# " + dumpMemory());
179  0 LOG.info("##############################################################");
180    }
181   
 
182  0 toggle protected void logAfterRun() {
183  0 LOG.info("##############################################################");
184  0 LOG.info("# ...finished test " + getFullTestName());
185  0 LOG.info("# " + dumpMemory());
186  0 for (final String report : this.reports) {
187  0 LOG.info("# " + report);
188    }
189  0 LOG.info("##############################################################\n\n\n");
190    }
191   
 
192  0 toggle protected String getFullTestName() {
193  0 return getClass().getSimpleName() + "." + getName();
194    }
195   
 
196  0 toggle protected void configureLogging() throws IOException {
197  0 ResourceLoader resourceLoader = new FileSystemResourceLoader();
198  0 String altLog4jConfigLocation = System.getProperty(ALT_LOG4J_CONFIG_LOCATION_PROP);
199  0 Resource log4jConfigResource = null;
200  0 if (!StringUtils.isEmpty(altLog4jConfigLocation)) {
201  0 log4jConfigResource = resourceLoader.getResource(altLog4jConfigLocation);
202    }
203  0 if (log4jConfigResource == null || !log4jConfigResource.exists()) {
204  0 System.out.println("Alternate Log4j config resource does not exist! " + altLog4jConfigLocation);
205  0 System.out.println("Using default log4j configuration: " + DEFAULT_LOG4J_CONFIG);
206  0 log4jConfigResource = resourceLoader.getResource(DEFAULT_LOG4J_CONFIG);
207    } else {
208  0 System.out.println("Using alternate log4j configuration at: " + altLog4jConfigLocation);
209    }
210  0 Properties p = new Properties();
211  0 p.load(log4jConfigResource.getInputStream());
212  0 PropertyConfigurator.configure(p);
213    }
214   
215    /**
216    * Executes the start() method of each of the lifecycles in the given list.
217    */
 
218  0 toggle protected void startLifecycles(List<Lifecycle> lifecycles) throws Exception {
219  0 for (Lifecycle lifecycle : lifecycles) {
220  0 lifecycle.start();
221    }
222    }
223   
224    /**
225    * Executes the stop() method of each of the lifecyles in the given list. The
226    * List of lifecycles is processed in reverse order.
227    */
 
228  0 toggle protected void stopLifecycles(List<Lifecycle> lifecycles) throws Exception {
229  0 final ListIterator<Lifecycle> iter = lifecycles.listIterator();
230  0 while (iter.hasNext()) {
231  0 iter.next();
232    }
233  0 while (iter.hasPrevious()) {
234  0 final Lifecycle lifeCycle = iter.previous();
235  0 try {
236  0 if (lifeCycle == null) {
237  0 LOG.warn("Attempted to stop a null lifecycle");
238    } else {
239  0 if (lifeCycle.isStarted()) {
240  0 lifeCycle.stop();
241    }
242    }
243    } catch (Exception e) {
244  0 LOG.warn("Failed to shutdown one of the lifecycles!", e);
245    }
246    }
247    }
248   
249    /**
250    * Returns the List of Lifecycles to start when the unit test suite is started
251    */
 
252  0 toggle protected List<Lifecycle> getSuiteLifecycles() {
253  0 List<Lifecycle> lifecycles = new LinkedList<Lifecycle>();
254   
255    /**
256    * Initializes Rice configuration from the test harness configuration file.
257    */
258  0 lifecycles.add(new BaseLifecycle() {
 
259  0 toggle public void start() throws Exception {
260  0 Config config = getTestHarnessConfig();
261  0 ConfigContext.init(config);
262  0 super.start();
263    }
264    });
265   
266    /**
267    * Loads the TestHarnessSpringBeans.xml file which obtains connections to the DB for us
268    */
269  0 lifecycles.add(getTestHarnessSpringResourceLoader());
270   
271    /**
272    * Establishes the TestHarnessServiceLocator so that it has a reference to the Spring context
273    * created from TestHarnessSpringBeans.xml
274    */
275  0 lifecycles.add(new BaseLifecycle() {
 
276  0 toggle public void start() throws Exception {
277  0 TestHarnessServiceLocator.setContext(getTestHarnessSpringResourceLoader().getContext());
278  0 super.start();
279    }
280    });
281   
282    /**
283    * Clears the tables in the database.
284    */
285  0 lifecycles.add(new ClearDatabaseLifecycle());
286   
287    /**
288    * Loads Suite Test Data
289    */
290  0 lifecycles.add(new BaseLifecycle() {
 
291  0 toggle public void start() throws Exception {
292  0 loadSuiteTestData();
293  0 super.start();
294    }
295    });
296   
297  0 Lifecycle loadApplicationLifecycle = getLoadApplicationLifecycle();
298  0 if (loadApplicationLifecycle != null) {
299  0 lifecycles.add(loadApplicationLifecycle);
300    }
301  0 return lifecycles;
302    }
303   
304    /**
305    * This should return a Lifecycle that can be used to load the application
306    * being tested. For example, this could start a Jetty Server which loads
307    * the application, or load a Spring context to establish a set of services,
308    * or any other application startup activities that the test depends upon.
309    */
 
310  0 toggle protected Lifecycle getLoadApplicationLifecycle() {
311    // by default return null, do nothing
312  0 return null;
313    }
314   
315    /**
316    * @return Lifecycles run every test run
317    */
 
318  0 toggle protected List<Lifecycle> getPerTestLifecycles() {
319  0 List<Lifecycle> lifecycles = new LinkedList<Lifecycle>();
320  0 if (getClass().isAnnotationPresent(TransactionalTest.class)) {
321  0 String transactionManagerName = getClass().getAnnotation(TransactionalTest.class).transactionManager();
322  0 TransactionalLifecycle transactionalLifecycle = new TransactionalLifecycle(transactionManagerName);
323  0 lifecycles.add(transactionalLifecycle);
324    }
325  0 lifecycles.add(getPerTestDataLoaderLifecycle());
326  0 lifecycles.add(new BaseLifecycle() {
 
327  0 toggle public void start() throws Exception {
328  0 loadPerTestData();
329  0 super.start();
330    }
331    });
332  0 return lifecycles;
333    }
334   
335    /**
336    * A method that can be overridden to load test data for the unit test Suite.
337    */
 
338  0 toggle protected void loadSuiteTestData() throws Exception {
339    // do nothing by default, subclass can override
340    }
341   
342    /**
343    * A method that can be overridden to load test data on a test-by-test basis
344    */
 
345  0 toggle protected void loadPerTestData() throws Exception {
346    // do nothing by default, subclass can override
347    }
348   
 
349  0 toggle protected void report(final String report) {
350  0 this.reports.add(report);
351    }
352   
 
353  0 toggle protected String dumpMemory() {
354  0 final long total = Runtime.getRuntime().totalMemory();
355  0 final long free = Runtime.getRuntime().freeMemory();
356  0 final long max = Runtime.getRuntime().maxMemory();
357  0 return "[Memory] max: " + max + ", total: " + total + ", free: " + free;
358    }
359   
 
360  0 toggle public SpringResourceLoader getTestHarnessSpringResourceLoader() {
361  0 if (testHarnessSpringResourceLoader == null) {
362  0 testHarnessSpringResourceLoader = new SpringResourceLoader(new QName("TestHarnessSpringContext"), getTestHarnessSpringBeansLocation(), null);
363    }
364  0 return testHarnessSpringResourceLoader;
365    }
366   
367    /**
368    * Returns the location of the test harness spring beans context file.
369    * Subclasses may override to specify a different location.
370    * @return the location of the test harness spring beans context file.
371    */
 
372  0 toggle protected String getTestHarnessSpringBeansLocation() {
373  0 return DEFAULT_TEST_HARNESS_SPRING_BEANS;
374    }
375   
 
376  0 toggle protected Config getTestHarnessConfig() throws Exception {
377  0 Config config = new JAXBConfigImpl(getConfigLocations(), System.getProperties());
378  0 config.parseConfig();
379  0 return config;
380    }
381   
382    /**
383    * Subclasses may override this method to customize the location(s) of the Rice configuration.
384    * By default it is: classpath:META-INF/" + getModuleName().toLowerCase() + "-test-config.xml"
385    * @return List of config locations to add to this tests config location.
386    */
 
387  0 toggle protected List<String> getConfigLocations() {
388  0 List<String> configLocations = new ArrayList<String>();
389  0 configLocations.add(getRiceMasterDefaultConfigFile());
390  0 configLocations.add(getModuleTestConfigLocation());
391  0 return configLocations;
392    }
393   
 
394  0 toggle protected String getModuleTestConfigLocation() {
395  0 return "classpath:META-INF/" + getModuleName().toLowerCase() + "-test-config.xml";
396    }
397   
 
398  0 toggle protected String getRiceMasterDefaultConfigFile() {
399  0 return "classpath:META-INF/test-config-defaults.xml";
400    }
401   
402    /**
403    * same as the module directory in the project.
404    *
405    * @return name of module that the tests located
406    */
407    protected abstract String getModuleName();
408   
409    }