summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Hahn <jrh3@att.com>2019-07-25 09:49:44 -0400
committerJim Hahn <jrh3@att.com>2019-07-25 17:25:27 -0400
commit22e9a3560b236460c4ae5c1f7cd8dc01f15ca8ad (patch)
treedde276322f1a93f19bbd6b5cf548b13a87c75c2a
parentce1121d3cbe7e7706c1cd3f653436a7bdc07c2bb (diff)
Add coverage to MavenDroolsController
Change-Id: I7234c0146ef77f685a9766bb03168e385090fd1b Issue-ID: POLICY-1772 Signed-off-by: Jim Hahn <jrh3@att.com>
-rw-r--r--feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpEntity.java29
-rw-r--r--feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpImpl.java44
-rw-r--r--feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java8
-rw-r--r--feature-active-standby-management/src/test/java/org/onap/policy/drools/activestandby/DroolsPdpObjectTest.java19
-rw-r--r--policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java93
-rw-r--r--policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest2.java1163
6 files changed, 1258 insertions, 98 deletions
diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpEntity.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpEntity.java
index 12d716a6..0055b9cb 100644
--- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpEntity.java
+++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpEntity.java
@@ -2,14 +2,14 @@
* ============LICENSE_START=======================================================
* feature-active-standby-management
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -72,7 +72,7 @@ public class DroolsPdpEntity extends DroolsPdpObject implements Serializable {
updatedDate = new Date();
//When this is translated to a TimeStamp in MySQL, it assumes the date is relative
//to the local timezone. So, a value of Date(0) is actually Dec 31 18:00:00 CST 1969
- //which is an invalid value for the MySql TimeStamp
+ //which is an invalid value for the MySql TimeStamp
designatedDate = new Date(864000000);
}
@@ -135,25 +135,4 @@ public class DroolsPdpEntity extends DroolsPdpObject implements Serializable {
public void setDesignatedDate(Date designatedDate) {
this.designatedDate = designatedDate;
}
-
- @Override
- public boolean equals(Object obj) {
-
- if (obj instanceof DroolsPdp) {
- DroolsPdpEntity entity = (DroolsPdpEntity) obj;
- return this.pdpId.equals(entity.getPdpId());
- } else {
- return false;
- }
-
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (this.pdpId == null ? 0 : this.pdpId.hashCode());
- return result;
- }
-
}
diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpImpl.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpImpl.java
index 31728bc2..0c50f82d 100644
--- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpImpl.java
+++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpImpl.java
@@ -2,14 +2,14 @@
* ============LICENSE_START=======================================================
* feature-active-standby-management
* ================================================================================
- * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -33,7 +33,7 @@ public class DroolsPdpImpl extends DroolsPdpObject {
/**
* Contructor.
- *
+ *
* @param pdpId ID for the PDP
* @param designated is designated
* @param priority priority
@@ -46,11 +46,11 @@ public class DroolsPdpImpl extends DroolsPdpObject {
this.updatedDate = updatedDate;
//When this is translated to a TimeStamp in MySQL, it assumes the date is relative
//to the local timezone. So, a value of Date(0) is actually Dec 31 18:00:00 CST 1969
- //which is an invalid value for the MySql TimeStamp
+ //which is an invalid value for the MySql TimeStamp
this.designatedDate = new Date(864000000);
}
-
+
@Override
public boolean isDesignated() {
@@ -61,12 +61,12 @@ public class DroolsPdpImpl extends DroolsPdpObject {
public int getPriority() {
return priority;
}
-
+
@Override
public void setUpdatedDate(Date date) {
this.updatedDate = date;
}
-
+
@Override
public Date getUpdatedDate() {
return updatedDate;
@@ -76,7 +76,7 @@ public class DroolsPdpImpl extends DroolsPdpObject {
public String getPdpId() {
return pdpId;
}
-
+
@Override
public void setDesignated(boolean isDesignated) {
this.designated = isDesignated;
@@ -87,41 +87,21 @@ public class DroolsPdpImpl extends DroolsPdpObject {
public String getSiteName() {
return site;
}
-
+
@Override
public void setSiteName(String siteName) {
this.site = siteName;
}
-
+
@Override
public Date getDesignatedDate() {
return designatedDate;
}
-
+
@Override
public void setDesignatedDate(Date designatedDate) {
this.designatedDate = designatedDate;
}
-
- @Override
- public boolean equals(Object obj) {
-
-
- if (obj instanceof DroolsPdp) {
- DroolsPdpImpl temp = (DroolsPdpImpl) obj;
- return this.pdpId.equals(temp.getPdpId());
- } else {
- return false;
- }
- }
-
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + (this.pdpId == null ? 0 : this.pdpId.hashCode());
- return result;
- }
}
diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java
index 8ac14f0e..75157bbe 100644
--- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java
+++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java
@@ -32,6 +32,14 @@ public abstract class DroolsPdpObject implements DroolsPdp {
}
}
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (this.getPdpId() == null ? 0 : this.getPdpId().hashCode());
+ return result;
+ }
+
private int nullSafeCompare(String one, String two) {
if (one != null) {
if (two != null) {
diff --git a/feature-active-standby-management/src/test/java/org/onap/policy/drools/activestandby/DroolsPdpObjectTest.java b/feature-active-standby-management/src/test/java/org/onap/policy/drools/activestandby/DroolsPdpObjectTest.java
index 310f9110..842d6c7f 100644
--- a/feature-active-standby-management/src/test/java/org/onap/policy/drools/activestandby/DroolsPdpObjectTest.java
+++ b/feature-active-standby-management/src/test/java/org/onap/policy/drools/activestandby/DroolsPdpObjectTest.java
@@ -66,6 +66,25 @@ public class DroolsPdpObjectTest {
}
@Test
+ public void testHashCode() {
+ int hc = pdp.hashCode();
+
+ // same data should yield same hash code
+ assertEquals(hc, pdp.hashCode());
+ assertEquals(hc, makePdp(PDP_ID, SITE, PRIORITY).hashCode());
+
+ // different data should yield different hash code
+ assertTrue(makePdp(PDP_ID2, SITE, PRIORITY).hashCode() != hc);
+
+ // these fields have no impact on hash code
+ assertEquals(hc, makePdp(PDP_ID, SITE, PRIORITY2).hashCode());
+ assertEquals(hc, makePdp(PDP_ID, SITE2, PRIORITY).hashCode());
+
+ // should not throw an exception
+ new MyPdp().hashCode();
+ }
+
+ @Test
public void testNullSafeCompare() {
// self, when null
pdp.setSiteName(null);
diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
index 818cae80..b09ae85c 100644
--- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
+++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java
@@ -41,6 +41,7 @@ import org.kie.api.runtime.rule.QueryResultsRow;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
import org.onap.policy.common.gson.annotation.GsonJsonIgnore;
import org.onap.policy.common.gson.annotation.GsonJsonProperty;
+import org.onap.policy.common.utils.services.OrderedServiceImpl;
import org.onap.policy.drools.controller.DroolsController;
import org.onap.policy.drools.core.PolicyContainer;
import org.onap.policy.drools.core.PolicySession;
@@ -148,7 +149,7 @@ public class MavenDroolsController implements DroolsController {
throw new IllegalArgumentException("Missing maven version coordinate");
}
- this.policyContainer = new PolicyContainer(groupId, artifactId, version);
+ this.policyContainer = makePolicyContainer(groupId, artifactId, version);
this.init(decoderConfigurations, encoderConfigurations);
logger.debug("{}: instantiation completed ", this);
@@ -203,7 +204,7 @@ public class MavenDroolsController implements DroolsController {
if (newGroupId.equalsIgnoreCase(this.getGroupId())
&& newArtifactId.equalsIgnoreCase(this.getArtifactId())
&& newVersion.equalsIgnoreCase(this.getVersion())) {
- logger.warn("Al in the right version: " + newGroupId + ":"
+ logger.warn("All in the right version: " + newGroupId + ":"
+ newArtifactId + ":" + newVersion + " vs. " + this);
return;
}
@@ -254,18 +255,15 @@ public class MavenDroolsController implements DroolsController {
String topic = coderConfig.getTopic();
CustomGsonCoder customGsonCoder = coderConfig.getCustomGsonCoder();
- if (coderConfig.getCustomGsonCoder() != null
- && coderConfig.getCustomGsonCoder().getClassContainer() != null
- && !coderConfig.getCustomGsonCoder().getClassContainer().isEmpty()) {
+ if (customGsonCoder != null
+ && customGsonCoder.getClassContainer() != null
+ && !customGsonCoder.getClassContainer().isEmpty()) {
- String customGsonCoderClass = coderConfig.getCustomGsonCoder().getClassContainer();
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
- customGsonCoderClass)) {
+ String customGsonCoderClass = customGsonCoder.getClassContainer();
+ if (!isClass(customGsonCoderClass)) {
throw makeRetrieveEx(customGsonCoderClass);
} else {
- if (logger.isInfoEnabled()) {
- logClassFetched(customGsonCoderClass);
- }
+ logClassFetched(customGsonCoderClass);
}
}
@@ -278,17 +276,14 @@ public class MavenDroolsController implements DroolsController {
String potentialCodedClass = coderFilter.getCodedClass();
JsonProtocolFilter protocolFilter = coderFilter.getFilter();
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(),
- potentialCodedClass)) {
+ if (!isClass(potentialCodedClass)) {
throw makeRetrieveEx(potentialCodedClass);
} else {
- if (logger.isInfoEnabled()) {
- logClassFetched(potentialCodedClass);
- }
+ logClassFetched(potentialCodedClass);
}
if (decoder) {
- EventProtocolCoder.manager.addDecoder(EventProtocolParams.builder()
+ getCoderManager().addDecoder(EventProtocolParams.builder()
.groupId(this.getGroupId())
.artifactId(this.getArtifactId())
.topic(topic)
@@ -297,7 +292,7 @@ public class MavenDroolsController implements DroolsController {
.customGsonCoder(customGsonCoder)
.modelClassLoaderHash(this.policyContainer.getClassLoader().hashCode()));
} else {
- EventProtocolCoder.manager.addEncoder(
+ getCoderManager().addEncoder(
EventProtocolParams.builder().groupId(this.getGroupId())
.artifactId(this.getArtifactId()).topic(topic)
.eventClass(potentialCodedClass).protocolFilter(protocolFilter)
@@ -340,7 +335,7 @@ public class MavenDroolsController implements DroolsController {
for (TopicCoderFilterConfiguration coderConfig: decoderConfigurations) {
String topic = coderConfig.getTopic();
- EventProtocolCoder.manager.removeDecoders(this.getGroupId(), this.getArtifactId(), topic);
+ getCoderManager().removeDecoders(this.getGroupId(), this.getArtifactId(), topic);
}
}
@@ -357,14 +352,14 @@ public class MavenDroolsController implements DroolsController {
for (TopicCoderFilterConfiguration coderConfig: encoderConfigurations) {
String topic = coderConfig.getTopic();
- EventProtocolCoder.manager.removeEncoders(this.getGroupId(), this.getArtifactId(), topic);
+ getCoderManager().removeEncoders(this.getGroupId(), this.getArtifactId(), topic);
}
}
@Override
public boolean ownsCoder(Class<? extends Object> coderClass, int modelHash) {
- if (!ReflectionUtil.isClass(this.policyContainer.getClassLoader(), coderClass.getName())) {
+ if (!isClass(coderClass.getName())) {
logger.error("{}{} cannot be retrieved. ", this, coderClass.getName());
return false;
}
@@ -473,7 +468,7 @@ public class MavenDroolsController implements DroolsController {
// 1. Now, check if this topic has a decoder:
- if (!EventProtocolCoder.manager.isDecodingSupported(this.getGroupId(),
+ if (!getCoderManager().isDecodingSupported(this.getGroupId(),
this.getArtifactId(),
topic)) {
@@ -486,7 +481,7 @@ public class MavenDroolsController implements DroolsController {
Object anEvent;
try {
- anEvent = EventProtocolCoder.manager.decode(this.getGroupId(),
+ anEvent = getCoderManager().decode(this.getGroupId(),
this.getArtifactId(),
topic,
event);
@@ -520,7 +515,7 @@ public class MavenDroolsController implements DroolsController {
// Broadcast
- for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : getDroolsProviders().getList()) {
try {
if (feature.beforeInsert(this, event)) {
return true;
@@ -536,7 +531,7 @@ public class MavenDroolsController implements DroolsController {
logger.warn(this + "Failed to inject into PolicyContainer {}", this.getSessionNames());
}
- for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : getDroolsProviders().getList()) {
try {
if (feature.afterInsert(this, event, successInject)) {
return true;
@@ -556,7 +551,7 @@ public class MavenDroolsController implements DroolsController {
logger.info("{}DELIVER: {} FROM {} TO {}", this, event, this, sink);
- for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : getDroolsProviders().getList()) {
try {
if (feature.beforeDeliver(this, sink, event)) {
return true;
@@ -585,7 +580,7 @@ public class MavenDroolsController implements DroolsController {
}
String json =
- EventProtocolCoder.manager.encode(sink.getTopic(), event, this);
+ getCoderManager().encode(sink.getTopic(), event, this);
synchronized (this.recentSinkEvents) {
this.recentSinkEvents.add(json);
@@ -593,7 +588,7 @@ public class MavenDroolsController implements DroolsController {
boolean success = sink.send(json);
- for (DroolsControllerFeatureApi feature : DroolsControllerFeatureApi.providers.getList()) {
+ for (DroolsControllerFeatureApi feature : getDroolsProviders().getList()) {
try {
if (feature.afterDeliver(this, sink, event, json, success)) {
return true;
@@ -743,16 +738,14 @@ public class MavenDroolsController implements DroolsController {
@Override
public Map<String,Integer> factClassNames(String sessionName) {
- if (sessionName == null || sessionName.isEmpty()) {
- throw invalidSessNameEx(sessionName);
- }
+ validateSessionName(sessionName);
Map<String,Integer> classNames = new HashMap<>();
PolicySession session = getSession(sessionName);
KieSession kieSession = session.getKieSession();
- Collection<FactHandle> facts = session.getKieSession().getFactHandles();
+ Collection<FactHandle> facts = kieSession.getFactHandles();
for (FactHandle fact : facts) {
try {
String className = kieSession.getObject(fact).getClass().getName();
@@ -769,11 +762,15 @@ public class MavenDroolsController implements DroolsController {
return classNames;
}
- @Override
- public long factCount(String sessionName) {
+ private void validateSessionName(String sessionName) {
if (sessionName == null || sessionName.isEmpty()) {
throw invalidSessNameEx(sessionName);
}
+ }
+
+ @Override
+ public long factCount(String sessionName) {
+ validateSessionName(sessionName);
PolicySession session = getSession(sessionName);
return session.getKieSession().getFactCount();
@@ -781,9 +778,7 @@ public class MavenDroolsController implements DroolsController {
@Override
public List<Object> facts(String sessionName, String className, boolean delete) {
- if (sessionName == null || sessionName.isEmpty()) {
- throw invalidSessNameEx(sessionName);
- }
+ validateSessionName(sessionName);
if (className == null || className.isEmpty()) {
throw new IllegalArgumentException("Invalid Class Name: " + className);
@@ -827,9 +822,7 @@ public class MavenDroolsController implements DroolsController {
@Override
public List<Object> factQuery(String sessionName, String queryName, String queriedEntity,
boolean delete, Object... queryParams) {
- if (sessionName == null || sessionName.isEmpty()) {
- throw invalidSessNameEx(sessionName);
- }
+ validateSessionName(sessionName);
if (queryName == null || queryName.isEmpty()) {
throw new IllegalArgumentException("Invalid Query Name: " + queryName);
@@ -965,7 +958,7 @@ public class MavenDroolsController implements DroolsController {
StringBuilder builder = new StringBuilder();
builder
.append("MavenDroolsController [policyContainer=")
- .append((policyContainer != null) ? policyContainer.getName() : "NULL")
+ .append(policyContainer.getName())
.append(":")
.append(", alive=")
.append(alive)
@@ -975,4 +968,22 @@ public class MavenDroolsController implements DroolsController {
.append("]");
return builder.toString();
}
+
+ // these may be overridden by junit tests
+
+ protected EventProtocolCoder getCoderManager() {
+ return EventProtocolCoder.manager;
+ }
+
+ protected OrderedServiceImpl<DroolsControllerFeatureApi> getDroolsProviders() {
+ return DroolsControllerFeatureApi.providers;
+ }
+
+ protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
+ return new PolicyContainer(groupId, artifactId, version);
+ }
+
+ protected boolean isClass(String className) {
+ return ReflectionUtil.isClass(this.policyContainer.getClassLoader(), className);
+ }
}
diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest2.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest2.java
new file mode 100644
index 00000000..cd99eef0
--- /dev/null
+++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest2.java
@@ -0,0 +1,1163 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.drools.controller.internal;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.api.KieBase;
+import org.kie.api.definition.KiePackage;
+import org.kie.api.definition.rule.Query;
+import org.kie.api.runtime.KieContainer;
+import org.kie.api.runtime.KieSession;
+import org.kie.api.runtime.rule.FactHandle;
+import org.kie.api.runtime.rule.QueryResults;
+import org.kie.api.runtime.rule.QueryResultsRow;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.utils.services.OrderedServiceImpl;
+import org.onap.policy.drools.core.PolicyContainer;
+import org.onap.policy.drools.core.PolicySession;
+import org.onap.policy.drools.features.DroolsControllerFeatureApi;
+import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
+import org.onap.policy.drools.protocol.coders.EventProtocolParams;
+import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder;
+import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter;
+
+public class MavenDroolsControllerTest2 {
+ private static final int FACT1_OBJECT = 1000;
+ private static final int FACT3_OBJECT = 1001;
+
+ private static final long FACT_COUNT = 200L;
+
+ private static final String EXPECTED_EXCEPTION = "expected exception";
+ private static final RuntimeException RUNTIME_EX = new RuntimeException(EXPECTED_EXCEPTION);
+ private static final IllegalArgumentException ARG_EX = new IllegalArgumentException(EXPECTED_EXCEPTION);
+
+ private static final String UNKNOWN_CLASS = "unknown class";
+
+ private static final String GROUP = "my-group";
+ private static final String ARTIFACT = "my-artifact";
+ private static final String VERSION = "my-version";
+
+ private static final String GROUP2 = "my-groupB";
+ private static final String ARTIFACT2 = "my-artifactB";
+ private static final String VERSION2 = "my-versionB";
+
+ private static final String TOPIC = "my-topic";
+ private static final String TOPIC2 = "my-topic";
+
+ private static final ClassLoader CLASS_LOADER = MavenDroolsControllerTest2.class.getClassLoader();
+ private static final int CLASS_LOADER_HASHCODE = CLASS_LOADER.hashCode();
+
+ private static final String SESSION1 = "session-A";
+ private static final String SESSION2 = "session-B";
+ private static final String FULL_SESSION1 = "full-A";
+ private static final String FULL_SESSION2 = "full-B";
+
+ private static final String EVENT_TEXT = "my-event-text";
+ private static final Object EVENT = new Object();
+
+ private static final String QUERY = "my-query";
+ private static final String QUERY2 = "my-query-B";
+ private static final String ENTITY = "my-entity";
+ private static final Object PARM1 = "parmA";
+ private static final Object PARM2 = "parmB";
+
+ @Mock
+ private EventProtocolCoder coderMgr;
+ @Mock
+ private DroolsControllerFeatureApi prov1;
+ @Mock
+ private DroolsControllerFeatureApi prov2;
+ @Mock
+ private OrderedServiceImpl<DroolsControllerFeatureApi> droolsProviders;
+ @Mock
+ private TopicCoderFilterConfiguration decoder1;
+ @Mock
+ private TopicCoderFilterConfiguration decoder2;
+ @Mock
+ private TopicCoderFilterConfiguration encoder1;
+ @Mock
+ private TopicCoderFilterConfiguration encoder2;
+ @Mock
+ private PolicyContainer container;
+ @Mock
+ private CustomGsonCoder gson1;
+ @Mock
+ private CustomGsonCoder gson2;
+ @Mock
+ private PotentialCoderFilter filter1a;
+ @Mock
+ private JsonProtocolFilter jsonFilter1a;
+ @Mock
+ private PotentialCoderFilter filter1b;
+ @Mock
+ private JsonProtocolFilter jsonFilter1b;
+ @Mock
+ private PotentialCoderFilter filter2;
+ @Mock
+ private JsonProtocolFilter jsonFilter2;
+ @Mock
+ private PolicySession sess1;
+ @Mock
+ private PolicySession sess2;
+ @Mock
+ private KieSession kieSess;
+ @Mock
+ private KieSession kieSess2;
+ @Mock
+ private TopicSink sink;
+ @Mock
+ private FactHandle fact1;
+ @Mock
+ private FactHandle fact2;
+ @Mock
+ private FactHandle fact3;
+ @Mock
+ private FactHandle factex;
+ @Mock
+ private KieBase kieBase;
+ @Mock
+ private KiePackage pkg1;
+ @Mock
+ private KiePackage pkg2;
+ @Mock
+ private Query query1;
+ @Mock
+ private Query query2;
+ @Mock
+ private Query query3;
+ @Mock
+ private QueryResults queryResults;
+ @Mock
+ private QueryResultsRow row1;
+ @Mock
+ private QueryResultsRow row2;
+
+ private List<TopicCoderFilterConfiguration> decoders;
+ private List<TopicCoderFilterConfiguration> encoders;
+
+ private MavenDroolsController drools;
+
+ /**
+ * Initializes objects, including the drools controller.
+ */
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ when(droolsProviders.getList()).thenReturn(Arrays.asList(prov1, prov2));
+
+ when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(true);
+ when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenReturn(EVENT);
+
+ when(kieSess.getFactCount()).thenReturn(FACT_COUNT);
+ when(kieSess.getFactHandles()).thenReturn(Arrays.asList(fact1, fact2, factex, fact3));
+ when(kieSess.getFactHandles(any())).thenReturn(Arrays.asList(fact1, fact3));
+ when(kieSess.getKieBase()).thenReturn(kieBase);
+ when(kieSess.getQueryResults(QUERY, PARM1, PARM2)).thenReturn(queryResults);
+
+ when(kieSess.getObject(fact1)).thenReturn(FACT1_OBJECT);
+ when(kieSess.getObject(fact2)).thenReturn("");
+ when(kieSess.getObject(fact3)).thenReturn(FACT3_OBJECT);
+ when(kieSess.getObject(factex)).thenThrow(RUNTIME_EX);
+
+ when(kieSess2.getFactHandles()).thenReturn(Collections.emptyList());
+
+ when(kieBase.getKiePackages()).thenReturn(Arrays.asList(pkg1, pkg2));
+
+ when(pkg1.getQueries()).thenReturn(Arrays.asList(query3));
+ when(pkg2.getQueries()).thenReturn(Arrays.asList(query2, query1));
+
+ when(query1.getName()).thenReturn(QUERY);
+ when(query2.getName()).thenReturn(QUERY2);
+
+ when(queryResults.iterator()).thenReturn(Arrays.asList(row1, row2).iterator());
+
+ when(row1.get(ENTITY)).thenReturn(FACT1_OBJECT);
+ when(row2.get(ENTITY)).thenReturn(FACT3_OBJECT);
+
+ when(row1.getFactHandle(ENTITY)).thenReturn(fact1);
+ when(row2.getFactHandle(ENTITY)).thenReturn(fact3);
+
+ when(sess1.getKieSession()).thenReturn(kieSess);
+ when(sess2.getKieSession()).thenReturn(kieSess2);
+
+ when(sess1.getName()).thenReturn(SESSION1);
+ when(sess2.getName()).thenReturn(SESSION2);
+
+ when(sess1.getFullName()).thenReturn(FULL_SESSION1);
+ when(sess2.getFullName()).thenReturn(FULL_SESSION2);
+
+ when(container.getClassLoader()).thenReturn(CLASS_LOADER);
+ when(container.getPolicySessions()).thenReturn(Arrays.asList(sess1, sess2));
+ when(container.insertAll(EVENT)).thenReturn(true);
+
+ when(decoder1.getTopic()).thenReturn(TOPIC);
+ when(decoder2.getTopic()).thenReturn(TOPIC2);
+
+ when(encoder1.getTopic()).thenReturn(TOPIC);
+ when(encoder2.getTopic()).thenReturn(TOPIC2);
+
+ decoders = Arrays.asList(decoder1, decoder2);
+ encoders = Arrays.asList(encoder1, encoder2);
+
+ when(decoder1.getCustomGsonCoder()).thenReturn(gson1);
+ when(encoder2.getCustomGsonCoder()).thenReturn(gson2);
+
+ when(filter1a.getCodedClass()).thenReturn(Object.class.getName());
+ when(filter1a.getFilter()).thenReturn(jsonFilter1a);
+
+ when(filter1b.getCodedClass()).thenReturn(String.class.getName());
+ when(filter1b.getFilter()).thenReturn(jsonFilter1b);
+
+ when(filter2.getCodedClass()).thenReturn(Integer.class.getName());
+ when(filter2.getFilter()).thenReturn(jsonFilter2);
+
+ when(decoder1.getCoderFilters()).thenReturn(Arrays.asList(filter1a, filter1b));
+ when(decoder2.getCoderFilters()).thenReturn(Collections.emptyList());
+
+ when(encoder1.getCoderFilters()).thenReturn(Collections.emptyList());
+ when(encoder2.getCoderFilters()).thenReturn(Arrays.asList(filter2));
+
+ when(sink.getTopic()).thenReturn(TOPIC);
+ when(sink.send(EVENT_TEXT)).thenReturn(true);
+
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null);
+
+ when(coderMgr.encode(TOPIC, EVENT, drools)).thenReturn(EVENT_TEXT);
+ }
+
+ @Test
+ public void testMavenDroolsController_InvalidArgs() {
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(null, ARTIFACT, VERSION, null, null))
+ .withMessageContaining("group");
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools("", ARTIFACT, VERSION, null, null))
+ .withMessageContaining("group");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, null, VERSION, null, null))
+ .withMessageContaining("artifact");
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, "", VERSION, null, null))
+ .withMessageContaining("artifact");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, null, null, null))
+ .withMessageContaining("version");
+ assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, "", null, null))
+ .withMessageContaining("version");
+ }
+
+ @Test
+ public void testUpdateToVersion() {
+ // add coders
+ drools.updateToVersion(GROUP, ARTIFACT, VERSION2, decoders, encoders);
+
+ verify(container).updateToVersion(VERSION2);
+
+ // nothing removed the first time
+ verify(coderMgr, never()).removeDecoders(GROUP, ARTIFACT, TOPIC2);
+ verify(coderMgr, never()).removeEncoders(GROUP, ARTIFACT, TOPIC);
+
+ verify(coderMgr, times(2)).addDecoder(any());
+ verify(coderMgr, times(1)).addEncoder(any());
+
+ // remove coders
+ when(container.getVersion()).thenReturn(VERSION2);
+ drools.updateToVersion(GROUP, ARTIFACT, VERSION, null, null);
+
+ verify(container).updateToVersion(VERSION);
+
+ verify(coderMgr, times(2)).removeDecoders(GROUP, ARTIFACT, TOPIC2);
+ verify(coderMgr, times(2)).removeEncoders(GROUP, ARTIFACT, TOPIC);
+
+ // not added again
+ verify(coderMgr, times(2)).addDecoder(any());
+ verify(coderMgr, times(1)).addEncoder(any());
+ }
+
+ @Test
+ public void testUpdateToVersion_Unchanged() {
+ drools.updateToVersion(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ verify(coderMgr, never()).addDecoder(any());
+ verify(coderMgr, never()).addEncoder(any());
+ }
+
+ @Test
+ public void testUpdateToVersion_InvalidArgs() {
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion(null, ARTIFACT, VERSION, null, null))
+ .withMessageContaining("group");
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion("", ARTIFACT, VERSION, null, null))
+ .withMessageContaining("group");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, null, VERSION, null, null))
+ .withMessageContaining("artifact");
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, "", VERSION, null, null))
+ .withMessageContaining("artifact");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, null, null, null))
+ .withMessageContaining("version");
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "", null, null))
+ .withMessageContaining("version");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion("no-group-id", ARTIFACT, VERSION, null, null))
+ .withMessageContaining("BRAINLESS");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion(GROUP, "no-artifact-id", VERSION, null, null))
+ .withMessageContaining("BRAINLESS");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "no-version", null, null))
+ .withMessageContaining("BRAINLESS");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion(GROUP2, ARTIFACT, VERSION, null, null))
+ .withMessageContaining("coordinates must be identical");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT2, VERSION, null, null))
+ .withMessageContaining("coordinates must be identical");
+ }
+
+ @Test
+ public void testInitCoders_NullCoders() {
+ // already constructed with null coders
+ verify(coderMgr, never()).addDecoder(any());
+ verify(coderMgr, never()).addEncoder(any());
+ }
+
+ @Test
+ public void testInitCoders_NullOrEmptyFilters() {
+ when(decoder1.getCoderFilters()).thenReturn(Collections.emptyList());
+ when(decoder2.getCoderFilters()).thenReturn(null);
+
+ when(encoder1.getCoderFilters()).thenReturn(null);
+ when(encoder2.getCoderFilters()).thenReturn(Collections.emptyList());
+
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ verify(coderMgr, never()).addDecoder(any());
+ verify(coderMgr, never()).addEncoder(any());
+ }
+
+ @Test
+ public void testInitCoders_GsonClass() {
+ when(gson1.getClassContainer()).thenReturn("");
+ when(gson2.getClassContainer()).thenReturn(Long.class.getName());
+
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ // all should be added
+ verify(coderMgr, times(2)).addDecoder(any());
+ verify(coderMgr, times(1)).addEncoder(any());
+ }
+
+ @Test
+ public void testInitCoders_InvalidGsonClass() {
+ when(gson1.getClassContainer()).thenReturn(UNKNOWN_CLASS);
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
+ .withMessageContaining("cannot be retrieved");
+ }
+
+ @Test
+ public void testInitCoders_InvalidFilterClass() {
+ when(filter2.getCodedClass()).thenReturn(UNKNOWN_CLASS);
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders))
+ .withMessageContaining("cannot be retrieved");
+ }
+
+ @Test
+ public void testInitCoders_Filters() {
+
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ ArgumentCaptor<EventProtocolParams> dec = ArgumentCaptor.forClass(EventProtocolParams.class);
+ verify(coderMgr, times(2)).addDecoder(dec.capture());
+
+ ArgumentCaptor<EventProtocolParams> enc = ArgumentCaptor.forClass(EventProtocolParams.class);
+ verify(coderMgr, times(1)).addEncoder(enc.capture());
+
+ // validate parameters
+ EventProtocolParams params = dec.getAllValues().get(0);
+ assertEquals(ARTIFACT, params.getArtifactId());
+ assertEquals(gson1, params.getCustomCoder());
+ assertEquals(Object.class.getName(), params.getEventClass());
+ assertEquals(GROUP, params.getGroupId());
+ assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
+ assertEquals(jsonFilter1a, params.getProtocolFilter());
+ assertEquals(TOPIC, params.getTopic());
+
+ params = dec.getAllValues().get(1);
+ assertEquals(ARTIFACT, params.getArtifactId());
+ assertEquals(gson1, params.getCustomCoder());
+ assertEquals(String.class.getName(), params.getEventClass());
+ assertEquals(GROUP, params.getGroupId());
+ assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
+ assertEquals(jsonFilter1b, params.getProtocolFilter());
+ assertEquals(TOPIC, params.getTopic());
+
+ params = enc.getAllValues().get(0);
+ assertEquals(ARTIFACT, params.getArtifactId());
+ assertEquals(gson2, params.getCustomCoder());
+ assertEquals(Integer.class.getName(), params.getEventClass());
+ assertEquals(GROUP, params.getGroupId());
+ assertEquals(CLASS_LOADER_HASHCODE, params.getModelClassLoaderHash());
+ assertEquals(jsonFilter2, params.getProtocolFilter());
+ assertEquals(TOPIC, params.getTopic());
+ }
+
+ @Test
+ public void testOwnsCoder() {
+ int hc = CLASS_LOADER_HASHCODE;
+
+ // wrong hash code
+ assertFalse(drools.ownsCoder(String.class, hc + 1));
+
+ // correct hash code
+ assertTrue(drools.ownsCoder(String.class, hc));
+
+ // unknown class
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null) {
+ @Override
+ protected boolean isClass(String className) {
+ return false;
+ }
+ };
+ assertFalse(drools.ownsCoder(String.class, hc));
+ }
+
+ @Test
+ public void testStart_testStop_testIsAlive() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ when(container.start()).thenReturn(true);
+ when(container.stop()).thenReturn(true);
+
+ assertFalse(drools.isAlive());
+
+ // start it
+ assertTrue(drools.start());
+ verify(container).start();
+ assertTrue(drools.isAlive());
+
+ // repeat - no changes
+ assertTrue(drools.start());
+ verify(container).start();
+ assertTrue(drools.isAlive());
+
+ // stop it
+ assertTrue(drools.stop());
+ verify(container).stop();
+ assertFalse(drools.isAlive());
+
+ // repeat - no changes
+ assertTrue(drools.stop());
+ verify(container).stop();
+ assertFalse(drools.isAlive());
+
+ // now check with container returning false - should still be invoked
+ when(container.start()).thenReturn(false);
+ when(container.stop()).thenReturn(false);
+ assertFalse(drools.start());
+ assertTrue(drools.isAlive());
+ assertFalse(drools.stop());
+ assertFalse(drools.isAlive());
+ verify(container, times(2)).start();
+ verify(container, times(2)).stop();
+
+ // coders should still be intact
+ verify(coderMgr, never()).removeDecoders(any(), any(), any());
+ verify(coderMgr, never()).removeEncoders(any(), any(), any());
+
+ verify(container, never()).shutdown();
+ verify(container, never()).destroy();
+ }
+
+ @Test
+ public void testShutdown() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ // start it
+ drools.start();
+
+ // shut down
+ drools.shutdown();
+
+ verify(container).stop();
+ assertFalse(drools.isAlive());
+
+ // coders should have been removed
+ verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
+ verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
+
+ verify(container).shutdown();
+ verify(container, never()).destroy();
+ }
+
+ @Test
+ public void testShutdown_Ex() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ // start it
+ drools.start();
+
+ when(container.stop()).thenThrow(RUNTIME_EX);
+
+ // shut down
+ drools.shutdown();
+
+ assertFalse(drools.isAlive());
+
+ verify(container).shutdown();
+ verify(container, never()).destroy();
+ }
+
+ @Test
+ public void testHalt() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ // start it
+ drools.start();
+
+ // halt
+ drools.halt();
+
+ verify(container).stop();
+ assertFalse(drools.isAlive());
+
+ // coders should have been removed
+ verify(coderMgr, times(2)).removeDecoders(any(), any(), any());
+ verify(coderMgr, times(2)).removeEncoders(any(), any(), any());
+
+ verify(container).destroy();
+ }
+
+ @Test
+ public void testHalt_Ex() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders);
+
+ // start it
+ drools.start();
+
+ when(container.stop()).thenThrow(RUNTIME_EX);
+
+ // halt
+ drools.halt();
+
+ assertFalse(drools.isAlive());
+
+ verify(container).destroy();
+ }
+
+ @Test
+ public void testRemoveCoders_Ex() {
+ drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders) {
+ @Override
+ protected void removeDecoders() {
+ throw ARG_EX;
+ }
+
+ @Override
+ protected void removeEncoders() {
+ throw ARG_EX;
+ }
+ };
+
+ drools.updateToVersion(GROUP, ARTIFACT, VERSION2, null, null);
+ }
+
+ @Test
+ public void testOfferStringString() {
+ drools.start();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+
+ verify(container).insertAll(EVENT);
+ }
+
+ @Test
+ public void testOfferStringString_NoDecode() {
+ when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(false);
+
+ drools.start();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+
+ verify(container, never()).insertAll(EVENT);
+ }
+
+ @Test
+ public void testOfferStringString_DecodeUnsupported() {
+ when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT))
+ .thenThrow(new UnsupportedOperationException(EXPECTED_EXCEPTION));
+
+ drools.start();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+
+ verify(container, never()).insertAll(EVENT);
+ }
+
+ @Test
+ public void testOfferStringString_DecodeEx() {
+ when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenThrow(RUNTIME_EX);
+
+ drools.start();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+
+ verify(container, never()).insertAll(EVENT);
+ }
+
+ @Test
+ public void testOfferStringString_Ignored() {
+ drools.start();
+
+ drools.lock();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ drools.unlock();
+
+ drools.stop();
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ drools.start();
+
+ // no sessions
+ when(container.getPolicySessions()).thenReturn(Collections.emptyList());
+ assertTrue(drools.offer(TOPIC, EVENT_TEXT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ }
+
+ @Test
+ public void testOfferT() {
+ drools.start();
+ assertTrue(drools.offer(EVENT));
+ assertEquals(1, drools.getRecentSourceEvents().length);
+ assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
+ verify(container).insertAll(EVENT);
+
+ verify(prov1).beforeInsert(drools, EVENT);
+ verify(prov2).beforeInsert(drools, EVENT);
+
+ verify(prov1).afterInsert(drools, EVENT, true);
+ verify(prov2).afterInsert(drools, EVENT, true);
+ }
+
+ @Test
+ public void testOfferT_Ex() {
+ when(prov1.beforeInsert(drools, EVENT)).thenThrow(RUNTIME_EX);
+ when(prov1.afterInsert(drools, EVENT, true)).thenThrow(RUNTIME_EX);
+
+ drools.start();
+ assertTrue(drools.offer(EVENT));
+ assertEquals(1, drools.getRecentSourceEvents().length);
+ assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
+ verify(container).insertAll(EVENT);
+
+ // should still invoke prov2
+ verify(prov2).beforeInsert(drools, EVENT);
+
+ verify(prov2).afterInsert(drools, EVENT, true);
+ }
+
+ @Test
+ public void testOfferT_NotInserted() {
+ when(container.insertAll(EVENT)).thenReturn(false);
+
+ drools.start();
+ assertTrue(drools.offer(EVENT));
+ assertEquals(1, drools.getRecentSourceEvents().length);
+ assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
+ verify(container).insertAll(EVENT);
+
+ verify(prov1).beforeInsert(drools, EVENT);
+ verify(prov2).beforeInsert(drools, EVENT);
+
+ verify(prov1).afterInsert(drools, EVENT, false);
+ verify(prov2).afterInsert(drools, EVENT, false);
+ }
+
+ @Test
+ public void testOfferT_BeforeInsertIntercept() {
+ drools.start();
+ when(prov1.beforeInsert(drools, EVENT)).thenReturn(true);
+
+ assertTrue(drools.offer(EVENT));
+ assertEquals(1, drools.getRecentSourceEvents().length);
+ assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
+ verify(container, never()).insertAll(EVENT);
+
+ verify(prov1).beforeInsert(drools, EVENT);
+
+ // nothing else invoked
+ verify(prov2, never()).beforeInsert(drools, EVENT);
+ verify(prov1, never()).afterInsert(drools, EVENT, true);
+ verify(prov2, never()).afterInsert(drools, EVENT, true);
+ }
+
+ @Test
+ public void testOfferT_AfterInsertIntercept() {
+ drools.start();
+
+ when(prov1.afterInsert(drools, EVENT, true)).thenReturn(true);
+
+ assertTrue(drools.offer(EVENT));
+ assertEquals(1, drools.getRecentSourceEvents().length);
+ assertEquals(EVENT, drools.getRecentSourceEvents()[0]);
+ verify(container).insertAll(EVENT);
+
+ verify(prov1).beforeInsert(drools, EVENT);
+ verify(prov2).beforeInsert(drools, EVENT);
+
+ verify(prov1).afterInsert(drools, EVENT, true);
+
+ // prov2 is never called
+ verify(prov2, never()).afterInsert(drools, EVENT, true);
+ }
+
+ @Test
+ public void testOfferT_Ignored() {
+ drools.start();
+
+ drools.lock();
+ assertTrue(drools.offer(EVENT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ drools.unlock();
+
+ drools.stop();
+ assertTrue(drools.offer(EVENT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ drools.start();
+
+ // no sessions
+ when(container.getPolicySessions()).thenReturn(Collections.emptyList());
+ assertTrue(drools.offer(EVENT));
+ assertEquals(0, drools.getRecentSourceEvents().length);
+ }
+
+ @Test
+ public void testDeliver() {
+ drools.start();
+ assertTrue(drools.deliver(sink, EVENT));
+ assertEquals(1, drools.getRecentSinkEvents().length);
+ assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
+
+ verify(sink).send(EVENT_TEXT);
+
+ verify(prov1).beforeDeliver(drools, sink, EVENT);
+ verify(prov2).beforeDeliver(drools, sink, EVENT);
+
+ verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ }
+
+ @Test
+ public void testDeliver_InvalidArgs() {
+ drools.start();
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(null, EVENT))
+ .withMessageContaining("sink");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(sink, null))
+ .withMessageContaining("event");
+
+ drools.lock();
+ assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT)).withMessageContaining("locked");
+ drools.unlock();
+
+ drools.stop();
+ assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT))
+ .withMessageContaining("stopped");
+ drools.start();
+
+ assertEquals(0, drools.getRecentSinkEvents().length);
+ }
+
+ @Test
+ public void testDeliver_BeforeIntercept() {
+ when(prov1.beforeDeliver(drools, sink, EVENT)).thenReturn(true);
+
+ drools.start();
+ assertTrue(drools.deliver(sink, EVENT));
+ assertEquals(0, drools.getRecentSinkEvents().length);
+
+ verify(prov1).beforeDeliver(drools, sink, EVENT);
+
+ // nothing else should have been invoked
+ verify(sink, never()).send(EVENT_TEXT);
+ verify(prov2, never()).beforeDeliver(drools, sink, EVENT);
+ verify(prov1, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ }
+
+ @Test
+ public void testDeliver_AfterIntercept() {
+ when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenReturn(true);
+
+ drools.start();
+ assertTrue(drools.deliver(sink, EVENT));
+ assertEquals(1, drools.getRecentSinkEvents().length);
+ assertEquals(EVENT_TEXT, drools.getRecentSinkEvents()[0]);
+
+ verify(prov1).beforeDeliver(drools, sink, EVENT);
+ verify(prov2).beforeDeliver(drools, sink, EVENT);
+
+ verify(sink).send(EVENT_TEXT);
+
+ verify(prov1).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+
+ // nothing else should have been invoked
+ verify(prov2, never()).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ }
+
+ @Test
+ public void testDeliver_InterceptEx() {
+ when(prov1.beforeDeliver(drools, sink, EVENT)).thenThrow(RUNTIME_EX);
+ when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenThrow(RUNTIME_EX);
+
+ drools.start();
+ assertTrue(drools.deliver(sink, EVENT));
+
+ verify(sink).send(EVENT_TEXT);
+
+ // should still invoke prov2
+ verify(prov2).beforeDeliver(drools, sink, EVENT);
+ verify(prov2).afterDeliver(drools, sink, EVENT, EVENT_TEXT, true);
+ }
+
+ @Test
+ public void testGetXxx() {
+ assertEquals(VERSION, drools.getVersion());
+ assertEquals(ARTIFACT, drools.getArtifactId());
+ assertEquals(GROUP, drools.getGroupId());
+ assertEquals(CLASS_LOADER_HASHCODE, drools.getModelClassLoaderHash());
+ assertSame(container, drools.getContainer());
+ assertEquals(Arrays.asList(sess1, sess2), drools.getSessions());
+
+ // test junit methods - need a controller with fewer overrides
+ drools = new MavenDroolsController(GROUP, ARTIFACT, VERSION, null, null) {
+ @Override
+ protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
+ return container;
+ }
+ };
+
+ assertSame(EventProtocolCoder.manager, drools.getCoderManager());
+ assertSame(DroolsControllerFeatureApi.providers, drools.getDroolsProviders());
+ }
+
+ @Test
+ public void testLock_testUnlock_testIsLocked() {
+ assertFalse(drools.isLocked());
+
+ assertTrue(drools.lock());
+ assertTrue(drools.isLocked());
+
+ assertTrue(drools.unlock());
+ assertFalse(drools.isLocked());
+
+ // repeat
+ assertTrue(drools.lock());
+ assertTrue(drools.isLocked());
+
+ assertTrue(drools.unlock());
+ assertFalse(drools.isLocked());
+ }
+
+ @Test
+ public void testGetSessionNames_testGetCanonicalSessionNames() {
+ assertEquals("[session-A, session-B]", drools.getSessionNames(true).toString());
+ assertEquals("[full-A, full-B]", drools.getSessionNames(false).toString());
+
+ assertEquals("[session-A, session-B]", drools.getSessionNames().toString());
+
+ assertEquals("[full-A, full-B]", drools.getCanonicalSessionNames().toString());
+
+ // exception case
+ when(container.getPolicySessions()).thenThrow(RUNTIME_EX);
+ assertEquals("[expected exception]", drools.getSessionNames().toString());
+ }
+
+ @Test
+ public void testGetBaseDomainNames() {
+ KieContainer kiecont = mock(KieContainer.class);
+ when(kiecont.getKieBaseNames()).thenReturn(Arrays.asList("kieA", "kieB"));
+ when(container.getKieContainer()).thenReturn(kiecont);
+
+ assertEquals("[kieA, kieB]", drools.getBaseDomainNames().toString());
+ }
+
+ @Test
+ public void testGetSession() {
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(null))
+ .withMessageContaining("must be provided");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(""))
+ .withMessageContaining("must be provided");
+
+ assertSame(sess1, drools.getSession(SESSION1));
+ assertSame(sess1, drools.getSession(FULL_SESSION1));
+
+ assertSame(sess2, drools.getSession(SESSION2));
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession("unknown session"))
+ .withMessageContaining("Invalid Session Name");
+ }
+
+ @Test
+ public void testFactClassNames() {
+ // copy to a sorted map so the order remains unchanged
+ Map<String, Integer> map = new TreeMap<>(drools.factClassNames(SESSION1));
+ assertEquals("{java.lang.Integer=2, java.lang.String=1}", map.toString());
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(null))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(""))
+ .withMessageContaining("Invalid Session Name");
+ }
+
+ @Test
+ public void testFactCount() {
+ assertEquals(FACT_COUNT, drools.factCount(SESSION1));
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(null))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(""))
+ .withMessageContaining("Invalid Session Name");
+ }
+
+ @Test
+ public void testFactsStringStringBoolean() {
+ assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), false).toString());
+ verify(kieSess, never()).delete(fact1);
+ verify(kieSess, never()).delete(fact2);
+ verify(kieSess, never()).delete(fact3);
+ verify(kieSess, never()).delete(factex);
+
+ // now delete - but should only delete 1 & 3
+ assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
+ verify(kieSess).delete(fact1);
+ verify(kieSess, never()).delete(fact2);
+ verify(kieSess).delete(fact3);
+ verify(kieSess, never()).delete(factex);
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(null, Integer.class.getName(), false))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.facts("", Integer.class.getName(), false))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, null, false))
+ .withMessageContaining("Invalid Class Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, "", false))
+ .withMessageContaining("Invalid Class Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, UNKNOWN_CLASS, false))
+ .withMessageContaining("classloader");
+ }
+
+ @Test
+ public void testFactsStringStringBoolean_DeleteEx() {
+ doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
+
+ assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString());
+
+ // should still have deleted #3
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testFactsStringClassOfT() {
+ assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class).toString());
+ }
+
+ @Test
+ public void testFactQuery() {
+ assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, false, PARM1, PARM2).toString());
+
+ verify(kieSess, never()).delete(fact1);
+ verify(kieSess, never()).delete(fact3);
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.factQuery(null, QUERY, ENTITY, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException().isThrownBy(() -> drools.factQuery("", QUERY, ENTITY, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Session Name");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.factQuery(SESSION1, null, ENTITY, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Query Name");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.factQuery(SESSION1, "", ENTITY, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Query Name");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, null, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Queried Entity");
+
+ assertThatIllegalArgumentException()
+ .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, "", false, PARM1, PARM2))
+ .withMessageContaining("Invalid Queried Entity");
+
+ assertThatIllegalArgumentException().isThrownBy(
+ () -> drools.factQuery(SESSION1, QUERY + "-unknown-query", ENTITY, false, PARM1, PARM2))
+ .withMessageContaining("Invalid Query Name");
+ }
+
+ @Test
+ public void testFactQuery_Delete() {
+ doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
+
+ assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, true, PARM1, PARM2).toString());
+
+ // should still delete fact #3
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testDeleteStringT() {
+ assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
+
+ verify(kieSess, never()).delete(fact1);
+ verify(kieSess).delete(fact3);
+
+ // not found
+ assertFalse(drools.delete(SESSION1, "hello"));
+
+ // repeat, but generate exception while getting the first object
+ when(kieSess.getObject(fact1)).thenThrow(RUNTIME_EX);
+ assertTrue(drools.delete(SESSION1, FACT3_OBJECT));
+
+ verify(kieSess, never()).delete(fact1);
+
+ // should still delete fact #3
+ verify(kieSess, times(2)).delete(fact3);
+ }
+
+ @Test
+ public void testDeleteT() {
+ assertTrue(drools.delete(FACT3_OBJECT));
+
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testDeleteStringClassOfT() {
+ assertTrue(drools.delete(SESSION1, Integer.class));
+
+ verify(kieSess).delete(fact1);
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testDeleteStringClassOfT_Ex() {
+ doThrow(RUNTIME_EX).when(kieSess).delete(fact1);
+
+ assertFalse(drools.delete(SESSION1, Integer.class));
+
+ // should still delete fact #3
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testDeleteClassOfT() {
+ assertTrue(drools.delete(Integer.class));
+
+ verify(kieSess).delete(fact1);
+ verify(kieSess).delete(fact3);
+ }
+
+ @Test
+ public void testFetchModelClass() {
+ assertSame(Long.class, drools.fetchModelClass(Long.class.getName()));
+ }
+
+ @Test
+ public void testIsBrained() {
+ assertTrue(drools.isBrained());
+ }
+
+ @Test
+ public void testToString() {
+ assertNotNull(drools.toString());
+ }
+
+ private class MyDrools extends MavenDroolsController {
+
+ public MyDrools(String groupId, String artifactId, String version,
+ List<TopicCoderFilterConfiguration> decoderConfigurations,
+ List<TopicCoderFilterConfiguration> encoderConfigurations) {
+
+ super(groupId, artifactId, version, decoderConfigurations, encoderConfigurations);
+ }
+
+ @Override
+ protected EventProtocolCoder getCoderManager() {
+ return coderMgr;
+ }
+
+ @Override
+ protected OrderedServiceImpl<DroolsControllerFeatureApi> getDroolsProviders() {
+ return droolsProviders;
+ }
+
+ @Override
+ protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) {
+ when(container.getGroupId()).thenReturn(groupId);
+ when(container.getArtifactId()).thenReturn(artifactId);
+ when(container.getVersion()).thenReturn(version);
+
+ return container;
+ }
+ }
+}