001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.krad.test;
017    
018    import org.apache.commons.lang.StringUtils;
019    import org.junit.Test;
020    import org.junit.runner.RunWith;
021    import org.kuali.rice.core.api.lifecycle.Lifecycle;
022    import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader;
023    import org.kuali.rice.krad.datadictionary.DataDictionary;
024    import org.kuali.rice.krad.util.LegacyUtils;
025    import org.kuali.rice.test.BaselineTestCase;
026    import org.kuali.rice.test.SQLDataLoader;
027    import org.kuali.rice.test.TestUtilities;
028    import org.kuali.rice.test.lifecycles.KEWXmlDataLoaderLifecycle;
029    import org.kuali.rice.test.runners.BootstrapTest;
030    import org.kuali.rice.test.runners.LoadTimeWeavableTestRunner;
031    import org.springframework.context.ConfigurableApplicationContext;
032    import org.springframework.context.support.ClassPathXmlApplicationContext;
033    
034    import javax.xml.namespace.QName;
035    import java.lang.annotation.Retention;
036    import java.lang.annotation.Target;
037    import java.util.HashSet;
038    import java.util.List;
039    
040    import static java.lang.annotation.ElementType.METHOD;
041    import static java.lang.annotation.ElementType.TYPE;
042    import static java.lang.annotation.RetentionPolicy.RUNTIME;
043    
044    /**
045     * Default test base for a full KRAD enabled integration test
046     *
047     * @author Kuali Rice Team (rice.collab@kuali.org)
048     */
049    @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK_CLEAR_DB)
050    @RunWith(LoadTimeWeavableTestRunner.class)
051    @BootstrapTest(KRADTestCase.BootstrapTest.class)
052    public abstract class KRADTestCase extends BaselineTestCase {
053        private static final String SQL_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.sql";
054        private static final String XML_FILE = "classpath:org/kuali/rice/krad/test/DefaultSuiteTestData.xml";
055        private static final String KRAD_MODULE_NAME = "krad";
056    
057        protected DataDictionary dd;
058    
059        protected static SpringResourceLoader kradTestHarnessSpringResourceLoader;
060    
061        private boolean legacyContext = false;
062    
063        public KRADTestCase() {
064            super(KRAD_MODULE_NAME);
065        }
066    
067        /**
068         * propagate constructor
069         * @param moduleName - the name of the module
070         */
071        public KRADTestCase(String moduleName) {
072            super(moduleName);
073        }
074    
075        protected ConfigurableApplicationContext getKRADTestHarnessContext() {
076            return kradTestHarnessSpringResourceLoader.getContext();
077        }
078    
079        @Override
080        public void setUp() throws Exception {
081            super.setUp();
082            setUpLegacyContext();
083    
084        }
085    
086        @Override
087        public void tearDown() throws Exception {
088            try {
089                tearDownLegacyContext();
090            } finally {
091                super.tearDown();    //To change body of overridden methods use File | Settings | File Templates.
092            }
093        }
094    
095        protected void setUpLegacyContext() {
096            if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) {
097                LegacyUtils.beginLegacyContext();
098                legacyContext = true;
099            }
100        }
101    
102        protected void tearDownLegacyContext() {
103            if (getTestMethod().getAnnotation(Legacy.class) != null || getClass().getAnnotation(Legacy.class) != null) {
104                if (legacyContext) {
105                    LegacyUtils.endLegacyContext();
106                    legacyContext = false;
107                }
108            }
109        }
110    
111        @Override
112        protected void setUpInternal() throws Exception {
113            super.setUpInternal();
114    
115            List<Class> classes = TestUtilities.getHierarchyClassesToHandle(getClass(),
116                    new Class[]{TestDictionaryConfig.class}, new HashSet<String>());
117    
118            // if annotation is present then initialize test data dictionary (setup once per suite)
119            if (!classes.isEmpty()) {
120                ConfigurableApplicationContext context  = new ClassPathXmlApplicationContext("TestDataDictionary.xml");
121                dd = (DataDictionary) context.getBean("testDataDictionary");
122    
123                // add any additional dictionary files required by the test
124                for (Class c : classes) {
125                    if (c.isAnnotationPresent(TestDictionaryConfig.class)) {
126                        TestDictionaryConfig testDictionaryConfig = (TestDictionaryConfig) c.getAnnotation(
127                                TestDictionaryConfig.class);
128    
129                        String namespaceCode = testDictionaryConfig.namespaceCode();
130                        String dictionaryFileString = testDictionaryConfig.dataDictionaryFiles();
131    
132                        String[] dictionaryFiles = StringUtils.split(dictionaryFileString, ",");
133                        for (String dictionaryFile : dictionaryFiles) {
134                            LOG.info("Adding test data dictionary file: " + dictionaryFile);
135    
136                            dd.addConfigFileLocation(namespaceCode, dictionaryFile);
137                        }
138                    }
139                }
140    
141                dd.parseDataDictionaryConfigurationFiles(false);
142                dd.validateDD(false); // Validation performs some necessary post-processing of the beans - we need to run this each time we add new files
143                dd.performBeanOverrides();
144            }
145        }
146    
147        /**
148         * Returns an instance of the bean with the given id that has been configured in the test dictionary
149         *
150         * @param id - id of the bean definition
151         * @return Object instance of the given bean class, or null if not found or dictionary is not loaded
152         */
153        protected Object getTestDictionaryObject(String id) {
154            if (dd != null) {
155                return dd.getDictionaryObject(id);
156            }
157    
158            return null;
159        }
160    
161        @Override
162        protected List<Lifecycle> getSuiteLifecycles() {
163            List<Lifecycle> suiteLifecycles = super.getSuiteLifecycles();
164            suiteLifecycles.add(new KEWXmlDataLoaderLifecycle(XML_FILE));
165    
166            return suiteLifecycles;
167        }
168    
169        @Override
170        protected void loadSuiteTestData() throws Exception {
171            super.loadSuiteTestData();
172            new SQLDataLoader(SQL_FILE, ";").runSql();
173        }
174    
175        @Override
176        protected Lifecycle getLoadApplicationLifecycle() {
177            // cache the KRAD test harness spring resource loader
178            // this is not great because it doesn't conform to the lifecycle
179            // ...but why are we creating sub-resourceloaders instead of just adding locations to the test harness context?
180            if (kradTestHarnessSpringResourceLoader == null) {
181                kradTestHarnessSpringResourceLoader = new SpringResourceLoader(new QName("KRADTestResourceLoader"),
182                        "classpath:KRADTestHarnessSpringBeans.xml", null);
183                kradTestHarnessSpringResourceLoader.setParentSpringResourceLoader(getTestHarnessSpringResourceLoader());
184            }
185            return kradTestHarnessSpringResourceLoader;
186        }
187    
188        /**
189         * Annotation which indicates that a Legacy Context should be used for this individual test method or for all tests
190         * in an annotated class.
191         *
192         * @see org.kuali.rice.krad.util.LegacyUtils#doInLegacyContext(java.util.concurrent.Callable)
193         */
194        @Target({TYPE, METHOD})
195        @Retention(RUNTIME)
196        public @interface Legacy {}
197    
198        public static final class BootstrapTest extends KRADTestCase {
199            @Test
200            public void bootstrapTest() {};
201        }
202    
203    }