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.kew.rule.service.impl;
017
018 import static org.junit.Assert.assertEquals;
019 import static org.junit.Assert.assertFalse;
020 import static org.junit.Assert.assertNotNull;
021 import static org.junit.Assert.assertNull;
022 import static org.junit.Assert.assertTrue;
023 import static org.junit.Assert.fail;
024
025 import java.util.Iterator;
026 import java.util.List;
027
028 import javax.persistence.PersistenceException;
029
030 import org.junit.Test;
031 import org.kuali.rice.core.framework.persistence.jpa.OrmUtils;
032 import org.kuali.rice.kew.rule.RuleBaseValues;
033 import org.kuali.rice.kew.rule.RuleExtensionBo;
034 import org.kuali.rice.kew.rule.RuleExtensionValue;
035 import org.kuali.rice.kew.service.KEWServiceLocator;
036 import org.kuali.rice.kew.test.KEWTestCase;
037 import org.kuali.rice.test.BaselineTestCase;
038 import org.springframework.dao.DataIntegrityViolationException;
039
040 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE)
041 public class RuleServiceTest extends KEWTestCase {
042
043 protected void loadTestData() throws Exception {
044 loadXmlFile("org/kuali/rice/kew/rule/RouteTemplateConfig.xml");
045 }
046
047 /**
048 * Tests the effect of adding a rule with an extension that has an empty value.
049 * Currently, depending on database, this may yield a constraint violation as the empty
050 * string may be interpreted as a NULL value by the database.
051 * @see https://test.kuali.org/jira/browse/KULRNE-6182
052 */
053 @Test
054 public void testEmptyRuleExtension() throws Exception {
055 final RuleBaseValues rbv = new RuleBaseValues();
056 rbv.setActive(Boolean.TRUE);
057 rbv.setCurrentInd(Boolean.TRUE);
058 rbv.setDescription("A test rule");
059 rbv.setDocTypeName("TestDocumentType");
060 rbv.setForceAction(Boolean.FALSE);
061
062 RuleExtensionBo ext = new RuleExtensionBo();
063 RuleExtensionValue val = new RuleExtensionValue();
064 val.setKey("emptyvalue");
065 val.setValue("");
066 ext.getExtensionValues().add(val);
067 rbv.getRuleExtensions().add(ext);
068
069 /*
070 * The AssertThrows below should work with OJB, but some problems are occurring when using JPA/Hibernate (see below).
071 *
072 * FIXME: When the operation below throws the expected exception (when JPA/Hibernate is used), it appears to do so while returning from the method call
073 * (at which time the expected-to-fail saving operation gets committed by Hibernate). Unfortunately, the exception gets thrown at the wrong time when returning,
074 * because any attempts to run subsequent unit tests or unit test methods during the same JUnit test run will fail, due to NOWAIT exceptions
075 * during test case startup.
076 *
077 * A temporary hack to bypass this problem is to add the following line at the end of the 3-argument RuleServiceImpl.save2() method, which will force the
078 * bad saving operation to take place at the right time for a proper rollback to occur:
079 *
080 * getRuleDAO().findRuleBaseValuesById(ruleBaseValues.getId());
081 *
082 * However, a longer-term solution will be needed in case there are similar areas in the system with these kinds of problems.
083 */
084 final boolean isKewJpaEnabled = OrmUtils.isJpaEnabled("rice.kew");
085 try {
086 KEWServiceLocator.getRuleService().save2(rbv);
087 fail("exception did not happen");
088 } catch (RuntimeException e) {
089 boolean fail = !isKewJpaEnabled ? e instanceof PersistenceException : e instanceof DataIntegrityViolationException;
090 if (fail) {
091 fail("Did not throw exception as expected. If rule service behavior has changed, update this test.");
092 }
093 }
094
095 //fail("Saving a rule extension value with an empty string as the value yields a constraint violation");
096 }
097
098 /**
099 * Tests the RuleService's ability to retrieve RuleBaseValues instances that lack an associated rule responsibility.
100 * @see https://test.kuali.org/jira/browse/KULRICE-3513
101 */
102 @Test
103 public void testRetrievalOfRulesWithoutResponsibilities() throws Exception {
104 loadXmlFile("org/kuali/rice/kew/rule/RulesWithoutResponsibilities.xml");
105 final String NULL_ID = null;
106 final String[] expectedRuleNames = {"NoResponsibilitiesRule1", "NoResponsibilitiesRule2", "NoResponsibilitiesRule3"};
107 final String[] expectedRuleDocTypes = {"RiceDocument.RuleDocument", "RiceDocument.child1", "RiceDocument.child1child"};
108 final String[] expectedRuleDescriptions = {"A rule with no responsibilities", "Another rule without responsibilities", "A third rule lacking responsibilities"};
109 final String[] personResponsibilities = {"rkirkend", "rkirkend", "user1"};
110 final String[] groupResponsibilities = {"TestWorkgroup", "NonSIT", "TestWorkgroup"};
111 int actualResponsibilitylessRuleCount = 0;
112 List<?> ruleList = null;
113
114 // First, check that a blank search will retrieve all of the expected responsibility-less rules above.
115 ruleList = KEWServiceLocator.getRuleService().search(null, NULL_ID, null, null, null, null, null, null, null, "");
116 assertNotNull("The returned rule list should not be null", ruleList);
117 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
118 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
119 if (rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty()) {
120 actualResponsibilitylessRuleCount++;
121 }
122 }
123 assertEquals("Wrong number of responsibility-less rules found", expectedRuleNames.length, actualResponsibilitylessRuleCount);
124
125 // Next, test the retrieval of each of these rules independently.
126 for (int i = 0; i < expectedRuleNames.length; i++) {
127 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, expectedRuleDescriptions[i], null, null, null, null, null, "");
128 assertNotNull("The returned rule list should not be null when searching for rule '" + expectedRuleNames[i] + "'", ruleList);
129 assertEquals("Exactly one rule should have been retrieved when searching for rule '" + expectedRuleNames[i] + "'", 1, ruleList.size());
130 RuleBaseValues rBaseValues = (RuleBaseValues) ruleList.get(0);
131 assertEquals("The retrieved rule has the wrong name", expectedRuleNames[i], rBaseValues.getName());
132 assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong doc type name", expectedRuleDocTypes[i], rBaseValues.getDocTypeName());
133 assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong description", expectedRuleDescriptions[i], rBaseValues.getDescription());
134 assertTrue("Rule '" + expectedRuleNames[i] + "' should not have any responsibilities",
135 rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty());
136 }
137
138 // Verify that when searching for rules with the same doc types but with a person responsibility specified, the responsibility-less rules are not retrieved.
139 for (int i = 0; i < expectedRuleNames.length; i++) {
140 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null, null,
141 KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName(personResponsibilities[i]).getPrincipalId(), null, null, null, "user");
142 assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList);
143 assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty());
144 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
145 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
146 assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append(
147 expectedRuleDocTypes[i]).append("' and principal '").append(personResponsibilities[i]).append("'").toString(),
148 rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty());
149 }
150 }
151
152 // Verify that when searching for rules with the same doc types but with a group responsibility specified, the responsibility-less rules are not retrieved.
153 for (int i = 0; i < expectedRuleNames.length; i++) {
154 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null,
155 KEWServiceLocator.getIdentityHelperService().getGroupByName("KR-WKFLW", groupResponsibilities[i]).getId(), null, null, null, null, "");
156 assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList);
157 assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty());
158 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
159 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
160 assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append(
161 expectedRuleDocTypes[i]).append("' and group '").append(groupResponsibilities[i]).append("' with namespace 'KR-WKFLW'").toString(),
162 rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty());
163 }
164 }
165 }
166 }