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.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.agenda.AgendaDefinition;
31  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
32  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
33  import org.kuali.rice.test.BaselineTestCase.BaselineMode;
34  import org.kuali.rice.test.BaselineTestCase.Mode;
35  import org.springframework.transaction.annotation.Transactional;
36  
37  import java.util.Collections;
38  import java.util.HashMap;
39  import java.util.List;
40  import java.util.Map;
41  
42  import static org.junit.Assert.*;
43  
44  @BaselineMode(Mode.CLEAR_DB)
45  public class RepositoryCreateAndExecuteIntegrationTest extends AbstractAgendaBoTest {
46  
47      static final String NAME = "name";
48      static final String PREREQ_TERM_VALUE = "prereqValue";
49      static final String NAMESPACE_CODE = "namespaceCode";
50  
51      static boolean localInitNeeded = true;
52  
53      /**
54       *   Override of setup of AbstractAgendaBoTest (not setUp) to ensure correct test values
55       */
56      @Override
57      @Before
58      public void setup() {
59          // Reset TestActionTypeService
60          TestActionTypeService.resetActionsFired();
61  
62          termBoService = KrmsRepositoryServiceLocator.getTermBoService();
63          contextRepository = KrmsRepositoryServiceLocator.getContextBoService();
64          krmsTypeRepository = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
65  
66          ruleBoService = KrmsRepositoryServiceLocator.getRuleBoService();
67          agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService();
68          actionBoService = KrmsRepositoryServiceLocator.getBean("actionBoService");
69          functionBoService = KrmsRepositoryServiceLocator.getBean("functionRepositoryService");
70          krmsAttributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
71  
72          ContextDefinition contextDefintion1 = contextRepository.getContextByNameAndNamespace(CONTEXT1, NAMESPACE1);
73  
74          // only set this stuff up if we don't already have Context1 (we don't clear out KRMS tables between test methods)
75          // run at least once in case previous tests have used this context and to ensure correct values
76          if (contextDefintion1 == null || localInitNeeded) {
77              localInitNeeded = false;
78              PerformanceLogger perfLog = new PerformanceLogger();
79              perfLog.log("starting agenda creation");
80  
81              contextDefintion1 = createContextDefinition(NAMESPACE1, CONTEXT1, Collections.singletonMap(CONTEXT1_QUALIFIER,
82                      CONTEXT1_QUALIFIER_VALUE));
83              createAgendaDefinition(AGENDA1, contextDefintion1, TSUNAMI_EVENT, NAMESPACE1);
84  
85              ContextDefinition contextDefinition2 = createContextDefinition(NAMESPACE2, CONTEXT2,
86                      Collections.singletonMap(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE));
87  
88              ContextDefinition contextDefinition3 = createContextDefinition(NAMESPACE1, CONTEXT3,
89                      Collections.<String,String>emptyMap());
90  
91              // Create multiple agendas so that we can test selection
92              createAgendaDefinition(AGENDA2, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
93              createAgendaDefinition(AGENDA3, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
94              createAgendaDefinition(AGENDA4, contextDefinition2, TSUNAMI_EVENT, NAMESPACE2);
95              createAgendaDefinition2(AGENDA5, contextDefinition3, NAMESPACE1);
96  
97              perfLog.log("finished agenda creation", true);
98          }
99      }
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 }