View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.rule.service.impl;
17  
18  import static org.junit.Assert.assertEquals;
19  import static org.junit.Assert.assertFalse;
20  import static org.junit.Assert.assertNotNull;
21  import static org.junit.Assert.assertNull;
22  import static org.junit.Assert.assertTrue;
23  import static org.junit.Assert.fail;
24  
25  import java.util.Iterator;
26  import java.util.List;
27  
28  import javax.persistence.PersistenceException;
29  
30  import org.junit.Test;
31  import org.kuali.rice.kew.rule.RuleBaseValues;
32  import org.kuali.rice.kew.rule.RuleExtensionBo;
33  import org.kuali.rice.kew.rule.RuleExtensionValue;
34  import org.kuali.rice.kew.service.KEWServiceLocator;
35  import org.kuali.rice.kew.test.KEWTestCase;
36  import org.kuali.rice.krad.util.LegacyUtils;
37  import org.kuali.rice.test.BaselineTestCase;
38  import org.springframework.dao.DataIntegrityViolationException;
39  
40  @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE)
41  public class RuleServiceTest extends KEWTestCase {
42  
43      protected void loadTestData() throws Exception {
44          loadXmlFile("org/kuali/rice/kew/rule/RouteTemplateConfig.xml");
45      }
46  
47      /**
48       * Tests the effect of adding a rule with an extension that has an empty value.
49       * Currently, depending on database, this may yield a constraint violation as the empty
50       * string may be interpreted as a NULL value by the database.
51       * @see https://test.kuali.org/jira/browse/KULRNE-6182
52       */
53      @Test
54      public void testEmptyRuleExtension() throws Exception {
55          final RuleBaseValues rbv = new RuleBaseValues();
56          rbv.setActive(Boolean.TRUE);
57          rbv.setCurrentInd(Boolean.TRUE);
58          rbv.setDescription("A test rule");
59          rbv.setDocTypeName("TestDocumentType");
60          rbv.setForceAction(Boolean.FALSE);
61  
62          RuleExtensionBo ext = new RuleExtensionBo();
63          RuleExtensionValue val = new RuleExtensionValue();
64          val.setKey("emptyvalue");
65          val.setValue("");
66          ext.getExtensionValues().add(val);
67          rbv.getRuleExtensions().add(ext);
68  
69          /*
70           * The AssertThrows below should work with OJB, but some problems are occurring when using JPA/Hibernate (see below).
71           * 
72           * 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
73           * (at which time the expected-to-fail saving operation gets committed by Hibernate). Unfortunately, the exception gets thrown at the wrong time when returning,
74           * because any attempts to run subsequent unit tests or unit test methods during the same JUnit test run will fail, due to NOWAIT exceptions
75           * during test case startup.
76           * 
77           * 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
78           * bad saving operation to take place at the right time for a proper rollback to occur:
79           * 
80           * getRuleDAO().findRuleBaseValuesById(ruleBaseValues.getId());
81           * 
82           * However, a longer-term solution will be needed in case there are similar areas in the system with these kinds of problems.
83           */
84          // TODO: this isn't really the same test as isJpaEnabled
85          // i.e. JPA will be present even when the legacy data framework is enabled
86          // what do we do in this case?
87          final boolean isKewJpaEnabled = !LegacyUtils.isLegacyDataFrameworkEnabled();
88          try {
89              KEWServiceLocator.getRuleService().save2(rbv);
90              fail("exception did not happen");
91          } catch (RuntimeException e) {
92              boolean fail = !isKewJpaEnabled ? e instanceof PersistenceException : e instanceof DataIntegrityViolationException;
93              if (fail) {
94                  fail("Did not throw exception as expected.  If rule service behavior has changed, update this test.");
95              }
96          }
97  
98          //fail("Saving a rule extension value with an empty string as the value yields a constraint violation");
99      }
100     
101     /**
102      * Tests the RuleService's ability to retrieve RuleBaseValues instances that lack an associated rule responsibility. 
103      * @see https://test.kuali.org/jira/browse/KULRICE-3513
104      */
105     @Test
106     public void testRetrievalOfRulesWithoutResponsibilities() throws Exception {
107     	loadXmlFile("org/kuali/rice/kew/rule/RulesWithoutResponsibilities.xml");
108     	final String NULL_ID = null;
109     	final String[] expectedRuleNames = {"NoResponsibilitiesRule1", "NoResponsibilitiesRule2", "NoResponsibilitiesRule3"};
110     	final String[] expectedRuleDocTypes = {"RiceDocument.RuleDocument", "RiceDocument.child1", "RiceDocument.child1child"};
111     	final String[] expectedRuleDescriptions = {"A rule with no responsibilities", "Another rule without responsibilities", "A third rule lacking responsibilities"};
112     	final String[] personResponsibilities = {"rkirkend", "rkirkend", "user1"};
113     	final String[] groupResponsibilities = {"TestWorkgroup", "NonSIT", "TestWorkgroup"};
114     	int actualResponsibilitylessRuleCount = 0;
115     	List<?> ruleList = null;
116     	
117     	// First, check that a blank search will retrieve all of the expected responsibility-less rules above.
118     	ruleList = KEWServiceLocator.getRuleService().search(null, NULL_ID, null, null, null, null, null, null, null, "");
119     	assertNotNull("The returned rule list should not be null", ruleList);
120     	for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
121     		RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
122     		if (rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty()) {
123    				actualResponsibilitylessRuleCount++;
124     		}
125     	}
126     	assertEquals("Wrong number of responsibility-less rules found", expectedRuleNames.length, actualResponsibilitylessRuleCount);
127     	
128     	// Next, test the retrieval of each of these rules independently.
129     	for (int i = 0; i < expectedRuleNames.length; i++) {
130     		ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, expectedRuleDescriptions[i], null, null, null, null, null, "");
131     		assertNotNull("The returned rule list should not be null when searching for rule '" + expectedRuleNames[i] + "'", ruleList);
132     		assertEquals("Exactly one rule should have been retrieved when searching for rule '" + expectedRuleNames[i] + "'", 1, ruleList.size());
133     		RuleBaseValues rBaseValues = (RuleBaseValues) ruleList.get(0);
134     		assertEquals("The retrieved rule has the wrong name", expectedRuleNames[i], rBaseValues.getName());
135     		assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong doc type name", expectedRuleDocTypes[i], rBaseValues.getDocTypeName());
136     		assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong description", expectedRuleDescriptions[i], rBaseValues.getDescription());
137     		assertTrue("Rule '" + expectedRuleNames[i] + "' should not have any responsibilities",
138     				rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty());
139     	}
140     	
141     	// Verify that when searching for rules with the same doc types but with a person responsibility specified, the responsibility-less rules are not retrieved.
142     	for (int i = 0; i < expectedRuleNames.length; i++) {
143     		ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null, null,
144     				KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName(personResponsibilities[i]).getPrincipalId(), null, null, null, "user");
145     		assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList);
146     		assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty());
147     		for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
148         		RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
149         		assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append(
150         				expectedRuleDocTypes[i]).append("' and principal '").append(personResponsibilities[i]).append("'").toString(),
151         					rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty());
152         	}
153     	}
154     	
155     	// Verify that when searching for rules with the same doc types but with a group responsibility specified, the responsibility-less rules are not retrieved.
156     	for (int i = 0; i < expectedRuleNames.length; i++) {
157     		ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null,
158     				KEWServiceLocator.getIdentityHelperService().getGroupByName("KR-WKFLW", groupResponsibilities[i]).getId(), null, null, null, null, "");
159     		assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList);
160     		assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty());
161     		for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) {
162         		RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next();
163         		assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append(
164         				expectedRuleDocTypes[i]).append("' and group '").append(groupResponsibilities[i]).append("' with namespace 'KR-WKFLW'").toString(),
165         					rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty());
166         	}
167     	}
168     }
169 }