2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2019-2020 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.assertThatCode;
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
26 import static org.junit.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertSame;
30 import static org.junit.Assert.assertTrue;
31 import static org.mockito.ArgumentMatchers.any;
32 import static org.mockito.Mockito.doThrow;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
39 import java.util.Arrays;
40 import java.util.Collections;
41 import java.util.List;
43 import java.util.TreeMap;
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.kie.api.KieBase;
47 import org.kie.api.definition.KiePackage;
48 import org.kie.api.definition.rule.Query;
49 import org.kie.api.runtime.KieContainer;
50 import org.kie.api.runtime.KieSession;
51 import org.kie.api.runtime.rule.FactHandle;
52 import org.kie.api.runtime.rule.QueryResults;
53 import org.kie.api.runtime.rule.QueryResultsRow;
54 import org.mockito.ArgumentCaptor;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 import org.onap.policy.common.endpoints.event.comm.TopicSink;
58 import org.onap.policy.common.utils.services.OrderedServiceImpl;
59 import org.onap.policy.drools.core.PolicyContainer;
60 import org.onap.policy.drools.core.PolicySession;
61 import org.onap.policy.drools.features.DroolsControllerFeatureApi;
62 import org.onap.policy.drools.features.DroolsControllerFeatureApiConstants;
63 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
64 import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
65 import org.onap.policy.drools.protocol.coders.EventProtocolParams;
66 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
67 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
68 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder;
69 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter;
71 public class MavenDroolsController2Test {
72 private static final int FACT1_OBJECT = 1000;
73 private static final int FACT3_OBJECT = 1001;
75 private static final long FACT_COUNT = 200L;
77 private static final String EXPECTED_EXCEPTION = "expected exception";
78 private static final RuntimeException RUNTIME_EX = new RuntimeException(EXPECTED_EXCEPTION);
79 private static final IllegalArgumentException ARG_EX = new IllegalArgumentException(EXPECTED_EXCEPTION);
81 private static final String UNKNOWN_CLASS = "unknown class";
83 private static final String GROUP = "my-group";
84 private static final String ARTIFACT = "my-artifact";
85 private static final String VERSION = "my-version";
87 private static final String GROUP2 = "my-groupB";
88 private static final String ARTIFACT2 = "my-artifactB";
89 private static final String VERSION2 = "my-versionB";
91 private static final String TOPIC = "my-topic";
92 private static final String TOPIC2 = "my-topic";
94 private static final ClassLoader CLASS_LOADER = MavenDroolsController2Test.class.getClassLoader();
95 private static final int CLASS_LOADER_HASHCODE = CLASS_LOADER.hashCode();
97 private static final String SESSION1 = "session-A";
98 private static final String SESSION2 = "session-B";
99 private static final String FULL_SESSION1 = "full-A";
100 private static final String FULL_SESSION2 = "full-B";
102 private static final String EVENT_TEXT = "my-event-text";
103 private static final Object EVENT = new Object();
105 private static final String QUERY = "my-query";
106 private static final String QUERY2 = "my-query-B";
107 private static final String ENTITY = "my-entity";
108 private static final Object PARM1 = "parmA";
109 private static final Object PARM2 = "parmB";
112 private EventProtocolCoder coderMgr;
114 private DroolsControllerFeatureApi prov1;
116 private DroolsControllerFeatureApi prov2;
118 private OrderedServiceImpl<DroolsControllerFeatureApi> droolsProviders;
120 private TopicCoderFilterConfiguration decoder1;
122 private TopicCoderFilterConfiguration decoder2;
124 private TopicCoderFilterConfiguration encoder1;
126 private TopicCoderFilterConfiguration encoder2;
128 private PolicyContainer container;
130 private CustomGsonCoder gson1;
132 private CustomGsonCoder gson2;
134 private PotentialCoderFilter filter1a;
136 private JsonProtocolFilter jsonFilter1a;
138 private PotentialCoderFilter filter1b;
140 private JsonProtocolFilter jsonFilter1b;
142 private PotentialCoderFilter filter2;
144 private JsonProtocolFilter jsonFilter2;
146 private PolicySession sess1;
148 private PolicySession sess2;
150 private KieSession kieSess;
152 private KieSession kieSess2;
154 private TopicSink sink;
156 private FactHandle fact1;
158 private FactHandle fact2;
160 private FactHandle fact3;
162 private FactHandle factex;
164 private KieBase kieBase;
166 private KiePackage pkg1;
168 private KiePackage pkg2;
170 private Query query1;
172 private Query query2;
174 private Query query3;
176 private QueryResults queryResults;
178 private QueryResultsRow row1;
180 private QueryResultsRow row2;
182 private List<TopicCoderFilterConfiguration> decoders;
183 private List<TopicCoderFilterConfiguration> encoders;
185 private MavenDroolsController drools;
188 * Initializes objects, including the drools controller.
191 public void setUp() {
192 MockitoAnnotations.initMocks(this);
194 when(droolsProviders.getList()).thenReturn(Arrays.asList(prov1, prov2));
196 when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(true);
197 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenReturn(EVENT);
199 when(kieSess.getFactCount()).thenReturn(FACT_COUNT);
200 when(kieSess.getFactHandles()).thenReturn(Arrays.asList(fact1, fact2, factex, fact3));
201 when(kieSess.getFactHandles(any())).thenReturn(Arrays.asList(fact1, fact3));
202 when(kieSess.getKieBase()).thenReturn(kieBase);
203 when(kieSess.getQueryResults(QUERY, PARM1, PARM2)).thenReturn(queryResults);
205 when(kieSess.getFactHandle(FACT1_OBJECT)).thenReturn(fact1);
206 when(kieSess.getFactHandle(FACT3_OBJECT)).thenReturn(fact3);
208 when(kieSess.getObject(fact1)).thenReturn(FACT1_OBJECT);
209 when(kieSess.getObject(fact2)).thenReturn("");
210 when(kieSess.getObject(fact3)).thenReturn(FACT3_OBJECT);
211 when(kieSess.getObject(factex)).thenThrow(RUNTIME_EX);
213 when(kieSess2.getFactHandles()).thenReturn(Collections.emptyList());
215 when(kieBase.getKiePackages()).thenReturn(Arrays.asList(pkg1, pkg2));
217 when(pkg1.getQueries()).thenReturn(Arrays.asList(query3));
218 when(pkg2.getQueries()).thenReturn(Arrays.asList(query2, query1));
220 when(query1.getName()).thenReturn(QUERY);
221 when(query2.getName()).thenReturn(QUERY2);
223 when(queryResults.iterator()).thenReturn(Arrays.asList(row1, row2).iterator());
225 when(row1.get(ENTITY)).thenReturn(FACT1_OBJECT);
226 when(row2.get(ENTITY)).thenReturn(FACT3_OBJECT);
228 when(row1.getFactHandle(ENTITY)).thenReturn(fact1);
229 when(row2.getFactHandle(ENTITY)).thenReturn(fact3);
231 when(sess1.getKieSession()).thenReturn(kieSess);
232 when(sess2.getKieSession()).thenReturn(kieSess2);
234 when(sess1.getName()).thenReturn(SESSION1);
235 when(sess2.getName()).thenReturn(SESSION2);
237 when(sess1.getFullName()).thenReturn(FULL_SESSION1);
238 when(sess2.getFullName()).thenReturn(FULL_SESSION2);
240 when(container.getClassLoader()).thenReturn(CLASS_LOADER);
241 when(container.getPolicySessions()).thenReturn(Arrays.asList(sess1, sess2));
242 when(container.insertAll(EVENT)).thenReturn(true);
244 when(decoder1.getTopic()).thenReturn(TOPIC);
245 when(decoder2.getTopic()).thenReturn(TOPIC2);
247 when(encoder1.getTopic()).thenReturn(TOPIC);
248 when(encoder2.getTopic()).thenReturn(TOPIC2);
250 decoders = Arrays.asList(decoder1, decoder2);
251 encoders = Arrays.asList(encoder1, encoder2);
253 when(decoder1.getCustomGsonCoder()).thenReturn(gson1);
254 when(encoder2.getCustomGsonCoder()).thenReturn(gson2);
256 when(filter1a.getCodedClass()).thenReturn(Object.class.getName());
257 when(filter1a.getFilter()).thenReturn(jsonFilter1a);
259 when(filter1b.getCodedClass()).thenReturn(String.class.getName());
260 when(filter1b.getFilter()).thenReturn(jsonFilter1b);
262 when(filter2.getCodedClass()).thenReturn(Integer.class.getName());
263 when(filter2.getFilter()).thenReturn(jsonFilter2);
265 when(decoder1.getCoderFilters()).thenReturn(Arrays.asList(filter1a, filter1b));
266 when(decoder2.getCoderFilters()).thenReturn(Collections.emptyList());
268 when(encoder1.getCoderFilters()).thenReturn(Collections.emptyList());
269 when(encoder2.getCoderFilters()).thenReturn(Arrays.asList(filter2));
271 when(sink.getTopic()).thenReturn(TOPIC);
272 when(sink.send(EVENT_TEXT)).thenReturn(true);
274 drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null);
276 when(coderMgr.encode(TOPIC, EVENT, drools)).thenReturn(EVENT_TEXT);
280 public void testMavenDroolsController_InvalidArgs() {
281 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(null, ARTIFACT, VERSION, null, null))
282 .withMessageContaining("group");
283 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools("", ARTIFACT, VERSION, null, null))
284 .withMessageContaining("group");
286 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, null, VERSION, null, null))
287 .withMessageContaining("artifact");
288 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, "", VERSION, null, null))
289 .withMessageContaining("artifact");
291 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, null, null, null))
292 .withMessageContaining("version");
293 assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, "", null, null))
294 .withMessageContaining("version");
298 public void testUpdateToVersion() {
300 drools.updateToVersion(GROUP, ARTIFACT, VERSION2, decoders, encoders);
302 verify(container).updateToVersion(VERSION2);
304 // nothing removed the first time
305 verify(coderMgr, never()).removeDecoders(GROUP, ARTIFACT, TOPIC2);
306 verify(coderMgr, never()).removeEncoders(GROUP, ARTIFACT, TOPIC);
308 verify(coderMgr, times(2)).addDecoder(any());
309 verify(coderMgr, times(1)).addEncoder(any());
312 when(container.getVersion()).thenReturn(VERSION2);
313 drools.updateToVersion(GROUP, ARTIFACT, VERSION, null, null);
315 verify(container).updateToVersion(VERSION);
317 verify(coderMgr, times(2)).removeDecoders(GROUP, ARTIFACT, TOPIC2);
318 verify(coderMgr, times(2)).removeEncoders(GROUP, ARTIFACT, TOPIC);
321 verify(coderMgr, times(2)).addDecoder(any());
322 verify(coderMgr, times(1)).addEncoder(any());
326 public void testUpdateToVersion_Unchanged() {
327 drools.updateToVersion(GROUP, ARTIFACT, VERSION, decoders, encoders);
329 verify(coderMgr, never()).addDecoder(any());
330 verify(coderMgr, never()).addEncoder(any());
334 public void testUpdateToVersion_InvalidArgs() {
335 assertThatIllegalArgumentException()
336 .isThrownBy(() -> drools.updateToVersion(null, ARTIFACT, VERSION, null, null))
337 .withMessageContaining("group");
338 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion("", ARTIFACT, VERSION, null, null))
339 .withMessageContaining("group");
341 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, null, VERSION, null, null))
342 .withMessageContaining("artifact");
343 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, "", VERSION, null, null))
344 .withMessageContaining("artifact");
346 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, null, null, null))
347 .withMessageContaining("version");
348 assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "", null, null))
349 .withMessageContaining("version");
351 assertThatIllegalArgumentException()
352 .isThrownBy(() -> drools.updateToVersion("no-group-id", ARTIFACT, VERSION, null, null))
353 .withMessageContaining("BRAINLESS");
355 assertThatIllegalArgumentException()
356 .isThrownBy(() -> drools.updateToVersion(GROUP, "no-artifact-id", VERSION, null, null))
357 .withMessageContaining("BRAINLESS");
359 assertThatIllegalArgumentException()
360 .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "no-version", null, null))
361 .withMessageContaining("BRAINLESS");
363 assertThatIllegalArgumentException()
364 .isThrownBy(() -> drools.updateToVersion(GROUP2, ARTIFACT, VERSION, null, null))
365 .withMessageContaining("coordinates must be identical");
367 assertThatIllegalArgumentException()
368 .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT2, VERSION, null, null))
369 .withMessageContaining("coordinates must be identical");
373 public void testInitCoders_NullCoders() {
374 // already constructed with null coders
375 verify(coderMgr, never()).addDecoder(any());
376 verify(coderMgr, never()).addEncoder(any());
380 public void testInitCoders_NullOrEmptyFilters() {
381 when(decoder1.getCoderFilters()).thenReturn(Collections.emptyList());
382 when(decoder2.getCoderFilters()).thenReturn(null);
384 when(encoder1.getCoderFilters()).thenReturn(null);
385 when(encoder2.getCoderFilters()).thenReturn(Collections.emptyList());
387 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
389 verify(coderMgr, never()).addDecoder(any());
390 verify(coderMgr, never()).addEncoder(any());
394 public void testInitCoders_GsonClass() {
395 when(gson1.getClassContainer()).thenReturn("");
396 when(gson2.getClassContainer()).thenReturn(Long.class.getName());
398 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
400 // all should be added
401 verify(coderMgr, times(2)).addDecoder(any());
402 verify(coderMgr, times(1)).addEncoder(any());
406 public void testInitCoders_InvalidGsonClass() {
407 when(gson1.getClassContainer()).thenReturn(UNKNOWN_CLASS);
409 assertThatIllegalArgumentException()
410 .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
411 .withMessageContaining("cannot be retrieved");
415 public void testInitCoders_InvalidFilterClass() {
416 when(filter2.getCodedClass()).thenReturn(UNKNOWN_CLASS);
418 assertThatIllegalArgumentException()
419 .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
420 .withMessageContaining("cannot be retrieved");
424 public void testInitCoders_Filters() {
426 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
428 ArgumentCaptor<EventProtocolParams> dec = ArgumentCaptor.forClass(EventProtocolParams.class);
429 verify(coderMgr, times(2)).addDecoder(dec.capture());
431 ArgumentCaptor<EventProtocolParams> enc = ArgumentCaptor.forClass(EventProtocolParams.class);
432 verify(coderMgr, times(1)).addEncoder(enc.capture());
434 // validate parameters
435 EventProtocolParams params = dec.getAllValues().get(0);
436 assertEquals(ARTIFACT, params.getArtifactId());
437 assertEquals(gson1, params.getCustomCoder());
438 assertEquals(Object.class.getName(), params.getEventClass());
439 assertEquals(GROUP, params.getGroupId());
440 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
441 assertEquals(jsonFilter1a, params.getProtocolFilter());
442 assertEquals(TOPIC, params.getTopic());
444 params = dec.getAllValues().get(1);
445 assertEquals(ARTIFACT, params.getArtifactId());
446 assertEquals(gson1, params.getCustomCoder());
447 assertEquals(String.class.getName(), params.getEventClass());
448 assertEquals(GROUP, params.getGroupId());
449 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
450 assertEquals(jsonFilter1b, params.getProtocolFilter());
451 assertEquals(TOPIC, params.getTopic());
453 params = enc.getAllValues().get(0);
454 assertEquals(ARTIFACT, params.getArtifactId());
455 assertEquals(gson2, params.getCustomCoder());
456 assertEquals(Integer.class.getName(), params.getEventClass());
457 assertEquals(GROUP, params.getGroupId());
458 assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
459 assertEquals(jsonFilter2, params.getProtocolFilter());
460 assertEquals(TOPIC, params.getTopic());
464 public void testOwnsCoder() {
465 int hc = CLASS_LOADER_HASHCODE;
468 assertFalse(drools.ownsCoder(String.class, hc + 1));
471 assertTrue(drools.ownsCoder(String.class, hc));
474 drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null) {
476 protected boolean isClass(String className) {
480 assertFalse(drools.ownsCoder(String.class, hc));
484 public void testStart_testStop_testIsAlive() {
485 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
487 when(container.start()).thenReturn(true);
488 when(container.stop()).thenReturn(true);
490 assertFalse(drools.isAlive());
493 assertTrue(drools.start());
494 verify(container).start();
495 assertTrue(drools.isAlive());
497 // repeat - no changes
498 assertTrue(drools.start());
499 verify(container).start();
500 assertTrue(drools.isAlive());
503 assertTrue(drools.stop());
504 verify(container).stop();
505 assertFalse(drools.isAlive());
507 // repeat - no changes
508 assertTrue(drools.stop());
509 verify(container).stop();
510 assertFalse(drools.isAlive());
512 // now check with container returning false - should still be invoked
513 when(container.start()).thenReturn(false);
514 when(container.stop()).thenReturn(false);
515 assertFalse(drools.start());
516 assertTrue(drools.isAlive());
517 assertFalse(drools.stop());
518 assertFalse(drools.isAlive());
519 verify(container, times(2)).start();
520 verify(container, times(2)).stop();
522 // coders should still be intact
523 verify(coderMgr, never()).removeDecoders(any(), any(), any());
524 verify(coderMgr, never()).removeEncoders(any(), any(), any());
526 verify(container, never()).shutdown();
527 verify(container, never()).destroy();
531 public void testShutdown() {
532 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
540 verify(container).stop();
541 assertFalse(drools.isAlive());
543 // coders should have been removed
544 verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
545 verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
547 verify(container).shutdown();
548 verify(container, never()).destroy();
552 public void testShutdown_Ex() {
553 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
558 when(container.stop()).thenThrow(RUNTIME_EX);
563 assertFalse(drools.isAlive());
565 verify(container).shutdown();
566 verify(container, never()).destroy();
570 public void testHalt() {
571 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
579 verify(container).stop();
580 assertFalse(drools.isAlive());
582 // coders should have been removed
583 verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
584 verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
586 verify(container).destroy();
590 public void testHalt_Ex() {
591 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
596 when(container.stop()).thenThrow(RUNTIME_EX);
601 assertFalse(drools.isAlive());
603 verify(container).destroy();
607 public void testRemoveCoders_Ex() {
608 drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders) {
610 protected void removeDecoders() {
615 protected void removeEncoders() {
620 assertThatCode(() -> drools.updateToVersion(GROUP, ARTIFACT, VERSION2, null, null)).doesNotThrowAnyException();
624 public void testOfferStringString() {
626 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
628 verify(container).insertAll(EVENT);
632 public void testOfferStringString_NoDecode() {
633 when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(false);
636 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
638 verify(container, never()).insertAll(EVENT);
642 public void testOfferStringString_DecodeUnsupported() {
643 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT))
644 .thenThrow(new UnsupportedOperationException(EXPECTED_EXCEPTION));
647 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
649 verify(container, never()).insertAll(EVENT);
653 public void testOfferStringString_DecodeEx() {
654 when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenThrow(RUNTIME_EX);
657 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
659 verify(container, never()).insertAll(EVENT);
663 public void testOfferStringString_Ignored() {
667 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
668 assertEquals(0, drools.getRecentSourceEvents().length);
672 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
673 assertEquals(0, drools.getRecentSourceEvents().length);
677 when(container.getPolicySessions()).thenReturn(Collections.emptyList());
678 assertTrue(drools.offer(TOPIC, EVENT_TEXT));
679 assertEquals(0, drools.getRecentSourceEvents().length);
683 public void testOfferT() {
685 assertTrue(drools.offer(EVENT));
686 assertEquals(1, drools.getRecentSourceEvents().length);
687 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
688 verify(container).insertAll(EVENT);
690 verify(prov1).beforeInsert(drools, EVENT);
691 verify(prov2).beforeInsert(drools, EVENT);
693 verify(prov1).afterInsert(drools, EVENT, true);
694 verify(prov2).afterInsert(drools, EVENT, true);
698 public void testOfferT_Ex() {
699 when(prov1.beforeInsert(drools, EVENT)).thenThrow(RUNTIME_EX);
700 when(prov1.afterInsert(drools, EVENT, true)).thenThrow(RUNTIME_EX);
703 assertTrue(drools.offer(EVENT));
704 assertEquals(1, drools.getRecentSourceEvents().length);
705 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
706 verify(container).insertAll(EVENT);
708 // should still invoke prov2
709 verify(prov2).beforeInsert(drools, EVENT);
711 verify(prov2).afterInsert(drools, EVENT, true);
715 public void testOfferT_NotInserted() {
716 when(container.insertAll(EVENT)).thenReturn(false);
719 assertTrue(drools.offer(EVENT));
720 assertEquals(1, drools.getRecentSourceEvents().length);
721 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
722 verify(container).insertAll(EVENT);
724 verify(prov1).beforeInsert(drools, EVENT);
725 verify(prov2).beforeInsert(drools, EVENT);
727 verify(prov1).afterInsert(drools, EVENT, false);
728 verify(prov2).afterInsert(drools, EVENT, false);
732 public void testOfferT_BeforeInsertIntercept() {
734 when(prov1.beforeInsert(drools, EVENT)).thenReturn(true);
736 assertTrue(drools.offer(EVENT));
737 assertEquals(1, drools.getRecentSourceEvents().length);
738 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
739 verify(container, never()).insertAll(EVENT);
741 verify(prov1).beforeInsert(drools, EVENT);
743 // nothing else invoked
744 verify(prov2, never()).beforeInsert(drools, EVENT);
745 verify(prov1, never()).afterInsert(drools, EVENT, true);
746 verify(prov2, never()).afterInsert(drools, EVENT, true);
750 public void testOfferT_AfterInsertIntercept() {
753 when(prov1.afterInsert(drools, EVENT, true)).thenReturn(true);
755 assertTrue(drools.offer(EVENT));
756 assertEquals(1, drools.getRecentSourceEvents().length);
757 assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
758 verify(container).insertAll(EVENT);
760 verify(prov1).beforeInsert(drools, EVENT);
761 verify(prov2).beforeInsert(drools, EVENT);
763 verify(prov1).afterInsert(drools, EVENT, true);
765 // prov2 is never called
766 verify(prov2, never()).afterInsert(drools, EVENT, true);
770 public void testOfferT_Ignored() {
774 assertTrue(drools.offer(EVENT));
775 assertEquals(0, drools.getRecentSourceEvents().length);
779 assertTrue(drools.offer(EVENT));
780 assertEquals(0, drools.getRecentSourceEvents().length);
784 when(container.getPolicySessions()).thenReturn(Collections.emptyList());
785 assertTrue(drools.offer(EVENT));
786 assertEquals(0, drools.getRecentSourceEvents().length);
790 public void testDeliver() {
792 assertTrue(drools.deliver(sink, EVENT));
793 assertEquals(1, drools.getRecentSinkEvents().length);
794 assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
796 verify(sink).send(EVENT_TEXT);
798 verify(prov1).beforeDeliver(drools, sink, EVENT);
799 verify(prov2).beforeDeliver(drools, sink, EVENT);
801 verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
802 verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
806 public void testDeliver_InvalidArgs() {
809 assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(null, EVENT))
810 .withMessageContaining("sink");
812 assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(sink, null))
813 .withMessageContaining("event");
816 assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT)).withMessageContaining("locked");
820 assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT))
821 .withMessageContaining("stopped");
824 assertEquals(0, drools.getRecentSinkEvents().length);
828 public void testDeliver_BeforeIntercept() {
829 when(prov1.beforeDeliver(drools, sink, EVENT)).thenReturn(true);
832 assertTrue(drools.deliver(sink, EVENT));
833 assertEquals(0, drools.getRecentSinkEvents().length);
835 verify(prov1).beforeDeliver(drools, sink, EVENT);
837 // nothing else should have been invoked
838 verify(sink, never()).send(EVENT_TEXT);
839 verify(prov2, never()).beforeDeliver(drools, sink, EVENT);
840 verify(prov1, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
841 verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
845 public void testDeliver_AfterIntercept() {
846 when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenReturn(true);
849 assertTrue(drools.deliver(sink, EVENT));
850 assertEquals(1, drools.getRecentSinkEvents().length);
851 assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
853 verify(prov1).beforeDeliver(drools, sink, EVENT);
854 verify(prov2).beforeDeliver(drools, sink, EVENT);
856 verify(sink).send(EVENT_TEXT);
858 verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
860 // nothing else should have been invoked
861 verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
865 public void testDeliver_InterceptEx() {
866 when(prov1.beforeDeliver(drools, sink, EVENT)).thenThrow(RUNTIME_EX);
867 when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenThrow(RUNTIME_EX);
870 assertTrue(drools.deliver(sink, EVENT));
872 verify(sink).send(EVENT_TEXT);
874 // should still invoke prov2
875 verify(prov2).beforeDeliver(drools, sink, EVENT);
876 verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
880 public void testGetXxx() {
881 assertEquals(VERSION, drools.getVersion());
882 assertEquals(ARTIFACT, drools.getArtifactId());
883 assertEquals(GROUP, drools.getGroupId());
884 assertEquals(CLASS_LOADER_HASHCODE, drools.getModelClassLoaderHash());
885 assertSame(container, drools.getContainer());
886 assertEquals(Arrays.asList(sess1, sess2), drools.getSessions());
888 // test junit methods - need a controller with fewer overrides
889 drools = new MavenDroolsController(GROUP, ARTIFACT, VERSION, null, null) {
891 protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
896 assertSame(EventProtocolCoderConstants.getManager(), drools.getCoderManager());
897 assertSame(DroolsControllerFeatureApiConstants.getProviders(), drools.getDroolsProviders());
901 public void testLock_testUnlock_testIsLocked() {
902 assertFalse(drools.isLocked());
904 assertTrue(drools.lock());
905 assertTrue(drools.isLocked());
907 assertTrue(drools.unlock());
908 assertFalse(drools.isLocked());
911 assertTrue(drools.lock());
912 assertTrue(drools.isLocked());
914 assertTrue(drools.unlock());
915 assertFalse(drools.isLocked());
919 public void testGetSessionNames_testGetCanonicalSessionNames() {
920 assertEquals("[session-A, session-B]", drools.getSessionNames(true).toString());
921 assertEquals("[full-A, full-B]", drools.getSessionNames(false).toString());
923 assertEquals("[session-A, session-B]", drools.getSessionNames().toString());
925 assertEquals("[full-A, full-B]", drools.getCanonicalSessionNames().toString());
928 when(container.getPolicySessions()).thenThrow(RUNTIME_EX);
929 assertEquals("[expected exception]", drools.getSessionNames().toString());
933 public void testGetBaseDomainNames() {
934 KieContainer kiecont = mock(KieContainer.class);
935 when(kiecont.getKieBaseNames()).thenReturn(Arrays.asList("kieA", "kieB"));
936 when(container.getKieContainer()).thenReturn(kiecont);
938 assertEquals("[kieA, kieB]", drools.getBaseDomainNames().toString());
942 public void testGetSession() {
943 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(null))
944 .withMessageContaining("must be provided");
946 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(""))
947 .withMessageContaining("must be provided");
949 assertSame(sess1, drools.getSession(SESSION1));
950 assertSame(sess1, drools.getSession(FULL_SESSION1));
952 assertSame(sess2, drools.getSession(SESSION2));
954 assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession("unknown session"))
955 .withMessageContaining("Invalid Session Name");
959 public void testFactClassNames() {
960 // copy to a sorted map so the order remains unchanged
961 Map<String, Integer> map = new TreeMap<>(drools.factClassNames(SESSION1));
962 assertEquals("{java.lang.Integer=2, java.lang.String=1}", map.toString());
964 assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(null))
965 .withMessageContaining("Invalid Session Name");
967 assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(""))
968 .withMessageContaining("Invalid Session Name");
972 public void testFactCount() {
973 assertEquals(FACT_COUNT, drools.factCount(SESSION1));
975 assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(null))
976 .withMessageContaining("Invalid Session Name");
978 assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(""))
979 .withMessageContaining("Invalid Session Name");
983 public void testFactsStringStringBoolean() {
984 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), false).toString());
985 verify(kieSess, never()).delete(fact1);
986 verify(kieSess, never()).delete(fact2);
987 verify(kieSess, never()).delete(fact3);
988 verify(kieSess, never()).delete(factex);
990 // now delete - but should only delete 1 & 3
991 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
992 verify(kieSess).delete(fact1);
993 verify(kieSess, never()).delete(fact2);
994 verify(kieSess).delete(fact3);
995 verify(kieSess, never()).delete(factex);
997 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(null, Integer.class.getName(), false))
998 .withMessageContaining("Invalid Session Name");
1000 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts("", Integer.class.getName(), false))
1001 .withMessageContaining("Invalid Session Name");
1003 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, null, false))
1004 .withMessageContaining("Invalid Class Name");
1006 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, "", false))
1007 .withMessageContaining("Invalid Class Name");
1009 assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, UNKNOWN_CLASS, false))
1010 .withMessageContaining("classloader");
1014 public void testFactsStringStringBoolean_DeleteEx() {
1015 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1017 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
1019 // should still have deleted #3
1020 verify(kieSess).delete(fact3);
1024 public void testFactsStringClassOfT() {
1025 assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class).toString());
1029 public void testFactQuery() {
1030 assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, false, PARM1, PARM2).toString());
1032 verify(kieSess, never()).delete(fact1);
1033 verify(kieSess, never()).delete(fact3);
1035 assertThatIllegalArgumentException()
1036 .isThrownBy(() -> drools.factQuery(null, QUERY, ENTITY, false, PARM1, PARM2))
1037 .withMessageContaining("Invalid Session Name");
1039 assertThatIllegalArgumentException().isThrownBy(() -> drools.factQuery("", QUERY, ENTITY, false, PARM1, PARM2))
1040 .withMessageContaining("Invalid Session Name");
1042 assertThatIllegalArgumentException()
1043 .isThrownBy(() -> drools.factQuery(SESSION1, null, ENTITY, false, PARM1, PARM2))
1044 .withMessageContaining("Invalid Query Name");
1046 assertThatIllegalArgumentException()
1047 .isThrownBy(() -> drools.factQuery(SESSION1, "", ENTITY, false, PARM1, PARM2))
1048 .withMessageContaining("Invalid Query Name");
1050 assertThatIllegalArgumentException()
1051 .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, null, false, PARM1, PARM2))
1052 .withMessageContaining("Invalid Queried Entity");
1054 assertThatIllegalArgumentException()
1055 .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, "", false, PARM1, PARM2))
1056 .withMessageContaining("Invalid Queried Entity");
1058 assertThatIllegalArgumentException().isThrownBy(
1059 () -> drools.factQuery(SESSION1, QUERY + "-unknown-query", ENTITY, false, PARM1, PARM2))
1060 .withMessageContaining("Invalid Query Name");
1064 public void testFactQuery_Delete() {
1065 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1067 assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, true, PARM1, PARM2).toString());
1069 // should still delete fact #3
1070 verify(kieSess).delete(fact3);
1074 public void testDeleteStringT() {
1075 assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
1077 verify(kieSess, never()).delete(fact1);
1078 verify(kieSess).delete(fact3);
1081 assertFalse(drools.delete(SESSION1, "hello"));
1083 // repeat, but generate exception while getting the first object
1084 when(kieSess.getObject(fact1)).thenThrow(RUNTIME_EX);
1085 assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
1087 verify(kieSess, never()).delete(fact1);
1089 // should still delete fact #3
1090 verify(kieSess, times(2)).delete(fact3);
1094 public void testDeleteT() {
1095 assertTrue(drools.delete(FACT3_OBJECT));
1097 verify(kieSess).delete(fact3);
1101 public void testDeleteStringClassOfT() {
1102 assertTrue(drools.delete(SESSION1, Integer.class));
1104 verify(kieSess).delete(fact1);
1105 verify(kieSess).delete(fact3);
1109 public void testDeleteStringClassOfT_Ex() {
1110 doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
1112 assertFalse(drools.delete(SESSION1, Integer.class));
1114 // should still delete fact #3
1115 verify(kieSess).delete(fact3);
1119 public void testDeleteClassOfT() {
1120 assertTrue(drools.delete(Integer.class));
1122 verify(kieSess).delete(fact1);
1123 verify(kieSess).delete(fact3);
1127 public void testFetchModelClass() {
1128 assertSame(Long.class, drools.fetchModelClass(Long.class.getName()));
1132 public void testIsBrained() {
1133 assertTrue(drools.isBrained());
1137 public void testToString() {
1138 assertNotNull(drools.toString());
1141 private class MyDrools extends MavenDroolsController {
1143 public MyDrools(String groupId, String artifactId, String version,
1144 List<TopicCoderFilterConfiguration> decoderConfigurations,
1145 List<TopicCoderFilterConfiguration> encoderConfigurations) {
1147 super(groupId, artifactId, version, decoderConfigurations, encoderConfigurations);
1151 protected EventProtocolCoder getCoderManager() {
1156 protected OrderedServiceImpl<DroolsControllerFeatureApi> getDroolsProviders() {
1157 return droolsProviders;
1161 protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
1162 when(container.getGroupId()).thenReturn(groupId);
1163 when(container.getArtifactId()).thenReturn(artifactId);
1164 when(container.getVersion()).thenReturn(version);