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.kew.rule.RuleBaseValues; 032 import org.kuali.rice.kew.rule.RuleExtensionBo; 033 import org.kuali.rice.kew.rule.RuleExtensionValue; 034 import org.kuali.rice.kew.service.KEWServiceLocator; 035 import org.kuali.rice.kew.test.KEWTestCase; 036 import org.kuali.rice.krad.util.LegacyUtils; 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 // TODO: this isn't really the same test as isJpaEnabled 085 // i.e. JPA will be present even when the legacy data framework is enabled 086 // what do we do in this case? 087 //final boolean isKewJpaEnabled = OrmUtils.isJpaEnabled("rice.kew"); 088 final boolean isKewJpaEnabled = !LegacyUtils.isLegacyDataFrameworkEnabled(); 089 try { 090 KEWServiceLocator.getRuleService().save2(rbv); 091 fail("exception did not happen"); 092 } catch (RuntimeException e) { 093 boolean fail = !isKewJpaEnabled ? e instanceof PersistenceException : e instanceof DataIntegrityViolationException; 094 if (fail) { 095 fail("Did not throw exception as expected. If rule service behavior has changed, update this test."); 096 } 097 } 098 099 //fail("Saving a rule extension value with an empty string as the value yields a constraint violation"); 100 } 101 102 /** 103 * Tests the RuleService's ability to retrieve RuleBaseValues instances that lack an associated rule responsibility. 104 * @see https://test.kuali.org/jira/browse/KULRICE-3513 105 */ 106 @Test 107 public void testRetrievalOfRulesWithoutResponsibilities() throws Exception { 108 loadXmlFile("org/kuali/rice/kew/rule/RulesWithoutResponsibilities.xml"); 109 final String NULL_ID = null; 110 final String[] expectedRuleNames = {"NoResponsibilitiesRule1", "NoResponsibilitiesRule2", "NoResponsibilitiesRule3"}; 111 final String[] expectedRuleDocTypes = {"RiceDocument.RuleDocument", "RiceDocument.child1", "RiceDocument.child1child"}; 112 final String[] expectedRuleDescriptions = {"A rule with no responsibilities", "Another rule without responsibilities", "A third rule lacking responsibilities"}; 113 final String[] personResponsibilities = {"rkirkend", "rkirkend", "user1"}; 114 final String[] groupResponsibilities = {"TestWorkgroup", "NonSIT", "TestWorkgroup"}; 115 int actualResponsibilitylessRuleCount = 0; 116 List<?> ruleList = null; 117 118 // First, check that a blank search will retrieve all of the expected responsibility-less rules above. 119 ruleList = KEWServiceLocator.getRuleService().search(null, NULL_ID, null, null, null, null, null, null, null, ""); 120 assertNotNull("The returned rule list should not be null", ruleList); 121 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) { 122 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next(); 123 if (rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty()) { 124 actualResponsibilitylessRuleCount++; 125 } 126 } 127 assertEquals("Wrong number of responsibility-less rules found", expectedRuleNames.length, actualResponsibilitylessRuleCount); 128 129 // Next, test the retrieval of each of these rules independently. 130 for (int i = 0; i < expectedRuleNames.length; i++) { 131 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, expectedRuleDescriptions[i], null, null, null, null, null, ""); 132 assertNotNull("The returned rule list should not be null when searching for rule '" + expectedRuleNames[i] + "'", ruleList); 133 assertEquals("Exactly one rule should have been retrieved when searching for rule '" + expectedRuleNames[i] + "'", 1, ruleList.size()); 134 RuleBaseValues rBaseValues = (RuleBaseValues) ruleList.get(0); 135 assertEquals("The retrieved rule has the wrong name", expectedRuleNames[i], rBaseValues.getName()); 136 assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong doc type name", expectedRuleDocTypes[i], rBaseValues.getDocTypeName()); 137 assertEquals("Rule '" + expectedRuleNames[i] + "' has the wrong description", expectedRuleDescriptions[i], rBaseValues.getDescription()); 138 assertTrue("Rule '" + expectedRuleNames[i] + "' should not have any responsibilities", 139 rBaseValues.getRuleResponsibilities() == null || rBaseValues.getRuleResponsibilities().isEmpty()); 140 } 141 142 // Verify that when searching for rules with the same doc types but with a person responsibility specified, the responsibility-less rules are not retrieved. 143 for (int i = 0; i < expectedRuleNames.length; i++) { 144 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null, null, 145 KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName(personResponsibilities[i]).getPrincipalId(), null, null, null, "user"); 146 assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList); 147 assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty()); 148 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) { 149 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next(); 150 assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append( 151 expectedRuleDocTypes[i]).append("' and principal '").append(personResponsibilities[i]).append("'").toString(), 152 rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty()); 153 } 154 } 155 156 // Verify that when searching for rules with the same doc types but with a group responsibility specified, the responsibility-less rules are not retrieved. 157 for (int i = 0; i < expectedRuleNames.length; i++) { 158 ruleList = KEWServiceLocator.getRuleService().search(expectedRuleDocTypes[i], NULL_ID, null, null, 159 KEWServiceLocator.getIdentityHelperService().getGroupByName("KR-WKFLW", groupResponsibilities[i]).getId(), null, null, null, null, ""); 160 assertNotNull("The returned rule list should not be null for doc type '" + expectedRuleDocTypes[i] + "'", ruleList); 161 assertFalse("The returned rule list should not be empty for doc type '" + expectedRuleDocTypes[i] + "'", ruleList.isEmpty()); 162 for (Iterator<?> ruleIter = ruleList.iterator(); ruleIter.hasNext();) { 163 RuleBaseValues rBaseValues = (RuleBaseValues) ruleIter.next(); 164 assertTrue((new StringBuilder()).append("Found a rule without responsibilities for doc type '").append( 165 expectedRuleDocTypes[i]).append("' and group '").append(groupResponsibilities[i]).append("' with namespace 'KR-WKFLW'").toString(), 166 rBaseValues.getRuleResponsibilities() != null && !rBaseValues.getRuleResponsibilities().isEmpty()); 167 } 168 } 169 } 170 }