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 }