001/**
002 * Copyright 2005-2014 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 */
016package org.kuali.rice.kew.test;
017
018import org.junit.Test;
019import org.junit.runner.RunWith;
020import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
021import org.kuali.rice.core.api.lifecycle.Lifecycle;
022import org.kuali.rice.core.api.util.ClasspathOrFileResourceLoader;
023import org.kuali.rice.core.framework.resourceloader.SpringResourceLoader;
024import org.kuali.rice.coreservice.impl.CoreServiceImplServiceLocator;
025import org.kuali.rice.kew.api.WorkflowRuntimeException;
026import org.kuali.rice.kew.batch.KEWXmlDataLoader;
027import org.kuali.rice.kew.service.KEWServiceLocator;
028import org.kuali.rice.kim.api.role.Role;
029import org.kuali.rice.kim.api.services.KimApiServiceLocator;
030import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
031import org.kuali.rice.krad.data.platform.MaxValueIncrementerFactory;
032import org.kuali.rice.test.BaselineTestCase;
033import org.kuali.rice.test.ClearDatabaseLifecycle;
034import org.kuali.rice.test.SQLDataLoader;
035import org.kuali.rice.test.TestHarnessServiceLocator;
036import org.kuali.rice.test.lifecycles.KEWXmlDataLoaderLifecycle;
037import org.kuali.rice.test.runners.BootstrapTest;
038import org.kuali.rice.test.runners.LoadTimeWeavableTestRunner;
039import org.springframework.cache.CacheManager;
040import org.springframework.transaction.support.TransactionTemplate;
041
042import javax.xml.namespace.QName;
043import java.io.InputStream;
044import java.util.ArrayList;
045import java.util.List;
046
047/**
048 * Useful superclass for all KEW test cases. Handles setup of test utilities and
049 * a test environment. Configures the Spring test environment providing a
050 * template method for custom context files in test mode. Also provides a
051 * template method for running custom transactional setUp. Tear down handles
052 * automatic tear down of objects created inside the test environment.
053 */
054@BaselineTestCase.BaselineMode(BaselineTestCase.Mode.ROLLBACK_CLEAR_DB)
055@RunWith(LoadTimeWeavableTestRunner.class)
056@BootstrapTest(KEWTestCase.BootstrapTest.class)
057public abstract class KEWTestCase extends BaselineTestCase {
058
059    private static final String SQL_FILE = "classpath:org/kuali/rice/kew/test/DefaultSuiteTestData.sql";
060        private static final String XML_FILE = "classpath:org/kuali/rice/kew/test/DefaultSuiteTestData.xml";
061    private static final String KRAD_MODULE_NAME = "kew";
062
063    public KEWTestCase() {
064                super(KRAD_MODULE_NAME);
065        }
066
067    @Override
068        protected List<Lifecycle> getSuiteLifecycles() {
069                List<Lifecycle> suiteLifecycles = super.getSuiteLifecycles();
070                suiteLifecycles.add(new KEWXmlDataLoaderLifecycle(XML_FILE));
071
072                return suiteLifecycles;
073        }
074
075        @Override
076        protected void loadSuiteTestData() throws Exception {
077                super.loadSuiteTestData();
078        new SQLDataLoader(SQL_FILE, ";").runSql();
079        }
080
081
082    /**
083         * By default this loads the "default" data set from the DefaultTestData.sql
084         * and DefaultTestData.xml files. Subclasses can override this to change
085         * this behaviour
086         */
087        protected void loadDefaultTestData() throws Exception {
088                // at this point this is constants. loading these through xml import is
089                // problematic because of cache notification
090                // issues in certain low level constants.
091                new SQLDataLoader(
092                                "classpath:org/kuali/rice/kew/test/DefaultPerTestData.sql", ";")
093                                .runSql();
094
095                KEWXmlDataLoader.loadXmlClassLoaderResource(KEWTestCase.class,
096                                "DefaultPerTestData.xml");
097        }
098
099        @Override
100        protected Lifecycle getLoadApplicationLifecycle() {
101        SpringResourceLoader springResourceLoader = new SpringResourceLoader(new QName("KEWTestResourceLoader"), "classpath:org/kuali/rice/kew/config/TestKEWSpringBeans.xml", null);
102        springResourceLoader.setParentSpringResourceLoader(getTestHarnessSpringResourceLoader());
103        return springResourceLoader;
104        }
105
106    /**
107         * Default implementation does nothing. Subclasses should override this
108         * method if they want to perform setup work inside of a database
109         * transaction.
110         */
111        protected void setUpAfterDataLoad() throws Exception {
112                // override
113        }
114
115        protected void loadTestData() throws Exception {
116                // override this to load your own test data
117        }
118
119        protected TransactionTemplate getTransactionTemplate() {
120                return TestUtilities.getTransactionTemplate();
121        }
122
123   /**
124         * Initiates loading of per-test data
125         */
126        @Override
127        protected void loadPerTestData() throws Exception {
128        final long t1 = System.currentTimeMillis();
129        loadDefaultTestData();
130
131                final long t2 = System.currentTimeMillis();
132                loadTestData();
133
134                final long t3 = System.currentTimeMillis();
135                report("Time to load test-specific test data: " + (t3 - t2));
136
137                setUpAfterDataLoad();
138
139                final long t4 = System.currentTimeMillis();
140                report("Time to run test-specific setup: " + (t4 - t3));
141        }
142
143        /**
144         * Override the standard per-test lifecycles to prepend
145         * ClearDatabaseLifecycle and ClearCacheLifecycle
146         *
147         * @see org.kuali.rice.test.RiceTestCase#getPerTestLifecycles()
148         */
149        @Override
150        protected List<Lifecycle> getPerTestLifecycles() {
151                List<Lifecycle> lifecycles = new ArrayList<Lifecycle>();
152                lifecycles.add(new ClearDatabaseLifecycle(getPerTestTablesToClear(),
153                                getPerTestTablesNotToClear()));
154                lifecycles.add(new ClearCacheLifecycle());
155                lifecycles.addAll(super.getPerTestLifecycles());
156                return lifecycles;
157        }
158
159        /**
160         * Flushes the KEW cache(s)
161         */
162        public class ClearCacheLifecycle extends BaseLifecycle {
163                @Override
164                public void stop() throws Exception {
165            clearCacheManagers(KimImplServiceLocator.getLocalCacheManager(), KEWServiceLocator.getLocalCacheManager(),
166                    CoreServiceImplServiceLocator.getLocalCacheManager());
167                        super.stop();
168                }
169        }
170
171    protected void clearCacheManagers(CacheManager... cacheManagers) {
172        for (CacheManager cacheManager : cacheManagers) {
173            for (String cacheName : cacheManager.getCacheNames()) {
174                LOG.info("Clearing cache: " + cacheName);
175                cacheManager.getCache(cacheName).clear();
176            }
177        }
178    }
179
180        /**
181         * Returns the List of tables that should be cleared on every test run.
182         */
183        protected List<String> getPerTestTablesToClear() {
184                List<String> tablesToClear = new ArrayList<String>();
185                tablesToClear.add("KREW_.*");
186                tablesToClear.add("KRSB_.*");
187                tablesToClear.add("KREN_.*");
188        tablesToClear.add("KRMS_.*");
189                return tablesToClear;
190        }
191
192        protected List<String> getPerTestTablesNotToClear() {
193                return new ArrayList<String>();
194        }
195
196        protected void loadXmlFile(String fileName) {
197                try {
198                        KEWXmlDataLoader.loadXmlClassLoaderResource(getClass(), fileName);
199                } catch (Exception e) {
200                        throw new WorkflowRuntimeException(e);
201                }
202        }
203
204        protected void loadXmlFile(Class clazz, String fileName) {
205                try {
206                        KEWXmlDataLoader.loadXmlClassLoaderResource(clazz, fileName);
207                } catch (Exception e) {
208                        throw new WorkflowRuntimeException(e);
209                }
210        }
211
212        protected void loadXmlFileFromFileSystem(String fileName) {
213                try {
214                        KEWXmlDataLoader.loadXmlFile(new ClasspathOrFileResourceLoader().getResource(fileName).getURL().getPath());
215                } catch (Exception e) {
216                        throw new WorkflowRuntimeException(e);
217                }
218        }
219
220        protected void loadXmlStream(InputStream xmlStream) {
221                try {
222                        KEWXmlDataLoader.loadXmlStream(xmlStream);
223                } catch (Exception e) {
224                        throw new WorkflowRuntimeException(e);
225                }
226        }
227
228        protected String getPrincipalIdForName(String principalName) {
229                return KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(principalName).getPrincipalId();
230        }
231
232        protected String getPrincipalNameForId(String principalId) {
233                return KimApiServiceLocator.getIdentityService().getPrincipal(principalId).getPrincipalName();
234        }
235
236        protected String getGroupIdForName(String namespace, String groupName) {
237                return KimApiServiceLocator.getGroupService().getGroupByNamespaceCodeAndName(namespace, groupName).getId();
238        }
239
240    protected Long getNextSequenceLongValue(String sequenceName) {
241        return Long.valueOf(MaxValueIncrementerFactory.getIncrementer(TestHarnessServiceLocator.getDataSource(),
242                sequenceName).nextLongValue());
243    }
244
245    protected String getNextSequenceStringValue(String sequenceName) {
246        return MaxValueIncrementerFactory.getIncrementer(TestHarnessServiceLocator.getDataSource(), sequenceName).nextStringValue();
247    }
248
249    protected String getRoleIdForName(String namespace, String roleName) {
250        Role role = KimApiServiceLocator.getRoleService().getRoleByNamespaceCodeAndName(namespace, roleName);
251        return (role == null) ? null : role.getId();
252    }
253
254    public static final class BootstrapTest extends KEWTestCase {
255        @Test
256        public void bootstrapTest() {};
257    }
258
259}