View Javadoc
1   /**
2    * Copyright 2005-2013 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.krms.test;
17  
18  import org.apache.commons.lang.exception.ExceptionUtils;
19  import org.joda.time.DateTime;
20  import org.junit.Before;
21  import org.junit.Test;
22  import org.kuali.rice.kew.util.PerformanceLogger;
23  import org.kuali.rice.krms.api.KrmsApiServiceLocator;
24  import org.kuali.rice.krms.api.engine.EngineResults;
25  import org.kuali.rice.krms.api.engine.ExecutionFlag;
26  import org.kuali.rice.krms.api.engine.ExecutionOptions;
27  import org.kuali.rice.krms.api.engine.Facts;
28  import org.kuali.rice.krms.api.engine.ResultEvent;
29  import org.kuali.rice.krms.api.engine.SelectionCriteria;
30  import org.kuali.rice.krms.api.repository.LogicalOperator;
31  import org.kuali.rice.krms.api.repository.action.ActionDefinition;
32  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
33  import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
34  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
35  import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
36  import org.kuali.rice.krms.api.repository.function.FunctionParameterDefinition;
37  import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
38  import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
39  import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
40  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
41  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
42  import org.kuali.rice.krms.api.repository.term.TermDefinition;
43  import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
44  import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
45  import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
46  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
47  import org.kuali.rice.krms.impl.repository.ActionBoService;
48  import org.kuali.rice.krms.impl.repository.AgendaBoService;
49  import org.kuali.rice.krms.impl.repository.FunctionBoServiceImpl;
50  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
51  import org.kuali.rice.krms.impl.repository.RuleBoService;
52  import org.kuali.rice.krms.impl.repository.TermBo;
53  import org.kuali.rice.krms.impl.repository.TermBoService;
54  import org.kuali.rice.test.BaselineTestCase.BaselineMode;
55  import org.kuali.rice.test.BaselineTestCase.Mode;
56  import org.springframework.transaction.annotation.Transactional;
57  
58  import java.util.ArrayList;
59  import java.util.Collections;
60  import java.util.HashMap;
61  import java.util.List;
62  import java.util.Map;
63  
64  import static org.junit.Assert.*;
65  
66  @BaselineMode(Mode.CLEAR_DB)
67  public class RepositoryCreateAndExecuteIntegrationTest extends AbstractAgendaBoTest {
68  
69      static final String NAME = "name";
70      static final String PREREQ_TERM_VALUE = "prereqValue";
71      static final String NAMESPACE_CODE = "namespaceCode";
72  
73      static boolean localInitNeeded = true;
74  
75      /**
76       *   Override of setup of AbstractAgendaBoTest (not setUp) to ensure correct test values
77       */
78      @Override
79      @Before
80      public void setup() {
81          // Reset TestActionTypeService
82          TestActionTypeService.resetActionsFired();
83  
84          termBoService = KrmsRepositoryServiceLocator.getTermBoService();
85          contextRepository = KrmsRepositoryServiceLocator.getContextBoService();
86          krmsTypeRepository = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
87  
88          ruleBoService = KrmsRepositoryServiceLocator.getRuleBoService();
89          agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService();
90          actionBoService = KrmsRepositoryServiceLocator.getBean("actionBoService");
91          functionBoService = KrmsRepositoryServiceLocator.getBean("functionRepositoryService");
92          krmsAttributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
93  
94          ContextDefinition contextDefintion1 = contextRepository.getContextByNameAndNamespace(CONTEXT1, NAMESPACE1);
95  
96          // only set this stuff up if we don't already have Context1 (we don't clear out KRMS tables between test methods)
97          // run at least once in case previous tests have used this context and to ensure correct values
98          if (contextDefintion1 == null || localInitNeeded) {
99              localInitNeeded = false;
100             PerformanceLogger perfLog = new PerformanceLogger();
101             perfLog.log("starting agenda creation");
102 
103             contextDefintion1 = createContextDefinition(NAMESPACE1, CONTEXT1, Collections.singletonMap(CONTEXT1_QUALIFIER,
104                     CONTEXT1_QUALIFIER_VALUE));
105             createAgendaDefinition(AGENDA1, contextDefintion1, TSUNAMI_EVENT, NAMESPACE1);
106 
107             ContextDefinition contextDefinition2 = createContextDefinition(NAMESPACE2, CONTEXT2,
108                     Collections.singletonMap(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE));
109 
110             ContextDefinition contextDefinition3 = createContextDefinition(NAMESPACE1, CONTEXT3,
111                     Collections.<String,String>emptyMap());
112 
113             // Create multiple agendas so that we can test selection
114             createAgendaDefinition(AGENDA2, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
115             createAgendaDefinition(AGENDA3, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
116             createAgendaDefinition(AGENDA4, contextDefinition2, TSUNAMI_EVENT, NAMESPACE2);
117             createAgendaDefinition2(AGENDA5, contextDefinition3, NAMESPACE1);
118 
119             perfLog.log("finished agenda creation", true);
120         }
121     }
122 
123     @Transactional
124     @Test
125     public void testNullFact() {
126 
127         Map<String,String> contextQualifiers = new HashMap<String,String>();
128         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1);
129         contextQualifiers.put(NAME, CONTEXT3);
130 
131         Map<String,String> agendaQualifiers = new HashMap<String,String>();
132         agendaQualifiers.put(NAME, AGENDA5);
133 
134         DateTime now = new DateTime();
135 
136         SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
137 
138         Facts.Builder factsBuilder1 = Facts.Builder.create();
139         factsBuilder1.addFact(NULL_FACT, null);
140 
141         ExecutionOptions xOptions1 = new ExecutionOptions();
142         xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true);
143 
144         PerformanceLogger perfLog = new PerformanceLogger();
145         perfLog.log("starting rule execution");
146         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1);
147         perfLog.log("finished rule execution", true);
148         List<ResultEvent> rEvents1 = executeEngileResults(eResults1);
149 
150         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
151 
152         assertEquals("1 rules should have been evaluated", 1, ruleEvaluationResults1.size());
153 
154         assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult());
155 
156         // ONLY agenda 5 should have been selected
157         assertTrue(TestActionTypeService.actionFired("Agenda5::Rule5::TestAction"));
158 
159         assertAgendaDidNotExecute(AGENDA1);
160         assertAgendaDidNotExecute(AGENDA2);
161         assertAgendaDidNotExecute(AGENDA3);
162         assertAgendaDidNotExecute(AGENDA4);
163     }    
164 
165     @Transactional
166     @Test
167     public void testSelectAgendaByAttributeAndName() {
168 
169         Map<String,String> contextQualifiers = new HashMap<String,String>();
170         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1);
171         contextQualifiers.put(NAME, CONTEXT1);
172         contextQualifiers.put(CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE);
173 
174         Map<String,String> agendaQualifiers = new HashMap<String,String>();
175         agendaQualifiers.put(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT);
176         agendaQualifiers.put(NAME, AGENDA1);
177 
178         DateTime now = new DateTime();
179 
180         SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers,
181                 Collections.singletonMap(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT));
182 
183         Facts.Builder factsBuilder1 = Facts.Builder.create();
184         factsBuilder1.addFact(CAMPUS_CODE_TERM_NAME, "BL");
185         factsBuilder1.addFact(BOOL1, "true");
186         factsBuilder1.addFact(BOOL2, Boolean.TRUE);
187         factsBuilder1.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
188 
189         ExecutionOptions xOptions1 = new ExecutionOptions();
190         xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true);
191 
192         PerformanceLogger perfLog = new PerformanceLogger();
193         perfLog.log("starting rule execution");
194         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1);
195         perfLog.log("finished rule execution", true);
196         List<ResultEvent> rEvents1 = executeEngileResults(eResults1);
197 
198         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
199 
200         assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size());
201 
202         assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult());
203         assertFalse("rule 1 should have evaluated to false", ruleEvaluationResults1.get(1).getResult());
204         assertTrue("rule 2 should have evaluated to true", ruleEvaluationResults1.get(2).getResult());
205 
206         // ONLY agenda 1 should have been selected
207         assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule1::TestAction"));
208         assertFalse(TestActionTypeService.actionFired("TestAgenda1::Rule2::TestAction"));
209         assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule3::TestAction"));
210 
211         assertAgendaDidNotExecute(AGENDA2);
212         assertAgendaDidNotExecute(AGENDA3);
213         assertAgendaDidNotExecute(AGENDA4);
214         assertAgendaDidNotExecute(AGENDA5);
215     }
216 
217     @Transactional
218     @Test
219     public void testSelectAgendaByName() {
220         Map<String,String> contextQualifiers = new HashMap<String,String>();
221         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
222         contextQualifiers.put(NAME, CONTEXT2);
223         contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
224         Map<String,String> agendaQualifiers = new HashMap<String,String>();
225 
226         /*
227          * We'll specifically NOT select this attribute to make sure that matching only takes place against qualifiers
228          * in the selection criteria
229          */
230         // agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT);
231 
232         agendaQualifiers.put(NAME, AGENDA3);
233         DateTime now = new DateTime();
234 
235         SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
236 
237         Facts.Builder factsBuilder2 = Facts.Builder.create();
238         factsBuilder2.addFact(BOOL1, "true");
239         factsBuilder2.addFact(BOOL2, Boolean.TRUE);
240         factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
241         factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
242 
243         ExecutionOptions xOptions2 = new ExecutionOptions();
244         xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
245 
246 
247         PerformanceLogger perfLog = new PerformanceLogger();
248         perfLog.log("starting rule execution 1");
249         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2);
250         perfLog.log("finished rule execution 1");
251         List<ResultEvent> rEvents1 = executeEngileResults(eResults1);
252 
253         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
254 
255         selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
256 
257         assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size());
258 
259         assertAgendaDidNotExecute(AGENDA1);
260         assertAgendaDidNotExecute(AGENDA2);
261 
262         // ONLY agenda 3 should have been selected
263         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction"));
264         assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction"));
265         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction"));
266 
267         assertAgendaDidNotExecute(AGENDA4);
268         assertAgendaDidNotExecute(AGENDA5);
269     }
270 
271 
272     @Transactional
273     @Test
274     public void testSelectMultipleAgendasByAttribute() {
275         Map<String,String> contextQualifiers = new HashMap<String,String>();
276         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
277         contextQualifiers.put(NAME, CONTEXT2);
278         contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
279 
280         Map<String,String> agendaQualifiers = new HashMap<String,String>();
281         agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT);
282 
283         DateTime now = new DateTime();
284 
285         SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
286 
287         Facts.Builder factsBuilder2 = Facts.Builder.create();
288         factsBuilder2.addFact(BOOL1, "true");
289         factsBuilder2.addFact(BOOL2, Boolean.TRUE);
290         factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
291         factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
292 
293         ExecutionOptions xOptions2 = new ExecutionOptions();
294         xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
295 
296 
297         PerformanceLogger perfLog = new PerformanceLogger();
298         perfLog.log("starting rule execution 1");
299         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2);
300         perfLog.log("finished rule execution 1");
301         List<ResultEvent> rEvents1 = executeEngileResults(eResults1);
302 
303         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
304 
305         selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
306 
307         assertEquals("8 rules should have been evaluated", 8, ruleEvaluationResults1.size());
308 
309         assertAgendaDidNotExecute(AGENDA1);
310 
311         // ONLY agendas 2 & 3 should have been selected
312 
313         assertTrue(TestActionTypeService.actionFired("Agenda2::Rule1::TestAction"));
314         assertFalse(TestActionTypeService.actionFired("Agenda2::Rule2::TestAction"));
315         assertTrue(TestActionTypeService.actionFired("Agenda2::Rule3::TestAction"));
316 
317         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction"));
318         assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction"));
319         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction"));
320 
321         assertAgendaDidNotExecute(AGENDA4);
322         assertAgendaDidNotExecute(AGENDA5);
323     }
324 
325     private List<ResultEvent> executeEngileResults(EngineResults eResults1) {
326         try {
327             return eResults1.getAllResults(); // CI NPE
328         } catch (NullPointerException npe) {
329             fail("https://jira.kuali.org/browse/KULRICE-8625 KRMS RepositoryCreateAndExecuteIntegrationTest fails with NPE in CI passes locally." + ExceptionUtils.getStackTrace(npe));
330         }
331         return null;
332     }
333 
334     private void assertAgendaDidNotExecute(String agendaName) {
335         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule1::TestAction"));
336         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule2::TestAction"));
337         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule3::TestAction"));
338     }
339 
340 }