001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package edu.iu.uis.eden.test;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.util.ArrayList;
024: import java.util.LinkedList;
025: import java.util.List;
026: import java.util.ListIterator;
027: import java.util.Properties;
028:
029: import org.apache.commons.lang.SystemUtils;
030: import org.apache.log4j.Logger;
031: import org.junit.After;
032: import org.junit.Before;
033: import org.kuali.rice.config.Config;
034: import org.kuali.rice.config.ConfigurationException;
035: import org.kuali.rice.config.SimpleConfig;
036: import org.kuali.rice.core.Core;
037: import org.kuali.rice.lifecycle.Lifecycle;
038: import org.kuali.rice.test.LoggableTestCase;
039: import org.kuali.rice.test.TestHarnessWebApp;
040: import org.springframework.transaction.PlatformTransactionManager;
041: import org.springframework.transaction.TransactionStatus;
042: import org.springframework.transaction.support.TransactionCallbackWithoutResult;
043: import org.springframework.transaction.support.TransactionTemplate;
044:
045: /**
046: * Useful superclass for all Workflow test cases. Handles setup of test
047: * utilities and a test environment. Configures the Spring test environment
048: * providing a template method for custom context files in test mode. Also
049: * provides a template method for running custom transactional setUp. Tear down
050: * handles automatic tear down of objects created inside the test environment.
051: *
052: * @author
053: * @version $Revision: 1.1.2.2.4.1 $ $Date: 2007/11/27 20:37:33 $
054: * @since 0.9
055: */
056: public abstract class OldRiceTestCase extends LoggableTestCase {
057:
058: private static final Logger LOG = Logger
059: .getLogger(OldRiceTestCase.class);
060:
061: private static final String TEST_CONFIG_LOCATION = "classpath:org/kuali/rice/test/rice-test-client-config.xml";
062:
063: private static final String BUILD_PROPERTIES = "build.properties";
064:
065: public static final String TEST_CONFIG_LOCATION_PROPERTY = "test.config.location";
066:
067: private boolean setUp = false;
068:
069: private boolean tornDown = false;
070:
071: private List<Lifecycle> lifeCycles = new LinkedList<Lifecycle>();
072:
073: private List<String> reports = new ArrayList<String>();
074:
075: public OldRiceTestCase() {
076: super ();
077: }
078:
079: @Before
080: public void setUp() throws Exception {
081: beforeRun();
082: final long startTime = System.currentTimeMillis();
083: final Config riceTestConfig = new SimpleConfig();
084: riceTestConfig.getProperties().putAll(System.getProperties());
085: loadBootstrapConfig(riceTestConfig);
086: Config testConfig = loadConfig(riceTestConfig);
087: testConfig.parseConfig();
088: riceTestConfig.getProperties().putAll(
089: testConfig.getProperties());
090: Core.init(riceTestConfig);
091: verifyTestConfiguration();
092: final long initTime = System.currentTimeMillis();
093: report("Time to initialize Core: " + (initTime - startTime));
094: this .lifeCycles = getLifecycles();
095: try {
096: startLifecycles();
097: } catch (Exception e) {
098: e.printStackTrace();
099: stopLifecycles();
100: throw e;
101: }
102: report("Time to start all Lifecycles: "
103: + (System.currentTimeMillis() - initTime));
104:
105: try {
106: loadTestDataInternal();
107: } catch (WrappedTransactionRuntimeException e) {
108: throw (Exception) e.getCause();
109: }
110: this .setUp = true;
111: }
112:
113: protected void loadBootstrapConfig(final Config config)
114: throws Exception {
115: final Properties buildProperties = loadBuildProperties();
116: config.getProperties().putAll(buildProperties);
117: }
118:
119: protected Properties loadBuildProperties() throws IOException {
120: Properties localProperties = loadLocalProperties();
121: if (localProperties == null) {
122: LOG.info("No local properties loaded from build file");
123: localProperties = new Properties();
124: }
125: final Properties userProperties = loadUserProperties();
126: if (userProperties != null) {
127: localProperties.putAll(userProperties);
128: } else {
129: LOG
130: .info("No user properties loaded from build file in user home: "
131: + SystemUtils.USER_HOME);
132: }
133: return localProperties;
134: }
135:
136: protected void verifyTestConfiguration() {
137: if (!Core.getCurrentContextConfig().getProperties()
138: .containsKey(TEST_CONFIG_LOCATION_PROPERTY)) {
139: throw new ConfigurationException(
140: "Could not locate the test.config.location property in your test configuration.");
141: }
142: }
143:
144: /**
145: * Load the user's build.properties in user's home
146: */
147: private Properties loadUserProperties() throws IOException {
148: return loadProperties(new File(SystemUtils.USER_HOME + "/"
149: + BUILD_PROPERTIES));
150: }
151:
152: /**
153: * Load the "local" build.properties in the current directory.
154: */
155: private Properties loadLocalProperties() throws IOException {
156: return loadProperties(new File(BUILD_PROPERTIES));
157: }
158:
159: /**
160: * Loads a file into a Properties object
161: *
162: * @param file the file
163: * @return a Properties object
164: */
165: private static Properties loadProperties(File file)
166: throws IOException {
167: if (!file.isFile()) {
168: return null;
169: }
170: final Properties properties = new Properties();
171: final FileInputStream fis = new FileInputStream(file);
172: try {
173: properties.load(fis);
174: } finally {
175: fis.close();
176: }
177: return properties;
178: }
179:
180: protected Config loadConfig(final Config rootConfig) {
181: return new SimpleConfig(TEST_CONFIG_LOCATION, rootConfig
182: .getProperties());
183: }
184:
185: /**
186: * Can be overridden to allow for specification of the client protocol to
187: * use in the test. If none is specified, then the default protocol is
188: * embedded.
189: */
190: protected String getClientProtocol() {
191: return null;
192: }
193:
194: protected void setUpTransaction() throws Exception {
195: // subclasses can override this method to do their setup within a
196: // transaction
197: }
198:
199: @After
200: public void tearDown() throws Exception {
201: stopLifecycles();
202: Core.destroy();
203: // super.tearDown();
204: this .tornDown = true;
205: afterRun();
206: }
207:
208: protected void beforeRun() {
209: System.out
210: .println("##############################################################");
211: System.out.println("# Starting test "
212: + getClass().getSimpleName() + "...");
213: System.out.println("# " + dumpMemory());
214: System.out
215: .println("##############################################################");
216: }
217:
218: protected void afterRun() {
219: System.out
220: .println("##############################################################");
221: System.out.println("# ...finished test "
222: + getClass().getSimpleName());
223: System.out.println("# " + dumpMemory());
224: for (final String report : this .reports) {
225: System.out.println("# " + report);
226: }
227: System.out
228: .println("##############################################################\n\n\n");
229: }
230:
231: /**
232: * By default this loads the "default" data set from the data/TestData.xml
233: * file. Subclasses can override this to change this behaviour
234: */
235: protected void loadDefaultTestData() throws Exception {
236: // template method
237: }
238:
239: protected void loadTestDataInternal() throws Exception {
240: final PlatformTransactionManager platformTransactionManager = getPlatformTransactionManager();
241: if (platformTransactionManager != null) {
242: new TransactionTemplate(platformTransactionManager)
243: .execute(new TransactionCallbackWithoutResult() {
244:
245: public void doInTransactionWithoutResult(
246: final TransactionStatus status) {
247: try {
248: setUpTransactionInternal();
249: } catch (Exception e) {
250: throw new WrappedTransactionRuntimeException(
251: e);
252: }
253: }
254: });
255: } else {
256: setUpTransactionInternal();
257: }
258: }
259:
260: protected void setUpTransactionInternal() throws Exception {
261: final long t1 = System.currentTimeMillis();
262: // we need the messaging to be default of only sending message out with
263: // the transaction
264: // otherwise the importing of constants can get messed up with the
265: // digital signature
266: // constant's notification of the other nodes.
267: loadDefaultTestData();
268:
269: final long t2 = System.currentTimeMillis();
270: report("Time to load default test data: " + (t2 - t1));
271:
272: loadTestData();
273:
274: final long t3 = System.currentTimeMillis();
275: report("Time to load test-specific test data: " + (t3 - t2));
276:
277: setUpTransaction();
278:
279: final long t4 = System.currentTimeMillis();
280: report("Time to run test-specific setup: " + (t4 - t3));
281: }
282:
283: /**
284: * @Override
285: */
286: protected void loadTestData() throws Exception {
287: // override this to load your own test data
288: }
289:
290: protected PlatformTransactionManager getPlatformTransactionManager() {
291: return null;
292: }
293:
294: private class WrappedTransactionRuntimeException extends
295: RuntimeException {
296:
297: private static final long serialVersionUID = 3097909333572509600L;
298:
299: public WrappedTransactionRuntimeException(Exception e) {
300: super (e);
301: }
302: }
303:
304: public void startLifecycles() throws Exception {
305: for (final Lifecycle lifecycle : this .lifeCycles) {
306: final long s = System.currentTimeMillis();
307: try {
308: lifecycle.start();
309: } catch (final Exception e) {
310: throw new Exception("Failed to start lifecycle "
311: + lifecycle, e);
312: }
313: final long e = System.currentTimeMillis();
314: LOG.info("Started lifecycle " + lifecycle + " in "
315: + (e - s) + " ms.");
316: report("Time to start lifecycle " + lifecycle + ": "
317: + (e - s));
318: }
319: }
320:
321: public void stopLifecycles() throws Exception {
322: final ListIterator<Lifecycle> iter = this .lifeCycles
323: .listIterator();
324: while (iter.hasNext()) {
325: iter.next();
326: }
327: while (iter.hasPrevious()) {
328: final Lifecycle lifeCycle = iter.previous();
329: try {
330: lifeCycle.stop();
331: } catch (Exception e) {
332: LOG
333: .warn(
334: "Failed to shutdown one of the lifecycles!",
335: e);
336: }
337: }
338: }
339:
340: public List<Lifecycle> getLifecycles() {
341: this .lifeCycles.add(new OldClearDatabaseLifecycle());
342: this .lifeCycles.add(new TestHarnessWebApp());
343: return this .lifeCycles;
344: }
345:
346: protected void report(final String report) {
347: this .reports.add(report);
348: }
349:
350: private String dumpMemory() {
351: final long total = Runtime.getRuntime().totalMemory();
352: final long free = Runtime.getRuntime().freeMemory();
353: final long max = Runtime.getRuntime().maxMemory();
354: return "[Memory] max: " + max + ", total: " + total
355: + ", free: " + free;
356: }
357:
358: public boolean isSetUp() {
359: return this .setUp;
360: }
361:
362: public boolean isTornDown() {
363: return this .tornDown;
364: }
365:
366: public static InputStream loadResource(final Class<?> packageClass,
367: final String resourceName) {
368: return packageClass.getResourceAsStream(resourceName);
369: }
370:
371: }
|