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 */ 016 package org.kuali.rice.krms.test; 017 018 import org.apache.commons.lang.exception.ExceptionUtils; 019 import org.joda.time.DateTime; 020 import org.junit.Before; 021 import org.junit.Test; 022 import org.kuali.rice.kew.util.PerformanceLogger; 023 import org.kuali.rice.krms.api.KrmsApiServiceLocator; 024 import org.kuali.rice.krms.api.engine.EngineResults; 025 import org.kuali.rice.krms.api.engine.ExecutionFlag; 026 import org.kuali.rice.krms.api.engine.ExecutionOptions; 027 import org.kuali.rice.krms.api.engine.Facts; 028 import org.kuali.rice.krms.api.engine.ResultEvent; 029 import org.kuali.rice.krms.api.engine.SelectionCriteria; 030 import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition; 031 import org.kuali.rice.krms.api.repository.context.ContextDefinition; 032 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator; 033 import org.kuali.rice.test.BaselineTestCase.BaselineMode; 034 import org.kuali.rice.test.BaselineTestCase.Mode; 035 import org.springframework.transaction.annotation.Transactional; 036 037 import java.util.Collections; 038 import java.util.HashMap; 039 import java.util.List; 040 import java.util.Map; 041 042 import static org.junit.Assert.*; 043 044 @BaselineMode(Mode.CLEAR_DB) 045 public class RepositoryCreateAndExecuteIntegrationTest extends AbstractAgendaBoTest { 046 047 static final String NAME = "name"; 048 static final String PREREQ_TERM_VALUE = "prereqValue"; 049 static final String NAMESPACE_CODE = "namespaceCode"; 050 051 static boolean localInitNeeded = true; 052 053 /** 054 * Override of setup of AbstractAgendaBoTest (not setUp) to ensure correct test values 055 */ 056 @Override 057 @Before 058 public void setup() { 059 // Reset TestActionTypeService 060 TestActionTypeService.resetActionsFired(); 061 062 termBoService = KrmsRepositoryServiceLocator.getTermBoService(); 063 contextRepository = KrmsRepositoryServiceLocator.getContextBoService(); 064 krmsTypeRepository = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService(); 065 066 ruleBoService = KrmsRepositoryServiceLocator.getRuleBoService(); 067 agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService(); 068 actionBoService = KrmsRepositoryServiceLocator.getBean("actionBoService"); 069 functionBoService = KrmsRepositoryServiceLocator.getBean("functionRepositoryService"); 070 krmsAttributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService(); 071 072 ContextDefinition contextDefintion1 = contextRepository.getContextByNameAndNamespace(CONTEXT1, NAMESPACE1); 073 074 // only set this stuff up if we don't already have Context1 (we don't clear out KRMS tables between test methods) 075 // run at least once in case previous tests have used this context and to ensure correct values 076 if (contextDefintion1 == null || localInitNeeded) { 077 localInitNeeded = false; 078 PerformanceLogger perfLog = new PerformanceLogger(); 079 perfLog.log("starting agenda creation"); 080 081 contextDefintion1 = createContextDefinition(NAMESPACE1, CONTEXT1, Collections.singletonMap(CONTEXT1_QUALIFIER, 082 CONTEXT1_QUALIFIER_VALUE)); 083 createAgendaDefinition(AGENDA1, contextDefintion1, TSUNAMI_EVENT, NAMESPACE1); 084 085 ContextDefinition contextDefinition2 = createContextDefinition(NAMESPACE2, CONTEXT2, 086 Collections.singletonMap(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE)); 087 088 ContextDefinition contextDefinition3 = createContextDefinition(NAMESPACE1, CONTEXT3, 089 Collections.<String,String>emptyMap()); 090 091 // Create multiple agendas so that we can test selection 092 createAgendaDefinition(AGENDA2, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2); 093 createAgendaDefinition(AGENDA3, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2); 094 createAgendaDefinition(AGENDA4, contextDefinition2, TSUNAMI_EVENT, NAMESPACE2); 095 createAgendaDefinition2(AGENDA5, contextDefinition3, NAMESPACE1); 096 097 perfLog.log("finished agenda creation", true); 098 } 099 } 100 101 @Transactional 102 @Test 103 public void testNullFact() { 104 105 Map<String,String> contextQualifiers = new HashMap<String,String>(); 106 contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1); 107 contextQualifiers.put(NAME, CONTEXT3); 108 109 Map<String,String> agendaQualifiers = new HashMap<String,String>(); 110 agendaQualifiers.put(NAME, AGENDA5); 111 112 DateTime now = new DateTime(); 113 114 SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers); 115 116 Facts.Builder factsBuilder1 = Facts.Builder.create(); 117 factsBuilder1.addFact(NULL_FACT, null); 118 119 ExecutionOptions xOptions1 = new ExecutionOptions(); 120 xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true); 121 122 PerformanceLogger perfLog = new PerformanceLogger(); 123 perfLog.log("starting rule execution"); 124 EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1); 125 perfLog.log("finished rule execution", true); 126 List<ResultEvent> rEvents1 = executeEngineResults(eResults1); 127 128 List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString()); 129 130 assertEquals("1 rules should have been evaluated", 1, ruleEvaluationResults1.size()); 131 132 assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult()); 133 134 // ONLY agenda 5 should have been selected 135 assertTrue(TestActionTypeService.actionFired("Agenda5::Rule5::TestAction")); 136 137 assertAgendaDidNotExecute(AGENDA1); 138 assertAgendaDidNotExecute(AGENDA2); 139 assertAgendaDidNotExecute(AGENDA3); 140 assertAgendaDidNotExecute(AGENDA4); 141 } 142 143 @Transactional 144 @Test 145 public void testSelectAgendaByAttributeAndName() { 146 147 Map<String,String> contextQualifiers = new HashMap<String,String>(); 148 contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1); 149 contextQualifiers.put(NAME, CONTEXT1); 150 contextQualifiers.put(CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE); 151 152 Map<String,String> agendaQualifiers = new HashMap<String,String>(); 153 agendaQualifiers.put(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT); 154 agendaQualifiers.put(NAME, AGENDA1); 155 156 DateTime now = new DateTime(); 157 158 SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers, 159 Collections.singletonMap(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT)); 160 161 Facts.Builder factsBuilder1 = Facts.Builder.create(); 162 factsBuilder1.addFact(CAMPUS_CODE_TERM_NAME, "BL"); 163 factsBuilder1.addFact(BOOL1, "true"); 164 factsBuilder1.addFact(BOOL2, Boolean.TRUE); 165 factsBuilder1.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE); 166 167 ExecutionOptions xOptions1 = new ExecutionOptions(); 168 xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true); 169 170 PerformanceLogger perfLog = new PerformanceLogger(); 171 perfLog.log("starting rule execution"); 172 EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1); 173 perfLog.log("finished rule execution", true); 174 List<ResultEvent> rEvents1 = executeEngineResults(eResults1); 175 176 List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString()); 177 178 assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size()); 179 180 assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult()); 181 assertFalse("rule 1 should have evaluated to false", ruleEvaluationResults1.get(1).getResult()); 182 assertTrue("rule 2 should have evaluated to true", ruleEvaluationResults1.get(2).getResult()); 183 184 // ONLY agenda 1 should have been selected 185 assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule1::TestAction")); 186 assertFalse(TestActionTypeService.actionFired("TestAgenda1::Rule2::TestAction")); 187 assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule3::TestAction")); 188 189 assertAgendaDidNotExecute(AGENDA2); 190 assertAgendaDidNotExecute(AGENDA3); 191 assertAgendaDidNotExecute(AGENDA4); 192 assertAgendaDidNotExecute(AGENDA5); 193 } 194 195 @Transactional 196 @Test 197 public void testSelectAgendaByName() { 198 Map<String,String> contextQualifiers = new HashMap<String,String>(); 199 contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2); 200 contextQualifiers.put(NAME, CONTEXT2); 201 contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE); 202 Map<String,String> agendaQualifiers = new HashMap<String,String>(); 203 204 /* 205 * We'll specifically NOT select this attribute to make sure that matching only takes place against qualifiers 206 * in the selection criteria 207 */ 208 // agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT); 209 210 agendaQualifiers.put(NAME, AGENDA3); 211 DateTime now = new DateTime(); 212 213 SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers); 214 215 Facts.Builder factsBuilder2 = Facts.Builder.create(); 216 factsBuilder2.addFact(BOOL1, "true"); 217 factsBuilder2.addFact(BOOL2, Boolean.TRUE); 218 factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL"); 219 factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE); 220 221 ExecutionOptions xOptions2 = new ExecutionOptions(); 222 xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true); 223 224 225 PerformanceLogger perfLog = new PerformanceLogger(); 226 perfLog.log("starting rule execution 1"); 227 EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2); 228 perfLog.log("finished rule execution 1"); 229 List<ResultEvent> rEvents1 = executeEngineResults(eResults1); 230 231 List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString()); 232 233 selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers); 234 235 assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size()); 236 237 assertAgendaDidNotExecute(AGENDA1); 238 assertAgendaDidNotExecute(AGENDA2); 239 240 // ONLY agenda 3 should have been selected 241 assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction")); 242 assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction")); 243 assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction")); 244 245 assertAgendaDidNotExecute(AGENDA4); 246 assertAgendaDidNotExecute(AGENDA5); 247 } 248 249 250 @Transactional 251 @Test 252 public void testSelectMultipleAgendasByAttribute() { 253 Map<String,String> contextQualifiers = new HashMap<String,String>(); 254 contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2); 255 contextQualifiers.put(NAME, CONTEXT2); 256 contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE); 257 258 Map<String,String> agendaQualifiers = new HashMap<String,String>(); 259 agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT); 260 261 DateTime now = new DateTime(); 262 263 SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers); 264 265 Facts.Builder factsBuilder2 = Facts.Builder.create(); 266 factsBuilder2.addFact(BOOL1, "true"); 267 factsBuilder2.addFact(BOOL2, Boolean.TRUE); 268 factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL"); 269 factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE); 270 271 ExecutionOptions xOptions2 = new ExecutionOptions(); 272 xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true); 273 274 275 PerformanceLogger perfLog = new PerformanceLogger(); 276 perfLog.log("starting rule execution 1"); 277 EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2); 278 perfLog.log("finished rule execution 1"); 279 List<ResultEvent> rEvents1 = executeEngineResults(eResults1); 280 281 List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString()); 282 283 selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers); 284 285 assertEquals("8 rules should have been evaluated", 8, ruleEvaluationResults1.size()); 286 287 assertAgendaDidNotExecute(AGENDA1); 288 289 // ONLY agendas 2 & 3 should have been selected 290 291 assertTrue(TestActionTypeService.actionFired("Agenda2::Rule1::TestAction")); 292 assertFalse(TestActionTypeService.actionFired("Agenda2::Rule2::TestAction")); 293 assertTrue(TestActionTypeService.actionFired("Agenda2::Rule3::TestAction")); 294 295 assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction")); 296 assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction")); 297 assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction")); 298 299 assertAgendaDidNotExecute(AGENDA4); 300 assertAgendaDidNotExecute(AGENDA5); 301 } 302 303 private List<ResultEvent> executeEngineResults(EngineResults eResults1) { 304 try { 305 return eResults1.getAllResults(); // CI NPE 306 } catch (NullPointerException npe) { 307 fail("https://jira.kuali.org/browse/KULRICE-8625 KRMS RepositoryCreateAndExecuteIntegrationTest fails with NPE in CI passes locally." + ExceptionUtils.getStackTrace(npe)); 308 } 309 return null; 310 } 311 312 private void assertAgendaDidNotExecute(String agendaName) { 313 assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule1::TestAction")); 314 assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule2::TestAction")); 315 assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule3::TestAction")); 316 } 317 318 }