2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.drools.controller.internal;
23 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
24 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.Matchers.any;
31 import static org.mockito.Mockito.doThrow;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.never;
34 import static org.mockito.Mockito.times;
35 import static org.mockito.Mockito.verify;
36 import static org.mockito.Mockito.when;
38 import java.util.Arrays;
39 import java.util.Collections;
40 import java.util.List;
42 import java.util.TreeMap;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.kie.api.KieBase;
46 import org.kie.api.definition.KiePackage;
47 import org.kie.api.definition.rule.Query;
48 import org.kie.api.runtime.KieContainer;
49 import org.kie.api.runtime.KieSession;
50 import org.kie.api.runtime.rule.FactHandle;
51 import org.kie.api.runtime.rule.QueryResults;
52 import org.kie.api.runtime.rule.QueryResultsRow;
53 import org.mockito.ArgumentCaptor;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 import org.onap.policy.common.endpoints.event.comm.TopicSink;
57 import org.onap.policy.common.utils.services.OrderedServiceImpl;
58 import org.onap.policy.drools.core.PolicyContainer;
59 import org.onap.policy.drools.core.PolicySession;
60 import org.onap.policy.drools.features.DroolsControllerFeatureApi;
61 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
62 import org.onap.policy.drools.protocol.coders.EventProtocolParams;
63 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
64 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
65 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder;
66 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter;
68 public class MavenDroolsController2Test {
69 private static final int FACT1_OBJECT = 1000;
70 private static final int FACT3_OBJECT = 1001;
72 private static final long FACT_COUNT = 200L;
74 private static final String EXPECTED_EXCEPTION = "expected exception";
75 private static final RuntimeException RUNTIME_EX = new RuntimeException(EXPECTED_EXCEPTION);
76 private static final IllegalArgumentException ARG_EX = new IllegalArgumentException(EXPECTED_EXCEPTION);
78 private static final String UNKNOWN_CLASS = "unknown class";
80 private static final String GROUP = "my-group";
81 private static final String ARTIFACT = "my-artifact";
82 private static final String VERSION = "my-version";
84 private static final String GROUP2 = "my-groupB";
85 private static final String ARTIFACT2 = "my-artifactB";
86 private static final String VERSION2 = "my-versionB";
88 private static final String TOPIC = "my-topic";
89 private static final String TOPIC2 = "my-topic";
91 private static final ClassLoader CLASS_LOADER = MavenDroolsController2Test.class.getClassLoader();
92 private static final int CLASS_LOADER_HASHCODE = CLASS_LOADER.hashCode();
94 private static final String SESSION1 = "session-A";
95 private static final String SESSION2 = "session-B";
96 private static final String FULL_SESSION1 = "full-A";
97 private static final String FULL_SESSION2 = "full-B";
99 private static final String EVENT_TEXT = "my-event-text";
100 private static final Object EVENT = new Object();
102 private static final String QUERY = "my-query";
103 private static final String QUERY2 = "my-query-B";
104 private static final String ENTITY = "my-entity";
105 private static final Object PARM1 = "parmA";
106 private static final Object PARM2 = "parmB";
109 private EventProtocolCoder coderMgr;
111 private DroolsControllerFeatureApi prov1;
113 private DroolsControllerFeatureApi prov2;
115 private OrderedServiceImpl<DroolsControllerFeatureApi> droolsProviders;
117 private TopicCoderFilterConfiguration decoder1;
119 private TopicCoderFilterConfiguration decoder2;
121 private TopicCoderFilterConfiguration encoder1;
123 private TopicCoderFilterConfiguration encoder2;
125 private PolicyContainer container;
127 private CustomGsonCoder gson1;
129 private CustomGsonCoder gson2;
131 private PotentialCoderFilter filter1a;
133 private JsonProtocolFilter jsonFilter1a;
135 private PotentialCoderFilter filter1b;
137 private JsonProtocolFilter jsonFilter1b;
139 private PotentialCoderFilter filter2;
141 private JsonProtocolFilter jsonFilter2;
143 private PolicySession sess1;
145 private PolicySession sess2;
147 private KieSession kieSess;
149 private KieSession kieSess2;
151 private TopicSink sink;
153 private FactHandle fact1;
155 private FactHandle fact2;
157 private FactHandle fact3;
159 private FactHandle factex;
161 private KieBase kieBase;
163 private KiePackage pkg1;
165 private KiePackage pkg2;
167 private Query query1;
169 private Query query2;
171 private Query query3;
173 private QueryResults queryResults;
175 private QueryResultsRow row1;
177 private QueryResultsRow row2;
179 private List<TopicCoderFilterConfiguration> decoders;
180 private List<TopicCoderFilterConfiguration> encoders;
182 private MavenDroolsController drools;
185 * Initializes objects, including the drools controller.
188 public void setUp() {
189 MockitoAnnotations.initMocks(this);
191 when(droolsProviders.getList()).thenReturn(Arrays.asList(prov1, prov2));
193 when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(true);
194 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenReturn(EVENT);
196 when(kieSess.getFactCount()).thenReturn(FACT_COUNT);
197 when(kieSess.getFactHandles()).thenReturn(Arrays.asList(fact1, fact2, factex, fact3));
198 when(kieSess.getFactHandles(any())).thenReturn(Arrays.asList(fact1, fact3));
199 when(kieSess.getKieBase()).thenReturn(kieBase);
200 when(kieSess.getQueryResults(QUERY, PARM1, PARM2)).thenReturn(queryResults);
202 when(kieSess.getObject(fact1)).thenReturn(FACT1_OBJECT);
203 when(kieSess.getObject(fact2)).thenReturn("");
204 when(kieSess.getObject(fact3)).thenReturn(FACT3_OBJECT);
205 when(kieSess.getObject(factex)).thenThrow(RUNTIME_EX);
207 when(kieSess2.getFactHandles()).thenReturn(Collections.emptyList());
209 when(kieBase.getKiePackages()).thenReturn(Arrays.asList(pkg1, pkg2));
211 when(pkg1.getQueries()).thenReturn(Arrays.asList(query3));
212 when(pkg2.getQueries()).thenReturn(Arrays.asList(query2, query1));
214 when(query1.getName()).thenReturn(QUERY);
215 when(query2.getName()).thenReturn(QUERY2);
217 when(queryResults.iterator()).thenReturn(Arrays.asList(row1, row2).iterator());
219 when(row1.get(ENTITY)).thenReturn(FACT1_OBJECT);
220 when(row2.get(ENTITY)).thenReturn(FACT3_OBJECT);
222 when(row1.getFactHandle(ENTITY)).thenReturn(fact1);
223 when(row2.getFactHandle(ENTITY)).thenReturn(fact3);
225 when(sess1.getKieSession()).thenReturn(kieSess);
226 when(sess2.getKieSession()).thenReturn(kieSess2);
228 when(sess1.getName()).thenReturn(SESSION1);
229 when(sess2.getName()).thenReturn(SESSION2);
231 when(sess1.getFullName()).thenReturn(FULL_SESSION1);
232 when(sess2.getFullName()).thenReturn(FULL_SESSION2);
234 when(container.getClassLoader()).thenReturn(CLASS_LOADER);
235 when(container.getPolicySessions()).thenReturn(Arrays.asList(sess1, sess2));
236 when(container.insertAll(EVENT)).thenReturn(true);
238 when(decoder1.getTopic()).thenReturn(TOPIC);
239 when(decoder2.getTopic()).thenReturn(TOPIC2);
241 when(encoder1.getTopic()).thenReturn(TOPIC);
242 when(encoder2.getTopic()).thenReturn(TOPIC2);
244 decoders = Arrays.asList(decoder1, decoder2);
245 encoders = Arrays.asList(encoder1, encoder2);
247 when(decoder1.getCustomGsonCoder()).thenReturn(gson1);
248 when(encoder2.getCustomGsonCoder()).thenReturn(gson2);
250 when(filter1a.getCodedClass()).thenReturn(Object.class.getName());
251 when(filter1a.getFilter()).thenReturn(jsonFilter1a);
253 when(filter1b.getCodedClass()).thenReturn(String.class.getName());
254 when(filter1b.getFilter()).thenReturn(jsonFilter1b);
256 when(filter2.getCodedClass()).thenReturn(Integer.class.getName());
257 when(filter2.getFilter()).thenReturn(jsonFilter2);
259 when(decoder1.getCoderFilters()).thenReturn(Arrays.asList(filter1a, filter1b));
260 when(decoder2.getCoderFilters()).thenReturn(Collections.emptyList());
262 when(encoder1.getCoderFilters()).thenReturn(Collections.emptyList());
263 when(encoder2.getCoderFilters()).thenReturn(Arrays.asList(filter2));
265 when(sink.getTopic()).thenReturn(TOPIC);
266 when(sink.send(EVENT_TEXT)).thenReturn(true);
268 drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null);
270 when(coderMgr.encode(TOPIC, EVENT, drools)).thenReturn(EVENT_TEXT);
274 public void testMavenDroolsController_InvalidArgs() {
275 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(null, ARTIFACT, VERSION, null, null))
276 .withMessageContaining("group");
277 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools("", ARTIFACT, VERSION, null, null))
278 .withMessageContaining("group");
280 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, null, VERSION, null, null))
281 .withMessageContaining("artifact");
282 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, "", VERSION, null, null))
283 .withMessageContaining("artifact");
285 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, null, null, null))
286 .withMessageContaining("version");
287 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, "", null, null))
288 .withMessageContaining("version");
292 public void testUpdateToVersion() {
294 drools.updateToVersion(GROUP, ARTIFACT, VERSION2, decoders, encoders);
296 verify(container).updateToVersion(VERSION2);
298 // nothing removed the first time
299 verify(coderMgr, never()).removeDecoders(GROUP, ARTIFACT, TOPIC2);
300 verify(coderMgr, never()).removeEncoders(GROUP, ARTIFACT, TOPIC);
302 verify(coderMgr, times(2)).addDecoder(any());
303 verify(coderMgr, times(1)).addEncoder(any());
306 when(container.getVersion()).thenReturn(VERSION2);
307 drools.updateToVersion(GROUP, ARTIFACT, VERSION, null, null);
309 verify(container).updateToVersion(VERSION);
311 verify(coderMgr, times(2)).removeDecoders(GROUP, ARTIFACT, TOPIC2);
312 verify(coderMgr, times(2)).removeEncoders(GROUP, ARTIFACT, TOPIC);
315 verify(coderMgr, times(2)).addDecoder(any());
316 verify(coderMgr, times(1)).addEncoder(any());
320 public void testUpdateToVersion_Unchanged() {
321 drools.updateToVersion(GROUP, ARTIFACT, VERSION, decoders, encoders);
323 verify(coderMgr, never()).addDecoder(any());
324 verify(coderMgr, never()).addEncoder(any());
328 public void testUpdateToVersion_InvalidArgs() {
329 assertThatIllegalArgumentException()
330 .isThrownBy(() -> drools.updateToVersion(null, ARTIFACT, VERSION, null, null))
331 .withMessageContaining("group");
332 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion("", ARTIFACT, VERSION, null, null))
333 .withMessageContaining("group");
335 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, null, VERSION, null, null))
336 .withMessageContaining("artifact");
337 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, "", VERSION, null, null))
338 .withMessageContaining("artifact");
340 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, null, null, null))
341 .withMessageContaining("version");
342 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "", null, null))
343 .withMessageContaining("version");
345 assertThatIllegalArgumentException()
346 .isThrownBy(() -> drools.updateToVersion("no-group-id", ARTIFACT, VERSION, null, null))
347 .withMessageContaining("BRAINLESS");
349 assertThatIllegalArgumentException()
350 .isThrownBy(() -> drools.updateToVersion(GROUP, "no-artifact-id", VERSION, null, null))
351 .withMessageContaining("BRAINLESS");
353 assertThatIllegalArgumentException()
354 .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "no-version", null, null))
355 .withMessageContaining("BRAINLESS");
357 assertThatIllegalArgumentException()
358 .isThrownBy(() -> drools.updateToVersion(GROUP2, ARTIFACT, VERSION, null, null))
359 .withMessageContaining("coordinates must be identical");
361 assertThatIllegalArgumentException()
362 .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT2, VERSION, null, null))
363 .withMessageContaining("coordinates must be identical");
367 public void testInitCoders_NullCoders() {
368 // already constructed with null coders
369 verify(coderMgr, never()).addDecoder(any());
370 verify(coderMgr, never()).addEncoder(any());
374 public void testInitCoders_NullOrEmptyFilters() {
375 when(decoder1.getCoderFilters()).thenReturn(Collections.emptyList());
376 when(decoder2.getCoderFilters()).thenReturn(null);
378 when(encoder1.getCoderFilters()).thenReturn(null);
379 when(encoder2.getCoderFilters()).thenReturn(Collections.emptyList());
381 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
383 verify(coderMgr, never()).addDecoder(any());
384 verify(coderMgr, never()).addEncoder(any());
388 public void testInitCoders_GsonClass() {
389 when(gson1.getClassContainer()).thenReturn("");
390 when(gson2.getClassContainer()).thenReturn(Long.class.getName());
392 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
394 // all should be added
395 verify(coderMgr, times(2)).addDecoder(any());
396 verify(coderMgr, times(1)).addEncoder(any());
400 public void testInitCoders_InvalidGsonClass() {
401 when(gson1.getClassContainer()).thenReturn(UNKNOWN_CLASS);
403 assertThatIllegalArgumentException()
404 .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
405 .withMessageContaining("cannot be retrieved");
409 public void testInitCoders_InvalidFilterClass() {
410 when(filter2.getCodedClass()).thenReturn(UNKNOWN_CLASS);
412 assertThatIllegalArgumentException()
413 .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
414 .withMessageContaining("cannot be retrieved");
418 public void testInitCoders_Filters() {
420 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
422 ArgumentCaptor<EventProtocolParams> dec = ArgumentCaptor.forClass(EventProtocolParams.class);
423 verify(coderMgr, times(2)).addDecoder(dec.capture());
425 ArgumentCaptor<EventProtocolParams> enc = ArgumentCaptor.forClass(EventProtocolParams.class);
426 verify(coderMgr, times(1)).addEncoder(enc.capture());
428 // validate parameters
429 EventProtocolParams params = dec.getAllValues().get(0);
430 assertEquals(ARTIFACT, params.getArtifactId());
431 assertEquals(gson1, params.getCustomCoder());
432 assertEquals(Object.class.getName(), params.getEventClass());
433 assertEquals(GROUP, params.getGroupId());
434 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
435 assertEquals(jsonFilter1a, params.getProtocolFilter());
436 assertEquals(TOPIC, params.getTopic());
438 params = dec.getAllValues().get(1);
439 assertEquals(ARTIFACT, params.getArtifactId());
440 assertEquals(gson1, params.getCustomCoder());
441 assertEquals(String.class.getName(), params.getEventClass());
442 assertEquals(GROUP, params.getGroupId());
443 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
444 assertEquals(jsonFilter1b, params.getProtocolFilter());
445 assertEquals(TOPIC, params.getTopic());
447 params = enc.getAllValues().get(0);
448 assertEquals(ARTIFACT, params.getArtifactId());
449 assertEquals(gson2, params.getCustomCoder());
450 assertEquals(Integer.class.getName(), params.getEventClass());
451 assertEquals(GROUP, params.getGroupId());
452 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
453 assertEquals(jsonFilter2, params.getProtocolFilter());
454 assertEquals(TOPIC, params.getTopic());
458 public void testOwnsCoder() {
459 int hc = CLASS_LOADER_HASHCODE;
462 assertFalse(drools.ownsCoder(String.class, hc + 1));
465 assertTrue(drools.ownsCoder(String.class, hc));
468 drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null) {
470 protected boolean isClass(String className) {
474 assertFalse(drools.ownsCoder(String.class, hc));
478 public void testStart_testStop_testIsAlive() {
479 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
481 when(container.start()).thenReturn(true);
482 when(container.stop()).thenReturn(true);
484 assertFalse(drools.isAlive());
487 assertTrue(drools.start());
488 verify(container).start();
489 assertTrue(drools.isAlive());
491 // repeat - no changes
492 assertTrue(drools.start());
493 verify(container).start();
494 assertTrue(drools.isAlive());
497 assertTrue(drools.stop());
498 verify(container).stop();
499 assertFalse(drools.isAlive());
501 // repeat - no changes
502 assertTrue(drools.stop());
503 verify(container).stop();
504 assertFalse(drools.isAlive());
506 // now check with container returning false - should still be invoked
507 when(container.start()).thenReturn(false);
508 when(container.stop()).thenReturn(false);
509 assertFalse(drools.start());
510 assertTrue(drools.isAlive());
511 assertFalse(drools.stop());
512 assertFalse(drools.isAlive());
513 verify(container, times(2)).start();
514 verify(container, times(2)).stop();
516 // coders should still be intact
517 verify(coderMgr, never()).removeDecoders(any(), any(), any());
518 verify(coderMgr, never()).removeEncoders(any(), any(), any());
520 verify(container, never()).shutdown();
521 verify(container, never()).destroy();
525 public void testShutdown() {
526 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
534 verify(container).stop();
535 assertFalse(drools.isAlive());
537 // coders should have been removed
538 verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
539 verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
541 verify(container).shutdown();
542 verify(container, never()).destroy();
546 public void testShutdown_Ex() {
547 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
552 when(container.stop()).thenThrow(RUNTIME_EX);
557 assertFalse(drools.isAlive());
559 verify(container).shutdown();
560 verify(container, never()).destroy();
564 public void testHalt() {
565 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
573 verify(container).stop();
574 assertFalse(drools.isAlive());
576 // coders should have been removed
577 verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
578 verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
580 verify(container).destroy();
584 public void testHalt_Ex() {
585 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
590 when(container.stop()).thenThrow(RUNTIME_EX);
595 assertFalse(drools.isAlive());
597 verify(container).destroy();
601 public void testRemoveCoders_Ex() {
602 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders) {
604 protected void removeDecoders() {
609 protected void removeEncoders() {
614 drools.updateToVersion(GROUP, ARTIFACT, VERSION2, null, null);
618 public void testOfferStringString() {
620 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
622 verify(container).insertAll(EVENT);
626 public void testOfferStringString_NoDecode() {
627 when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(false);
630 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
632 verify(container, never()).insertAll(EVENT);
636 public void testOfferStringString_DecodeUnsupported() {
637 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT))
638 .thenThrow(new UnsupportedOperationException(EXPECTED_EXCEPTION));
641 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
643 verify(container, never()).insertAll(EVENT);
647 public void testOfferStringString_DecodeEx() {
648 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenThrow(RUNTIME_EX);
651 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
653 verify(container, never()).insertAll(EVENT);
657 public void testOfferStringString_Ignored() {
661 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
662 assertEquals(0, drools.getRecentSourceEvents().length);
666 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
667 assertEquals(0, drools.getRecentSourceEvents().length);
671 when(container.getPolicySessions()).thenReturn(Collections.emptyList());
672 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
673 assertEquals(0, drools.getRecentSourceEvents().length);
677 public void testOfferT() {
679 assertTrue(drools.offer(EVENT));
680 assertEquals(1, drools.getRecentSourceEvents().length);
681 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
682 verify(container).insertAll(EVENT);
684 verify(prov1).beforeInsert(drools, EVENT);
685 verify(prov2).beforeInsert(drools, EVENT);
687 verify(prov1).afterInsert(drools, EVENT, true);
688 verify(prov2).afterInsert(drools, EVENT, true);
692 public void testOfferT_Ex() {
693 when(prov1.beforeInsert(drools, EVENT)).thenThrow(RUNTIME_EX);
694 when(prov1.afterInsert(drools, EVENT, true)).thenThrow(RUNTIME_EX);
697 assertTrue(drools.offer(EVENT));
698 assertEquals(1, drools.getRecentSourceEvents().length);
699 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
700 verify(container).insertAll(EVENT);
702 // should still invoke prov2
703 verify(prov2).beforeInsert(drools, EVENT);
705 verify(prov2).afterInsert(drools, EVENT, true);
709 public void testOfferT_NotInserted() {
710 when(container.insertAll(EVENT)).thenReturn(false);
713 assertTrue(drools.offer(EVENT));
714 assertEquals(1, drools.getRecentSourceEvents().length);
715 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
716 verify(container).insertAll(EVENT);
718 verify(prov1).beforeInsert(drools, EVENT);
719 verify(prov2).beforeInsert(drools, EVENT);
721 verify(prov1).afterInsert(drools, EVENT, false);
722 verify(prov2).afterInsert(drools, EVENT, false);
726 public void testOfferT_BeforeInsertIntercept() {
728 when(prov1.beforeInsert(drools, EVENT)).thenReturn(true);
730 assertTrue(drools.offer(EVENT));
731 assertEquals(1, drools.getRecentSourceEvents().length);
732 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
733 verify(container, never()).insertAll(EVENT);
735 verify(prov1).beforeInsert(drools, EVENT);
737 // nothing else invoked
738 verify(prov2, never()).beforeInsert(drools, EVENT);
739 verify(prov1, never()).afterInsert(drools, EVENT, true);
740 verify(prov2, never()).afterInsert(drools, EVENT, true);
744 public void testOfferT_AfterInsertIntercept() {
747 when(prov1.afterInsert(drools, EVENT, true)).thenReturn(true);
749 assertTrue(drools.offer(EVENT));
750 assertEquals(1, drools.getRecentSourceEvents().length);
751 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
752 verify(container).insertAll(EVENT);
754 verify(prov1).beforeInsert(drools, EVENT);
755 verify(prov2).beforeInsert(drools, EVENT);
757 verify(prov1).afterInsert(drools, EVENT, true);
759 // prov2 is never called
760 verify(prov2, never()).afterInsert(drools, EVENT, true);
764 public void testOfferT_Ignored() {
768 assertTrue(drools.offer(EVENT));
769 assertEquals(0, drools.getRecentSourceEvents().length);
773 assertTrue(drools.offer(EVENT));
774 assertEquals(0, drools.getRecentSourceEvents().length);
778 when(container.getPolicySessions()).thenReturn(Collections.emptyList());
779 assertTrue(drools.offer(EVENT));
780 assertEquals(0, drools.getRecentSourceEvents().length);
784 public void testDeliver() {
786 assertTrue(drools.deliver(sink, EVENT));
787 assertEquals(1, drools.getRecentSinkEvents().length);
788 assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
790 verify(sink).send(EVENT_TEXT);
792 verify(prov1).beforeDeliver(drools, sink, EVENT);
793 verify(prov2).beforeDeliver(drools, sink, EVENT);
795 verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
796 verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
800 public void testDeliver_InvalidArgs() {
803 assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(null, EVENT))
804 .withMessageContaining("sink");
806 assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(sink, null))
807 .withMessageContaining("event");
810 assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT)).withMessageContaining("locked");
814 assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT))
815 .withMessageContaining("stopped");
818 assertEquals(0, drools.getRecentSinkEvents().length);
822 public void testDeliver_BeforeIntercept() {
823 when(prov1.beforeDeliver(drools, sink, EVENT)).thenReturn(true);
826 assertTrue(drools.deliver(sink, EVENT));
827 assertEquals(0, drools.getRecentSinkEvents().length);
829 verify(prov1).beforeDeliver(drools, sink, EVENT);
831 // nothing else should have been invoked
832 verify(sink, never()).send(EVENT_TEXT);
833 verify(prov2, never()).beforeDeliver(drools, sink, EVENT);
834 verify(prov1, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
835 verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
839 public void testDeliver_AfterIntercept() {
840 when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenReturn(true);
843 assertTrue(drools.deliver(sink, EVENT));
844 assertEquals(1, drools.getRecentSinkEvents().length);
845 assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
847 verify(prov1).beforeDeliver(drools, sink, EVENT);
848 verify(prov2).beforeDeliver(drools, sink, EVENT);
850 verify(sink).send(EVENT_TEXT);
852 verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
854 // nothing else should have been invoked
855 verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
859 public void testDeliver_InterceptEx() {
860 when(prov1.beforeDeliver(drools, sink, EVENT)).thenThrow(RUNTIME_EX);
861 when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenThrow(RUNTIME_EX);
864 assertTrue(drools.deliver(sink, EVENT));
866 verify(sink).send(EVENT_TEXT);
868 // should still invoke prov2
869 verify(prov2).beforeDeliver(drools, sink, EVENT);
870 verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
874 public void testGetXxx() {
875 assertEquals(VERSION, drools.getVersion());
876 assertEquals(ARTIFACT, drools.getArtifactId());
877 assertEquals(GROUP, drools.getGroupId());
878 assertEquals(CLASS_LOADER_HASHCODE, drools.getModelClassLoaderHash());
879 assertSame(container, drools.getContainer());
880 assertEquals(Arrays.asList(sess1, sess2), drools.getSessions());
882 // test junit methods - need a controller with fewer overrides
883 drools = new MavenDroolsController(GROUP, ARTIFACT, VERSION, null, null) {
885 protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
890 assertSame(EventProtocolCoder.manager, drools.getCoderManager());
891 assertSame(DroolsControllerFeatureApi.providers, drools.getDroolsProviders());
895 public void testLock_testUnlock_testIsLocked() {
896 assertFalse(drools.isLocked());
898 assertTrue(drools.lock());
899 assertTrue(drools.isLocked());
901 assertTrue(drools.unlock());
902 assertFalse(drools.isLocked());
905 assertTrue(drools.lock());
906 assertTrue(drools.isLocked());
908 assertTrue(drools.unlock());
909 assertFalse(drools.isLocked());
913 public void testGetSessionNames_testGetCanonicalSessionNames() {
914 assertEquals("[session-A, session-B]", drools.getSessionNames(true).toString());
915 assertEquals("[full-A, full-B]", drools.getSessionNames(false).toString());
917 assertEquals("[session-A, session-B]", drools.getSessionNames().toString());
919 assertEquals("[full-A, full-B]", drools.getCanonicalSessionNames().toString());
922 when(container.getPolicySessions()).thenThrow(RUNTIME_EX);
923 assertEquals("[expected exception]", drools.getSessionNames().toString());
927 public void testGetBaseDomainNames() {
928 KieContainer kiecont = mock(KieContainer.class);
929 when(kiecont.getKieBaseNames()).thenReturn(Arrays.asList("kieA", "kieB"));
930 when(container.getKieContainer()).thenReturn(kiecont);
932 assertEquals("[kieA, kieB]", drools.getBaseDomainNames().toString());
936 public void testGetSession() {
937 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(null))
938 .withMessageContaining("must be provided");
940 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(""))
941 .withMessageContaining("must be provided");
943 assertSame(sess1, drools.getSession(SESSION1));
944 assertSame(sess1, drools.getSession(FULL_SESSION1));
946 assertSame(sess2, drools.getSession(SESSION2));
948 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession("unknown session"))
949 .withMessageContaining("Invalid Session Name");
953 public void testFactClassNames() {
954 // copy to a sorted map so the order remains unchanged
955 Map<String, Integer> map = new TreeMap<>(drools.factClassNames(SESSION1));
956 assertEquals("{java.lang.Integer=2, java.lang.String=1}", map.toString());
958 assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(null))
959 .withMessageContaining("Invalid Session Name");
961 assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(""))
962 .withMessageContaining("Invalid Session Name");
966 public void testFactCount() {
967 assertEquals(FACT_COUNT, drools.factCount(SESSION1));
969 assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(null))
970 .withMessageContaining("Invalid Session Name");
972 assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(""))
973 .withMessageContaining("Invalid Session Name");
977 public void testFactsStringStringBoolean() {
978 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), false).toString());
979 verify(kieSess, never()).delete(fact1);
980 verify(kieSess, never()).delete(fact2);
981 verify(kieSess, never()).delete(fact3);
982 verify(kieSess, never()).delete(factex);
984 // now delete - but should only delete 1 & 3
985 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
986 verify(kieSess).delete(fact1);
987 verify(kieSess, never()).delete(fact2);
988 verify(kieSess).delete(fact3);
989 verify(kieSess, never()).delete(factex);
991 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(null, Integer.class.getName(), false))
992 .withMessageContaining("Invalid Session Name");
994 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts("", Integer.class.getName(), false))
995 .withMessageContaining("Invalid Session Name");
997 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, null, false))
998 .withMessageContaining("Invalid Class Name");
1000 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, "", false))
1001 .withMessageContaining("Invalid Class Name");
1003 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, UNKNOWN_CLASS, false))
1004 .withMessageContaining("classloader");
1008 public void testFactsStringStringBoolean_DeleteEx() {
1009 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1011 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
1013 // should still have deleted #3
1014 verify(kieSess).delete(fact3);
1018 public void testFactsStringClassOfT() {
1019 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class).toString());
1023 public void testFactQuery() {
1024 assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, false, PARM1, PARM2).toString());
1026 verify(kieSess, never()).delete(fact1);
1027 verify(kieSess, never()).delete(fact3);
1029 assertThatIllegalArgumentException()
1030 .isThrownBy(() -> drools.factQuery(null, QUERY, ENTITY, false, PARM1, PARM2))
1031 .withMessageContaining("Invalid Session Name");
1033 assertThatIllegalArgumentException().isThrownBy(() -> drools.factQuery("", QUERY, ENTITY, false, PARM1, PARM2))
1034 .withMessageContaining("Invalid Session Name");
1036 assertThatIllegalArgumentException()
1037 .isThrownBy(() -> drools.factQuery(SESSION1, null, ENTITY, false, PARM1, PARM2))
1038 .withMessageContaining("Invalid Query Name");
1040 assertThatIllegalArgumentException()
1041 .isThrownBy(() -> drools.factQuery(SESSION1, "", ENTITY, false, PARM1, PARM2))
1042 .withMessageContaining("Invalid Query Name");
1044 assertThatIllegalArgumentException()
1045 .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, null, false, PARM1, PARM2))
1046 .withMessageContaining("Invalid Queried Entity");
1048 assertThatIllegalArgumentException()
1049 .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, "", false, PARM1, PARM2))
1050 .withMessageContaining("Invalid Queried Entity");
1052 assertThatIllegalArgumentException().isThrownBy(
1053 () -> drools.factQuery(SESSION1, QUERY + "-unknown-query", ENTITY, false, PARM1, PARM2))
1054 .withMessageContaining("Invalid Query Name");
1058 public void testFactQuery_Delete() {
1059 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1061 assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, true, PARM1, PARM2).toString());
1063 // should still delete fact #3
1064 verify(kieSess).delete(fact3);
1068 public void testDeleteStringT() {
1069 assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
1071 verify(kieSess, never()).delete(fact1);
1072 verify(kieSess).delete(fact3);
1075 assertFalse(drools.delete(SESSION1, "hello"));
1077 // repeat, but generate exception while getting the first object
1078 when(kieSess.getObject(fact1)).thenThrow(RUNTIME_EX);
1079 assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
1081 verify(kieSess, never()).delete(fact1);
1083 // should still delete fact #3
1084 verify(kieSess, times(2)).delete(fact3);
1088 public void testDeleteT() {
1089 assertTrue(drools.delete(FACT3_OBJECT));
1091 verify(kieSess).delete(fact3);
1095 public void testDeleteStringClassOfT() {
1096 assertTrue(drools.delete(SESSION1, Integer.class));
1098 verify(kieSess).delete(fact1);
1099 verify(kieSess).delete(fact3);
1103 public void testDeleteStringClassOfT_Ex() {
1104 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1106 assertFalse(drools.delete(SESSION1, Integer.class));
1108 // should still delete fact #3
1109 verify(kieSess).delete(fact3);
1113 public void testDeleteClassOfT() {
1114 assertTrue(drools.delete(Integer.class));
1116 verify(kieSess).delete(fact1);
1117 verify(kieSess).delete(fact3);
1121 public void testFetchModelClass() {
1122 assertSame(Long.class, drools.fetchModelClass(Long.class.getName()));
1126 public void testIsBrained() {
1127 assertTrue(drools.isBrained());
1131 public void testToString() {
1132 assertNotNull(drools.toString());
1135 private class MyDrools extends MavenDroolsController {
1137 public MyDrools(String groupId, String artifactId, String version,
1138 List<TopicCoderFilterConfiguration> decoderConfigurations,
1139 List<TopicCoderFilterConfiguration> encoderConfigurations) {
1141 super(groupId, artifactId, version, decoderConfigurations, encoderConfigurations);
1145 protected EventProtocolCoder getCoderManager() {
1150 protected OrderedServiceImpl<DroolsControllerFeatureApi> getDroolsProviders() {
1151 return droolsProviders;
1155 protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
1156 when(container.getGroupId()).thenReturn(groupId);
1157 when(container.getArtifactId()).thenReturn(artifactId);
1158 when(container.getVersion()).thenReturn(version);