summaryrefslogtreecommitdiffstats
path: root/feature-pooling-dmaap/src
diff options
context:
space:
mode:
Diffstat (limited to 'feature-pooling-dmaap/src')
-rw-r--r--feature-pooling-dmaap/src/assembly/assemble_zip.xml76
-rw-r--r--feature-pooling-dmaap/src/main/feature/config/feature-pooling-dmaap.properties87
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java33
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java232
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java396
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java50
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java50
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java132
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java646
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java149
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/Serializer.java123
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java204
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java51
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Identification.java40
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Leader.java69
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Message.java78
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java67
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Offline.java40
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Query.java39
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java269
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java33
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java80
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java399
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java204
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StartState.java98
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/State.java372
-rw-r--r--feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java36
-rw-r--r--feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi1
-rw-r--r--feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi1
-rw-r--r--feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi1
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java319
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java809
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java1040
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java35
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java35
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java547
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java994
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java191
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java84
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/feature-pooling-dmaap.properties46
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java360
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java58
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java73
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java73
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java81
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java37
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java37
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java250
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java113
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java470
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java97
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java121
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java393
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java444
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java184
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java465
-rw-r--r--feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java282
-rw-r--r--feature-pooling-dmaap/src/test/resources/logback-test.xml36
58 files changed, 0 insertions, 11730 deletions
diff --git a/feature-pooling-dmaap/src/assembly/assemble_zip.xml b/feature-pooling-dmaap/src/assembly/assemble_zip.xml
deleted file mode 100644
index 9908a2b9..00000000
--- a/feature-pooling-dmaap/src/assembly/assemble_zip.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<!--
- ============LICENSE_START=======================================================
- feature-pooling-dmaap
- ================================================================================
- Copyright (C) 2018 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=========================================================
- -->
-
-<!-- Defines how we build the .zip file which is our distribution. -->
-
-<assembly
- xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
- <id>feature-pooling-dmaap</id>
- <formats>
- <format>zip</format>
- </formats>
-
- <!-- we want "system" and related files right at the root level as this
- file is suppose to be unzip on top of a karaf distro. -->
- <includeBaseDirectory>false</includeBaseDirectory>
-
- <fileSets>
- <fileSet>
- <directory>target</directory>
- <outputDirectory>lib/feature</outputDirectory>
- <includes>
- <include>feature-pooling-dmaap-${project.version}.jar</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>target/assembly/lib</directory>
- <outputDirectory>lib/dependencies</outputDirectory>
- <includes>
- <include>*.jar</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>src/main/feature/config</directory>
- <outputDirectory>config</outputDirectory>
- <fileMode>0644</fileMode>
- <excludes/>
- </fileSet>
- <fileSet>
- <directory>src/main/feature/bin</directory>
- <outputDirectory>bin</outputDirectory>
- <fileMode>0744</fileMode>
- <excludes/>
- </fileSet>
- <fileSet>
- <directory>src/main/feature/db</directory>
- <outputDirectory>db</outputDirectory>
- <fileMode>0744</fileMode>
- <excludes/>
- </fileSet>
- <fileSet>
- <directory>src/main/feature/install</directory>
- <outputDirectory>install</outputDirectory>
- <fileMode>0744</fileMode>
- <excludes/>
- </fileSet>
- </fileSets>
-</assembly>
diff --git a/feature-pooling-dmaap/src/main/feature/config/feature-pooling-dmaap.properties b/feature-pooling-dmaap/src/main/feature/config/feature-pooling-dmaap.properties
deleted file mode 100644
index 59c4b472..00000000
--- a/feature-pooling-dmaap/src/main/feature/config/feature-pooling-dmaap.properties
+++ /dev/null
@@ -1,87 +0,0 @@
-###
-# ============LICENSE_START=======================================================
-# feature-pooling-dmaap
-# ================================================================================
-# Copyright (C) 2018-2020 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=========================================================
-###
-
-# In general, the feature-specific properties begin with "pooling",
-# and they may be made specific to a controller by prepending with
-# "pooling.<controller-name>", instead.
-#
-# The available properties and their default values are shown below.
-
-# Whether or not the feature is enabled.
-#pooling.enabled=false
-
-# The internal DMaaP topic used by a controller. Note: the controller
-# name is required for this property.
-#pooling.<controller-name>.topic =
-
-# Maximum number of events to retain in the queue while a new host waits
-# to be assigned work.
-#pooling.offline.queue.limit=1000
-
-# Maximum age, in milliseconds, of events to be retained in the queue.
-# Events older than this are discarded.
-#pooling.offline.queue.age.milliseconds=60000
-
-# Time, in milliseconds, to wait for an "Offline" message to be published
-# to DMaaP before the connection may be closed.
-#pooling.offline.publish.wait.milliseconds=3000
-
-# Time, in milliseconds, to wait for this host's initial heart beat. This
-# is used to verify connectivity to the internal DMaaP topic.
-#pooling.start.heartbeat.milliseconds=100000
-
-# Time, in milliseconds, to wait before attempting to re-active this
-# host when it was not assigned any work.
-#pooling.reactivate.milliseconds=50000
-
-# Time, in milliseconds, to wait for other hosts to identify themselves
-# when this host is started.
-#pooling.identification.milliseconds=50000
-
-# Time, in milliseconds, to wait for heart beats from this host, or its
-# predecessor, during the active state.
-#pooling.active.heartbeat.milliseconds=50000
-
-# Time, in milliseconds, to wait between heart beat generations.
-#pooling.inter.heartbeat.milliseconds=15000
-
-# Topic used for inter-host communication for a particular controller
-# pooling.<controller-name>.topic=XXX
-
-# Each controller that is enabled should have its own topic and the
-# corresponding dmaap.xxx properties. However, for now, just assume that
-# the usecases features will not both be enabled at the same time.
-
-pooling.usecases.enabled=true
-pooling.usecases.topic=${env:POOLING_TOPIC}
-
-# the list of sources and sinks should be identical
-dmaap.source.topics=POOLING_TOPIC
-dmaap.sink.topics=POOLING_TOPIC
-
-dmaap.source.topics.POOLING_TOPIC.servers=${env:DMAAP_SERVERS}
-dmaap.source.topics.POOLING_TOPIC.effectiveTopic=${env:POOLING_TOPIC}
-dmaap.source.topics.POOLING_TOPIC.apiKey=
-dmaap.source.topics.POOLING_TOPIC.apiSecret=
-
-dmaap.sink.topics.POOLING_TOPIC.servers=${env:DMAAP_SERVERS}
-dmaap.sink.topics.POOLING_TOPIC.effectiveTopic=${env:POOLING_TOPIC}
-dmaap.sink.topics.POOLING_TOPIC.apiKey=
-dmaap.sink.topics.POOLING_TOPIC.apiSecret=
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java
deleted file mode 100644
index f0d3b267..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-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.pooling;
-
-/**
- * A scheduled task that can be cancelled.
- */
-@FunctionalInterface
-public interface CancellableScheduledTask {
-
- /**
- * Cancels the scheduled task.
- */
- void cancel();
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java
deleted file mode 100644
index c0358f65..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling;
-
-import java.util.List;
-import lombok.Getter;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Manages the internal DMaaP topic. Assumes all topics are managed by
- * {@link TopicEndpoint#manager}.
- */
-public class DmaapManager {
-
- private static final Logger logger = LoggerFactory.getLogger(DmaapManager.class);
-
- /**
- * Name of the DMaaP topic.
- */
- @Getter
- private final String topic;
-
- /**
- * Topic source whose filter is to be manipulated.
- */
- private final TopicSource topicSource;
-
- /**
- * Where to publish messages.
- */
- private final TopicSink topicSink;
-
- /**
- * {@code True} if the consumer is running, {@code false} otherwise.
- */
- private boolean consuming = false;
-
- /**
- * {@code True} if the publisher is running, {@code false} otherwise.
- */
- private boolean publishing = false;
-
- /**
- * Constructs the manager, but does not start the source or sink.
- *
- * @param topic name of the internal DMaaP topic
- * @throws PoolingFeatureException if an error occurs
- */
- public DmaapManager(String topic) throws PoolingFeatureException {
-
- logger.info("initializing bus for topic {}", topic);
-
- try {
- this.topic = topic;
-
- this.topicSource = findTopicSource();
- this.topicSink = findTopicSink();
-
- } catch (IllegalArgumentException e) {
- logger.error("failed to attach to topic {}", topic);
- throw new PoolingFeatureException(e);
- }
- }
-
- /**
- * Finds the topic source associated with the internal DMaaP topic.
- *
- * @return the topic source
- * @throws PoolingFeatureException if the source doesn't exist or is not filterable
- */
- private TopicSource findTopicSource() throws PoolingFeatureException {
- for (TopicSource src : getTopicSources()) {
- if (topic.equals(src.getTopic())) {
- return src;
- }
- }
-
- throw new PoolingFeatureException("missing topic source " + topic);
- }
-
- /**
- * Finds the topic sink associated with the internal DMaaP topic.
- *
- * @return the topic sink
- * @throws PoolingFeatureException if the sink doesn't exist
- */
- private TopicSink findTopicSink() throws PoolingFeatureException {
- for (TopicSink sink : getTopicSinks()) {
- if (topic.equals(sink.getTopic())) {
- return sink;
- }
- }
-
- throw new PoolingFeatureException("missing topic sink " + topic);
- }
-
- /**
- * Starts the publisher, if it isn't already running.
- */
- public void startPublisher() {
- if (publishing) {
- return;
- }
-
- logger.info("start publishing to topic {}", topic);
- publishing = true;
- }
-
- /**
- * Stops the publisher.
- *
- * @param waitMs time, in milliseconds, to wait for the sink to transmit any queued messages and
- * close
- */
- public void stopPublisher(long waitMs) {
- if (!publishing) {
- return;
- }
-
- /*
- * Give the sink a chance to transmit messages in the queue. It would be better if "waitMs"
- * could be passed to sink.stop(), but that isn't an option at this time.
- */
- try {
- Thread.sleep(waitMs);
-
- } catch (InterruptedException e) {
- logger.warn("message transmission stopped due to {}", e.getMessage());
- Thread.currentThread().interrupt();
- }
-
- logger.info("stop publishing to topic {}", topic);
- publishing = false;
- }
-
- /**
- * Starts the consumer, if it isn't already running.
- *
- * @param listener listener to register with the source
- */
- public void startConsumer(TopicListener listener) {
- if (consuming) {
- return;
- }
-
- logger.info("start consuming from topic {}", topic);
- topicSource.register(listener);
- consuming = true;
- }
-
- /**
- * Stops the consumer.
- *
- * @param listener listener to unregister with the source
- */
- public void stopConsumer(TopicListener listener) {
- if (!consuming) {
- return;
- }
-
- logger.info("stop consuming from topic {}", topic);
- consuming = false;
- topicSource.unregister(listener);
- }
-
- /**
- * Publishes a message to the sink.
- *
- * @param msg message to be published
- * @throws PoolingFeatureException if an error occurs or the publisher isn't running
- */
- public void publish(String msg) throws PoolingFeatureException {
- if (!publishing) {
- throw new PoolingFeatureException(new IllegalStateException("no topic sink " + topic));
- }
-
- try {
- if (!topicSink.send(msg)) {
- throw new PoolingFeatureException("failed to send to topic sink " + topic);
- }
-
- } catch (IllegalStateException e) {
- throw new PoolingFeatureException("cannot send to topic sink " + topic, e);
- }
- }
-
- /*
- * The remaining methods may be overridden by junit tests.
- */
-
- /**
- * Get topic source.
- *
- * @return the topic sources
- */
- protected List<TopicSource> getTopicSources() {
- return TopicEndpointManager.getManager().getTopicSources();
- }
-
- /**
- * Get topic sinks.
- *
- * @return the topic sinks
- */
- protected List<TopicSink> getTopicSinks() {
- return TopicEndpointManager.getManager().getTopicSinks();
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java
deleted file mode 100644
index 5c61fb85..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling;
-
-import java.util.List;
-import java.util.Properties;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
-import lombok.AccessLevel;
-import lombok.Getter;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.common.utils.properties.SpecProperties;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.features.DroolsControllerFeatureApi;
-import org.onap.policy.drools.features.PolicyControllerFeatureApi;
-import org.onap.policy.drools.features.PolicyEngineFeatureApi;
-import org.onap.policy.drools.persistence.SystemPersistenceConstants;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyControllerConstants;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.onap.policy.drools.util.FeatureEnabledChecker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Controller/session pooling. Multiple hosts may be launched, all servicing the same
- * controllers/sessions. When this feature is enabled, the requests are divided across the different
- * hosts, instead of all running on a single, active host.
- *
- * <p>With each controller, there is an
- * associated DMaaP topic that is used for internal communication between the different hosts
- * serving the controller.
- */
-public class PoolingFeature implements PolicyEngineFeatureApi, PolicyControllerFeatureApi, DroolsControllerFeatureApi {
-
- private static final Logger logger = LoggerFactory.getLogger(PoolingFeature.class);
-
- /**
- * ID of this host.
- */
- @Getter
- private final String host;
-
- /**
- * Entire set of feature properties, including those specific to various controllers.
- */
- private Properties featProps = null;
-
- /**
- * Maps a controller name to its associated manager.
- */
- private final ConcurrentHashMap<String, PoolingManagerImpl> ctlr2pool = new ConcurrentHashMap<>(107);
-
- /**
- * Decremented each time a manager enters the Active state. Used by junit tests.
- */
- @Getter(AccessLevel.PROTECTED)
- private final CountDownLatch activeLatch = new CountDownLatch(1);
-
- /**
- * Topic names passed to beforeOffer(), which are saved for when the beforeInsert() is
- * called later. As multiple threads can be active within the methods at the same
- * time, we must keep this in thread local storage.
- */
- private ThreadLocal<String> offerTopics = new ThreadLocal<>();
-
- /**
- * Constructor.
- */
- public PoolingFeature() {
- super();
-
- this.host = UUID.randomUUID().toString();
- }
-
- @Override
- public int getSequenceNumber() {
- return 0;
- }
-
- @Override
- public boolean beforeStart(PolicyEngine engine) {
- logger.info("initializing {}", PoolingProperties.FEATURE_NAME);
- featProps = getProperties(PoolingProperties.FEATURE_NAME);
-
- // remove any generic pooling topic - always use controller-specific property
- featProps.remove(PoolingProperties.POOLING_TOPIC);
-
- initTopicSources(featProps);
- initTopicSinks(featProps);
-
- return false;
- }
-
- @Override
- public boolean beforeStart(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.beforeStart();
- return false;
- });
- }
-
- /**
- * Adds the controller and a new pooling manager to {@link #ctlr2pool}.
- *
- * @throws PoolingFeatureRtException if an error occurs
- */
- @Override
- public boolean afterCreate(PolicyController controller) {
-
- if (featProps == null) {
- logger.error("pooling feature properties have not been loaded");
- throw new PoolingFeatureRtException(new IllegalStateException("missing pooling feature properties"));
- }
-
- String name = controller.getName();
-
- var specProps = new SpecProperties(PoolingProperties.PREFIX, name, featProps);
-
- if (FeatureEnabledChecker.isFeatureEnabled(specProps, PoolingProperties.FEATURE_ENABLED)) {
- try {
- // get & validate the properties
- var props = new PoolingProperties(name, featProps);
-
- logger.info("pooling enabled for {}", name);
- ctlr2pool.computeIfAbsent(name, xxx -> makeManager(host, controller, props, activeLatch));
-
- } catch (PropertyException e) {
- logger.error("pooling disabled due to exception for {}", name);
- throw new PoolingFeatureRtException(e);
- }
-
- } else {
- logger.info("pooling disabled for {}", name);
- }
-
-
- return false;
- }
-
- @Override
- public boolean afterStart(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.afterStart();
- return false;
- });
- }
-
- @Override
- public boolean beforeStop(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.beforeStop();
- return false;
- });
- }
-
- @Override
- public boolean afterStop(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.afterStop();
- return false;
- });
- }
-
- @Override
- public boolean afterShutdown(PolicyController controller) {
- return commonShutdown(controller);
- }
-
- @Override
- public boolean afterHalt(PolicyController controller) {
- return commonShutdown(controller);
- }
-
- private boolean commonShutdown(PolicyController controller) {
- deleteManager(controller);
- return false;
- }
-
- @Override
- public boolean beforeLock(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.beforeLock();
- return false;
- });
- }
-
- @Override
- public boolean afterUnlock(PolicyController controller) {
- return doManager(controller, mgr -> {
- mgr.afterUnlock();
- return false;
- });
- }
-
- @Override
- public boolean beforeOffer(PolicyController controller, CommInfrastructure protocol, String topic2, String event) {
- /*
- * As this is invoked a lot, we'll directly call the manager's method instead of using the
- * functional interface via doManager().
- */
- PoolingManagerImpl mgr = ctlr2pool.get(controller.getName());
- if (mgr == null) {
- return false;
- }
-
- if (mgr.beforeOffer(topic2, event)) {
- return true;
- }
-
- offerTopics.set(topic2);
- return false;
- }
-
- @Override
- public boolean beforeInsert(DroolsController droolsController, Object fact) {
-
- String topic = offerTopics.get();
- if (topic == null) {
- logger.warn("missing arguments for feature-pooling-dmaap in beforeInsert");
- return false;
- }
-
- PolicyController controller;
- try {
- controller = getController(droolsController);
-
- } catch (IllegalArgumentException | IllegalStateException e) {
- logger.warn("cannot get controller for {} {}", droolsController.getGroupId(),
- droolsController.getArtifactId(), e);
- return false;
- }
-
-
- if (controller == null) {
- logger.warn("cannot determine controller for {} {}", droolsController.getGroupId(),
- droolsController.getArtifactId());
- return false;
- }
-
- /*
- * As this is invoked a lot, we'll directly call the manager's method instead of using the
- * functional interface via doManager().
- */
- PoolingManagerImpl mgr = ctlr2pool.get(controller.getName());
- if (mgr == null) {
- return false;
- }
-
- return mgr.beforeInsert(topic, fact);
- }
-
- @Override
- public boolean afterOffer(PolicyController controller, CommInfrastructure protocol, String topic, String event,
- boolean success) {
-
- // clear any stored arguments
- offerTopics.remove();
-
- return false;
- }
-
- /**
- * Executes a function using the manager associated with the controller. Catches any exceptions
- * from the function and re-throws it as a runtime exception.
- *
- * @param controller controller
- * @param func function to be executed
- * @return {@code true} if the function handled the request, {@code false} otherwise
- * @throws PoolingFeatureRtException if an error occurs
- */
- private boolean doManager(PolicyController controller, MgrFunc func) {
- PoolingManagerImpl mgr = ctlr2pool.get(controller.getName());
- if (mgr == null) {
- return false;
- }
-
- try {
- return func.apply(mgr);
-
- } catch (PoolingFeatureException e) {
- throw new PoolingFeatureRtException(e);
- }
- }
-
- /**
- * Deletes the manager associated with a controller.
- *
- * @param controller controller
- * @throws PoolingFeatureRtException if an error occurs
- */
- private void deleteManager(PolicyController controller) {
-
- String name = controller.getName();
- logger.info("remove feature-pool-dmaap manager for {}", name);
-
- ctlr2pool.remove(name);
- }
-
- /**
- * Function that operates on a manager.
- */
- @FunctionalInterface
- private static interface MgrFunc {
-
- /**
- * Apply.
- *
- * @param mgr manager
- * @return {@code true} if the request was handled by the manager, {@code false} otherwise
- * @throws PoolingFeatureException feature exception
- */
- boolean apply(PoolingManagerImpl mgr) throws PoolingFeatureException;
- }
-
- /*
- * The remaining methods may be overridden by junit tests.
- */
-
- /**
- * Get properties.
- *
- * @param featName feature name
- * @return the properties for the specified feature
- */
- protected Properties getProperties(String featName) {
- return SystemPersistenceConstants.getManager().getProperties(featName);
- }
-
- /**
- * Makes a pooling manager for a controller.
- *
- * @param host name/uuid of this host
- * @param controller controller
- * @param props properties to use to configure the manager
- * @param activeLatch decremented when the manager goes Active
- * @return a new pooling manager
- */
- protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
- return new PoolingManagerImpl(host, controller, props, activeLatch);
- }
-
- /**
- * Gets the policy controller associated with a drools controller.
- *
- * @param droolsController drools controller
- * @return the policy controller associated with a drools controller
- */
- protected PolicyController getController(DroolsController droolsController) {
- return PolicyControllerConstants.getFactory().get(droolsController);
- }
-
- /**
- * Initializes the topic sources.
- *
- * @param props properties used to configure the topics
- * @return the topic sources
- */
- protected List<TopicSource> initTopicSources(Properties props) {
- return TopicEndpointManager.getManager().addTopicSources(props);
- }
-
- /**
- * Initializes the topic sinks.
- *
- * @param props properties used to configure the topics
- * @return the topic sinks
- */
- protected List<TopicSink> initTopicSinks(Properties props) {
- return TopicEndpointManager.getManager().addTopicSinks(props);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java
deleted file mode 100644
index c3c81879..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling;
-
-/**
- * Exception thrown by the pooling feature.
- */
-public class PoolingFeatureException extends Exception {
- private static final long serialVersionUID = 1L;
-
- public PoolingFeatureException() {
- super();
- }
-
- public PoolingFeatureException(String message) {
- super(message);
- }
-
- public PoolingFeatureException(Throwable cause) {
- super(cause);
- }
-
- public PoolingFeatureException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public PoolingFeatureException(String message, Throwable cause, boolean enableSuppression,
- boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java
deleted file mode 100644
index 6fdb6c69..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling;
-
-/**
- * A runtime exception thrown by the pooling feature.
- */
-public class PoolingFeatureRtException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public PoolingFeatureRtException() {
- super();
- }
-
- public PoolingFeatureRtException(String message) {
- super(message);
- }
-
- public PoolingFeatureRtException(Throwable cause) {
- super(cause);
- }
-
- public PoolingFeatureRtException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public PoolingFeatureRtException(String message, Throwable cause, boolean enableSuppression,
- boolean writableStackTrace) {
- super(message, cause, enableSuppression, writableStackTrace);
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java
deleted file mode 100644
index cc8e3a4d..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2020 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.pooling;
-
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.state.State;
-import org.onap.policy.drools.pooling.state.StateTimerTask;
-
-/**
- * Pooling manager for a single PolicyController.
- */
-public interface PoolingManager {
-
- /**
- * Gets the properties used to configure the manager.
- *
- * @return pooling properties
- */
- PoolingProperties getProperties();
-
- /**
- * Gets the host id.
- *
- * @return the host id
- */
- String getHost();
-
- /**
- * Gets the name of the internal DMaaP topic used by this manager to communicate with
- * its other hosts.
- *
- * @return the name of the internal DMaaP topic
- */
- String getTopic();
-
- /**
- * Starts distributing requests according to the given bucket assignments.
- *
- * @param assignments must <i>not</i> be {@code null}
- */
- void startDistributing(BucketAssignments assignments);
-
- /**
- * Gets the current bucket assignments.
- *
- * @return the current bucket assignments, or {@code null} if no assignments have been
- * made
- */
- BucketAssignments getAssignments();
-
- /**
- * Publishes a message to the internal topic on the administrative channel.
- *
- * @param msg message to be published
- */
- void publishAdmin(Message msg);
-
- /**
- * Publishes a message to the internal topic on a particular channel.
- *
- * @param channel channel on which the message should be published
- * @param msg message to be published
- */
- void publish(String channel, Message msg);
-
- /**
- * Schedules a timer to fire after a delay.
- *
- * @param delayMs delay, in milliseconds
- * @param task task
- * @return a new scheduled task
- */
- CancellableScheduledTask schedule(long delayMs, StateTimerTask task);
-
- /**
- * Schedules a timer to fire repeatedly.
- *
- * @param initialDelayMs initial delay, in milliseconds
- * @param delayMs delay, in milliseconds
- * @param task task
- * @return a new scheduled task
- */
- CancellableScheduledTask scheduleWithFixedDelay(long initialDelayMs, long delayMs, StateTimerTask task);
-
- /**
- * Transitions to the "start" state.
- *
- * @return the new state
- */
- State goStart();
-
- /**
- * Transitions to the "query" state.
- *
- * @return the new state
- */
- State goQuery();
-
- /**
- * Transitions to the "active" state.
- *
- * @return the new state
- */
- State goActive();
-
- /**
- * Transitions to the "inactive" state.
- *
- * @return the new state
- */
- State goInactive();
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java
deleted file mode 100644
index a50997c2..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java
+++ /dev/null
@@ -1,646 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling;
-
-import com.google.gson.JsonParseException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import lombok.Getter;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.state.ActiveState;
-import org.onap.policy.drools.pooling.state.IdleState;
-import org.onap.policy.drools.pooling.state.InactiveState;
-import org.onap.policy.drools.pooling.state.QueryState;
-import org.onap.policy.drools.pooling.state.StartState;
-import org.onap.policy.drools.pooling.state.State;
-import org.onap.policy.drools.pooling.state.StateTimerTask;
-import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
-import org.onap.policy.drools.system.PolicyController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Implementation of a {@link PoolingManager}. Until bucket assignments have been made,
- * events coming from external topics are saved in a queue for later processing. Once
- * assignments are made, the saved events are processed. In addition, while the controller
- * is locked, events are still forwarded to other hosts and bucket assignments are still
- * updated, based on any {@link Leader} messages that it receives.
- */
-public class PoolingManagerImpl implements PoolingManager, TopicListener {
-
- private static final Logger logger = LoggerFactory.getLogger(PoolingManagerImpl.class);
-
- /**
- * Maximum number of times a message can be forwarded.
- */
- public static final int MAX_HOPS = 5;
-
- /**
- * ID of this host.
- */
- @Getter
- private final String host;
-
- /**
- * Properties with which this was configured.
- */
- @Getter
- private final PoolingProperties properties;
-
- /**
- * Associated controller.
- */
- private final PolicyController controller;
-
- /**
- * Decremented each time the manager enters the Active state. Used by junit tests.
- */
- private final CountDownLatch activeLatch;
-
- /**
- * Used to encode & decode request objects received from & sent to a rule engine.
- */
- private final Serializer serializer;
-
- /**
- * Internal DMaaP topic used by this controller.
- */
- @Getter
- private final String topic;
-
- /**
- * Manager for the internal DMaaP topic.
- */
- private final DmaapManager dmaapMgr;
-
- /**
- * Lock used while updating {@link #current}. In general, public methods must use
- * this, while private methods assume the lock is already held.
- */
- private final Object curLocker = new Object();
-
- /**
- * Current state.
- *
- * <p>This uses a finite state machine, wherein the state object contains all of the data
- * relevant to that state. Each state object has a process() method, specific to each
- * type of {@link Message} subclass. The method returns the next state object, or
- * {@code null} if the state is to remain the same.
- */
- private State current;
-
- /**
- * Current bucket assignments or {@code null}.
- */
- @Getter
- private BucketAssignments assignments = null;
-
- /**
- * Pool used to execute timers.
- */
- private ScheduledThreadPoolExecutor scheduler = null;
-
- /**
- * Constructs the manager, initializing all of the data structures.
- *
- * @param host name/uuid of this host
- * @param controller controller with which this is associated
- * @param props feature properties specific to the controller
- * @param activeLatch latch to be decremented each time the manager enters the Active
- * state
- */
- public PoolingManagerImpl(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
- this.host = host;
- this.controller = controller;
- this.properties = props;
- this.activeLatch = activeLatch;
-
- try {
- this.serializer = new Serializer();
- this.topic = props.getPoolingTopic();
- this.dmaapMgr = makeDmaapManager(props.getPoolingTopic());
- this.current = new IdleState(this);
-
- logger.info("allocating host {} to controller {} for topic {}", host, controller.getName(), topic);
-
- } catch (ClassCastException e) {
- logger.error("not a topic listener, controller {}", controller.getName());
- throw new PoolingFeatureRtException(e);
-
- } catch (PoolingFeatureException e) {
- logger.error("failed to attach internal DMaaP topic to controller {}", controller.getName());
- throw new PoolingFeatureRtException(e);
- }
- }
-
- /**
- * Should only be used by junit tests.
- *
- * @return the current state
- */
- protected State getCurrent() {
- synchronized (curLocker) {
- return current;
- }
- }
-
- /**
- * Indicates that the controller is about to start. Starts the publisher for the
- * internal topic, and creates a thread pool for the timers.
- */
- public void beforeStart() {
- synchronized (curLocker) {
- if (scheduler == null) {
- dmaapMgr.startPublisher();
-
- logger.debug("make scheduler thread for topic {}", getTopic());
- scheduler = makeScheduler();
-
- /*
- * Only a handful of timers at any moment, thus we can afford to take the
- * time to remove them when they're cancelled.
- */
- scheduler.setRemoveOnCancelPolicy(true);
- scheduler.setMaximumPoolSize(1);
- scheduler.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
- scheduler.setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
- }
- }
- }
-
- /**
- * Indicates that the controller has successfully started. Starts the consumer for the
- * internal topic, enters the {@link StartState}, and sets the filter for the initial
- * state.
- */
- public void afterStart() {
- synchronized (curLocker) {
- if (current instanceof IdleState) {
- dmaapMgr.startConsumer(this);
- changeState(new StartState(this));
- }
- }
- }
-
- /**
- * Indicates that the controller is about to stop. Stops the consumer, the scheduler,
- * and the current state.
- */
- public void beforeStop() {
- ScheduledThreadPoolExecutor sched;
-
- synchronized (curLocker) {
- sched = scheduler;
- scheduler = null;
-
- if (!(current instanceof IdleState)) {
- changeState(new IdleState(this));
- dmaapMgr.stopConsumer(this);
- publishAdmin(new Offline(getHost()));
- }
-
- assignments = null;
- }
-
- if (sched != null) {
- logger.debug("stop scheduler for topic {}", getTopic());
- sched.shutdownNow();
- }
- }
-
- /**
- * Indicates that the controller has stopped. Stops the publisher and logs a warning
- * if any events are still in the queue.
- */
- public void afterStop() {
- synchronized (curLocker) {
- /*
- * stop the publisher, but allow time for any Offline message to be
- * transmitted
- */
- dmaapMgr.stopPublisher(properties.getOfflinePubWaitMs());
- }
- }
-
- /**
- * Indicates that the controller is about to be locked. Enters the idle state, as all
- * it will be doing is forwarding messages.
- */
- public void beforeLock() {
- logger.info("locking manager for topic {}", getTopic());
-
- synchronized (curLocker) {
- changeState(new IdleState(this));
- }
- }
-
- /**
- * Indicates that the controller has been unlocked. Enters the start state, if the
- * controller is running.
- */
- public void afterUnlock() {
- logger.info("unlocking manager for topic {}", getTopic());
-
- synchronized (curLocker) {
- if (controller.isAlive() && current instanceof IdleState && scheduler != null) {
- changeState(new StartState(this));
- }
- }
- }
-
- /**
- * Changes the finite state machine to a new state, provided the new state is not
- * {@code null}.
- *
- * @param newState new state, or {@code null} if to remain unchanged
- */
- private void changeState(State newState) {
- if (newState != null) {
- current.cancelTimers();
- current = newState;
-
- newState.start();
- }
- }
-
- @Override
- public CancellableScheduledTask schedule(long delayMs, StateTimerTask task) {
- // wrap the task in a TimerAction and schedule it
- ScheduledFuture<?> fut = scheduler.schedule(new TimerAction(task), delayMs, TimeUnit.MILLISECONDS);
-
- // wrap the future in a "CancellableScheduledTask"
- return () -> fut.cancel(false);
- }
-
- @Override
- public CancellableScheduledTask scheduleWithFixedDelay(long initialDelayMs, long delayMs, StateTimerTask task) {
- // wrap the task in a TimerAction and schedule it
- ScheduledFuture<?> fut = scheduler.scheduleWithFixedDelay(new TimerAction(task), initialDelayMs, delayMs,
- TimeUnit.MILLISECONDS);
-
- // wrap the future in a "CancellableScheduledTask"
- return () -> fut.cancel(false);
- }
-
- @Override
- public void publishAdmin(Message msg) {
- publish(Message.ADMIN, msg);
- }
-
- @Override
- public void publish(String channel, Message msg) {
- logger.info("publish {} to {} on topic {}", msg.getClass().getSimpleName(), channel, getTopic());
-
- msg.setChannel(channel);
-
- try {
- // ensure it's valid before we send it
- msg.checkValidity();
-
- String txt = serializer.encodeMsg(msg);
- dmaapMgr.publish(txt);
-
- } catch (JsonParseException e) {
- logger.error("failed to serialize message for topic {} channel {}", topic, channel, e);
-
- } catch (PoolingFeatureException e) {
- logger.error("failed to publish message for topic {} channel {}", topic, channel, e);
- }
- }
-
- /**
- * Handles an event from the internal topic.
- *
- * @param commType comm infrastructure
- * @param topic2 topic
- * @param event event
- */
- @Override
- public void onTopicEvent(CommInfrastructure commType, String topic2, String event) {
-
- if (event == null) {
- logger.error("null event on topic {}", topic);
- return;
- }
-
- synchronized (curLocker) {
- // it's on the internal topic
- handleInternal(event);
- }
- }
-
- /**
- * Called by the PolicyController before it offers the event to the DroolsController.
- * If the controller is locked, then it isn't processing events. However, they still
- * need to be forwarded, thus in that case, they are decoded and forwarded.
- *
- * <p>On the other hand, if the controller is not locked, then we just return immediately
- * and let {@link #beforeInsert(Object, String, String, Object) beforeInsert()} handle
- * it instead, as it already has the decoded message.
- *
- * @param topic2 topic
- * @param event event
- * @return {@code true} if the event was handled by the manager, {@code false} if it
- * must still be handled by the invoker
- */
- public boolean beforeOffer(String topic2, String event) {
-
- if (!controller.isLocked()) {
- // we should NOT intercept this message - let the invoker handle it
- return false;
- }
-
- return handleExternal(topic2, decodeEvent(topic2, event));
- }
-
- /**
- * Called by the DroolsController before it inserts the event into the rule engine.
- *
- * @param topic2 topic
- * @param event event, as an object
- * @return {@code true} if the event was handled by the manager, {@code false} if it
- * must still be handled by the invoker
- */
- public boolean beforeInsert(String topic2, Object event) {
- return handleExternal(topic2, event);
- }
-
- /**
- * Handles an event from an external topic.
- *
- * @param topic2 topic
- * @param event event, as an object, or {@code null} if it cannot be decoded
- * @return {@code true} if the event was handled by the manager, {@code false} if it
- * must still be handled by the invoker
- */
- private boolean handleExternal(String topic2, Object event) {
- if (event == null) {
- // no event - let the invoker handle it
- return false;
- }
-
- synchronized (curLocker) {
- return handleExternal(topic2, event, event.hashCode());
- }
- }
-
- /**
- * Handles an event from an external topic.
- *
- * @param topic2 topic
- * @param event event, as an object
- * @param eventHashCode event's hash code
- * @return {@code true} if the event was handled, {@code false} if the invoker should
- * handle it
- */
- private boolean handleExternal(String topic2, Object event, int eventHashCode) {
- if (assignments == null) {
- // no bucket assignments yet - handle locally
- logger.info("handle event locally for request {}", event);
-
- // we did NOT consume the event
- return false;
-
- } else {
- return handleEvent(topic2, event, eventHashCode);
- }
- }
-
- /**
- * Handles a {@link Forward} event, possibly forwarding it again.
- *
- * @param topic2 topic
- * @param event event, as an object
- * @param eventHashCode event's hash code
- * @return {@code true} if the event was handled, {@code false} if the invoker should
- * handle it
- */
- private boolean handleEvent(String topic2, Object event, int eventHashCode) {
- String target = assignments.getAssignedHost(eventHashCode);
-
- if (target == null) {
- /*
- * This bucket has no assignment - just discard the event
- */
- logger.warn("discarded event for unassigned bucket from topic {}", topic2);
- return true;
- }
-
- if (target.equals(host)) {
- /*
- * Message belongs to this host - allow the controller to handle it.
- */
- logger.info("handle local event for request {} from topic {}", event, topic2);
- return false;
- }
-
- // not our message, consume the event
- logger.warn("discarded event for host {} from topic {}", target, topic2);
- return true;
- }
-
- /**
- * Decodes an event from a String into an event Object.
- *
- * @param topic2 topic
- * @param event event
- * @return the decoded event object, or {@code null} if it can't be decoded
- */
- private Object decodeEvent(String topic2, String event) {
- DroolsController drools = controller.getDrools();
-
- // check if this topic has a decoder
-
- if (!canDecodeEvent(drools, topic2)) {
-
- logger.warn("{}: DECODING-UNSUPPORTED {}:{}:{}", drools, topic2, drools.getGroupId(),
- drools.getArtifactId());
- return null;
- }
-
- // decode
-
- try {
- return decodeEventWrapper(drools, topic2, event);
-
- } catch (UnsupportedOperationException | IllegalStateException | IllegalArgumentException e) {
- logger.debug("{}: DECODE FAILED: {} <- {} because of {}", drools, topic2, event, e.getMessage(), e);
- return null;
- }
- }
-
- /**
- * Handles an event from the internal topic. This uses reflection to identify the
- * appropriate process() method to invoke, based on the type of Message that was
- * decoded.
- *
- * @param event the serialized {@link Message} read from the internal topic
- */
- private void handleInternal(String event) {
- Class<?> clazz = null;
-
- try {
- Message msg = serializer.decodeMsg(event);
-
- // get the class BEFORE checking the validity
- clazz = msg.getClass();
-
- msg.checkValidity();
-
- var meth = current.getClass().getMethod("process", msg.getClass());
- changeState((State) meth.invoke(current, msg));
-
- } catch (JsonParseException e) {
- logger.warn("failed to decode message for topic {}", topic, e);
-
- } catch (NoSuchMethodException | SecurityException e) {
- logger.error("no processor for message {} for topic {}", clazz, topic, e);
-
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
- | PoolingFeatureException e) {
- logger.error("failed to process message {} for topic {}", clazz, topic, e);
- }
- }
-
- @Override
- public void startDistributing(BucketAssignments asgn) {
- synchronized (curLocker) {
- int sz = (asgn == null ? 0 : asgn.getAllHosts().size());
- logger.info("new assignments for {} hosts on topic {}", sz, getTopic());
- assignments = asgn;
- }
- }
-
- @Override
- public State goStart() {
- return new StartState(this);
- }
-
- @Override
- public State goQuery() {
- return new QueryState(this);
- }
-
- @Override
- public State goActive() {
- activeLatch.countDown();
- return new ActiveState(this);
- }
-
- @Override
- public State goInactive() {
- return new InactiveState(this);
- }
-
- /**
- * Action to run a timer task. Only runs the task if the machine is still in the state
- * that it was in when the timer was created.
- */
- private class TimerAction implements Runnable {
-
- /**
- * State of the machine when the timer was created.
- */
- private State origState;
-
- /**
- * Task to be executed.
- */
- private StateTimerTask task;
-
- /**
- * Constructor.
- *
- * @param task task to execute when this timer runs
- */
- public TimerAction(StateTimerTask task) {
- this.origState = current;
- this.task = task;
- }
-
- @Override
- public void run() {
- synchronized (curLocker) {
- if (current == origState) {
- changeState(task.fire());
- }
- }
- }
- }
-
- /**
- * Creates a DMaaP manager.
- *
- * @param topic name of the internal DMaaP topic
- * @return a new DMaaP manager
- * @throws PoolingFeatureException if an error occurs
- */
- protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
- return new DmaapManager(topic);
- }
-
- /**
- * Creates a scheduled thread pool.
- *
- * @return a new scheduled thread pool
- */
- protected ScheduledThreadPoolExecutor makeScheduler() {
- return new ScheduledThreadPoolExecutor(1);
- }
-
- /**
- * Determines if the event can be decoded.
- *
- * @param drools drools controller
- * @param topic topic on which the event was received
- * @return {@code true} if the event can be decoded, {@code false} otherwise
- */
- protected boolean canDecodeEvent(DroolsController drools, String topic) {
- return EventProtocolCoderConstants.getManager().isDecodingSupported(drools.getGroupId(), drools.getArtifactId(),
- topic);
- }
-
- /**
- * Decodes the event.
- *
- * @param drools drools controller
- * @param topic topic on which the event was received
- * @param event event text to be decoded
- * @return the decoded event
- * @throws IllegalArgumentException illegal argument
- * @throw UnsupportedOperationException unsupported operation
- * @throws IllegalStateException illegal state
- */
- protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
- return EventProtocolCoderConstants.getManager().decode(drools.getGroupId(), drools.getArtifactId(), topic,
- event);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java
deleted file mode 100644
index 08b2753f..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling;
-
-import java.util.Properties;
-import lombok.Getter;
-import lombok.Setter;
-import org.onap.policy.common.utils.properties.BeanConfigurator;
-import org.onap.policy.common.utils.properties.Property;
-import org.onap.policy.common.utils.properties.SpecProperties;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-
-/**
- * Properties used by the pooling feature, specific to a controller.
- */
-@Getter
-@Setter
-public class PoolingProperties {
-
- /**
- * The feature name, used to retrieve properties.
- */
- public static final String FEATURE_NAME = "feature-pooling-dmaap";
-
- /**
- * Feature properties all begin with this prefix.
- */
- public static final String PREFIX = "pooling.";
-
- public static final String FEATURE_ENABLED = PREFIX + "enabled";
- public static final String POOLING_TOPIC = PREFIX + "topic";
- public static final String OFFLINE_LIMIT = PREFIX + "offline.queue.limit";
- public static final String OFFLINE_AGE_MS = PREFIX + "offline.queue.age.milliseconds";
- public static final String OFFLINE_PUB_WAIT_MS = PREFIX + "offline.publish.wait.milliseconds";
- public static final String START_HEARTBEAT_MS = PREFIX + "start.heartbeat.milliseconds";
- public static final String REACTIVATE_MS = PREFIX + "reactivate.milliseconds";
- public static final String IDENTIFICATION_MS = PREFIX + "identification.milliseconds";
- public static final String ACTIVE_HEARTBEAT_MS = PREFIX + "active.heartbeat.milliseconds";
- public static final String INTER_HEARTBEAT_MS = PREFIX + "inter.heartbeat.milliseconds";
-
- /**
- * Type of item that the extractors will be extracting.
- */
- public static final String EXTRACTOR_TYPE = "requestId";
-
- /**
- * Prefix for extractor properties.
- */
- public static final String PROP_EXTRACTOR_PREFIX = "extractor." + EXTRACTOR_TYPE;
-
- /**
- * Properties from which this was constructed.
- */
- private Properties source;
-
- /**
- * Topic used for inter-host communication.
- */
- @Property(name = POOLING_TOPIC)
- private String poolingTopic;
-
- /**
- * Maximum number of events to retain in the queue while waiting for
- * buckets to be assigned.
- */
- @Property(name = OFFLINE_LIMIT, defaultValue = "1000")
- private int offlineLimit;
-
- /**
- * Maximum age, in milliseconds, of events to be retained in the queue.
- * Events older than this are discarded.
- */
- @Property(name = OFFLINE_AGE_MS, defaultValue = "60000")
- private long offlineAgeMs;
-
- /**
- * Time, in milliseconds, to wait for an "Offline" message to be published
- * to DMaaP.
- */
- @Property(name = OFFLINE_PUB_WAIT_MS, defaultValue = "3000")
- private long offlinePubWaitMs;
-
- /**
- * Time, in milliseconds, to wait for this host's heart beat during the
- * start-up state.
- */
- @Property(name = START_HEARTBEAT_MS, defaultValue = "100000")
- private long startHeartbeatMs;
-
- /**
- * Time, in milliseconds, to wait before attempting to re-active this
- * host when it has no bucket assignments.
- */
- @Property(name = REACTIVATE_MS, defaultValue = "50000")
- private long reactivateMs;
-
- /**
- * Time, in milliseconds, to wait for all Identification messages to
- * arrive during the query state.
- */
- @Property(name = IDENTIFICATION_MS, defaultValue = "50000")
- private long identificationMs;
-
- /**
- * Time, in milliseconds, to wait for heart beats from this host, or its
- * predecessor, during the active state.
- */
- @Property(name = ACTIVE_HEARTBEAT_MS, defaultValue = "50000")
- private long activeHeartbeatMs;
-
- /**
- * Time, in milliseconds, to wait between heart beat generations during
- * the active and start-up states.
- */
- @Property(name = INTER_HEARTBEAT_MS, defaultValue = "15000")
- private long interHeartbeatMs;
-
- /**
- * Constructor.
- *
- * @param controllerName the name of the controller
- * @param props set of properties used to configure this
- * @throws PropertyException if an error occurs
- *
- */
- public PoolingProperties(String controllerName, Properties props) throws PropertyException {
- source = props;
-
- new BeanConfigurator().configureFromProperties(this, new SpecProperties(PREFIX, controllerName, props));
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/Serializer.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/Serializer.java
deleted file mode 100644
index 15c98e0d..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/Serializer.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParseException;
-import java.util.HashMap;
-import java.util.Map;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-
-/**
- * Serialization helper functions.
- */
-public class Serializer {
-
- /**
- * The message type is stored in fields of this name within the JSON.
- */
- private static final String TYPE_FIELD = "type";
-
- /**
- * Used to encode & decode JSON messages sent & received, respectively, on the
- * internal DMaaP topic.
- */
- private final Gson gson = new Gson();
-
- /**
- * Maps a message subclass to its type.
- */
- private static final Map<Class<? extends Message>, String> class2type = new HashMap<>();
-
- /**
- * Maps a message type to the appropriate subclass.
- */
- private static final Map<String, Class<? extends Message>> type2class = new HashMap<>();
-
- static {
- class2type.put(Heartbeat.class, "heartbeat");
- class2type.put(Identification.class, "identification");
- class2type.put(Leader.class, "leader");
- class2type.put(Offline.class, "offline");
- class2type.put(Query.class, "query");
-
- class2type.forEach((clazz, type) -> type2class.put(type, clazz));
- }
-
- /**
- * Encodes a filter.
- *
- * @param filter filter to be encoded
- * @return the filter, serialized as a JSON string
- */
- public String encodeFilter(Map<String, Object> filter) {
- return gson.toJson(filter);
- }
-
- /**
- * Encodes a message.
- *
- * @param msg message to be encoded
- * @return the message, serialized as a JSON string
- */
- public String encodeMsg(Message msg) {
- JsonElement jsonEl = gson.toJsonTree(msg);
-
- String type = class2type.get(msg.getClass());
- if (type == null) {
- throw new JsonParseException("cannot serialize " + msg.getClass());
- }
-
- jsonEl.getAsJsonObject().addProperty(TYPE_FIELD, type);
-
- return gson.toJson(jsonEl);
- }
-
- /**
- * Decodes a JSON string into a Message.
- *
- * @param msg JSON string representing the message
- * @return the message
- */
- public Message decodeMsg(String msg) {
- JsonElement jsonEl = gson.fromJson(msg, JsonElement.class);
-
- JsonElement typeEl = jsonEl.getAsJsonObject().get(TYPE_FIELD);
- if (typeEl == null) {
- throw new JsonParseException("cannot deserialize " + Message.class
- + " because it does not contain a field named " + TYPE_FIELD);
-
- }
-
- Class<? extends Message> clazz = type2class.get(typeEl.getAsString());
- if (clazz == null) {
- throw new JsonParseException("cannot deserialize " + typeEl);
- }
-
- return gson.fromJson(jsonEl, clazz);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java
deleted file mode 100644
index 584edcec..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling.message;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Bucket assignments, which is simply an array of host names.
- */
-@Getter
-@Setter
-@NoArgsConstructor
-public class BucketAssignments {
-
- private static final Logger logger = LoggerFactory.getLogger(BucketAssignments.class);
-
- /**
- * The number of bits in the maximum number of buckets.
- */
- private static final int MAX_BUCKET_BITS = 10;
-
- /**
- * Maximum number of buckets. Must be a power of two.
- */
- public static final int MAX_BUCKETS = 1 << MAX_BUCKET_BITS;
-
- /**
- * Used to ensure that a hash code is not negative.
- */
- private static final int MAX_BUCKETS_MASK = MAX_BUCKETS - 1;
-
- /**
- * Identifies the host serving a particular bucket.
- */
- private String[] hostArray = null;
-
-
- /**
- * Constructor.
- *
- * @param hostArray maps a bucket number (i.e., array index) to a host. All values
- * must be non-null
- */
- public BucketAssignments(String[] hostArray) {
- this.hostArray = hostArray;
- }
-
- /**
- * Gets the leader, which is the host with the minimum UUID.
- *
- * @return the assignment leader
- */
- public String getLeader() {
- if (hostArray == null) {
- return null;
- }
-
- String leader = null;
-
- for (String host : hostArray) {
- if (host != null && (leader == null || host.compareTo(leader) < 0)) {
- leader = host;
- }
- }
-
- return leader;
-
- }
-
- /**
- * Determines if a host has an assignment.
- *
- * @param host host to be checked
- * @return {@code true} if the host has an assignment, {@code false} otherwise
- */
- public boolean hasAssignment(String host) {
- if (hostArray == null) {
- return false;
- }
-
- for (String host2 : hostArray) {
- if (host.equals(host2)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Gets all of the hosts that have an assignment.
- *
- * @return all of the hosts that have an assignment
- */
- public Set<String> getAllHosts() {
- Set<String> set = new HashSet<>();
- if (hostArray == null) {
- return set;
- }
-
- for (String host : hostArray) {
- if (host != null) {
- set.add(host);
- }
- }
-
- return set;
- }
-
- /**
- * Gets the host assigned to a given bucket.
- *
- * @param hashCode hash code of the item whose assignment is desired
- * @return the assigned host, or {@code null} if the item has no assigned host
- */
- public String getAssignedHost(int hashCode) {
- if (hostArray == null || hostArray.length == 0) {
- logger.error("no buckets have been assigned");
- return null;
- }
-
- return hostArray[(Math.abs(hashCode) & MAX_BUCKETS_MASK) % hostArray.length];
- }
-
- /**
- * Gets the number of buckets.
- *
- * @return the number of buckets
- */
- public int size() {
- return (hostArray != null ? hostArray.length : 0);
- }
-
- /**
- * Checks the validity of the assignments, verifying that all buckets have been
- * assigned to a host.
- *
- * @throws PoolingFeatureException if the assignments are invalid
- */
- public void checkValidity() throws PoolingFeatureException {
- if (hostArray == null || hostArray.length == 0) {
- throw new PoolingFeatureException("missing hosts in message bucket assignments");
- }
-
- if (hostArray.length > MAX_BUCKETS) {
- throw new PoolingFeatureException("too many hosts in message bucket assignments");
- }
-
- for (var x = 0; x < hostArray.length; ++x) {
- if (hostArray[x] == null) {
- throw new PoolingFeatureException("bucket " + x + " has no assignment");
- }
- }
- }
-
- @Override
- public int hashCode() {
- final var prime = 31;
- var result = 1;
- result = prime * result + Arrays.hashCode(hostArray);
- return result;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- BucketAssignments other = (BucketAssignments) obj;
- return Arrays.equals(hostArray, other.hostArray);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java
deleted file mode 100644
index 0721fe7a..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling.message;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Heart beat message sent to self, or to the succeeding host.
- */
-@Getter
-@Setter
-@NoArgsConstructor
-public class Heartbeat extends Message {
-
- /**
- * Time, in milliseconds, when this was created.
- */
- private long timestampMs;
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- * @param timestampMs time, in milliseconds, associated with the message
- */
- public Heartbeat(String source, long timestampMs) {
- super(source);
-
- this.timestampMs = timestampMs;
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Identification.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Identification.java
deleted file mode 100644
index 2ca4dd75..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Identification.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling.message;
-
-import lombok.NoArgsConstructor;
-
-/**
- * Identifies the source host and the bucket assignments which it knows about.
- */
-@NoArgsConstructor
-public class Identification extends MessageWithAssignments {
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- * @param assignments assignments
- */
- public Identification(String source, BucketAssignments assignments) {
- super(source, assignments);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Leader.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Leader.java
deleted file mode 100644
index 239f7491..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Leader.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2019, 2021 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.pooling.message;
-
-import lombok.NoArgsConstructor;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-
-/**
- * Indicates that the "source" of this message is now the "lead" host.
- */
-@NoArgsConstructor
-public class Leader extends MessageWithAssignments {
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- * @param assignments assignments
- */
- public Leader(String source, BucketAssignments assignments) {
- super(source, assignments);
- }
-
- /**
- * Also verifies that buckets have been assigned and that the source is
- * indeed the leader.
- */
- @Override
- public void checkValidity() throws PoolingFeatureException {
-
- super.checkValidity();
-
- BucketAssignments assignments = getAssignments();
- if (assignments == null) {
- throw new PoolingFeatureException("missing message bucket assignments");
- }
-
- String leader = getSource();
-
- if (!assignments.hasAssignment(leader)) {
- throw new PoolingFeatureException("leader " + leader + " has no bucket assignments");
- }
-
- for (String host : assignments.getHostArray()) {
- if (host.compareTo(leader) < 0) {
- throw new PoolingFeatureException("invalid leader " + leader + ", should be " + host);
- }
- }
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Message.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Message.java
deleted file mode 100644
index 0154fc7c..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Message.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2019, 2021 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.pooling.message;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-
-/**
- * Messages sent on the internal topic.
- */
-@Getter
-@Setter
-@NoArgsConstructor
-public class Message {
-
- /**
- * Name of the administrative channel.
- */
- public static final String ADMIN = "_admin";
-
- /**
- * Host that originated the message.
- */
- private String source;
-
- /**
- * Channel on which the message is routed, which is either the target host
- * or {@link #ADMIN}.
- */
- private String channel;
-
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- */
- public Message(String source) {
- this.source = source;
- }
-
- /**
- * Checks the validity of the message, including verifying that required
- * fields are not missing.
- *
- * @throws PoolingFeatureException if the message is invalid
- */
- public void checkValidity() throws PoolingFeatureException {
- if (source == null || source.isEmpty()) {
- throw new PoolingFeatureException("missing message source");
- }
-
- if (channel == null || channel.isEmpty()) {
- throw new PoolingFeatureException("missing message channel");
- }
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java
deleted file mode 100644
index adf17b25..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2019, 2021 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.pooling.message;
-
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-
-/**
- * A Message that includes bucket assignments.
- */
-@NoArgsConstructor
-public class MessageWithAssignments extends Message {
-
- /**
- * Bucket assignments, as known by the source host.
- */
- @Getter
- @Setter
- private BucketAssignments assignments;
-
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- * @param assignments assignements
- */
- public MessageWithAssignments(String source, BucketAssignments assignments) {
- super(source);
-
- this.assignments = assignments;
- }
-
- /**
- * If there are any assignments, it verifies there validity.
- */
- @Override
- public void checkValidity() throws PoolingFeatureException {
-
- super.checkValidity();
-
- if (assignments != null) {
- assignments.checkValidity();
- }
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Offline.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Offline.java
deleted file mode 100644
index 7a3a3b47..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Offline.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling.message;
-
-import lombok.NoArgsConstructor;
-
-/**
- * Indicates that the source host is going offline and will be unable to process
- * any further requests.
- */
-@NoArgsConstructor
-public class Offline extends Message {
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- */
- public Offline(String source) {
- super(source);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Query.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Query.java
deleted file mode 100644
index d349a789..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Query.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling.message;
-
-import lombok.NoArgsConstructor;
-
-/**
- * Query the other hosts for their identification.
- */
-@NoArgsConstructor
-public class Query extends Message {
-
- /**
- * Constructor.
- *
- * @param source host on which the message originated
- */
- public Query(String source) {
- super(source);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java
deleted file mode 100644
index a53e7572..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020-2021 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.pooling.state;
-
-import java.util.Arrays;
-import java.util.TreeSet;
-import lombok.AccessLevel;
-import lombok.Getter;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The active state. In this state, this host has one more more bucket assignments and
- * processes any events associated with one of its buckets. Other events are forwarded to
- * appropriate target hosts.
- */
-@Getter(AccessLevel.PROTECTED)
-public class ActiveState extends ProcessingState {
-
- private static final Logger logger = LoggerFactory.getLogger(ActiveState.class);
-
- /**
- * Set of hosts that have been assigned a bucket.
- */
- @Getter(AccessLevel.NONE)
- private final TreeSet<String> assigned = new TreeSet<>();
-
- /**
- * Host that comes after this host, or {@code null} if it has no successor.
- */
- private String succHost = null;
-
- /**
- * Host that comes before this host, or "" if it has no predecessor.
- */
- private String predHost = "";
-
- /**
- * {@code True} if we saw this host's heart beat since the last check, {@code false}
- * otherwise.
- */
- private boolean myHeartbeatSeen = false;
-
- /**
- * {@code True} if we saw the predecessor's heart beat since the last check,
- * {@code false} otherwise.
- */
- private boolean predHeartbeatSeen = false;
-
-
- /**
- * Constructor.
- *
- * @param mgr pooling manager
- */
- public ActiveState(PoolingManager mgr) {
- super(mgr, mgr.getAssignments().getLeader());
-
- assigned.addAll(Arrays.asList(mgr.getAssignments().getHostArray()));
-
- detmNeighbors();
- }
-
- /**
- * Determine this host's neighbors based on the order of the host UUIDs. Updates
- * {@link #succHost} and {@link #predHost}.
- */
- private void detmNeighbors() {
- if (assigned.size() < 2) {
- logger.info("this host has no neighbors on topic {}", getTopic());
- /*
- * this host is the only one with any assignments - it has no neighbors
- */
- succHost = null;
- predHost = "";
- return;
- }
-
- if ((succHost = assigned.higher(getHost())) == null) {
- // wrapped around - successor is the first host in the set
- succHost = assigned.first();
- }
- logger.info("this host's successor is {} on topic {}", succHost, getTopic());
-
- if ((predHost = assigned.lower(getHost())) == null) {
- // wrapped around - predecessor is the last host in the set
- predHost = assigned.last();
- }
- logger.info("this host's predecessor is {} on topic {}", predHost, getTopic());
- }
-
- @Override
- public void start() {
- super.start();
- addTimers();
- genHeartbeat();
- }
-
- /**
- * Adds the timers.
- */
- private void addTimers() {
- logger.info("add timers");
-
- /*
- * heart beat generator
- */
- long genMs = getProperties().getInterHeartbeatMs();
-
- scheduleWithFixedDelay(genMs, genMs, () -> {
- genHeartbeat();
- return null;
- });
-
- /*
- * my heart beat checker
- */
- long waitMs = getProperties().getActiveHeartbeatMs();
-
- scheduleWithFixedDelay(waitMs, waitMs, () -> {
- if (myHeartbeatSeen) {
- myHeartbeatSeen = false;
- return null;
- }
-
- // missed my heart beat
- logger.error("missed my heartbeat on topic {}", getTopic());
-
- return missedHeartbeat();
- });
-
- /*
- * predecessor heart beat checker
- */
- if (!predHost.isEmpty()) {
-
- scheduleWithFixedDelay(waitMs, waitMs, () -> {
- if (predHeartbeatSeen) {
- predHeartbeatSeen = false;
- return null;
- }
-
- // missed the predecessor's heart beat
- logger.warn("missed predecessor's heartbeat on topic {}", getTopic());
-
- publish(makeQuery());
-
- return goQuery();
- });
- }
- }
-
- /**
- * Generates a heart beat for this host and its successor.
- */
- private void genHeartbeat() {
- var msg = makeHeartbeat(System.currentTimeMillis());
- publish(getHost(), msg);
-
- if (succHost != null) {
- publish(succHost, msg);
- }
- }
-
- @Override
- public State process(Heartbeat msg) {
- String src = msg.getSource();
-
- if (src == null) {
- logger.warn("Heartbeat message has no source on topic {}", getTopic());
-
- } else if (src.equals(getHost())) {
- logger.info("saw my heartbeat on topic {}", getTopic());
- myHeartbeatSeen = true;
-
- } else if (src.equals(predHost)) {
- logger.info("saw heartbeat from {} on topic {}", src, getTopic());
- predHeartbeatSeen = true;
-
- } else {
- logger.info("ignored heartbeat message from {} on topic {}", src, getTopic());
- }
-
- return null;
- }
-
- @Override
- public State process(Leader msg) {
- if (!isValid(msg)) {
- return null;
- }
-
- String src = msg.getSource();
-
- if (getHost().compareTo(src) < 0) {
- // our host would be a better leader - find out what's up
- logger.warn("unexpected Leader message from {} on topic {}", src, getTopic());
- return goQuery();
- }
-
- logger.info("have a new leader {} on topic {}", src, getTopic());
-
- return goActive(msg.getAssignments());
- }
-
- @Override
- public State process(Offline msg) {
- String src = msg.getSource();
-
- if (src == null) {
- logger.warn("Offline message has no source on topic {}", getTopic());
- return null;
-
- } else if (!assigned.contains(src)) {
- /*
- * the offline host wasn't assigned any buckets, so just ignore the message
- */
- logger.info("ignore Offline message from unassigned source {} on topic {}", src, getTopic());
- return null;
-
- } else if (isLeader() || (predHost.equals(src) && predHost.equals(assigned.first()))) {
- /*
- * Case 1: We are the leader.
- *
- * Case 2: Our predecessor was the leader and it has gone offline - we should
- * become the leader.
- *
- * In either case, we are now the leader and we must re-balance the buckets
- * since one of the hosts has gone offline.
- */
-
- logger.info("Offline message from source {} on topic {}", src, getTopic());
-
- assigned.remove(src);
-
- return becomeLeader(assigned);
-
- } else {
- /*
- * Otherwise, we don't care right now - we'll wait for the leader to tell us
- * it's been removed.
- */
- logger.info("ignore Offline message from source {} on topic {}", src, getTopic());
- return null;
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java
deleted file mode 100644
index 4878c241..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.state;
-
-import org.onap.policy.drools.pooling.PoolingManager;
-
-/**
- * Idle state, used when offline.
- */
-public class IdleState extends State {
-
- public IdleState(PoolingManager mgr) {
- super(mgr);
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java
deleted file mode 100644
index 579dc16d..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.state;
-
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Query;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The inactive state. In this state, we just wait a bit and then try to re-activate. In
- * the meantime, all messages are ignored.
- */
-public class InactiveState extends State {
-
- private static final Logger logger = LoggerFactory.getLogger(InactiveState.class);
-
- /**
- * Constructor.
- *
- * @param mgr pooling manager
- */
- public InactiveState(PoolingManager mgr) {
- super(mgr);
- }
-
- @Override
- public void start() {
- super.start();
- schedule(getProperties().getReactivateMs(), this::goStart);
- }
-
- @Override
- public State process(Leader msg) {
- if (isValid(msg)) {
- logger.info("received Leader message from {} on topic {}", msg.getSource(), getTopic());
- return goActive(msg.getAssignments());
- }
-
- return null;
- }
-
- /**
- * Generates an Identification message and goes to the query state.
- */
- @Override
- public State process(Query msg) {
- logger.info("received Query message on topic {}", getTopic());
- publish(makeIdentification());
- return goQuery();
- }
-
- /**
- * Remains in this state, without resetting any timers.
- */
- @Override
- protected State goInactive() {
- return null;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java
deleted file mode 100644
index 8bbb6ad8..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2021 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.pooling.state;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Queue;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import lombok.Getter;
-import lombok.NonNull;
-import lombok.Setter;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Query;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Any state in which events are being processed locally and forwarded, as appropriate.
- */
-@Getter
-public class ProcessingState extends State {
-
- private static final Logger logger = LoggerFactory.getLogger(ProcessingState.class);
-
- /**
- * Current known leader, never {@code null}.
- */
- @NonNull
- @Setter
- private String leader;
-
- /**
- * Constructor.
- *
- * @param mgr pooling manager
- * @param leader current known leader, which need not be the same as the assignment
- * leader. Never {@code null}
- * @throws IllegalArgumentException if an argument is invalid
- */
- public ProcessingState(PoolingManager mgr, String leader) {
- super(mgr);
-
- if (leader == null) {
- throw new IllegalArgumentException("null leader");
- }
-
- BucketAssignments assignments = mgr.getAssignments();
-
- if (assignments != null) {
- String[] arr = assignments.getHostArray();
- if (arr != null && arr.length == 0) {
- throw new IllegalArgumentException("zero-length bucket assignments");
- }
- }
-
- this.leader = leader;
- }
-
- /**
- * Generates an Identification message and goes to the query state.
- */
- @Override
- public State process(Query msg) {
- logger.info("received Query message on topic {}", getTopic());
- publish(makeIdentification());
- return goQuery();
- }
-
- /**
- * Sets the assignments.
- *
- * @param assignments new assignments, or {@code null}
- */
- protected final void setAssignments(BucketAssignments assignments) {
- if (assignments != null) {
- startDistributing(assignments);
- }
- }
-
- /**
- * Determines if this host is the leader, based on the current assignments.
- *
- * @return {@code true} if this host is the leader, {@code false} otherwise
- */
- public boolean isLeader() {
- return getHost().equals(leader);
- }
-
- /**
- * Becomes the leader. Publishes a Leader message and enters the {@link ActiveState}.
- *
- * @param alive hosts that are known to be alive
- *
- * @return the new state
- */
- protected State becomeLeader(SortedSet<String> alive) {
- String newLeader = getHost();
-
- if (!newLeader.equals(alive.first())) {
- throw new IllegalArgumentException(newLeader + " cannot replace " + alive.first());
- }
-
- var msg = makeLeader(alive);
- logger.info("{}/{} hosts have an assignment", msg.getAssignments().getAllHosts().size(), alive.size());
-
- publish(msg);
-
- return goActive(msg.getAssignments());
- }
-
- /**
- * Makes a leader message. Assumes "this" host is the leader, and thus appears as the
- * first host in the set of hosts that are still alive.
- *
- * @param alive hosts that are known to be alive
- *
- * @return a new message
- */
- private Leader makeLeader(Set<String> alive) {
- return new Leader(getHost(), makeAssignments(alive));
- }
-
- /**
- * Makes a set of bucket assignments. Assumes "this" host is the leader.
- *
- * @param alive hosts that are known to be alive
- *
- * @return a new set of bucket assignments
- */
- private BucketAssignments makeAssignments(Set<String> alive) {
-
- // make a working array from the CURRENT assignments
- String[] bucket2host = makeBucketArray();
-
- TreeSet<String> avail = new TreeSet<>(alive);
-
- // if we have more hosts than buckets, then remove the extra hosts
- removeExcessHosts(bucket2host.length, avail);
-
- // create a host bucket for each available host
- Map<String, HostBucket> host2hb = new HashMap<>();
- avail.forEach(host -> host2hb.put(host, new HostBucket(host)));
-
- // add bucket indices to the appropriate host bucket
- addIndicesToHostBuckets(bucket2host, host2hb);
-
- // convert the collection back to an array
- fillArray(host2hb.values(), bucket2host);
-
- // update bucket2host with new assignments
- rebalanceBuckets(host2hb.values(), bucket2host);
-
- return new BucketAssignments(bucket2host);
- }
-
- /**
- * Makes a bucket array, copying the current assignments, if available.
- *
- * @return a new bucket array
- */
- private String[] makeBucketArray() {
- BucketAssignments asgn = getAssignments();
- if (asgn == null) {
- return new String[BucketAssignments.MAX_BUCKETS];
- }
-
- String[] oldArray = asgn.getHostArray();
- if (oldArray.length == 0) {
- return new String[BucketAssignments.MAX_BUCKETS];
- }
-
- var newArray = new String[oldArray.length];
- System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
-
- return newArray;
- }
-
- /**
- * Removes excess hosts from the set of available hosts. Assumes "this" host is the
- * leader, and thus appears as the first host in the set.
- *
- * @param maxHosts maximum number of hosts to be retained
- * @param avail available hosts
- */
- private void removeExcessHosts(int maxHosts, SortedSet<String> avail) {
- while (avail.size() > maxHosts) {
- /*
- * Don't remove this host, as it's the leader. Since the leader is always at
- * the front of the sorted set, we'll just pick off hosts from the back of the
- * set.
- */
- String host = avail.last();
- avail.remove(host);
-
- logger.warn("not using extra host {} for topic {}", host, getTopic());
- }
- }
-
- /**
- * Adds bucket indices to {@link HostBucket} objects. Buckets that are unassigned or
- * assigned to a host that does not appear within the map are re-assigned to a host
- * that appears within the map.
- *
- * @param bucket2host bucket assignments
- * @param host2data maps a host name to its {@link HostBucket}
- */
- private void addIndicesToHostBuckets(String[] bucket2host, Map<String, HostBucket> host2data) {
- LinkedList<Integer> nullBuckets = new LinkedList<>();
-
- for (var x = 0; x < bucket2host.length; ++x) {
- String host = bucket2host[x];
- if (host == null) {
- nullBuckets.add(x);
-
- } else {
- HostBucket hb = host2data.get(host);
- if (hb == null) {
- nullBuckets.add(x);
-
- } else {
- hb.add(x);
- }
- }
- }
-
- // assign the null buckets to other hosts
- assignNullBuckets(nullBuckets, host2data.values());
- }
-
- /**
- * Assigns null buckets (i.e., those having no assignment) to available hosts.
- *
- * @param buckets buckets that still need to be assigned to hosts
- * @param coll collection of current host-bucket assignments
- */
- private void assignNullBuckets(Queue<Integer> buckets, Collection<HostBucket> coll) {
- // assign null buckets to the hosts with the fewest buckets
- TreeSet<HostBucket> assignments = new TreeSet<>(coll);
-
- for (Integer index : buckets) {
- // add it to the host with the shortest bucket list
- HostBucket newhb = assignments.pollFirst();
- newhb.add(index);
-
- // put the item back into the queue, with its new count
- assignments.add(newhb);
- }
- }
-
- /**
- * Re-balances the buckets, taking from those that have a larger count and giving to
- * those that have a smaller count. Populates an output array with the new
- * assignments.
- *
- * @param coll current bucket assignment
- * @param bucket2host array to be populated with the new assignments
- */
- private void rebalanceBuckets(Collection<HostBucket> coll, String[] bucket2host) {
- if (coll.size() <= 1) {
- // only one hosts - nothing to rebalance
- return;
- }
-
- TreeSet<HostBucket> assignments = new TreeSet<>(coll);
-
- for (;;) {
- HostBucket smaller = assignments.pollFirst();
- HostBucket larger = assignments.pollLast();
-
- if (larger.size() - smaller.size() <= 1) {
- // it's as balanced as it will get
- break;
- }
-
- // move the bucket from the larger to the smaller
- Integer bucket = larger.remove();
- smaller.add(bucket);
-
- bucket2host[bucket] = smaller.host;
-
- // put the items back, with their new counts
- assignments.add(larger);
- assignments.add(smaller);
- }
-
- }
-
- /**
- * Fills the array with the host assignments.
- *
- * @param coll the host assignments
- * @param bucket2host array to be filled
- */
- private void fillArray(Collection<HostBucket> coll, String[] bucket2host) {
- for (HostBucket hb : coll) {
- for (Integer index : hb.buckets) {
- bucket2host[index] = hb.host;
- }
- }
- }
-
- /**
- * Tracks buckets that have been assigned to a host.
- */
- protected static class HostBucket implements Comparable<HostBucket> {
- /**
- * Host to which the buckets have been assigned.
- */
- private String host;
-
- /**
- * Buckets that have been assigned to this host.
- */
- private Queue<Integer> buckets = new LinkedList<>();
-
- /**
- * Constructor.
- *
- * @param host host
- */
- public HostBucket(String host) {
- this.host = host;
- }
-
- /**
- * Removes the next bucket from the list.
- *
- * @return the next bucket
- */
- public final Integer remove() {
- return buckets.remove();
- }
-
- /**
- * Adds a bucket to the list.
- *
- * @param index index of the bucket to add
- */
- public final void add(Integer index) {
- buckets.add(index);
- }
-
- /**
- * Size.
- *
- * @return the number of buckets assigned to this host
- */
- public final int size() {
- return buckets.size();
- }
-
- /**
- * Compares host buckets, first by the number of buckets, and then by the host
- * name.
- */
- @Override
- public final int compareTo(HostBucket other) {
- int diff = buckets.size() - other.buckets.size();
- if (diff == 0) {
- diff = host.compareTo(other.host);
- }
- return diff;
- }
-
- @Override
- public final int hashCode() {
- throw new UnsupportedOperationException("HostBucket cannot be hashed");
- }
-
- @Override
- public final boolean equals(Object obj) {
- throw new UnsupportedOperationException("cannot compare HostBuckets");
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java
deleted file mode 100644
index 3e6f9d58..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) Nordix Foundation.
- * ================================================================================
- * 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.pooling.state;
-
-import java.util.TreeSet;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The Query state. In this state, the host waits for the other hosts to identify
- * themselves. Eventually, a leader should come forth. If not, it will transition to the
- * active or inactive state, depending on whether it has an assignment in the
- * current bucket assignments. The other possibility is that it may <i>become</i> the
- * leader, in which case it will also transition to the active state.
- */
-public class QueryState extends ProcessingState {
-
- private static final Logger logger = LoggerFactory.getLogger(QueryState.class);
-
- /**
- * Hosts that have sent an "Identification" message. Always includes this host.
- */
- private final TreeSet<String> alive = new TreeSet<>();
-
- /**
- * {@code True} if we saw our own Identification method, {@code false} otherwise.
- */
- private boolean sawSelfIdent = false;
-
- /**
- * Constructor.
- *
- * @param mgr manager
- */
- public QueryState(PoolingManager mgr) {
- // this host is the leader, until a better candidate identifies itself
- super(mgr, mgr.getHost());
-
- alive.add(getHost());
- }
-
- @Override
- public void start() {
- super.start();
-
- // start identification timer
- awaitIdentification();
- }
-
- /**
- * Starts a timer to wait for all Identification messages to arrive.
- */
- private void awaitIdentification() {
-
- /*
- * Once we've waited long enough for all Identification messages to arrive, become
- * the leader, assuming we should.
- */
-
- schedule(getProperties().getIdentificationMs(), () -> {
-
- if (!sawSelfIdent) {
- // didn't see our identification
- logger.error("missed our own Ident message on topic {}", getTopic());
- return missedHeartbeat();
-
- } else if (isLeader()) {
- // "this" host is the new leader
- logger.info("this host is the new leader for topic {}", getTopic());
- return becomeLeader(alive);
-
- } else {
- // not the leader - return to previous state
- logger.info("no new leader on topic {}", getTopic());
- return goActive(getAssignments());
- }
- });
- }
-
- @Override
- public State goQuery() {
- return null;
- }
-
- @Override
- public State process(Identification msg) {
-
- if (getHost().equals(msg.getSource())) {
- logger.info("saw our own Ident message on topic {}", getTopic());
- sawSelfIdent = true;
-
- } else {
- logger.info("received Ident message from {} on topic {}", msg.getSource(), getTopic());
- recordInfo(msg.getSource(), msg.getAssignments());
- }
-
- return null;
- }
-
- /**
- * If the message leader is better than the leader we have, then go active with it.
- * Otherwise, simply treat it like an {@link Identification} message.
- */
- @Override
- public State process(Leader msg) {
- if (!isValid(msg)) {
- return null;
- }
-
- String source = msg.getSource();
- BucketAssignments asgn = msg.getAssignments();
-
- // go active, if this has a leader that's the same or better than the one we have
- if (source.compareTo(getLeader()) <= 0) {
- logger.warn("leader with {} on topic {}", source, getTopic());
- return goActive(asgn);
- }
-
- /*
- * The message does not have an acceptable leader, but we'll still record its
- * info.
- */
- logger.info("record leader info from {} on topic {}", source, getTopic());
- recordInfo(source, asgn);
-
- return null;
- }
-
- @Override
- public State process(Offline msg) {
- String host = msg.getSource();
-
- if (host != null && !host.equals(getHost())) {
- logger.warn("host {} offline on topic {}", host, getTopic());
- alive.remove(host);
- setLeader(alive.first());
-
- } else {
- logger.info("ignored offline message from {} on topic {}", msg.getSource(), getTopic());
- }
-
- return null;
- }
-
- /**
- * Records info from a message, adding the source host name to {@link #alive}, and
- * updating the bucket assignments.
- *
- * @param source the message's source host
- * @param assignments assignments, or {@code null}
- */
- private void recordInfo(String source, BucketAssignments assignments) {
- // add this message's source host to "alive"
- if (source != null) {
- alive.add(source);
- setLeader(alive.first());
- }
-
- if (assignments == null || assignments.getLeader() == null) {
- return;
- }
-
- // record assignments, if we don't have any yet
- BucketAssignments current = getAssignments();
- if (current == null) {
- logger.info("received initial assignments on topic {}", getTopic());
- setAssignments(assignments);
- return;
- }
-
- /*
- * Record assignments, if the new assignments have a better (i.e., lesser) leader.
- */
- String curldr = current.getLeader();
- if (curldr == null || assignments.getLeader().compareTo(curldr) < 0) {
- logger.info("use new assignments from {} on topic {}", source, getTopic());
- setAssignments(assignments);
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StartState.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StartState.java
deleted file mode 100644
index c582d6e0..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StartState.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020-2021 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.pooling.state;
-
-import lombok.Getter;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * The start state. Upon entry, a heart beat is generated and the event filter is changed
- * to look for just that particular message. Once the message is seen, it goes into the
- * {@link QueryState}.
- */
-@Getter
-public class StartState extends State {
-
- private static final Logger logger = LoggerFactory.getLogger(StartState.class);
-
- /**
- * Time stamp inserted into the heart beat message.
- */
- private long hbTimestampMs = System.currentTimeMillis();
-
- /**
- * Constructor.
- *
- * @param mgr pooling manager
- */
- public StartState(PoolingManager mgr) {
- super(mgr);
- }
-
- @Override
- public void start() {
-
- super.start();
-
- var hb = makeHeartbeat(hbTimestampMs);
- publish(getHost(), hb);
-
- /*
- * heart beat generator
- */
- long genMs = getProperties().getInterHeartbeatMs();
-
- scheduleWithFixedDelay(genMs, genMs, () -> {
- publish(getHost(), hb);
- return null;
- });
-
- /*
- * my heart beat checker
- */
- schedule(getProperties().getStartHeartbeatMs(), () -> {
- logger.error("missed heartbeat on topic {}", getTopic());
- return internalTopicFailed();
- });
- }
-
- /**
- * Transitions to the query state if the heart beat originated from this host and its
- * time stamp matches.
- */
- @Override
- public State process(Heartbeat msg) {
- if (msg.getTimestampMs() == hbTimestampMs && getHost().equals(msg.getSource())) {
- // saw our own heart beat - transition to query state
- logger.info("saw our own heartbeat on topic {}", getTopic());
- publish(makeQuery());
- return goQuery();
-
- } else {
- logger.info("ignored old heartbeat message from {} on topic {}", msg.getSource(), getTopic());
- }
-
- return null;
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/State.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/State.java
deleted file mode 100644
index 66728ee2..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/State.java
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020-2021 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.pooling.state;
-
-import java.util.LinkedList;
-import java.util.List;
-import org.onap.policy.drools.pooling.CancellableScheduledTask;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.PoolingProperties;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * A state in the finite state machine.
- *
- * <p>A state may have several timers associated with it, which must be cancelled whenever
- * the state is changed. Assumes that timers are not continuously added to the same state.
- */
-public abstract class State {
-
- private static final Logger logger = LoggerFactory.getLogger(State.class);
-
- /**
- * Host pool manager.
- */
- private final PoolingManager mgr;
-
- /**
- * Timers added by this state.
- */
- private final List<CancellableScheduledTask> timers = new LinkedList<>();
-
- /**
- * Constructor.
- *
- * @param mgr pooling manager
- */
- protected State(PoolingManager mgr) {
- this.mgr = mgr;
- }
-
- /**
- * Cancels the timers added by this state.
- */
- public final void cancelTimers() {
- timers.forEach(CancellableScheduledTask::cancel);
- }
-
- /**
- * Starts the state. The default method simply logs a message and returns.
- */
- public void start() {
- logger.info("entered {} for topic {}", getClass().getSimpleName(), getTopic());
- }
-
- /**
- * Transitions to the "start" state.
- *
- * @return the new state
- */
- public final State goStart() {
- return mgr.goStart();
- }
-
- /**
- * Transitions to the "query" state.
- *
- * @return the new state
- */
- public State goQuery() {
- return mgr.goQuery();
- }
-
- /**
- * Goes active with a new set of assignments.
- *
- * @param asgn new assignments
- * @return the new state, either Active or Inactive, depending on whether or not this
- * host has an assignment
- */
- protected State goActive(BucketAssignments asgn) {
- startDistributing(asgn);
-
- if (asgn != null && asgn.hasAssignment(getHost())) {
- return mgr.goActive();
-
- } else {
- return goInactive();
- }
- }
-
- /**
- * Transitions to the "inactive" state.
- *
- * @return the new state
- */
- protected State goInactive() {
- return mgr.goInactive();
- }
-
- /**
- * Processes a message. The default method just returns {@code null}.
- *
- * @param msg message to be processed
- * @return the new state, or {@code null} if the state is unchanged
- */
- public State process(Heartbeat msg) {
- logger.info("ignored heartbeat message from {} on topic {}", msg.getSource(), getTopic());
- return null;
- }
-
- /**
- * Processes a message. The default method just returns {@code null}.
- *
- * @param msg message to be processed
- * @return the new state, or {@code null} if the state is unchanged
- */
- public State process(Identification msg) {
- logger.info("ignored ident message from {} on topic {}", msg.getSource(), getTopic());
- return null;
- }
-
- /**
- * Processes a message. The default method copies the assignments and then returns
- * {@code null}.
- *
- * @param msg message to be processed
- * @return the new state, or {@code null} if the state is unchanged
- */
- public State process(Leader msg) {
- if (isValid(msg)) {
- logger.info("extract assignments from Leader message from {} on topic {}", msg.getSource(), getTopic());
- startDistributing(msg.getAssignments());
- }
-
- return null;
- }
-
- /**
- * Processes a message. The default method just returns {@code null}.
- *
- * @param msg message to be processed
- * @return the new state, or {@code null} if the state is unchanged
- */
- public State process(Offline msg) {
- logger.info("ignored offline message from {} on topic {}", msg.getSource(), getTopic());
- return null;
- }
-
- /**
- * Processes a message. The default method just returns {@code null}.
- *
- * @param msg message to be processed
- * @return the new state, or {@code null} if the state is unchanged
- */
- public State process(Query msg) {
- logger.info("ignored Query message from {} on topic {}", msg.getSource(), getTopic());
- return null;
- }
-
- /**
- * Determines if a message is valid and did not originate from this host.
- *
- * @param msg message to be validated
- * @return {@code true} if the message is valid, {@code false} otherwise
- */
- protected boolean isValid(Leader msg) {
- BucketAssignments asgn = msg.getAssignments();
- if (asgn == null) {
- logger.warn("Leader message from {} has no assignments for topic {}", msg.getSource(), getTopic());
- return false;
- }
-
- // ignore Leader messages from ourself
- String source = msg.getSource();
- if (source == null || source.equals(getHost())) {
- logger.debug("ignore Leader message from {} for topic {}", msg.getSource(), getTopic());
- return false;
- }
-
- // the new leader must equal the source
- boolean result = source.equals(asgn.getLeader());
-
- if (!result) {
- logger.warn("Leader message from {} has an invalid assignment for topic {}", msg.getSource(), getTopic());
- }
-
- return result;
- }
-
- /**
- * Publishes a message.
- *
- * @param msg message to be published
- */
- protected final void publish(Identification msg) {
- mgr.publishAdmin(msg);
- }
-
- /**
- * Publishes a message.
- *
- * @param msg message to be published
- */
- protected final void publish(Leader msg) {
- mgr.publishAdmin(msg);
- }
-
- /**
- * Publishes a message.
- *
- * @param msg message to be published
- */
- protected final void publish(Offline msg) {
- mgr.publishAdmin(msg);
- }
-
- /**
- * Publishes a message.
- *
- * @param msg message to be published
- */
- protected final void publish(Query msg) {
- mgr.publishAdmin(msg);
- }
-
- /**
- * Publishes a message on the specified channel.
- *
- * @param channel channel
- * @param msg message to be published
- */
- protected final void publish(String channel, Heartbeat msg) {
- mgr.publish(channel, msg);
- }
-
- /**
- * Starts distributing messages using the specified bucket assignments.
- *
- * @param assignments assignments
- */
- protected final void startDistributing(BucketAssignments assignments) {
- if (assignments != null) {
- mgr.startDistributing(assignments);
- }
- }
-
- /**
- * Schedules a timer to fire after a delay.
- *
- * @param delayMs delay in ms
- * @param task task
- */
- protected final void schedule(long delayMs, StateTimerTask task) {
- timers.add(mgr.schedule(delayMs, task));
- }
-
- /**
- * Schedules a timer to fire repeatedly.
- *
- * @param initialDelayMs initial delay ms
- * @param delayMs delay ms
- * @param task task
- */
- protected final void scheduleWithFixedDelay(long initialDelayMs, long delayMs, StateTimerTask task) {
- timers.add(mgr.scheduleWithFixedDelay(initialDelayMs, delayMs, task));
- }
-
- /**
- * Indicates that we failed to see our own heartbeat; must be a problem with the
- * internal topic. Assumes the problem is temporary and continues to use the current
- * bucket assignments.
- *
- * @return a new {@link StartState}
- */
- protected final State missedHeartbeat() {
- publish(makeOffline());
-
- return mgr.goStart();
- }
-
- /**
- * Indicates that the internal topic failed; this should only be invoked from the
- * StartState. Discards bucket assignments and begins processing everything locally.
- *
- * @return a new {@link InactiveState}
- */
- protected final State internalTopicFailed() {
- publish(makeOffline());
- mgr.startDistributing(null);
-
- return mgr.goInactive();
- }
-
- /**
- * Makes a heart beat message.
- *
- * @param timestampMs time, in milliseconds, associated with the message
- *
- * @return a new message
- */
- protected final Heartbeat makeHeartbeat(long timestampMs) {
- return new Heartbeat(getHost(), timestampMs);
- }
-
- /**
- * Makes an Identification message.
- *
- * @return a new message
- */
- protected Identification makeIdentification() {
- return new Identification(getHost(), getAssignments());
- }
-
- /**
- * Makes an "offline" message.
- *
- * @return a new message
- */
- protected final Offline makeOffline() {
- return new Offline(getHost());
- }
-
- /**
- * Makes a query message.
- *
- * @return a new message
- */
- protected final Query makeQuery() {
- return new Query(getHost());
- }
-
- public final BucketAssignments getAssignments() {
- return mgr.getAssignments();
- }
-
- public final String getHost() {
- return mgr.getHost();
- }
-
- public final String getTopic() {
- return mgr.getTopic();
- }
-
- public final PoolingProperties getProperties() {
- return mgr.getProperties();
- }
-}
diff --git a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java b/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java
deleted file mode 100644
index e4607f81..00000000
--- a/feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-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.pooling.state;
-
-/**
- * Task to be executed when a timer fires within a {@link State}.
- */
-@FunctionalInterface
-public interface StateTimerTask {
-
- /**
- * Fires the timer.
- *
- * @return the new state, or {@code null} if the state is unchanged
- */
- State fire();
-
-}
diff --git a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi b/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi
deleted file mode 100644
index cd59e469..00000000
--- a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi
+++ /dev/null
@@ -1 +0,0 @@
-org.onap.policy.drools.pooling.PoolingFeature
diff --git a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi b/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi
deleted file mode 100644
index cd59e469..00000000
--- a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi
+++ /dev/null
@@ -1 +0,0 @@
-org.onap.policy.drools.pooling.PoolingFeature
diff --git a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi b/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi
deleted file mode 100644
index cd59e469..00000000
--- a/feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi
+++ /dev/null
@@ -1 +0,0 @@
-org.onap.policy.drools.pooling.PoolingFeature
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java
deleted file mode 100644
index ec554fc9..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2020 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.pooling;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-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.concurrent.CountDownLatch;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-
-public class DmaapManagerTest {
-
- private static final String EXPECTED = "expected";
- private static final String MY_TOPIC = "my.topic";
- private static final String MSG = "a message";
-
- private TopicListener listener;
- private TopicSource source;
- private boolean gotSources;
- private TopicSink sink;
- private boolean gotSinks;
- private DmaapManager mgr;
-
- /**
- * Setup.
- *
- * @throws Exception throws an exception
- */
- @Before
- public void setUp() throws Exception {
- listener = mock(TopicListener.class);
- source = mock(TopicSource.class);
- gotSources = false;
- sink = mock(TopicSink.class);
- gotSinks = false;
-
- when(source.getTopic()).thenReturn(MY_TOPIC);
-
- when(sink.getTopic()).thenReturn(MY_TOPIC);
- when(sink.send(any())).thenReturn(true);
-
- mgr = new DmaapManagerImpl(MY_TOPIC);
- }
-
- @Test
- public void testDmaapManager() {
- // verify that the init methods were called
- assertTrue(gotSources);
- assertTrue(gotSinks);
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testDmaapManager_PoolingEx() throws PoolingFeatureException {
- // force error by having no topics match
- when(source.getTopic()).thenReturn("");
-
- new DmaapManagerImpl(MY_TOPIC);
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testDmaapManager_IllegalArgEx() throws PoolingFeatureException {
- // force error
- new DmaapManagerImpl(MY_TOPIC) {
- @Override
- protected List<TopicSource> getTopicSources() {
- throw new IllegalArgumentException(EXPECTED);
- }
- };
- }
-
- @Test
- public void testGetTopic() {
- assertEquals(MY_TOPIC, mgr.getTopic());
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testFindTopicSource_NotFound() throws PoolingFeatureException {
- // one item in list, and its topic doesn't match
- new DmaapManagerImpl(MY_TOPIC) {
- @Override
- protected List<TopicSource> getTopicSources() {
- return Arrays.asList(mock(TopicSource.class));
- }
- };
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testFindTopicSource_EmptyList() throws PoolingFeatureException {
- // empty list
- new DmaapManagerImpl(MY_TOPIC) {
- @Override
- protected List<TopicSource> getTopicSources() {
- return Collections.emptyList();
- }
- };
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testFindTopicSink_NotFound() throws PoolingFeatureException {
- // one item in list, and its topic doesn't match
- new DmaapManagerImpl(MY_TOPIC) {
- @Override
- protected List<TopicSink> getTopicSinks() {
- return Arrays.asList(mock(TopicSink.class));
- }
- };
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testFindTopicSink_EmptyList() throws PoolingFeatureException {
- // empty list
- new DmaapManagerImpl(MY_TOPIC) {
- @Override
- protected List<TopicSink> getTopicSinks() {
- return Collections.emptyList();
- }
- };
- }
-
- @Test
- public void testStartPublisher() throws PoolingFeatureException {
-
- mgr.startPublisher();
-
- // restart should have no effect
- mgr.startPublisher();
-
- // should be able to publish now
- mgr.publish(MSG);
- verify(sink).send(MSG);
- }
-
- @Test
- public void testStopPublisher() throws PoolingFeatureException {
- // not publishing yet, so stopping should have no effect
- mgr.stopPublisher(0);
-
- // now start it
- mgr.startPublisher();
-
- // this time, stop should do something
- mgr.stopPublisher(0);
-
- // re-stopping should have no effect
- assertThatCode(() -> mgr.stopPublisher(0)).doesNotThrowAnyException();
- }
-
- @Test
- public void testStopPublisher_WithDelay() throws PoolingFeatureException {
-
- mgr.startPublisher();
-
- long tbeg = System.currentTimeMillis();
-
- mgr.stopPublisher(100L);
-
- assertTrue(System.currentTimeMillis() >= tbeg + 100L);
- }
-
- @Test
- public void testStopPublisher_WithDelayInterrupted() throws Exception {
-
- mgr.startPublisher();
-
- long minms = 2000L;
-
- // tell the publisher to stop in minms + additional time
- CountDownLatch latch = new CountDownLatch(1);
- Thread thread = new Thread(() -> {
- latch.countDown();
- mgr.stopPublisher(minms + 3000L);
- });
- thread.start();
-
- // wait for the thread to start
- latch.await();
-
- // interrupt it - it should immediately finish its work
- thread.interrupt();
-
- // wait for it to stop, but only wait the minimum time
- thread.join(minms);
-
- assertFalse(thread.isAlive());
- }
-
- @Test
- public void testStartConsumer() {
- // not started yet
- verify(source, never()).register(any());
-
- mgr.startConsumer(listener);
- verify(source).register(listener);
-
- // restart should have no effect
- mgr.startConsumer(listener);
- verify(source).register(listener);
- }
-
- @Test
- public void testStopConsumer() {
- // not consuming yet, so stopping should have no effect
- mgr.stopConsumer(listener);
- verify(source, never()).unregister(any());
-
- // now start it
- mgr.startConsumer(listener);
-
- // this time, stop should do something
- mgr.stopConsumer(listener);
- verify(source).unregister(listener);
-
- // re-stopping should have no effect
- mgr.stopConsumer(listener);
- verify(source).unregister(listener);
- }
-
- @Test
- public void testPublish() throws PoolingFeatureException {
- // cannot publish before starting
- assertThatThrownBy(() -> mgr.publish(MSG)).as("publish,pre").isInstanceOf(PoolingFeatureException.class);
-
- mgr.startPublisher();
-
- // publish several messages
- mgr.publish(MSG);
- verify(sink).send(MSG);
-
- mgr.publish(MSG + "a");
- verify(sink).send(MSG + "a");
-
- mgr.publish(MSG + "b");
- verify(sink).send(MSG + "b");
-
- // stop and verify we can no longer publish
- mgr.stopPublisher(0);
- assertThatThrownBy(() -> mgr.publish(MSG)).as("publish,stopped").isInstanceOf(PoolingFeatureException.class);
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testPublish_SendFailed() throws PoolingFeatureException {
- mgr.startPublisher();
-
- // arrange for send() to fail
- when(sink.send(MSG)).thenReturn(false);
-
- mgr.publish(MSG);
- }
-
- @Test(expected = PoolingFeatureException.class)
- public void testPublish_SendEx() throws PoolingFeatureException {
- mgr.startPublisher();
-
- // arrange for send() to throw an exception
- doThrow(new IllegalStateException(EXPECTED)).when(sink).send(MSG);
-
- mgr.publish(MSG);
- }
-
- /**
- * Manager with overrides.
- */
- private class DmaapManagerImpl extends DmaapManager {
-
- public DmaapManagerImpl(String topic) throws PoolingFeatureException {
- super(topic);
- }
-
- @Override
- protected List<TopicSource> getTopicSources() {
- gotSources = true;
-
- // three sources, with the desired one in the middle
- return Arrays.asList(mock(TopicSource.class), source, mock(TopicSource.class));
- }
-
- @Override
- protected List<TopicSink> getTopicSinks() {
- gotSinks = true;
-
- // three sinks, with the desired one in the middle
- return Arrays.asList(mock(TopicSink.class), sink, mock(TopicSink.class));
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java
deleted file mode 100644
index b8970f1f..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java
+++ /dev/null
@@ -1,809 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 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.pooling;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.onap.policy.drools.pooling.PoolingProperties.PREFIX;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonParseException;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.IdentityHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
-import java.util.TreeMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * End-to-end tests of the pooling feature. Launches one or more "hosts", each one having its own
- * feature object. Uses real feature objects, as well as real DMaaP sources and sinks. However, the
- * following are not: <dl> <dt>PolicyEngine, PolicyController, DroolsController</dt> <dd>mocked</dd>
- * </dl>
- *
- * <p>The following fields must be set before executing this: <ul> <li>UEB_SERVERS</li>
- * <li>INTERNAL_TOPIC</li> <li>EXTERNAL_TOPIC</li> </ul>
- */
-public class EndToEndFeatureTest {
-
- private static final Logger logger = LoggerFactory.getLogger(EndToEndFeatureTest.class);
-
- /**
- * UEB servers for both internal & external topics.
- */
- private static final String UEB_SERVERS = "";
-
- /**
- * Name of the topic used for inter-host communication.
- */
- private static final String INTERNAL_TOPIC = "";
-
- /**
- * Name of the topic from which "external" events "arrive".
- */
- private static final String EXTERNAL_TOPIC = "";
-
- /**
- * Consumer group to use when polling the external topic.
- */
- private static final String EXTERNAL_GROUP = EndToEndFeatureTest.class.getName();
-
- /**
- * Name of the controller.
- */
- private static final String CONTROLLER1 = "controller.one";
-
- /**
- * Maximum number of items to fetch from DMaaP in a single poll.
- */
- private static final String FETCH_LIMIT = "5";
-
- private static final long STD_REACTIVATE_WAIT_MS = 10000;
- private static final long STD_IDENTIFICATION_MS = 10000;
- private static final long STD_START_HEARTBEAT_MS = 15000;
- private static final long STD_ACTIVE_HEARTBEAT_MS = 12000;
- private static final long STD_INTER_HEARTBEAT_MS = 5000;
- private static final long STD_OFFLINE_PUB_WAIT_MS = 2;
- private static final long EVENT_WAIT_SEC = 15;
-
- /**
- * Used to decode events from the external topic.
- */
- private static final Gson mapper = new Gson();
-
- /**
- * Used to identify the current host.
- */
- private static final ThreadLocal<Host> currentHost = new ThreadLocal<Host>();
-
- /**
- * Sink for external DMaaP topic.
- */
- private static TopicSink externalSink;
-
- /**
- * Sink for internal DMaaP topic.
- */
- private static TopicSink internalSink;
-
- /**
- * Context for the current test case.
- */
- private Context ctx;
-
- /**
- * Setup before class.
- *
- */
- @BeforeClass
- public static void setUpBeforeClass() {
- externalSink = TopicEndpointManager.getManager().addTopicSinks(makeSinkProperties(EXTERNAL_TOPIC)).get(0);
- externalSink.start();
-
- internalSink = TopicEndpointManager.getManager().addTopicSinks(makeSinkProperties(INTERNAL_TOPIC)).get(0);
- internalSink.start();
- }
-
- /**
- * Tear down after class.
- *
- */
- @AfterClass
- public static void tearDownAfterClass() {
- externalSink.stop();
- internalSink.stop();
- }
-
- /**
- * Setup.
- */
- @Before
- public void setUp() {
- ctx = null;
- }
-
- /**
- * Tear down.
- */
- @After
- public void tearDown() {
- if (ctx != null) {
- ctx.destroy();
- }
- }
-
- /*
- * This test should only be run manually, after configuring all of the fields,
- * thus it is ignored.
- */
- @Ignore
- @Test
- public void test_SingleHost() throws Exception { // NOSONAR
- run(70, 1);
- }
-
- /*
- * This test should only be run manually, after configuring all of the fields,
- * thus it is ignored.
- */
- @Ignore
- @Test
- public void test_TwoHosts() throws Exception { // NOSONAR
- run(200, 2);
- }
-
- /*
- * This test should only be run manually, after configuring all of the fields,
- * thus it is ignored.
- */
- @Ignore
- @Test
- public void test_ThreeHosts() throws Exception { // NOSONAR
- run(200, 3);
- }
-
- private void run(int nmessages, int nhosts) throws Exception {
- ctx = new Context(nmessages);
-
- for (int x = 0; x < nhosts; ++x) {
- ctx.addHost();
- }
-
- ctx.startHosts();
- ctx.awaitAllActive(STD_IDENTIFICATION_MS * 2);
-
- for (int x = 0; x < nmessages; ++x) {
- ctx.offerExternal(makeMessage(x));
- }
-
- ctx.awaitEvents(EVENT_WAIT_SEC, TimeUnit.SECONDS);
-
- assertEquals(0, ctx.getDecodeErrors());
- assertEquals(0, ctx.getRemainingEvents());
- ctx.checkAllSawAMsg();
- }
-
- private String makeMessage(int reqnum) {
- return "{\"reqid\":\"req" + reqnum + "\", \"data\":\"hello " + reqnum + "\"}";
- }
-
- private static Properties makeSinkProperties(String topic) {
- Properties props = new Properties();
-
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS, topic);
-
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX, UEB_SERVERS);
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_TOPIC_SINK_PARTITION_KEY_SUFFIX, "0");
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "false");
-
- return props;
- }
-
- private static Properties makeSourceProperties(String topic) {
- Properties props = new Properties();
-
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS, topic);
-
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX, UEB_SERVERS);
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_TOPIC_SOURCE_FETCH_LIMIT_SUFFIX, FETCH_LIMIT);
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_MANAGED_SUFFIX, "false");
-
- if (EXTERNAL_TOPIC.equals(topic)) {
- // consumer group is a constant
- props.setProperty(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + topic
- + PolicyEndPointProperties.PROPERTY_TOPIC_SOURCE_CONSUMER_GROUP_SUFFIX, EXTERNAL_GROUP);
-
- // consumer instance is generated by the BusConsumer code
- }
-
- // else internal topic: feature populates info for internal topic
-
- return props;
- }
-
- /**
- * Decodes an event.
- *
- * @param event event
- * @return the decoded event, or {@code null} if it cannot be decoded
- */
- private static Object decodeEvent(String event) {
- try {
- return mapper.fromJson(event, TreeMap.class);
-
- } catch (JsonParseException e) {
- logger.warn("cannot decode external event", e);
- return null;
- }
- }
-
- /**
- * Context used for a single test case.
- */
- private static class Context {
-
- /**
- * Hosts that have been added to this context.
- */
- private final Deque<Host> hosts = new LinkedList<>();
-
- /**
- * Maps a drools controller to its policy controller.
- */
- private final IdentityHashMap<DroolsController, PolicyController> drools2policy = new IdentityHashMap<>();
-
- /**
- * Counts the number of decode errors.
- */
- private final AtomicInteger decodeErrors = new AtomicInteger(0);
-
- /**
- * Number of events we're still waiting to receive.
- */
- private final CountDownLatch eventCounter;
-
- /**
- * Constructor.
- *
- * @param events number of events to be processed
- */
- public Context(int events) {
- eventCounter = new CountDownLatch(events);
- }
-
- /**
- * Destroys the context, stopping any hosts that remain.
- */
- public void destroy() {
- stopHosts();
- hosts.clear();
- }
-
- /**
- * Creates and adds a new host to the context.
- *
- * @return the new Host
- */
- public Host addHost() {
- Host host = new Host(this);
- hosts.add(host);
-
- return host;
- }
-
- /**
- * Starts the hosts.
- */
- public void startHosts() {
- hosts.forEach(host -> host.start());
- }
-
- /**
- * Stops the hosts.
- */
- public void stopHosts() {
- hosts.forEach(host -> host.stop());
- }
-
- /**
- * Verifies that all hosts processed at least one message.
- */
- public void checkAllSawAMsg() {
- int msgs = 0;
- for (Host host : hosts) {
- assertTrue("msgs=" + msgs, host.messageSeen());
- ++msgs;
- }
- }
-
- /**
- * Offers an event to the external topic.
- *
- * @param event event
- */
- public void offerExternal(String event) {
- externalSink.send(event);
- }
-
- /**
- * Associates a controller with its drools controller.
- *
- * @param controller controller
- * @param droolsController drools controller
- */
- public void addController(PolicyController controller, DroolsController droolsController) {
- drools2policy.put(droolsController, controller);
- }
-
- /**
- * Get controller.
- *
- * @param droolsController drools controller
- * @return the controller associated with a drools controller, or {@code null} if it has no
- * associated controller
- */
- public PolicyController getController(DroolsController droolsController) {
- return drools2policy.get(droolsController);
- }
-
- /**
- * Get decode errors.
- *
- * @return the number of decode errors so far
- */
- public int getDecodeErrors() {
- return decodeErrors.get();
- }
-
- /**
- * Increments the count of decode errors.
- */
- public void bumpDecodeErrors() {
- decodeErrors.incrementAndGet();
- }
-
- /**
- * Get remaining events.
- *
- * @return the number of events that haven't been processed
- */
- public long getRemainingEvents() {
- return eventCounter.getCount();
- }
-
- /**
- * Adds an event to the counter.
- */
- public void addEvent() {
- eventCounter.countDown();
- }
-
- /**
- * Waits, for a period of time, for all events to be processed.
- *
- * @param time time
- * @param units units
- * @return {@code true} if all events have been processed, {@code false} otherwise
- * @throws InterruptedException throws interrupted exception
- */
- public boolean awaitEvents(long time, TimeUnit units) throws InterruptedException {
- return eventCounter.await(time, units);
- }
-
- /**
- * Waits, for a period of time, for all hosts to enter the Active state.
- *
- * @param timeMs maximum time to wait, in milliseconds
- * @throws InterruptedException throws interrupted exception
- */
- public void awaitAllActive(long timeMs) throws InterruptedException {
- long tend = timeMs + System.currentTimeMillis();
-
- for (Host host : hosts) {
- long tremain = Math.max(0, tend - System.currentTimeMillis());
- assertTrue(host.awaitActive(tremain));
- }
- }
- }
-
- /**
- * Simulates a single "host".
- */
- private static class Host {
-
- private final PoolingFeature feature;
-
- /**
- * {@code True} if this host has processed a message, {@code false} otherwise.
- */
- private final AtomicBoolean sawMsg = new AtomicBoolean(false);
-
- private final TopicSource externalSource;
- private final TopicSource internalSource;
-
- // mock objects
- private final PolicyEngine engine = mock(PolicyEngine.class);
- private final ListenerController controller = mock(ListenerController.class);
- private final DroolsController drools = mock(DroolsController.class);
-
- /**
- * Constructor.
- *
- * @param context context
- */
- public Host(Context context) {
-
- when(controller.getName()).thenReturn(CONTROLLER1);
- when(controller.getDrools()).thenReturn(drools);
-
- externalSource = TopicEndpointManager.getManager().addTopicSources(makeSourceProperties(EXTERNAL_TOPIC))
- .get(0);
- internalSource = TopicEndpointManager.getManager().addTopicSources(makeSourceProperties(INTERNAL_TOPIC))
- .get(0);
-
- // stop consuming events if the controller stops
- when(controller.stop()).thenAnswer(args -> {
- externalSource.unregister(controller);
- return true;
- });
-
- doAnswer(new MyExternalTopicListener(context, this)).when(controller).onTopicEvent(any(), any(), any());
-
- context.addController(controller, drools);
-
- feature = new PoolingFeatureImpl(context, this);
- }
-
- /**
- * Waits, for a period of time, for the host to enter the Active state.
- *
- * @param timeMs time to wait, in milliseconds
- * @return {@code true} if the host entered the Active state within the given amount of
- * time, {@code false} otherwise
- * @throws InterruptedException throws interrupted exception
- */
- public boolean awaitActive(long timeMs) throws InterruptedException {
- return feature.getActiveLatch().await(timeMs, TimeUnit.MILLISECONDS);
- }
-
- /**
- * Starts threads for the host so that it begins consuming from both the external "DMaaP"
- * topic and its own internal "DMaaP" topic.
- */
- public void start() {
- feature.beforeStart(engine);
- feature.afterCreate(controller);
-
- feature.beforeStart(controller);
-
- // start consuming events from the external topic
- externalSource.register(controller);
-
- feature.afterStart(controller);
- }
-
- /**
- * Stops the host's threads.
- */
- public void stop() {
- feature.beforeStop(controller);
- externalSource.unregister(controller);
- feature.afterStop(controller);
- }
-
- /**
- * Offers an event to the feature, before the policy controller handles it.
- *
- * @param protocol protocol
- * @param topic2 topic
- * @param event event
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
- public boolean beforeOffer(CommInfrastructure protocol, String topic2, String event) {
- return feature.beforeOffer(controller, protocol, topic2, event);
- }
-
- /**
- * Offers an event to the feature, after the policy controller handles it.
- *
- * @param protocol protocol
- * @param topic topic
- * @param event event
- * @param success success
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
- public boolean afterOffer(CommInfrastructure protocol, String topic, String event, boolean success) {
-
- return feature.afterOffer(controller, protocol, topic, event, success);
- }
-
- /**
- * Offers an event to the feature, before the drools controller handles it.
- *
- * @param fact fact
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
- public boolean beforeInsert(Object fact) {
- return feature.beforeInsert(drools, fact);
- }
-
- /**
- * Offers an event to the feature, after the drools controller handles it.
- *
- * @param fact fact
- * @param successInsert {@code true} if it was successfully inserted by the drools
- * controller, {@code false} otherwise
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
- public boolean afterInsert(Object fact, boolean successInsert) {
- return feature.afterInsert(drools, fact, successInsert);
- }
-
- /**
- * Indicates that a message was seen for this host.
- */
- public void sawMessage() {
- sawMsg.set(true);
- }
-
- /**
- * Message seen.
- *
- * @return {@code true} if a message was seen for this host, {@code false} otherwise
- */
- public boolean messageSeen() {
- return sawMsg.get();
- }
- }
-
- /**
- * Listener for the external topic. Simulates the actions taken by
- * <i>AggregatedPolicyController.onTopicEvent</i>.
- */
- private static class MyExternalTopicListener implements Answer<Void> {
-
- private final Context context;
- private final Host host;
-
- public MyExternalTopicListener(Context context, Host host) {
- this.context = context;
- this.host = host;
- }
-
- @Override
- public Void answer(InvocationOnMock args) throws Throwable {
- int index = 0;
- CommInfrastructure commType = args.getArgument(index++);
- String topic = args.getArgument(index++);
- String event = args.getArgument(index++);
-
- if (host.beforeOffer(commType, topic, event)) {
- return null;
- }
-
- boolean result;
- Object fact = decodeEvent(event);
-
- if (fact == null) {
- result = false;
- context.bumpDecodeErrors();
-
- } else {
- result = true;
-
- if (!host.beforeInsert(fact)) {
- // feature did not handle it so we handle it here
- host.afterInsert(fact, result);
-
- host.sawMessage();
- context.addEvent();
- }
- }
-
- host.afterOffer(commType, topic, event, result);
- return null;
- }
- }
-
- /**
- * Feature with overrides.
- */
- private static class PoolingFeatureImpl extends PoolingFeature {
-
- private final Context context;
- private final Host host;
-
- /**
- * Constructor.
- *
- * @param context context
- */
- public PoolingFeatureImpl(Context context, Host host) {
- this.context = context;
- this.host = host;
-
- /*
- * Note: do NOT extract anything from "context" at this point, because it hasn't been
- * fully initialized yet
- */
- }
-
- @Override
- public Properties getProperties(String featName) {
- Properties props = new Properties();
-
- props.setProperty(PoolingProperties.PROP_EXTRACTOR_PREFIX + ".java.util.Map", "${reqid}");
-
- props.setProperty(specialize(PoolingProperties.FEATURE_ENABLED, CONTROLLER1), "true");
- props.setProperty(specialize(PoolingProperties.POOLING_TOPIC, CONTROLLER1), INTERNAL_TOPIC);
- props.setProperty(specialize(PoolingProperties.OFFLINE_LIMIT, CONTROLLER1), "10000");
- props.setProperty(specialize(PoolingProperties.OFFLINE_AGE_MS, CONTROLLER1), "1000000");
- props.setProperty(specialize(PoolingProperties.OFFLINE_PUB_WAIT_MS, CONTROLLER1),
- "" + STD_OFFLINE_PUB_WAIT_MS);
- props.setProperty(specialize(PoolingProperties.START_HEARTBEAT_MS, CONTROLLER1),
- "" + STD_START_HEARTBEAT_MS);
- props.setProperty(specialize(PoolingProperties.REACTIVATE_MS, CONTROLLER1), "" + STD_REACTIVATE_WAIT_MS);
- props.setProperty(specialize(PoolingProperties.IDENTIFICATION_MS, CONTROLLER1), "" + STD_IDENTIFICATION_MS);
- props.setProperty(specialize(PoolingProperties.ACTIVE_HEARTBEAT_MS, CONTROLLER1),
- "" + STD_ACTIVE_HEARTBEAT_MS);
- props.setProperty(specialize(PoolingProperties.INTER_HEARTBEAT_MS, CONTROLLER1),
- "" + STD_INTER_HEARTBEAT_MS);
-
- props.putAll(makeSinkProperties(INTERNAL_TOPIC));
- props.putAll(makeSourceProperties(INTERNAL_TOPIC));
-
- return props;
- }
-
- @Override
- public PolicyController getController(DroolsController droolsController) {
- return context.getController(droolsController);
- }
-
- /**
- * Embeds a specializer within a property name, after the prefix.
- *
- * @param propnm property name into which it should be embedded
- * @param spec specializer to be embedded
- * @return the property name, with the specializer embedded within it
- */
- private String specialize(String propnm, String spec) {
- String suffix = propnm.substring(PREFIX.length());
- return PREFIX + spec + "." + suffix;
- }
-
- @Override
- protected PoolingManagerImpl makeManager(String hostName, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
-
- /*
- * Set this before creating the test, because the test's superclass
- * constructor uses it before the test object has a chance to store it.
- */
- currentHost.set(host);
-
- return new PoolingManagerTest(hostName, controller, props, activeLatch);
- }
- }
-
- /**
- * Pooling Manager with overrides.
- */
- private static class PoolingManagerTest extends PoolingManagerImpl {
-
- /**
- * Constructor.
- *
- * @param hostName the host
- * @param controller the controller
- * @param props the properties
- * @param activeLatch the latch
- */
- public PoolingManagerTest(String hostName, PolicyController controller,
- PoolingProperties props, CountDownLatch activeLatch) {
-
- super(hostName, controller, props, activeLatch);
- }
-
- @Override
- protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
- return new DmaapManagerImpl(topic);
- }
-
- @Override
- protected boolean canDecodeEvent(DroolsController drools, String topic) {
- return true;
- }
-
- @Override
- protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
- return decodeEvent(event);
- }
- }
-
- /**
- * DMaaP Manager with overrides.
- */
- private static class DmaapManagerImpl extends DmaapManager {
-
- /**
- * Constructor.
- *
- * @param topic the topic
- * @throws PoolingFeatureException if an error occurs
- */
- public DmaapManagerImpl(String topic) throws PoolingFeatureException {
- super(topic);
- }
-
- @Override
- protected List<TopicSource> getTopicSources() {
- Host host = currentHost.get();
- return Arrays.asList(host.internalSource, host.externalSource);
- }
-
- @Override
- protected List<TopicSink> getTopicSinks() {
- return Arrays.asList(internalSink, externalSink);
- }
- }
-
- /**
- * Controller that also implements the {@link TopicListener} interface.
- */
- private static interface ListenerController extends PolicyController, TopicListener {
-
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java
deleted file mode 100644
index bbd4c19f..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java
+++ /dev/null
@@ -1,1040 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.onap.policy.drools.pooling.PoolingProperties.PREFIX;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonParseException;
-import java.util.Arrays;
-import java.util.Deque;
-import java.util.IdentityHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
-import java.util.TreeMap;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import lombok.Getter;
-import org.apache.commons.lang3.tuple.Pair;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-import org.onap.policy.common.endpoints.event.comm.Topic;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyEngine;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * End-to-end tests of the pooling feature. Launches one or more "hosts", each one having
- * its own feature object. Uses real feature objects. However, the following are not:
- * <dl>
- * <dt>DMaaP sources and sinks</dt>
- * <dd>simulated using queues. There is one queue for the external topic, and one queue
- * for each host's internal topic. Messages published to the "admin" channel are simply
- * sent to all of the hosts' internal topic queues</dd>
- * <dt>PolicyEngine, PolicyController, DroolsController</dt>
- * <dd>mocked</dd>
- * </dl>
- *
- * <p>Invoke {@link #runSlow()}, before the test, to slow things down.
- */
-
-public class FeatureTest {
- private static final Logger logger = LoggerFactory.getLogger(FeatureTest.class);
- /**
- * Name of the topic used for inter-host communication.
- */
- private static final String INTERNAL_TOPIC = "my.internal.topic";
- /**
- * Name of the topic from which "external" events "arrive".
- */
- private static final String EXTERNAL_TOPIC = "my.external.topic";
- /**
- * Name of the controller.
- */
- private static final String CONTROLLER1 = "controller.one";
- private static long stdReactivateWaitMs = 200;
- private static long stdIdentificationMs = 60;
- private static long stdStartHeartbeatMs = 60;
- private static long stdActiveHeartbeatMs = 50;
- private static long stdInterHeartbeatMs = 5;
- private static long stdOfflinePubWaitMs = 2;
- private static long stdPollMs = 2;
- private static long stdInterPollMs = 2;
- private static long stdEventWaitSec = 10;
- /**
- * Used to decode events from the external topic.
- */
- private static final Gson mapper = new Gson();
- /**
- * Used to identify the current context.
- */
- private static final ThreadLocal<Context> currentContext = new ThreadLocal<Context>();
- /**
- * Context for the current test case.
- */
- private Context ctx;
- /**
- * Setup.
- */
-
- @Before
- public void setUp() {
- ctx = null;
- }
- /**
- * Tear down.
- */
-
- @After
- public void tearDown() {
- if (ctx != null) {
- ctx.destroy();
- }
- }
-
- @Test
- public void test_SingleHost() throws Exception {
- run(70, 1);
- }
-
- @Test
- public void test_TwoHosts() throws Exception {
- run(200, 2);
- }
-
- @Test
- public void test_ThreeHosts() throws Exception {
- run(200, 3);
- }
-
- private void run(int nmessages, int nhosts) throws Exception {
- ctx = new Context(nmessages);
- for (int x = 0; x < nhosts; ++x) {
- ctx.addHost();
- }
- ctx.startHosts();
- for (int x = 0; x < nmessages; ++x) {
- ctx.offerExternal(makeMessage(x));
- }
- ctx.awaitEvents(stdEventWaitSec, TimeUnit.SECONDS);
- assertEquals(0, ctx.getDecodeErrors());
- assertEquals(0, ctx.getRemainingEvents());
- ctx.checkAllSawAMsg();
- }
-
- private String makeMessage(int reqnum) {
- return "{\"reqid\":\"req" + reqnum + "\", \"data\":\"hello " + reqnum + "\"}";
- }
- /**
- * Invoke this to slow the timers down.
- */
-
- protected static void runSlow() {
- stdReactivateWaitMs = 10000;
- stdIdentificationMs = 10000;
- stdStartHeartbeatMs = 15000;
- stdActiveHeartbeatMs = 12000;
- stdInterHeartbeatMs = 5000;
- stdOfflinePubWaitMs = 2;
- stdPollMs = 2;
- stdInterPollMs = 2000;
- stdEventWaitSec = 1000;
- }
- /**
- * Decodes an event.
- *
- * @param event event
- * @return the decoded event, or {@code null} if it cannot be decoded
- */
-
- private static Object decodeEvent(String event) {
- try {
- return mapper.fromJson(event, TreeMap.class);
- } catch (JsonParseException e) {
- logger.warn("cannot decode external event", e);
- return null;
- }
- }
- /**
- * Context used for a single test case.
- */
-
- private static class Context {
- /**
- * Hosts that have been added to this context.
- */
- private final Deque<Host> hosts = new LinkedList<>();
- /**
- * Maps a drools controller to its policy controller.
- */
- private final IdentityHashMap<DroolsController, PolicyController> drools2policy = new IdentityHashMap<>();
- /**
- * Maps a channel to its queue. Does <i>not</i> include the "admin" channel.
- */
- private final ConcurrentMap<String, BlockingQueue<String>> channel2queue = new ConcurrentHashMap<>(7);
- /**
- * Counts the number of decode errors.
- */
- private final AtomicInteger numDecodeErrors = new AtomicInteger(0);
- /**
- * Number of events we're still waiting to receive.
- */
- private final CountDownLatch eventCounter;
- /**
- * The current host. Set by {@link #withHost(Host, VoidFunction)} and used by
- * {@link #getCurrentHost()}.
- */
- private Host currentHost = null;
-
- /**
- * Constructor.
- *
- * @param events number of events to be processed
- */
-
- public Context(int events) {
- eventCounter = new CountDownLatch(events);
- }
- /**
- * Destroys the context, stopping any hosts that remain.
- */
-
- public void destroy() {
- stopHosts();
- hosts.clear();
- }
-
- /**
- * Creates and adds a new host to the context.
- *
- * @return the new Host
- */
-
- public Host addHost() {
- Host host = new Host(this);
- hosts.add(host);
- return host;
- }
-
- /**
- * Starts the hosts.
- */
-
- public void startHosts() {
- hosts.forEach(host -> host.start());
- }
-
- /**
- * Stops the hosts.
- */
-
- public void stopHosts() {
- hosts.forEach(host -> host.stop());
- }
-
- /**
- * Verifies that all hosts processed at least one message.
- */
-
- public void checkAllSawAMsg() {
- int msgs = 0;
- for (Host host : hosts) {
- assertTrue("msgs=" + msgs, host.messageSeen());
- ++msgs;
- }
- }
-
- /**
- * Sets {@link #currentHost} to the specified host, and then invokes the given
- * function. Resets {@link #currentHost} to {@code null} before returning.
- *
- * @param host host
- * @param func function to invoke
- */
-
- public void withHost(Host host, VoidFunction func) {
- currentHost = host;
- func.apply();
- currentHost = null;
- }
-
- /**
- * Offers an event to the external topic. As each host needs a copy, it is posted
- * to each Host's queue.
- *
- * @param event event
- */
-
- public void offerExternal(String event) {
- for (Host host : hosts) {
- host.getExternalTopic().offer(event);
- }
- }
-
- /**
- * Adds an internal channel to the set of channels.
- *
- * @param channel channel
- * @param queue the channel's queue
- */
-
- public void addInternal(String channel, BlockingQueue<String> queue) {
- channel2queue.put(channel, queue);
- }
-
- /**
- * Offers a message to all internal channels.
- *
- * @param message message
- */
-
- public void offerInternal(String message) {
- channel2queue.values().forEach(queue -> queue.offer(message));
- }
-
- /**
- * Associates a controller with its drools controller.
- *
- * @param controller controller
- * @param droolsController drools controller
- */
-
- public void addController(PolicyController controller, DroolsController droolsController) {
- drools2policy.put(droolsController, controller);
- }
-
- /**
- * Get controller.
- *
- * @param droolsController drools controller
- * @return the controller associated with a drools controller, or {@code null} if
- * it has no associated controller
- */
-
- public PolicyController getController(DroolsController droolsController) {
- return drools2policy.get(droolsController);
- }
-
- /**
- * Get decode errors.
- *
- * @return the number of decode errors so far
- */
-
- public int getDecodeErrors() {
- return numDecodeErrors.get();
- }
-
- /**
- * Increments the count of decode errors.
- */
-
- public void bumpDecodeErrors() {
- numDecodeErrors.incrementAndGet();
- }
-
- /**
- * Get remaining events.
- *
- * @return the number of events that haven't been processed
- */
-
- public long getRemainingEvents() {
- return eventCounter.getCount();
- }
-
- /**
- * Adds an event to the counter.
- */
-
- public void addEvent() {
- eventCounter.countDown();
- }
-
- /**
- * Waits, for a period of time, for all events to be processed.
- *
- * @param time time
- * @param units units
- * @return {@code true} if all events have been processed, {@code false} otherwise
- * @throws InterruptedException throws interrupted
- */
-
- public boolean awaitEvents(long time, TimeUnit units) throws InterruptedException {
- return eventCounter.await(time, units);
- }
-
- /**
- * Gets the current host, provided this is used from within a call to
- * {@link #withHost(Host, VoidFunction)}.
- *
- * @return the current host, or {@code null} if there is no current host
- */
-
- public Host getCurrentHost() {
- return currentHost;
- }
- }
-
- /**
- * Simulates a single "host".
- */
-
- private static class Host {
- private final Context context;
- private final PoolingFeature feature;
-
- /**
- * {@code True} if this host has processed a message, {@code false} otherwise.
- */
-
- private final AtomicBoolean sawMsg = new AtomicBoolean(false);
-
- /**
- * This host's internal "DMaaP" topic.
- */
-
- private final BlockingQueue<String> msgQueue = new LinkedBlockingQueue<>();
-
- /**
- * Queue for the external "DMaaP" topic.
- */
- @Getter
- private final BlockingQueue<String> externalTopic = new LinkedBlockingQueue<String>();
-
- /**
- * Source that reads from the external topic and posts to the listener.
- */
-
- private TopicSource externalSource;
-
- // mock objects
- private final PolicyEngine engine = mock(PolicyEngine.class);
- private final ListenerController controller = mock(ListenerController.class);
- private final DroolsController drools = mock(DroolsController.class);
-
- /**
- * Constructor.
- *
- * @param context context
- */
-
- public Host(Context context) {
- this.context = context;
- when(controller.getName()).thenReturn(CONTROLLER1);
- when(controller.getDrools()).thenReturn(drools);
- // stop consuming events if the controller stops
- when(controller.stop()).thenAnswer(args -> {
- externalSource.unregister(controller);
- return true;
- });
- doAnswer(new MyExternalTopicListener(context, this)).when(controller).onTopicEvent(any(), any(), any());
- context.addController(controller, drools);
- // arrange to read from the external topic
- externalSource = new TopicSourceImpl(EXTERNAL_TOPIC, externalTopic);
- feature = new PoolingFeatureImpl(context);
- }
-
- /**
- * Get name.
- *
- * @return the host name
- */
-
- public String getName() {
- return feature.getHost();
- }
-
- /**
- * Starts threads for the host so that it begins consuming from both the external
- * "DMaaP" topic and its own internal "DMaaP" topic.
- */
-
- public void start() {
- context.withHost(this, () -> {
- feature.beforeStart(engine);
- feature.afterCreate(controller);
- // assign the queue for this host's internal topic
- context.addInternal(getName(), msgQueue);
- feature.beforeStart(controller);
- // start consuming events from the external topic
- externalSource.register(controller);
- feature.afterStart(controller);
- });
- }
-
- /**
- * Stops the host's threads.
- */
-
- public void stop() {
- feature.beforeStop(controller);
- externalSource.unregister(controller);
- feature.afterStop(controller);
- }
-
- /**
- * Offers an event to the feature, before the policy controller handles it.
- *
- * @param protocol protocol
- * @param topic2 topic
- * @param event event
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
-
- public boolean beforeOffer(CommInfrastructure protocol, String topic2, String event) {
- return feature.beforeOffer(controller, protocol, topic2, event);
- }
-
- /**
- * Offers an event to the feature, after the policy controller handles it.
- *
- * @param protocol protocol
- * @param topic topic
- * @param event event
- * @param success success
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
-
- public boolean afterOffer(CommInfrastructure protocol, String topic, String event, boolean success) {
- return feature.afterOffer(controller, protocol, topic, event, success);
- }
-
- /**
- * Offers an event to the feature, before the drools controller handles it.
- *
- * @param fact fact
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
-
- public boolean beforeInsert(Object fact) {
- return feature.beforeInsert(drools, fact);
- }
-
- /**
- * Offers an event to the feature, after the drools controller handles it.
- *
- * @param fact fact
- * @param successInsert {@code true} if it was successfully inserted by the drools
- * controller, {@code false} otherwise
- * @return {@code true} if the event was handled, {@code false} otherwise
- */
-
- public boolean afterInsert(Object fact, boolean successInsert) {
- return feature.afterInsert(drools, fact, successInsert);
- }
-
- /**
- * Indicates that a message was seen for this host.
- */
-
- public void sawMessage() {
- sawMsg.set(true);
- }
-
- /**
- * Message seen.
- *
- * @return {@code true} if a message was seen for this host, {@code false}
- * otherwise
- */
-
- public boolean messageSeen() {
- return sawMsg.get();
- }
-
- /**
- * Get internal queue.
- *
- * @return the queue associated with this host's internal topic
- */
-
- public BlockingQueue<String> getInternalQueue() {
- return msgQueue;
- }
- }
-
- /**
- * Listener for the external topic. Simulates the actions taken by
- * <i>AggregatedPolicyController.onTopicEvent</i>.
- */
-
- private static class MyExternalTopicListener implements Answer<Void> {
- private final Context context;
- private final Host host;
-
- public MyExternalTopicListener(Context context, Host host) {
- this.context = context;
- this.host = host;
- }
-
- @Override
- public Void answer(InvocationOnMock args) throws Throwable {
- int index = 0;
- CommInfrastructure commType = args.getArgument(index++);
- String topic = args.getArgument(index++);
- String event = args.getArgument(index++);
- if (host.beforeOffer(commType, topic, event)) {
- return null;
- }
- boolean result;
- Object fact = decodeEvent(event);
- if (fact == null) {
- result = false;
- context.bumpDecodeErrors();
- } else {
- result = true;
- if (!host.beforeInsert(fact)) {
- // feature did not handle it so we handle it here
- host.afterInsert(fact, result);
- host.sawMessage();
- context.addEvent();
- }
- }
- host.afterOffer(commType, topic, event, result);
- return null;
- }
- }
-
- /**
- * Sink implementation that puts a message on the queue specified by the
- * <i>channel</i> embedded within the message. If it's the "admin" channel, then the
- * message is placed on all queues.
- */
-
- private static class TopicSinkImpl extends TopicImpl implements TopicSink {
- private final Context context;
-
- /**
- * Constructor.
- *
- * @param context context
- */
-
- public TopicSinkImpl(Context context) {
- this.context = context;
- }
-
- @Override
- public synchronized boolean send(String message) {
- if (!isAlive()) {
- return false;
- }
- try {
- context.offerInternal(message);
- return true;
- } catch (JsonParseException e) {
- logger.warn("could not decode message: {}", message);
- context.bumpDecodeErrors();
- return false;
- }
- }
- }
-
- /**
- * Source implementation that reads from a queue associated with a topic.
- */
-
- private static class TopicSourceImpl extends TopicImpl implements TopicSource {
-
- private final String topic;
- /**
- * Queue from which to retrieve messages.
- */
- private final BlockingQueue<String> queue;
- /**
- * Manages the current consumer thread. The "first" item is used as a trigger to
- * tell the thread to stop processing, while the "second" item is triggered <i>by
- * the thread</i> when it completes.
- */
- private AtomicReference<Pair<CountDownLatch, CountDownLatch>> pair = new AtomicReference<>(null);
-
- /**
- * Constructor.
- *
- * @param type topic type
- * @param queue topic from which to read
- */
-
- public TopicSourceImpl(String type, BlockingQueue<String> queue) {
- this.topic = type;
- this.queue = queue;
- }
-
- @Override
- public String getTopic() {
- return topic;
- }
-
- @Override
- public boolean offer(String event) {
- throw new UnsupportedOperationException("offer topic source");
- }
-
- /**
- * Starts a thread that takes messages from the queue and gives them to the
- * listener. Stops the thread of any previously registered listener.
- */
-
- @Override
- public void register(TopicListener listener) {
- Pair<CountDownLatch, CountDownLatch> newPair = Pair.of(new CountDownLatch(1), new CountDownLatch(1));
- reregister(newPair);
- Thread thread = new Thread(() -> {
- try {
- do {
- processMessages(newPair.getLeft(), listener);
- } while (!newPair.getLeft().await(stdInterPollMs, TimeUnit.MILLISECONDS));
- logger.info("topic source thread completed");
- } catch (InterruptedException e) {
- logger.warn("topic source thread aborted", e);
- Thread.currentThread().interrupt();
- } catch (RuntimeException e) {
- logger.warn("topic source thread aborted", e);
- }
- newPair.getRight().countDown();
- });
- thread.setDaemon(true);
- thread.start();
- }
-
- /**
- * Stops the thread of <i>any</i> currently registered listener.
- */
-
- @Override
- public void unregister(TopicListener listener) {
- reregister(null);
- }
-
- /**
- * Registers a new "pair" with this source, stopping the consumer associated with
- * any previous registration.
- *
- * @param newPair the new "pair", or {@code null} to unregister
- */
-
- private void reregister(Pair<CountDownLatch, CountDownLatch> newPair) {
- try {
- Pair<CountDownLatch, CountDownLatch> oldPair = pair.getAndSet(newPair);
- if (oldPair == null) {
- if (newPair == null) {
- // unregister was invoked twice in a row
- logger.warn("re-unregister for topic source");
- }
- // no previous thread to stop
- return;
- }
- // need to stop the previous thread
- // tell it to stop
- oldPair.getLeft().countDown();
- // wait for it to stop
- if (!oldPair.getRight().await(2, TimeUnit.SECONDS)) {
- logger.warn("old topic registration is still running");
- }
- } catch (InterruptedException e) {
- logger.warn("old topic registration may still be running", e);
- Thread.currentThread().interrupt();
- }
- if (newPair != null) {
- // register was invoked twice in a row
- logger.warn("re-register for topic source");
- }
- }
-
- /**
- * Polls for messages from the topic and offers them to the listener.
- *
- * @param stopped triggered if processing should stop
- * @param listener listener
- * @throws InterruptedException throws interrupted exception
- */
-
- private void processMessages(CountDownLatch stopped, TopicListener listener) throws InterruptedException {
- for (int x = 0; x < 5 && stopped.getCount() > 0; ++x) {
- String msg = queue.poll(stdPollMs, TimeUnit.MILLISECONDS);
- if (msg == null) {
- return;
- }
- listener.onTopicEvent(CommInfrastructure.UEB, topic, msg);
- }
- }
- }
-
- /**
- * Topic implementation. Most methods just throw
- * {@link UnsupportedOperationException}.
- */
-
- private static class TopicImpl implements Topic {
-
- /**
- * Constructor.
- */
-
- public TopicImpl() {
- super();
- }
-
- @Override
- public String getTopic() {
- return INTERNAL_TOPIC;
- }
-
- @Override
- public String getEffectiveTopic() {
- return INTERNAL_TOPIC;
- }
-
- @Override
- public CommInfrastructure getTopicCommInfrastructure() {
- throw new UnsupportedOperationException("topic protocol");
- }
-
- @Override
- public List<String> getServers() {
- throw new UnsupportedOperationException("topic servers");
- }
-
- @Override
- public String[] getRecentEvents() {
- throw new UnsupportedOperationException("topic events");
- }
-
- @Override
- public void register(TopicListener topicListener) {
- throw new UnsupportedOperationException("register topic");
- }
-
- @Override
- public void unregister(TopicListener topicListener) {
- throw new UnsupportedOperationException("unregister topic");
- }
-
- @Override
- public synchronized boolean start() {
- return true;
- }
-
- @Override
- public synchronized boolean stop() {
- return true;
- }
-
- @Override
- public synchronized void shutdown() {
- // do nothing
- }
-
- @Override
- public synchronized boolean isAlive() {
- return true;
- }
-
- @Override
- public boolean lock() {
- throw new UnsupportedOperationException("lock topicink");
- }
-
- @Override
- public boolean unlock() {
- throw new UnsupportedOperationException("unlock topic");
- }
-
- @Override
- public boolean isLocked() {
- throw new UnsupportedOperationException("topic isLocked");
- }
- }
-
- /**
- * Feature with overrides.
- */
-
- private static class PoolingFeatureImpl extends PoolingFeature {
- private final Context context;
-
- /**
- * Constructor.
- *
- * @param context context
- */
-
- public PoolingFeatureImpl(Context context) {
- this.context = context;
- /*
- * Note: do NOT extract anything from "context" at this point, because it
- * hasn't been fully initialized yet
- */
- }
-
- @Override
- public Properties getProperties(String featName) {
- Properties props = new Properties();
- props.setProperty(PoolingProperties.PROP_EXTRACTOR_PREFIX + ".java.util.Map", "${reqid}");
- props.setProperty(specialize(PoolingProperties.FEATURE_ENABLED, CONTROLLER1), "true");
- props.setProperty(specialize(PoolingProperties.POOLING_TOPIC, CONTROLLER1), INTERNAL_TOPIC);
- props.setProperty(specialize(PoolingProperties.OFFLINE_LIMIT, CONTROLLER1), "10000");
- props.setProperty(specialize(PoolingProperties.OFFLINE_AGE_MS, CONTROLLER1), "1000000");
- props.setProperty(specialize(PoolingProperties.OFFLINE_PUB_WAIT_MS, CONTROLLER1),
- "" + stdOfflinePubWaitMs);
- props.setProperty(specialize(PoolingProperties.START_HEARTBEAT_MS, CONTROLLER1),
- "" + stdStartHeartbeatMs);
- props.setProperty(specialize(PoolingProperties.REACTIVATE_MS, CONTROLLER1), "" + stdReactivateWaitMs);
- props.setProperty(specialize(PoolingProperties.IDENTIFICATION_MS, CONTROLLER1), "" + stdIdentificationMs);
- props.setProperty(specialize(PoolingProperties.ACTIVE_HEARTBEAT_MS, CONTROLLER1),
- "" + stdActiveHeartbeatMs);
- props.setProperty(specialize(PoolingProperties.INTER_HEARTBEAT_MS, CONTROLLER1),
- "" + stdInterHeartbeatMs);
- return props;
- }
-
- @Override
- public PolicyController getController(DroolsController droolsController) {
- return context.getController(droolsController);
- }
-
- /**
- * Embeds a specializer within a property name, after the prefix.
- *
- * @param propnm property name into which it should be embedded
- * @param spec specializer to be embedded
- * @return the property name, with the specializer embedded within it
- */
-
- private String specialize(String propnm, String spec) {
- String suffix = propnm.substring(PREFIX.length());
- return PREFIX + spec + "." + suffix;
- }
-
- @Override
- protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
- currentContext.set(context);
- return new PoolingManagerTest(host, controller, props, activeLatch);
- }
- }
-
- /**
- * Pooling Manager with overrides.
- */
-
- private static class PoolingManagerTest extends PoolingManagerImpl {
-
- /**
- * Constructor.
- *
- * @param host the host
- * @param controller the controller
- * @param props the properties
- * @param activeLatch the latch
- */
-
- public PoolingManagerTest(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
- super(host, controller, props, activeLatch);
- }
-
- @Override
- protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
- return new DmaapManagerImpl(topic);
- }
-
- @Override
- protected boolean canDecodeEvent(DroolsController drools, String topic) {
- return true;
- }
-
- @Override
- protected Object decodeEventWrapper(DroolsController drools, String topic, String event) {
- return decodeEvent(event);
- }
- }
-
- /**
- * DMaaP Manager with overrides.
- */
-
- private static class DmaapManagerImpl extends DmaapManager {
-
- /**
- * Constructor.
- *
- * @param topic the topic
- * @throws PoolingFeatureException if an error occurs
- */
-
- public DmaapManagerImpl(String topic) throws PoolingFeatureException {
- super(topic);
- }
-
- @Override
- protected List<TopicSource> getTopicSources() {
- return Arrays.asList(new TopicSourceImpl(INTERNAL_TOPIC,
- currentContext.get().getCurrentHost().getInternalQueue()));
- }
-
- @Override
- protected List<TopicSink> getTopicSinks() {
- return Arrays.asList(new TopicSinkImpl(currentContext.get()));
- }
- }
-
- /**
- * Controller that also implements the {@link TopicListener} interface.
- */
-
- private static interface ListenerController extends PolicyController, TopicListener {
- }
-
- /**
- * Simple function that takes no arguments and returns nothing.
- */
-
- @FunctionalInterface
- private static interface VoidFunction {
- void apply();
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java
deleted file mode 100644
index 731736a1..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-import org.onap.policy.common.utils.test.ExceptionsTester;
-
-public class PoolingFeatureExceptionTest extends ExceptionsTester {
-
- @Test
- public void test() {
- assertEquals(5, test(PoolingFeatureException.class));
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java
deleted file mode 100644
index f505ccdf..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling;
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-import org.onap.policy.common.utils.test.ExceptionsTester;
-
-public class PoolingFeatureRtExceptionTest extends ExceptionsTester {
-
- @Test
- public void test() {
- assertEquals(5, test(PoolingFeatureRtException.class));
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java
deleted file mode 100644
index 02a4db5c..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java
+++ /dev/null
@@ -1,547 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.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.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.CountDownLatch;
-import org.apache.commons.lang3.tuple.Pair;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicSink;
-import org.onap.policy.common.endpoints.event.comm.TopicSource;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.system.PolicyController;
-import org.onap.policy.drools.system.PolicyEngine;
-
-public class PoolingFeatureTest {
-
- private static final String CONTROLLER1 = "controllerA";
- private static final String CONTROLLER2 = "controllerB";
- private static final String CONTROLLER_DISABLED = "controllerDisabled";
- private static final String CONTROLLER_EX = "controllerException";
- private static final String CONTROLLER_UNKNOWN = "controllerUnknown";
-
- private static final String TOPIC1 = "topic.one";
- private static final String TOPIC2 = "topic.two";
-
- private static final String EVENT1 = "event.one";
- private static final String EVENT2 = "event.two";
-
- private static final Object OBJECT1 = new Object();
- private static final Object OBJECT2 = new Object();
-
- private Properties props;
- private PolicyEngine engine;
- private PolicyController controller1;
- private PolicyController controller2;
- private PolicyController controllerDisabled;
- private PolicyController controllerException;
- private PolicyController controllerUnknown;
- private DroolsController drools1;
- private DroolsController drools2;
- private DroolsController droolsDisabled;
- private List<Pair<PoolingManagerImpl, PoolingProperties>> managers;
- private PoolingManagerImpl mgr1;
- private PoolingManagerImpl mgr2;
-
- private PoolingFeature pool;
-
- /**
- * Setup.
- *
- * @throws Exception exception
- */
- @Before
- public void setUp() throws Exception {
- props = initProperties();
- engine = mock(PolicyEngine.class);
- controller1 = mock(PolicyController.class);
- controller2 = mock(PolicyController.class);
- controllerDisabled = mock(PolicyController.class);
- controllerException = mock(PolicyController.class);
- controllerUnknown = mock(PolicyController.class);
- drools1 = mock(DroolsController.class);
- drools2 = mock(DroolsController.class);
- droolsDisabled = mock(DroolsController.class);
- managers = new LinkedList<>();
-
- when(controller1.getName()).thenReturn(CONTROLLER1);
- when(controller2.getName()).thenReturn(CONTROLLER2);
- when(controllerDisabled.getName()).thenReturn(CONTROLLER_DISABLED);
- when(controllerException.getName()).thenReturn(CONTROLLER_EX);
- when(controllerUnknown.getName()).thenReturn(CONTROLLER_UNKNOWN);
-
- pool = new PoolingFeatureImpl();
-
- pool.beforeStart(engine);
-
- pool.afterCreate(controller1);
- pool.afterCreate(controller2);
-
- mgr1 = managers.get(0).getLeft();
- mgr2 = managers.get(1).getLeft();
- }
-
- @Test
- public void test() {
- assertEquals(2, managers.size());
- }
-
- @Test
- public void testGetHost() {
- String host = pool.getHost();
- assertNotNull(host);
-
- // create another and ensure it generates another host name
- pool = new PoolingFeatureImpl();
- String host2 = pool.getHost();
- assertNotNull(host2);
-
- assertNotEquals(host, host2);
- }
-
- @Test
- public void testGetSequenceNumber() {
- assertEquals(0, pool.getSequenceNumber());
- }
-
- @Test
- public void testBeforeStartEngine() {
- pool = new PoolingFeatureImpl();
-
- assertFalse(pool.beforeStart(engine));
- }
-
- @Test
- public void testAfterCreate() {
- managers.clear();
- pool = new PoolingFeatureImpl();
- pool.beforeStart(engine);
-
- assertFalse(pool.afterCreate(controller1));
- assertEquals(1, managers.size());
-
- // duplicate
- assertFalse(pool.afterCreate(controller1));
- assertEquals(1, managers.size());
-
- // second controller
- assertFalse(pool.afterCreate(controller2));
- assertEquals(2, managers.size());
- }
-
- @Test
- public void testAfterCreate_NotEnabled() {
- managers.clear();
- pool = new PoolingFeatureImpl();
- pool.beforeStart(engine);
-
- assertFalse(pool.afterCreate(controllerDisabled));
- assertTrue(managers.isEmpty());
- }
-
- @Test(expected = PoolingFeatureRtException.class)
- public void testAfterCreate_PropertyEx() {
- managers.clear();
- pool = new PoolingFeatureImpl();
- pool.beforeStart(engine);
-
- pool.afterCreate(controllerException);
- }
-
- @Test(expected = PoolingFeatureRtException.class)
- public void testAfterCreate_NoProps() {
- pool = new PoolingFeatureImpl();
-
- // did not perform globalInit, which is an error
-
- pool.afterCreate(controller1);
- }
-
- @Test
- public void testAfterCreate_NoFeatProps() {
- managers.clear();
- pool = new PoolingFeatureImpl();
- pool.beforeStart(engine);
-
- assertFalse(pool.afterCreate(controllerUnknown));
- assertTrue(managers.isEmpty());
- }
-
- @Test
- public void testBeforeStart() throws Exception {
- assertFalse(pool.beforeStart(controller1));
- verify(mgr1).beforeStart();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeStart(controller1));
- verify(mgr1, times(2)).beforeStart();
-
- assertFalse(pool.beforeStart(controllerDisabled));
- }
-
- @Test
- public void testAfterStart() {
- assertFalse(pool.afterStart(controller1));
- verify(mgr1).afterStart();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.afterStart(controller1));
- verify(mgr1, times(2)).afterStart();
-
- assertFalse(pool.afterStart(controllerDisabled));
- }
-
- @Test
- public void testBeforeStop() {
- assertFalse(pool.beforeStop(controller1));
- verify(mgr1).beforeStop();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeStop(controller1));
- verify(mgr1, times(2)).beforeStop();
-
- assertFalse(pool.beforeStop(controllerDisabled));
- }
-
- @Test
- public void testAfterStop() {
- assertFalse(pool.afterStop(controller1));
- verify(mgr1).afterStop();
-
- assertFalse(pool.afterStop(controllerDisabled));
-
- // count should be unchanged
- verify(mgr1).afterStop();
- }
-
- @Test
- public void testAfterHalt() {
- assertFalse(pool.afterHalt(controller1));
- assertFalse(pool.afterHalt(controller1));
-
- verify(mgr1, never()).afterStop();
-
- assertFalse(pool.afterStop(controllerDisabled));
- }
-
- @Test
- public void testAfterShutdown() {
- assertFalse(pool.afterShutdown(controller1));
- assertFalse(pool.afterShutdown(controller1));
-
- verify(mgr1, never()).afterStop();
-
- assertFalse(pool.afterStop(controllerDisabled));
- }
-
- @Test
- public void testBeforeLock() {
- assertFalse(pool.beforeLock(controller1));
- verify(mgr1).beforeLock();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeLock(controller1));
- verify(mgr1, times(2)).beforeLock();
-
- assertFalse(pool.beforeLock(controllerDisabled));
- }
-
- @Test
- public void testAfterUnlock() {
- assertFalse(pool.afterUnlock(controller1));
- verify(mgr1).afterUnlock();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.afterUnlock(controller1));
- verify(mgr1, times(2)).afterUnlock();
-
- assertFalse(pool.afterUnlock(controllerDisabled));
- }
-
- @Test
- public void testBeforeOffer() {
- assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
- verify(mgr1).beforeOffer(TOPIC1, EVENT1);
-
- // ensure that the args were captured
- pool.beforeInsert(drools1, OBJECT1);
- verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
-
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
- verify(mgr1).beforeOffer(TOPIC2, EVENT2);
-
- // ensure that the new args were captured
- pool.beforeInsert(drools1, OBJECT2);
- verify(mgr1).beforeInsert(TOPIC2, OBJECT2);
-
-
- assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
- }
-
- @Test
- public void testBeforeOffer_NotFound() {
- assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
- }
-
- @Test
- public void testBeforeOffer_MgrTrue() {
-
- // manager will return true
- when(mgr1.beforeOffer(any(), any())).thenReturn(true);
-
- assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
- verify(mgr1).beforeOffer(TOPIC1, EVENT1);
-
- // ensure it's still in the map by re-invoking
- assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
- verify(mgr1).beforeOffer(TOPIC2, EVENT2);
-
- assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
- }
-
- @Test
- public void testBeforeInsert() {
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
-
- // ensure it's still in the map by re-invoking
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2);
- assertFalse(pool.beforeInsert(drools1, OBJECT2));
- verify(mgr1).beforeInsert(TOPIC2, OBJECT2);
-
- pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
- assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
- }
-
- @Test
- public void testBeforeInsert_NoArgs() {
-
- // call beforeInsert without beforeOffer
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
-
- assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
- }
-
- @Test
- public void testBeforeInsert_ArgEx() {
- // generate exception
- pool = new PoolingFeatureImpl() {
- @Override
- protected PolicyController getController(DroolsController droolsController) {
- throw new IllegalArgumentException();
- }
- };
-
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
- }
-
- @Test
- public void testBeforeInsert_StateEx() {
- // generate exception
- pool = new PoolingFeatureImpl() {
- @Override
- protected PolicyController getController(DroolsController droolsController) {
- throw new IllegalStateException();
- }
- };
-
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
- }
-
- @Test
- public void testBeforeInsert_NullController() {
-
- // return null controller
- pool = new PoolingFeatureImpl() {
- @Override
- protected PolicyController getController(DroolsController droolsController) {
- return null;
- }
- };
-
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
- }
-
- @Test
- public void testBeforeInsert_NotFound() {
-
- pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
- assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
- }
-
- @Test
- public void testAfterOffer() {
- // this will create OfferArgs
- pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
-
- // this should clear them
- assertFalse(pool.afterOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2, true));
-
- assertFalse(pool.beforeInsert(drools1, OBJECT1));
- verify(mgr1, never()).beforeInsert(any(), any());
-
-
- assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
- }
-
- @Test
- public void testDoManager() throws Exception {
- assertFalse(pool.beforeStart(controller1));
- verify(mgr1).beforeStart();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeStart(controller1));
- verify(mgr1, times(2)).beforeStart();
-
-
- // different controller
- assertFalse(pool.beforeStart(controller2));
- verify(mgr2).beforeStart();
-
- // ensure it's still in the map by re-invoking
- assertFalse(pool.beforeStart(controller2));
- verify(mgr2, times(2)).beforeStart();
-
-
- assertFalse(pool.beforeStart(controllerDisabled));
- }
-
- @Test
- public void testDoManager_NotFound() {
- assertFalse(pool.beforeStart(controllerDisabled));
- }
-
- @Test(expected = RuntimeException.class)
- public void testDoManager_Ex() throws Exception {
-
- // generate exception
- doThrow(new RuntimeException()).when(mgr1).beforeStart();
-
- pool.beforeStart(controller1);
- }
-
- private Properties initProperties() {
- Properties props = new Properties();
-
- initProperties(props, "A", 0);
- initProperties(props, "B", 1);
- initProperties(props, "Exception", 2);
-
- props.setProperty("pooling.controllerDisabled.enabled", "false");
-
- props.setProperty("pooling.controllerException.offline.queue.limit", "INVALID NUMBER");
-
- return props;
- }
-
- private void initProperties(Properties props, String suffix, int offset) {
- props.setProperty("pooling.controller" + suffix + ".topic", "topic." + suffix);
- props.setProperty("pooling.controller" + suffix + ".enabled", "true");
- props.setProperty("pooling.controller" + suffix + ".offline.queue.limit", String.valueOf(5 + offset));
- props.setProperty("pooling.controller" + suffix + ".offline.queue.age.milliseconds",
- String.valueOf(100 + offset));
- props.setProperty("pooling.controller" + suffix + ".start.heartbeat.milliseconds", String.valueOf(10 + offset));
- props.setProperty("pooling.controller" + suffix + ".reactivate.milliseconds", String.valueOf(20 + offset));
- props.setProperty("pooling.controller" + suffix + ".identification.milliseconds", String.valueOf(30 + offset));
- props.setProperty("pooling.controller" + suffix + ".active.heartbeat.milliseconds",
- String.valueOf(40 + offset));
- props.setProperty("pooling.controller" + suffix + ".inter.heartbeat.milliseconds", String.valueOf(50 + offset));
- }
-
- /**
- * Feature with overrides.
- */
- private class PoolingFeatureImpl extends PoolingFeature {
-
- @Override
- protected Properties getProperties(String featName) {
- if (PoolingProperties.FEATURE_NAME.equals(featName)) {
- return props;
- } else {
- throw new IllegalArgumentException("unknown feature name");
- }
- }
-
- @Override
- protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
-
- PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
-
- managers.add(Pair.of(mgr, props));
-
- return mgr;
- }
-
- @Override
- protected PolicyController getController(DroolsController droolsController) {
- if (droolsController == drools1) {
- return controller1;
- } else if (droolsController == drools2) {
- return controller2;
- } else if (droolsController == droolsDisabled) {
- return controllerDisabled;
- } else {
- throw new IllegalArgumentException("unknown drools controller");
- }
- }
-
- @Override
- protected List<TopicSource> initTopicSources(Properties props) {
- return Collections.emptyList();
- }
-
- @Override
- protected List<TopicSink> initTopicSinks(Properties props) {
- return Collections.emptyList();
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java
deleted file mode 100644
index 21bd62d1..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java
+++ /dev/null
@@ -1,994 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2020 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.pooling;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.contains;
-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.LinkedList;
-import java.util.Properties;
-import java.util.Queue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
-import org.onap.policy.common.endpoints.event.comm.TopicListener;
-import org.onap.policy.drools.controller.DroolsController;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.state.ActiveState;
-import org.onap.policy.drools.pooling.state.IdleState;
-import org.onap.policy.drools.pooling.state.InactiveState;
-import org.onap.policy.drools.pooling.state.QueryState;
-import org.onap.policy.drools.pooling.state.StartState;
-import org.onap.policy.drools.pooling.state.State;
-import org.onap.policy.drools.system.PolicyController;
-
-public class PoolingManagerImplTest {
-
- protected static final long STD_HEARTBEAT_WAIT_MS = 10;
- protected static final long STD_REACTIVATE_WAIT_MS = STD_HEARTBEAT_WAIT_MS + 1;
- protected static final long STD_IDENTIFICATION_MS = STD_REACTIVATE_WAIT_MS + 1;
- protected static final long STD_ACTIVE_HEARTBEAT_MS = STD_IDENTIFICATION_MS + 1;
- protected static final long STD_INTER_HEARTBEAT_MS = STD_ACTIVE_HEARTBEAT_MS + 1;
- protected static final long STD_OFFLINE_PUB_WAIT_MS = STD_INTER_HEARTBEAT_MS + 1;
-
- private static final String MY_HOST = "my.host";
- private static final String HOST2 = "other.host";
-
- private static final String MY_CONTROLLER = "my.controller";
- private static final String MY_TOPIC = "my.topic";
-
- private static final String TOPIC2 = "topic.two";
-
- private static final String THE_EVENT = "the event";
-
- private static final Object DECODED_EVENT = new Object();
-
- /**
- * Number of dmaap.publish() invocations that should be issued when the manager is
- * started.
- */
- private static final int START_PUB = 1;
-
- /**
- * Futures that have been allocated due to calls to scheduleXxx().
- */
- private Queue<ScheduledFuture<?>> futures;
-
- private PoolingProperties poolProps;
- private ListeningController controller;
- private DmaapManager dmaap;
- private boolean gotDmaap;
- private ScheduledThreadPoolExecutor sched;
- private int schedCount;
- private DroolsController drools;
- private Serializer ser;
- private CountDownLatch active;
-
- private PoolingManagerImpl mgr;
-
- /**
- * Setup.
- *
- * @throws Exception throws exception
- */
- @Before
- public void setUp() throws Exception {
- Properties plainProps = new Properties();
-
- poolProps = mock(PoolingProperties.class);
- when(poolProps.getSource()).thenReturn(plainProps);
- when(poolProps.getPoolingTopic()).thenReturn(MY_TOPIC);
- when(poolProps.getStartHeartbeatMs()).thenReturn(STD_HEARTBEAT_WAIT_MS);
- when(poolProps.getReactivateMs()).thenReturn(STD_REACTIVATE_WAIT_MS);
- when(poolProps.getIdentificationMs()).thenReturn(STD_IDENTIFICATION_MS);
- when(poolProps.getActiveHeartbeatMs()).thenReturn(STD_ACTIVE_HEARTBEAT_MS);
- when(poolProps.getInterHeartbeatMs()).thenReturn(STD_INTER_HEARTBEAT_MS);
- when(poolProps.getOfflinePubWaitMs()).thenReturn(STD_OFFLINE_PUB_WAIT_MS);
-
- futures = new LinkedList<>();
- ser = new Serializer();
- active = new CountDownLatch(1);
-
- dmaap = mock(DmaapManager.class);
- gotDmaap = false;
- controller = mock(ListeningController.class);
- sched = mock(ScheduledThreadPoolExecutor.class);
- schedCount = 0;
- drools = mock(DroolsController.class);
-
- when(controller.getName()).thenReturn(MY_CONTROLLER);
- when(controller.getDrools()).thenReturn(drools);
- when(controller.isAlive()).thenReturn(true);
-
- when(sched.schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class))).thenAnswer(args -> {
- ScheduledFuture<?> fut = mock(ScheduledFuture.class);
- futures.add(fut);
-
- return fut;
- });
-
- when(sched.scheduleWithFixedDelay(any(Runnable.class), any(Long.class), any(Long.class), any(TimeUnit.class)))
- .thenAnswer(args -> {
- ScheduledFuture<?> fut = mock(ScheduledFuture.class);
- futures.add(fut);
-
- return fut;
- });
-
- mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active);
- }
-
- @Test
- public void testPoolingManagerImpl() throws Exception {
- assertTrue(gotDmaap);
-
- State st = mgr.getCurrent();
- assertTrue(st instanceof IdleState);
-
- // ensure the state is attached to the manager
- assertEquals(mgr.getHost(), st.getHost());
- }
-
- @Test
- public void testPoolingManagerImpl_PoolEx() throws PoolingFeatureException {
- // throw an exception when we try to create the dmaap manager
- PoolingFeatureException ex = new PoolingFeatureException();
-
- assertThatThrownBy(() -> new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
- @Override
- protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
- throw ex;
- }
- }).isInstanceOf(PoolingFeatureRtException.class).hasCause(ex);
- }
-
- @Test
- public void testGetCurrent() throws Exception {
- assertEquals(IdleState.class, mgr.getCurrent().getClass());
-
- startMgr();
-
- assertEquals(StartState.class, mgr.getCurrent().getClass());
- }
-
- @Test
- public void testGetHost() {
- assertEquals(MY_HOST, mgr.getHost());
-
- mgr = new PoolingManagerTest(HOST2, controller, poolProps, active);
- assertEquals(HOST2, mgr.getHost());
- }
-
- @Test
- public void testGetTopic() {
- assertEquals(MY_TOPIC, mgr.getTopic());
- }
-
- @Test
- public void testGetProperties() {
- assertEquals(poolProps, mgr.getProperties());
- }
-
- @Test
- public void testBeforeStart() throws Exception {
- // not running yet
- mgr.beforeStart();
-
- verify(dmaap).startPublisher();
-
- assertEquals(1, schedCount);
- verify(sched).setMaximumPoolSize(1);
- verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
-
-
- // try again - nothing should happen
- mgr.beforeStart();
-
- verify(dmaap).startPublisher();
-
- assertEquals(1, schedCount);
- verify(sched).setMaximumPoolSize(1);
- verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false);
- }
-
- @Test
- public void testAfterStart() throws Exception {
- startMgr();
-
- verify(dmaap).startConsumer(mgr);
-
- State st = mgr.getCurrent();
- assertTrue(st instanceof StartState);
-
- // ensure the state is attached to the manager
- assertEquals(mgr.getHost(), st.getHost());
-
- ArgumentCaptor<Long> timeCap = ArgumentCaptor.forClass(Long.class);
- ArgumentCaptor<TimeUnit> unitCap = ArgumentCaptor.forClass(TimeUnit.class);
- verify(sched).schedule(any(Runnable.class), timeCap.capture(), unitCap.capture());
-
- assertEquals(STD_HEARTBEAT_WAIT_MS, timeCap.getValue().longValue());
- assertEquals(TimeUnit.MILLISECONDS, unitCap.getValue());
-
-
- // already started - nothing else happens
- mgr.afterStart();
-
- verify(dmaap).startConsumer(mgr);
-
- assertTrue(mgr.getCurrent() instanceof StartState);
-
- verify(sched).schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class));
- }
-
- @Test
- public void testBeforeStop() throws Exception {
- startMgr();
- mgr.startDistributing(makeAssignments(false));
-
- verify(dmaap, times(START_PUB)).publish(any());
-
- mgr.beforeStop();
-
- verify(dmaap).stopConsumer(mgr);
- verify(sched).shutdownNow();
- verify(dmaap, times(START_PUB + 1)).publish(any());
- verify(dmaap).publish(contains("offline"));
-
- assertTrue(mgr.getCurrent() instanceof IdleState);
-
- // verify that next message is handled locally
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- verify(dmaap, times(START_PUB + 1)).publish(any());
- }
-
- @Test
- public void testBeforeStop_NotRunning() throws Exception {
- final State st = mgr.getCurrent();
-
- mgr.beforeStop();
-
- verify(dmaap, never()).stopConsumer(any());
- verify(sched, never()).shutdownNow();
-
- // hasn't changed states either
- assertEquals(st, mgr.getCurrent());
- }
-
- @Test
- public void testBeforeStop_AfterPartialStart() throws Exception {
- // call beforeStart but not afterStart
- mgr.beforeStart();
-
- final State st = mgr.getCurrent();
-
- mgr.beforeStop();
-
- // should still shut the scheduler down
- verify(sched).shutdownNow();
-
- verify(dmaap, never()).stopConsumer(any());
-
- // hasn't changed states
- assertEquals(st, mgr.getCurrent());
- }
-
- @Test
- public void testAfterStop() throws Exception {
- startMgr();
- mgr.beforeStop();
-
- mgr.afterStop();
-
- verify(dmaap).stopPublisher(STD_OFFLINE_PUB_WAIT_MS);
- }
-
- @Test
- public void testBeforeLock() throws Exception {
- startMgr();
-
- mgr.beforeLock();
-
- assertTrue(mgr.getCurrent() instanceof IdleState);
- }
-
- @Test
- public void testAfterUnlock_AliveIdle() throws Exception {
- // this really shouldn't happen
-
- lockMgr();
-
- mgr.afterUnlock();
-
- // stays in idle state, because it has no scheduler
- assertTrue(mgr.getCurrent() instanceof IdleState);
- }
-
- @Test
- public void testAfterUnlock_AliveStarted() throws Exception {
- startMgr();
- lockMgr();
-
- mgr.afterUnlock();
-
- assertTrue(mgr.getCurrent() instanceof StartState);
- }
-
- @Test
- public void testAfterUnlock_StoppedIdle() throws Exception {
- startMgr();
- lockMgr();
-
- // controller is stopped
- when(controller.isAlive()).thenReturn(false);
-
- mgr.afterUnlock();
-
- assertTrue(mgr.getCurrent() instanceof IdleState);
- }
-
- @Test
- public void testAfterUnlock_StoppedStarted() throws Exception {
- startMgr();
-
- // Note: don't lockMgr()
-
- // controller is stopped
- when(controller.isAlive()).thenReturn(false);
-
- mgr.afterUnlock();
-
- assertTrue(mgr.getCurrent() instanceof StartState);
- }
-
- @Test
- public void testChangeState() throws Exception {
- // start should invoke changeState()
- startMgr();
-
- /*
- * now go offline while it's locked
- */
- lockMgr();
-
- // should have cancelled the timers
- assertEquals(2, futures.size());
- verify(futures.poll()).cancel(false);
- verify(futures.poll()).cancel(false);
-
- /*
- * now go back online
- */
- unlockMgr();
-
- // new timers should now be active
- assertEquals(2, futures.size());
- verify(futures.poll(), never()).cancel(false);
- verify(futures.poll(), never()).cancel(false);
- }
-
- @Test
- public void testSchedule() throws Exception {
- // must start the scheduler
- startMgr();
-
- CountDownLatch latch = new CountDownLatch(1);
-
- mgr.schedule(STD_ACTIVE_HEARTBEAT_MS, () -> {
- latch.countDown();
- return null;
- });
-
- // capture the task
- ArgumentCaptor<Runnable> taskCap = ArgumentCaptor.forClass(Runnable.class);
- ArgumentCaptor<Long> timeCap = ArgumentCaptor.forClass(Long.class);
- ArgumentCaptor<TimeUnit> unitCap = ArgumentCaptor.forClass(TimeUnit.class);
-
- verify(sched, times(2)).schedule(taskCap.capture(), timeCap.capture(), unitCap.capture());
-
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timeCap.getValue().longValue());
- assertEquals(TimeUnit.MILLISECONDS, unitCap.getValue());
-
- // execute it
- taskCap.getValue().run();
-
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testScheduleWithFixedDelay() throws Exception {
- // must start the scheduler
- startMgr();
-
- CountDownLatch latch = new CountDownLatch(1);
-
- mgr.scheduleWithFixedDelay(STD_HEARTBEAT_WAIT_MS, STD_ACTIVE_HEARTBEAT_MS, () -> {
- latch.countDown();
- return null;
- });
-
- // capture the task
- ArgumentCaptor<Runnable> taskCap = ArgumentCaptor.forClass(Runnable.class);
- ArgumentCaptor<Long> initCap = ArgumentCaptor.forClass(Long.class);
- ArgumentCaptor<Long> timeCap = ArgumentCaptor.forClass(Long.class);
- ArgumentCaptor<TimeUnit> unitCap = ArgumentCaptor.forClass(TimeUnit.class);
-
- verify(sched, times(2)).scheduleWithFixedDelay(taskCap.capture(), initCap.capture(), timeCap.capture(),
- unitCap.capture());
-
- assertEquals(STD_HEARTBEAT_WAIT_MS, initCap.getValue().longValue());
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timeCap.getValue().longValue());
- assertEquals(TimeUnit.MILLISECONDS, unitCap.getValue());
-
- // execute it
- taskCap.getValue().run();
-
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testPublishAdmin() throws Exception {
- Offline msg = new Offline(mgr.getHost());
- mgr.publishAdmin(msg);
-
- assertEquals(Message.ADMIN, msg.getChannel());
-
- verify(dmaap).publish(any());
- }
-
- @Test
- public void testPublish() throws Exception {
- Offline msg = new Offline(mgr.getHost());
- mgr.publish("my.channel", msg);
-
- assertEquals("my.channel", msg.getChannel());
-
- verify(dmaap).publish(any());
- }
-
- @Test
- public void testPublish_InvalidMsg() throws Exception {
- // message is missing data
- mgr.publish(Message.ADMIN, new Offline());
-
- // should not have attempted to publish it
- verify(dmaap, never()).publish(any());
- }
-
- @Test
- public void testPublish_DmaapEx() throws Exception {
-
- // generate exception
- doThrow(new PoolingFeatureException()).when(dmaap).publish(any());
-
- assertThatCode(() -> mgr.publish(Message.ADMIN, new Offline(mgr.getHost()))).doesNotThrowAnyException();
- }
-
- @Test
- public void testOnTopicEvent() throws Exception {
- startMgr();
-
- StartState st = (StartState) mgr.getCurrent();
-
- /*
- * give it its heart beat, that should cause it to transition to the Query state.
- */
- Heartbeat hb = new Heartbeat(mgr.getHost(), st.getHbTimestampMs());
- hb.setChannel(Message.ADMIN);
-
- String msg = ser.encodeMsg(hb);
-
- mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, msg);
-
- assertTrue(mgr.getCurrent() instanceof QueryState);
- }
-
- @Test
- public void testOnTopicEvent_NullEvent() throws Exception {
- startMgr();
-
- assertThatCode(() -> mgr.onTopicEvent(CommInfrastructure.UEB, TOPIC2, null)).doesNotThrowAnyException();
- }
-
- @Test
- public void testBeforeOffer_Unlocked() throws Exception {
- startMgr();
-
- // route the message to another host
- mgr.startDistributing(makeAssignments(false));
-
- assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testBeforeOffer_Locked() throws Exception {
- startMgr();
- lockMgr();
-
- // route the message to another host
- mgr.startDistributing(makeAssignments(false));
-
- assertTrue(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testBeforeInsert() throws Exception {
- startMgr();
- lockMgr();
-
- // route the message to this host
- mgr.startDistributing(makeAssignments(true));
-
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- }
-
- @Test
- public void testHandleExternalCommInfrastructureStringStringString_NullReqId() throws Exception {
- validateHandleReqId(null);
- }
-
- @Test
- public void testHandleExternalCommInfrastructureStringStringString_EmptyReqId() throws Exception {
- validateHandleReqId("");
- }
-
- @Test
- public void testHandleExternalCommInfrastructureStringStringString_InvalidMsg() throws Exception {
- startMgr();
-
- assertFalse(mgr.beforeInsert(TOPIC2, "invalid message"));
- }
-
- @Test
- public void testHandleExternalCommInfrastructureStringStringString() throws Exception {
- validateUnhandled();
- }
-
- @Test
- public void testHandleExternalForward_NoAssignments() throws Exception {
- validateUnhandled();
- }
-
- @Test
- public void testHandleExternalForward() throws Exception {
- validateNoForward();
- }
-
- @Test
- public void testHandleEvent_NullTarget() throws Exception {
- // buckets have null targets
- validateDiscarded(new BucketAssignments(new String[] {null, null}));
- }
-
- @Test
- public void testHandleEvent_SameHost() throws Exception {
- validateNoForward();
- }
-
- @Test
- public void testHandleEvent_DiffHost() throws Exception {
- // route the message to the *OTHER* host
- validateDiscarded(makeAssignments(false));
- }
-
- @Test
- public void testDecodeEvent_CannotDecode() throws Exception {
-
- mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
- @Override
- protected boolean canDecodeEvent(DroolsController drools2, String topic2) {
- return false;
- }
- };
-
- startMgr();
-
- when(controller.isLocked()).thenReturn(true);
-
- // create assignments, though they are irrelevant
- mgr.startDistributing(makeAssignments(false));
-
- assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testDecodeEvent_UnsuppEx() throws Exception {
-
- // generate exception
- mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
- @Override
- protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
- throw new UnsupportedOperationException();
- }
- };
-
- startMgr();
-
- when(controller.isLocked()).thenReturn(true);
-
- // create assignments, though they are irrelevant
- mgr.startDistributing(makeAssignments(false));
-
- assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testDecodeEvent_ArgEx() throws Exception {
- // generate exception
- mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
- @Override
- protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
- throw new IllegalArgumentException();
- }
- };
-
- startMgr();
-
- when(controller.isLocked()).thenReturn(true);
-
- // create assignments, though they are irrelevant
- mgr.startDistributing(makeAssignments(false));
-
- assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testDecodeEvent_StateEx() throws Exception {
- // generate exception
- mgr = new PoolingManagerTest(MY_HOST, controller, poolProps, active) {
- @Override
- protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
- throw new IllegalStateException();
- }
- };
-
- startMgr();
-
- when(controller.isLocked()).thenReturn(true);
-
- // create assignments, though they are irrelevant
- mgr.startDistributing(makeAssignments(false));
-
- assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testDecodeEvent() throws Exception {
- startMgr();
-
- when(controller.isLocked()).thenReturn(true);
-
- // route to another host
- mgr.startDistributing(makeAssignments(false));
-
- assertTrue(mgr.beforeOffer(TOPIC2, THE_EVENT));
- }
-
- @Test
- public void testHandleInternal() throws Exception {
- startMgr();
-
- StartState st = (StartState) mgr.getCurrent();
-
- /*
- * give it its heart beat, that should cause it to transition to the Query state.
- */
- Heartbeat hb = new Heartbeat(mgr.getHost(), st.getHbTimestampMs());
- hb.setChannel(Message.ADMIN);
-
- String msg = ser.encodeMsg(hb);
-
- mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, msg);
-
- assertTrue(mgr.getCurrent() instanceof QueryState);
- }
-
- @Test
- public void testHandleInternal_IoEx() throws Exception {
- startMgr();
-
- mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, "invalid message");
-
- assertTrue(mgr.getCurrent() instanceof StartState);
- }
-
- @Test
- public void testHandleInternal_PoolEx() throws Exception {
- startMgr();
-
- StartState st = (StartState) mgr.getCurrent();
-
- Heartbeat hb = new Heartbeat(mgr.getHost(), st.getHbTimestampMs());
-
- /*
- * do NOT set the channel - this will cause the message to be invalid, triggering
- * an exception
- */
-
- String msg = ser.encodeMsg(hb);
-
- mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, msg);
-
- assertTrue(mgr.getCurrent() instanceof StartState);
- }
-
- @Test
- public void testStartDistributing() throws Exception {
- validateNoForward();
-
-
- // null assignments should cause message to be processed locally
- mgr.startDistributing(null);
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- verify(dmaap, times(START_PUB)).publish(any());
-
-
- // message for this host
- mgr.startDistributing(makeAssignments(true));
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
-
-
- // message for another host
- mgr.startDistributing(makeAssignments(false));
- assertTrue(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- }
-
- @Test
- public void testGoStart() {
- State st = mgr.goStart();
- assertTrue(st instanceof StartState);
- assertEquals(mgr.getHost(), st.getHost());
- }
-
- @Test
- public void testGoQuery() {
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST2});
- mgr.startDistributing(asgn);
-
- State st = mgr.goQuery();
-
- assertTrue(st instanceof QueryState);
- assertEquals(mgr.getHost(), st.getHost());
- assertEquals(asgn, mgr.getAssignments());
- }
-
- @Test
- public void testGoActive() {
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST2});
- mgr.startDistributing(asgn);
-
- State st = mgr.goActive();
-
- assertTrue(st instanceof ActiveState);
- assertEquals(mgr.getHost(), st.getHost());
- assertEquals(asgn, mgr.getAssignments());
- assertEquals(0, active.getCount());
- }
-
- @Test
- public void testGoInactive() {
- State st = mgr.goInactive();
- assertTrue(st instanceof InactiveState);
- assertEquals(mgr.getHost(), st.getHost());
- assertEquals(1, active.getCount());
- }
-
- @Test
- public void testTimerActionRun() throws Exception {
- // must start the scheduler
- startMgr();
-
- CountDownLatch latch = new CountDownLatch(1);
-
- mgr.schedule(STD_ACTIVE_HEARTBEAT_MS, () -> {
- latch.countDown();
- return null;
- });
-
- // capture the task
- ArgumentCaptor<Runnable> taskCap = ArgumentCaptor.forClass(Runnable.class);
-
- verify(sched, times(2)).schedule(taskCap.capture(), any(Long.class), any(TimeUnit.class));
-
- // execute it
- taskCap.getValue().run();
-
- assertEquals(0, latch.getCount());
- }
-
- @Test
- public void testTimerActionRun_DiffState() throws Exception {
- // must start the scheduler
- startMgr();
-
- CountDownLatch latch = new CountDownLatch(1);
-
- mgr.schedule(STD_ACTIVE_HEARTBEAT_MS, () -> {
- latch.countDown();
- return null;
- });
-
- // capture the task
- ArgumentCaptor<Runnable> taskCap = ArgumentCaptor.forClass(Runnable.class);
-
- verify(sched, times(2)).schedule(taskCap.capture(), any(Long.class), any(TimeUnit.class));
-
- // give it a heartbeat so that it transitions to the query state
- StartState st = (StartState) mgr.getCurrent();
- Heartbeat hb = new Heartbeat(mgr.getHost(), st.getHbTimestampMs());
- hb.setChannel(Message.ADMIN);
-
- String msg = ser.encodeMsg(hb);
-
- mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, msg);
-
- assertTrue(mgr.getCurrent() instanceof QueryState);
-
- // execute it
- taskCap.getValue().run();
-
- // it should NOT have counted down
- assertEquals(1, latch.getCount());
- }
-
- private void validateHandleReqId(String requestId) throws PoolingFeatureException {
- startMgr();
-
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- }
-
- private void validateNoForward() throws PoolingFeatureException {
- startMgr();
-
- // route the message to this host
- mgr.startDistributing(makeAssignments(true));
-
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
-
- verify(dmaap, times(START_PUB)).publish(any());
- }
-
- private void validateUnhandled() throws PoolingFeatureException {
- startMgr();
- assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- }
-
- private void validateDiscarded(BucketAssignments bucketAssignments) throws PoolingFeatureException {
- startMgr();
-
- // buckets have null targets
- mgr.startDistributing(bucketAssignments);
-
- assertTrue(mgr.beforeInsert(TOPIC2, DECODED_EVENT));
- }
-
- /**
- * Makes an assignment with two buckets.
- *
- * @param sameHost {@code true} if the {@link #REQUEST_ID} should hash to the
- * manager's bucket, {@code false} if it should hash to the other host's bucket
- * @return a new bucket assignment
- */
- private BucketAssignments makeAssignments(boolean sameHost) {
- int slot = DECODED_EVENT.hashCode() % 2;
-
- // slot numbers are 0 and 1 - reverse them if it's for a different host
- if (!sameHost) {
- slot = 1 - slot;
- }
-
- String[] asgn = new String[2];
- asgn[slot] = mgr.getHost();
- asgn[1 - slot] = HOST2;
-
- return new BucketAssignments(asgn);
- }
-
- /**
- * Invokes methods necessary to start the manager.
- *
- * @throws PoolingFeatureException if an error occurs
- */
- private void startMgr() throws PoolingFeatureException {
- mgr.beforeStart();
- mgr.afterStart();
- }
-
- /**
- * Invokes methods necessary to lock the manager.
- */
- private void lockMgr() {
- mgr.beforeLock();
- when(controller.isLocked()).thenReturn(true);
- }
-
- /**
- * Invokes methods necessary to unlock the manager.
- */
- private void unlockMgr() {
- mgr.afterUnlock();
- when(controller.isLocked()).thenReturn(false);
- }
-
- /**
- * Used to create a mock object that implements both super interfaces.
- */
- private static interface ListeningController extends TopicListener, PolicyController {
-
- }
-
- /**
- * Manager with overrides.
- */
- private class PoolingManagerTest extends PoolingManagerImpl {
-
- public PoolingManagerTest(String host, PolicyController controller, PoolingProperties props,
- CountDownLatch activeLatch) {
-
- super(host, controller, props, activeLatch);
- }
-
- @Override
- protected DmaapManager makeDmaapManager(String topic) throws PoolingFeatureException {
- gotDmaap = true;
- return dmaap;
- }
-
- @Override
- protected ScheduledThreadPoolExecutor makeScheduler() {
- ++schedCount;
- return sched;
- }
-
- @Override
- protected boolean canDecodeEvent(DroolsController drools2, String topic2) {
- return (drools2 == drools && TOPIC2.equals(topic2));
- }
-
- @Override
- protected Object decodeEventWrapper(DroolsController drools2, String topic2, String event) {
- if (drools2 == drools && TOPIC2.equals(topic2) && event == THE_EVENT) {
- return DECODED_EVENT;
- } else {
- return null;
- }
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java
deleted file mode 100644
index b15908dc..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 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.pooling;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.junit.Assert.assertEquals;
-import static org.onap.policy.drools.pooling.PoolingProperties.ACTIVE_HEARTBEAT_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.FEATURE_ENABLED;
-import static org.onap.policy.drools.pooling.PoolingProperties.IDENTIFICATION_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.INTER_HEARTBEAT_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.OFFLINE_AGE_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.OFFLINE_LIMIT;
-import static org.onap.policy.drools.pooling.PoolingProperties.OFFLINE_PUB_WAIT_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.POOLING_TOPIC;
-import static org.onap.policy.drools.pooling.PoolingProperties.PREFIX;
-import static org.onap.policy.drools.pooling.PoolingProperties.REACTIVATE_MS;
-import static org.onap.policy.drools.pooling.PoolingProperties.START_HEARTBEAT_MS;
-
-import java.util.Properties;
-import java.util.function.Function;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.common.utils.properties.exception.PropertyException;
-
-public class PoolingPropertiesTest {
-
- private static final String CONTROLLER = "a.controller";
-
- private static final String STD_POOLING_TOPIC = "my.topic";
- public static final boolean STD_FEATURE_ENABLED = true;
- public static final int STD_OFFLINE_LIMIT = 10;
- public static final long STD_OFFLINE_AGE_MS = 1000L;
- public static final long STD_OFFLINE_PUB_WAIT_MS = 2000L;
- public static final long STD_START_HEARTBEAT_MS = 3000L;
- public static final long STD_REACTIVATE_MS = 4000L;
- public static final long STD_IDENTIFICATION_MS = 5000L;
- public static final long STD_LEADER_MS = 6000L;
- public static final long STD_ACTIVE_HEARTBEAT_MS = 7000L;
- public static final long STD_INTER_HEARTBEAT_MS = 8000L;
-
- private Properties plain;
- private PoolingProperties pooling;
-
- /**
- * Setup.
- *
- * @throws Exception throws an exception
- */
- @Before
- public void setUp() throws Exception {
- plain = makeProperties();
-
- pooling = new PoolingProperties(CONTROLLER, plain);
- }
-
- @Test
- public void testPoolingProperties() throws PropertyException {
- // ensure no exceptions
- assertThatCode(() -> new PoolingProperties(CONTROLLER, plain)).doesNotThrowAnyException();
- }
-
- @Test
- public void testGetSource() {
- assertEquals(plain, pooling.getSource());
- }
-
- @Test
- public void testGetPoolingTopic() {
- assertEquals(STD_POOLING_TOPIC, pooling.getPoolingTopic());
- }
-
- @Test
- public void testGetOfflineLimit() throws PropertyException {
- doTest(OFFLINE_LIMIT, STD_OFFLINE_LIMIT, 1000, xxx -> pooling.getOfflineLimit());
- }
-
- @Test
- public void testGetOfflineAgeMs() throws PropertyException {
- doTest(OFFLINE_AGE_MS, STD_OFFLINE_AGE_MS, 60000L, xxx -> pooling.getOfflineAgeMs());
- }
-
- @Test
- public void testGetOfflinePubWaitMs() throws PropertyException {
- doTest(OFFLINE_PUB_WAIT_MS, STD_OFFLINE_PUB_WAIT_MS, 3000L, xxx -> pooling.getOfflinePubWaitMs());
- }
-
- @Test
- public void testGetStartHeartbeatMs() throws PropertyException {
- doTest(START_HEARTBEAT_MS, STD_START_HEARTBEAT_MS, 100000L, xxx -> pooling.getStartHeartbeatMs());
- }
-
- @Test
- public void testGetReactivateMs() throws PropertyException {
- doTest(REACTIVATE_MS, STD_REACTIVATE_MS, 50000L, xxx -> pooling.getReactivateMs());
- }
-
- @Test
- public void testGetIdentificationMs() throws PropertyException {
- doTest(IDENTIFICATION_MS, STD_IDENTIFICATION_MS, 50000L, xxx -> pooling.getIdentificationMs());
- }
-
- @Test
- public void testGetActiveHeartbeatMs() throws PropertyException {
- doTest(ACTIVE_HEARTBEAT_MS, STD_ACTIVE_HEARTBEAT_MS, 50000L, xxx -> pooling.getActiveHeartbeatMs());
- }
-
- @Test
- public void testGetInterHeartbeatMs() throws PropertyException {
- doTest(INTER_HEARTBEAT_MS, STD_INTER_HEARTBEAT_MS, 15000L, xxx -> pooling.getInterHeartbeatMs());
- }
-
- /**
- * Tests a particular property. Verifies that the correct value is returned if the
- * specialized property has a value or the property has no value. Also verifies that
- * the property name can be generalized.
- *
- * @param propnm name of the property of interest
- * @param specValue expected specialized value
- * @param dfltValue expected default value
- * @param func function to get the field
- * @throws PropertyException if an error occurs
- */
- private <T> void doTest(String propnm, T specValue, T dfltValue, Function<Void, T> func) throws PropertyException {
- /*
- * With specialized property
- */
- pooling = new PoolingProperties(CONTROLLER, plain);
- assertEquals("special " + propnm, specValue, func.apply(null));
-
- /*
- * Without the property - should use the default value.
- */
- plain.remove(specialize(propnm, CONTROLLER));
- plain.remove(propnm);
- pooling = new PoolingProperties(CONTROLLER, plain);
- assertEquals("default " + propnm, dfltValue, func.apply(null));
- }
-
- /**
- * Makes a set of properties, where all of the properties are specialized for the
- * controller.
- *
- * @return a new property set
- */
- private Properties makeProperties() {
- Properties props = new Properties();
-
- props.setProperty(specialize(POOLING_TOPIC, CONTROLLER), STD_POOLING_TOPIC);
- props.setProperty(specialize(FEATURE_ENABLED, CONTROLLER), "" + STD_FEATURE_ENABLED);
- props.setProperty(specialize(OFFLINE_LIMIT, CONTROLLER), "" + STD_OFFLINE_LIMIT);
- props.setProperty(specialize(OFFLINE_AGE_MS, CONTROLLER), "" + STD_OFFLINE_AGE_MS);
- props.setProperty(specialize(OFFLINE_PUB_WAIT_MS, CONTROLLER), "" + STD_OFFLINE_PUB_WAIT_MS);
- props.setProperty(specialize(START_HEARTBEAT_MS, CONTROLLER), "" + STD_START_HEARTBEAT_MS);
- props.setProperty(specialize(REACTIVATE_MS, CONTROLLER), "" + STD_REACTIVATE_MS);
- props.setProperty(specialize(IDENTIFICATION_MS, CONTROLLER), "" + STD_IDENTIFICATION_MS);
- props.setProperty(specialize(ACTIVE_HEARTBEAT_MS, CONTROLLER), "" + STD_ACTIVE_HEARTBEAT_MS);
- props.setProperty(specialize(INTER_HEARTBEAT_MS, CONTROLLER), "" + STD_INTER_HEARTBEAT_MS);
-
- return props;
- }
-
- /**
- * Embeds a specializer within a property name, after the prefix.
- *
- * @param propnm property name into which it should be embedded
- * @param spec specializer to be embedded
- * @return the property name, with the specializer embedded within it
- */
- private String specialize(String propnm, String spec) {
- String suffix = propnm.substring(PREFIX.length());
- return PREFIX + spec + "." + suffix;
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java
deleted file mode 100644
index f4cd940c..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-2020 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.pooling;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import com.google.gson.JsonParseException;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class SerializerTest {
-
- @Test
- public void testSerializer() {
- assertThatCode(() -> new Serializer()).doesNotThrowAnyException();
- }
-
- @Test
- public void testEncodeMsg_testDecodeMsg() throws Exception {
- Serializer ser = new Serializer();
-
- Query msg = new Query("hostA");
- msg.setChannel("channelB");
-
- String encoded = ser.encodeMsg(msg);
- assertNotNull(encoded);
-
- Message decoded = ser.decodeMsg(encoded);
- assertEquals(Query.class, decoded.getClass());
-
- assertEquals(msg.getSource(), decoded.getSource());
- assertEquals(msg.getChannel(), decoded.getChannel());
-
- // should work a second time, too
- encoded = ser.encodeMsg(msg);
- assertNotNull(encoded);
-
- decoded = ser.decodeMsg(encoded);
- assertEquals(Query.class, decoded.getClass());
-
- assertEquals(msg.getSource(), decoded.getSource());
- assertEquals(msg.getChannel(), decoded.getChannel());
-
- // invalid subclass when encoding
- Message msg2 = new Message() {};
- assertThatThrownBy(() -> ser.encodeMsg(msg2)).isInstanceOf(JsonParseException.class)
- .hasMessageContaining("cannot serialize");
-
- // missing type when decoding
- final String enc2 = encoded.replaceAll("type", "other-field-name");
-
- assertThatThrownBy(() -> ser.decodeMsg(enc2)).isInstanceOf(JsonParseException.class)
- .hasMessageContaining("does not contain a field named");
-
- // invalid type
- final String enc3 = encoded.replaceAll("query", "invalid-type");
-
- assertThatThrownBy(() -> ser.decodeMsg(enc3)).isInstanceOf(JsonParseException.class)
- .hasMessage("cannot deserialize \"invalid-type\"");
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/feature-pooling-dmaap.properties b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/feature-pooling-dmaap.properties
deleted file mode 100644
index 3273a21e..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/feature-pooling-dmaap.properties
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2018 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.
-
-pooling.controllerA.topic = topic.A
-pooling.controllerA.enabled = true
-pooling.controllerA.offline.queue.limit = 5
-pooling.controllerA.offline.queue.age.milliseconds = 100
-pooling.controllerA.start.heartbeat.milliseconds = 10
-pooling.controllerA.reactivate.milliseconds = 20
-pooling.controllerA.identification.milliseconds = 30
-pooling.controllerA.active.heartbeat.milliseconds = 40
-pooling.controllerA.inter.heartbeat.milliseconds = 50
-
-pooling.controllerB.topic = topic.B
-pooling.controllerB.enabled = true
-pooling.controllerB.offline.queue.limit = 6
-pooling.controllerB.offline.queue.age.milliseconds = 101
-pooling.controllerB.start.heartbeat.milliseconds = 11
-pooling.controllerB.reactivate.milliseconds = 21
-pooling.controllerB.identification.milliseconds = 31
-pooling.controllerB.active.heartbeat.milliseconds = 41
-pooling.controllerB.inter.heartbeat.milliseconds = 51
-
-pooling.controllerDisabled.enabled = false
-
-# this has an invalid property
-pooling.controllerException.topic = topic.B
-pooling.controllerException.enabled = true
-pooling.controllerException.offline.queue.limit = INVALID NUMBER
-pooling.controllerException.offline.queue.age.milliseconds = 101
-pooling.controllerException.start.heartbeat.milliseconds = 11
-pooling.controllerException.reactivate.milliseconds = 21
-pooling.controllerException.identification.milliseconds = 31
-pooling.controllerException.active.heartbeat.milliseconds = 41
-pooling.controllerException.inter.heartbeat.milliseconds = 51
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java
deleted file mode 100644
index 5eaeddca..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 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.pooling.message;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.util.Arrays;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-
-public class BucketAssignmentsTest {
-
- @Test
- public void testBucketAssignments() {
- assertThatCode(() -> new BucketAssignments()).doesNotThrowAnyException();
- }
-
- @Test
- public void testBucketAssignmentsStringArray() {
- String[] arr = {"abc", "def"};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertNotNull(asgn.getHostArray());
- assertEquals(arr.toString(), asgn.getHostArray().toString());
- }
-
- @Test
- public void testGetHostArray_testSetHostArray() {
-
- String[] arr = {"abc", "def"};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertNotNull(asgn.getHostArray());
- assertEquals(arr.toString(), asgn.getHostArray().toString());
-
- String[] arr2 = {"xyz"};
- asgn.setHostArray(arr2);
-
- assertNotNull(asgn.getHostArray());
- assertEquals(arr2.toString(), asgn.getHostArray().toString());
- }
-
- @Test
- public void testGetLeader() {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- assertNull(asgn.getLeader());
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- assertNull(asgn.getLeader());
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- assertNull(asgn.getLeader());
-
- // some entries are null
- asgn.setHostArray(new String[] {null, "abc", null});
- assertEquals("abc", asgn.getLeader());
-
- // only one entry
- asgn.setHostArray(new String[] {"abc"});
- assertEquals("abc", asgn.getLeader());
-
- // first is least
- asgn.setHostArray(new String[] {"Ahost", "Bhost", "Chost"});
- assertEquals("Ahost", asgn.getLeader());
-
- // middle is least
- asgn.setHostArray(new String[] {"Xhost", "Bhost", "Chost"});
- assertEquals("Bhost", asgn.getLeader());
-
- // last is least
- asgn.setHostArray(new String[] {"Xhost", "Yhost", "Chost"});
- assertEquals("Chost", asgn.getLeader());
-
- // multiple entries
- asgn.setHostArray(new String[] {"Xhost", "Bhost", "Chost", "Bhost", "Xhost", "Chost"});
- assertEquals("Bhost", asgn.getLeader());
- }
-
- @Test
- public void testHasAssignment() {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- assertFalse(asgn.hasAssignment("abc"));
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- assertFalse(asgn.hasAssignment("abc"));
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- assertFalse(asgn.hasAssignment("abc"));
-
- // some entries are null
- asgn.setHostArray(new String[] {null, "abc", null});
- assertTrue(asgn.hasAssignment("abc"));
-
- // only one entry
- asgn.setHostArray(new String[] {"abc"});
- assertTrue(asgn.hasAssignment("abc"));
-
- // appears as first entry
- asgn.setHostArray(new String[] {"abc", "Bhost", "Chost"});
- assertTrue(asgn.hasAssignment("abc"));
-
- // appears in middle
- asgn.setHostArray(new String[] {"Xhost", "abc", "Chost"});
- assertTrue(asgn.hasAssignment("abc"));
-
- // appears last
- asgn.setHostArray(new String[] {"Xhost", "Yhost", "abc"});
- assertTrue(asgn.hasAssignment("abc"));
-
- // appears repeatedly
- asgn.setHostArray(new String[] {"Xhost", "Bhost", "Chost", "Bhost", "Xhost", "Chost"});
- assertTrue(asgn.hasAssignment("Bhost"));
- }
-
- @Test
- public void testGetAllHosts() {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- assertEquals("[]", getSortedHosts(asgn).toString());
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- assertEquals("[]", getSortedHosts(asgn).toString());
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- assertEquals("[]", getSortedHosts(asgn).toString());
-
- // some entries are null
- asgn.setHostArray(new String[] {null, "abc", null});
- assertEquals("[abc]", getSortedHosts(asgn).toString());
-
- // only one entry
- asgn.setHostArray(new String[] {"abc"});
- assertEquals("[abc]", getSortedHosts(asgn).toString());
-
- // multiple, repeated entries
- asgn.setHostArray(new String[] {"def", "abc", "def", "ghi", "def", "def", "xyz"});
- assertEquals("[abc, def, ghi, xyz]", getSortedHosts(asgn).toString());
- }
-
- /**
- * Gets the hosts, sorted, so that the order is predictable.
- *
- * @param asgn assignment whose hosts are to be retrieved
- * @return a new, sorted set of hosts
- */
- private SortedSet<String> getSortedHosts(BucketAssignments asgn) {
- return new TreeSet<>(asgn.getAllHosts());
- }
-
- @Test
- public void testGetAssignedHost() {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- assertNull(asgn.getAssignedHost(3));
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- assertNull(asgn.getAssignedHost(3));
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- assertNull(asgn.getAssignedHost(3));
-
- // multiple, repeated entries
- String[] arr = {"def", "abc", "def", "ghi", "def", "def", "xyz"};
- asgn.setHostArray(arr);
-
- /*
- * get assignments for consecutive integers, including negative numbers and
- * numbers extending past the length of the array.
- *
- */
- TreeSet<String> seen = new TreeSet<>();
- for (int x = -1; x < arr.length + 2; ++x) {
- seen.add(asgn.getAssignedHost(x));
- }
-
- TreeSet<String> expected = new TreeSet<>(Arrays.asList(arr));
- assertEquals(expected, seen);
-
- // try a much bigger number
- assertNotNull(asgn.getAssignedHost(arr.length * 1000));
- }
-
- @Test
- public void testSize() {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- assertEquals(0, asgn.size());
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- assertEquals(0, asgn.size());
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- assertEquals(5, asgn.size());
-
- // multiple, repeated entries
- String[] arr = {"def", "abc", "def", "ghi", "def", "def", "xyz"};
- asgn.setHostArray(arr);
- assertEquals(arr.length, asgn.size());
- }
-
- @Test
- public void testCheckValidity() throws Exception {
- // host array is null
- BucketAssignments asgn = new BucketAssignments();
- expectException(asgn);
-
- // array is non-null, but empty
- asgn.setHostArray(new String[0]);
- expectException(asgn);
-
- // array is too big
- asgn.setHostArray(new String[BucketAssignments.MAX_BUCKETS + 1]);
- expectException(asgn);
-
- // all entries are null
- asgn.setHostArray(new String[5]);
- expectException(asgn);
-
- // null at the beginning
- asgn.setHostArray(new String[] {null, "Bhost", "Chost"});
- expectException(asgn);
-
- // null in the middle
- asgn.setHostArray(new String[] {"Ahost", null, "Chost"});
- expectException(asgn);
-
- // null at the end
- asgn.setHostArray(new String[] {"Ahost", "Bhost", null});
- expectException(asgn);
-
- // only one entry
- asgn.setHostArray(new String[] {"abc"});
- asgn.checkValidity();
-
- // multiple entries
- asgn.setHostArray(new String[] {"Ahost", "Bhost", "Chost"});
- asgn.checkValidity();
- }
-
- @Test
- public void testHashCode() {
- // with null assignments
- BucketAssignments asgn = new BucketAssignments();
- asgn.hashCode();
-
- // with empty array
- asgn = new BucketAssignments(new String[0]);
- asgn.hashCode();
-
- // with null items
- asgn = new BucketAssignments(new String[] {"abc", null, "def"});
- asgn.hashCode();
-
- // same assignments
- asgn = new BucketAssignments(new String[] {"abc", null, "def"});
- int code = asgn.hashCode();
-
- asgn = new BucketAssignments(new String[] {"abc", null, "def"});
- assertEquals(code, asgn.hashCode());
-
- // slightly different values (i.e., changed "def" to "eef")
- asgn = new BucketAssignments(new String[] {"abc", null, "eef"});
- assertNotEquals(code, asgn.hashCode());
- }
-
- @Test
- public void testEquals() {
- // null object
- BucketAssignments asgn = new BucketAssignments();
- assertNotEquals(asgn, null);
-
- // same object
- asgn = new BucketAssignments();
- assertEquals(asgn, asgn);
-
- // different class of object
- asgn = new BucketAssignments();
- assertNotEquals(asgn, "not an assignment object");
-
- assertNotEquals(asgn, new BucketAssignments(new String[] {"abc"}));
-
- // with null assignments
- asgn = new BucketAssignments();
- assertEquals(asgn, new BucketAssignments());
-
- // with empty array
- asgn = new BucketAssignments(new String[0]);
- assertEquals(asgn, asgn);
-
- assertNotEquals(asgn, new BucketAssignments());
- assertNotEquals(asgn, new BucketAssignments(new String[] {"abc"}));
-
- // with null items
- String[] arr = {"abc", null, "def"};
- asgn = new BucketAssignments(arr);
- assertEquals(asgn, asgn);
- assertEquals(asgn, new BucketAssignments(arr));
- assertEquals(asgn, new BucketAssignments(new String[] {"abc", null, "def"}));
-
- assertNotEquals(asgn, new BucketAssignments());
- assertNotEquals(asgn, new BucketAssignments(new String[] {"abc", null, "XYZ"}));
-
- assertNotEquals(asgn, new BucketAssignments());
- }
-
- /**
- * Expects an exception when checkValidity() is called.
- *
- * @param asgn assignments to be checked
- */
- private void expectException(BucketAssignments asgn) {
- try {
- asgn.checkValidity();
- fail("missing exception");
-
- } catch (PoolingFeatureException expected) {
- // success
- }
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java
deleted file mode 100644
index d1a82f4f..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-import static org.junit.Assert.assertEquals;
-
-public class HeartbeatTest extends SupportBasicMessageTester<Heartbeat> {
-
- /**
- * Sequence number to validate time stamps within the heart beat.
- */
- private long sequence = 0;
-
- public HeartbeatTest() {
- super(Heartbeat.class);
- }
-
- @Override
- public Heartbeat makeValidMessage() {
- Heartbeat msg = new Heartbeat(VALID_HOST, ++sequence);
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
- @Override
- public void testDefaultConstructorFields(Heartbeat msg) {
- super.testDefaultConstructorFields(msg);
-
- assertEquals(sequence, msg.getTimestampMs());
- }
-
- @Override
- public void testValidFields(Heartbeat msg) {
- super.testValidFields(msg);
-
- assertEquals(sequence, msg.getTimestampMs());
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java
deleted file mode 100644
index 06336b3e..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class IdentificationTest extends SupportMessageWithAssignmentsTester<Identification> {
-
- public IdentificationTest() {
- super(Identification.class);
- }
-
- @Before
- public void setUp() {
- setNullAssignments(false);
- }
-
- /**
- * The superclass will already invoke testJsonEncodeDecode() to verify that
- * things work with a fully populated message. This verifies that it also
- * works if the assignments are null.
- *
- * @throws Exception if an error occurs
- */
- @Test
- public final void testJsonEncodeDecode_WithNullAssignments() throws Exception {
- setNullAssignments(true);
- testJsonEncodeDecode();
- }
-
- /**
- * The superclass will already invoke testCheckValidity() to
- * verify that things work with a fully populated message. This verifies
- * that it also works if the assignments are null.
- *
- * @throws Exception if an error occurs
- */
- @Test
- public void testCheckValidity_NullAssignments() throws Exception {
- // null assignments are OK
- Identification msg = makeValidMessage();
- msg.setAssignments(null);
- msg.checkValidity();
- }
-
- @Override
- public Identification makeValidMessage() {
- Identification msg = new Identification(VALID_HOST, (isNullAssignments() ? null : VALID_ASGN));
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java
deleted file mode 100644
index eefd45d4..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-import org.junit.Before;
-import org.junit.Test;
-
-public class LeaderTest extends SupportMessageWithAssignmentsTester<Leader> {
-
- public LeaderTest() {
- super(Leader.class);
- }
-
- @Before
- public void setUp() {
- setNullAssignments(false);
- }
-
- /**
- * The superclass will already invoke testCheckValidity_InvalidFields() to
- * verify that things work with a fully populated message. This verifies
- * that it also works if the assignments are null.
- *
- * @throws Exception if an error occurs
- */
- @Test
- public void testCheckValidity_InvalidFields_NullAssignments() throws Exception {
- // null assignments are invalid
- expectCheckValidityFailure(msg -> msg.setAssignments(null));
- }
-
- @Test
- public void testCheckValidity_SourceIsNotLeader() throws Exception {
- Leader ldr = makeValidMessage();
-
- ldr.setSource("xyz");
-
- // the source does not have an assignment
- BucketAssignments asgnUnassigned = new BucketAssignments(new String[] {"abc", "def"});
- expectCheckValidityFailure(msg -> msg.setAssignments(asgnUnassigned));
-
- // the source is not the smallest UUID in this assignment
- BucketAssignments asgnNotSmallest = new BucketAssignments(new String[] {VALID_HOST_PREDECESSOR, VALID_HOST});
- expectCheckValidityFailure(msg -> msg.setAssignments(asgnNotSmallest));
- }
-
- @Override
- public Leader makeValidMessage() {
- Leader msg = new Leader(VALID_HOST, (isNullAssignments() ? null : VALID_ASGN));
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java
deleted file mode 100644
index db8cd9f9..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-public class MessageTest extends SupportBasicMessageTester<Message> {
-
- public MessageTest() {
- super(Message.class);
- }
-
- @Test
- public void testGetSource_testSetSource() {
- Message msg = new Message();
-
- msg.setSource("hello");
- assertEquals("hello", msg.getSource());
- assertNull(msg.getChannel());
-
- msg.setSource("world");
- assertEquals("world", msg.getSource());
- assertNull(msg.getChannel());
- }
-
- @Test
- public void testGetChannel_testSetChannel() {
- Message msg = new Message();
-
- msg.setChannel("hello");
- assertEquals("hello", msg.getChannel());
- assertNull(msg.getSource());
-
- msg.setChannel("world");
- assertEquals("world", msg.getChannel());
- assertNull(msg.getSource());
- }
-
- @Test
- public void testCheckValidity_InvalidFields() {
- // null or empty source
- expectCheckValidityFailure_NullOrEmpty((msg, value) -> msg.setSource(value));
-
- // null or empty channel
- expectCheckValidityFailure_NullOrEmpty((msg, value) -> msg.setChannel(value));
- }
-
- /**
- * Makes a message that will pass the validity check.
- *
- * @return a valid Message
- */
- public Message makeValidMessage() {
- Message msg = new Message(VALID_HOST);
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java
deleted file mode 100644
index 906733e9..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-public class OfflineTest extends SupportBasicMessageTester<Offline> {
-
- public OfflineTest() {
- super(Offline.class);
- }
-
- @Override
- public Offline makeValidMessage() {
- Offline msg = new Offline(VALID_HOST);
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java
deleted file mode 100644
index 933dddfd..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-public class QueryTest extends SupportBasicMessageTester<Query> {
-
- public QueryTest() {
- super(Query.class);
- }
-
- @Override
- public Query makeValidMessage() {
- Query msg = new Query(VALID_HOST);
- msg.setChannel(VALID_CHANNEL);
-
- return msg;
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java
deleted file mode 100644
index 86247835..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018-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.pooling.message;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.fail;
-
-import org.junit.Test;
-import org.onap.policy.drools.pooling.PoolingFeatureException;
-import org.onap.policy.drools.pooling.Serializer;
-
-/**
- * Superclass used to test subclasses of {@link Message}.
- *
- * @param <T> type of {@link Message} subclass that this tests
- */
-public abstract class SupportBasicMessageTester<T extends Message> {
- // values set by makeValidMessage()
- public static final String VALID_HOST_PREDECESSOR = "hostA";
- public static final String VALID_HOST = "hostB";
- public static final String VALID_CHANNEL = "channelC";
-
- /**
- * Used to perform JSON serialization and de-serialization.
- */
- public final Serializer mapper = new Serializer();
-
- /**
- * The subclass of the type of Message being tested.
- */
- private final Class<T> subclazz;
-
- /**
- * Constructor.
- *
- * @param subclazz subclass of {@link Message} being tested
- */
- public SupportBasicMessageTester(Class<T> subclazz) {
- this.subclazz = subclazz;
- }
-
- /**
- * Creates a default Message and verifies that the source and channel are
- * {@code null}.
- *
- */
- @Test
- public final void testDefaultConstructor() {
- testDefaultConstructorFields(makeDefaultMessage());
- }
-
- /**
- * Tests that the Message has the correct source, and that the channel is
- * {@code null}.
- *
- */
- @Test
- public final void testConstructorWithArgs() {
- testValidFields(makeValidMessage());
- }
-
- /**
- * Makes a valid message and then verifies that it can be serialized and
- * de-serialized. Verifies that the de-serialized message is of the same
- * type, and has the same content, as the original.
- *
- * @throws Exception if an error occurs
- */
- @Test
- public final void testJsonEncodeDecode() throws Exception {
- T originalMsg = makeValidMessage();
-
- Message msg;
- if (originalMsg.getClass() == Message.class) {
- msg = originalMsg;
- } else {
- msg = mapper.decodeMsg(mapper.encodeMsg(originalMsg));
- }
-
- assertEquals(subclazz, msg.getClass());
-
- msg.checkValidity();
-
- testValidFields(subclazz.cast(msg));
- }
-
- /**
- * Creates a valid Message and verifies that checkValidity() passes.
- *
- * @throws PoolingFeatureException if an error occurs
- */
- @Test
- public final void testCheckValidity_Ok() throws PoolingFeatureException {
- T msg = makeValidMessage();
- msg.checkValidity();
-
- testValidFields(subclazz.cast(msg));
- }
-
- /**
- * Creates a default Message and verifies that checkValidity() fails. Does
- * not throw an exception.
- */
- @Test
- public final void testCheckValidity_DefaultConstructor() {
- try {
- makeDefaultMessage().checkValidity();
- fail("missing exception");
-
- } catch (PoolingFeatureException expected) {
- // success
- }
- }
-
- /**
- * Creates a message via {@link #makeValidMessage()}, updates it via the
- * given function, and then invokes the checkValidity() method on it. It is
- * expected that the checkValidity() will throw an exception.
- *
- * @param func function to update the message prior to invoking
- * checkValidity()
- */
- public void expectCheckValidityFailure(MessageUpdateFunction<T> func) {
- try {
- T msg = makeValidMessage();
- func.update(msg);
-
- msg.checkValidity();
-
- fail("missing exception");
-
- } catch (PoolingFeatureException expected) {
- // success
- }
- }
-
- /**
- * Creates a message via {@link #makeValidMessage()}, updates one of its
- * fields via the given function, and then invokes the checkValidity()
- * method on it. It is expected that the checkValidity() will throw an
- * exception. It checks both the case when the message's field is set to
- * {@code null}, and when it is set to empty (i.e., "").
- *
- * @param func function to update the message's field prior to invoking
- * checkValidity()
- */
- public void expectCheckValidityFailure_NullOrEmpty(MessageFieldUpdateFunction<T> func) {
- expectCheckValidityFailure(msg -> func.update(msg, null));
- expectCheckValidityFailure(msg -> func.update(msg, ""));
- }
-
- /**
- * Makes a message using the default constructor.
- *
- * @return a new Message
- */
- public final T makeDefaultMessage() {
- try {
- return subclazz.getConstructor().newInstance();
-
- } catch (Exception e) {
- throw new AssertionError(e);
- }
- }
-
-
- // the remaining methods will typically be overridden
-
- /**
- * Makes a message that will pass the validity check. Note: this should use
- * the non-default constructor, and the source and channel should be set to
- * {@link VALID_HOST} and {@link VALID_CHANNEL}, respectively.
- *
- * @return a valid Message
- */
- public abstract T makeValidMessage();
-
- /**
- * Verifies that fields are set as expected by
- * {@link #makeDefaultMessage()}.
- *
- * @param msg the default Message
- */
- public void testDefaultConstructorFields(T msg) {
- assertNull(msg.getSource());
- assertNull(msg.getChannel());
- }
-
- /**
- * Verifies that fields are set as expected by {@link #makeValidMessage()}.
- *
- * @param msg message whose fields are to be validated
- */
- public void testValidFields(T msg) {
- assertEquals(VALID_HOST, msg.getSource());
- assertEquals(VALID_CHANNEL, msg.getChannel());
- }
-
- /**
- * Function that updates a message.
- *
- * @param <T> type of Message the function updates
- */
- @FunctionalInterface
- public static interface MessageUpdateFunction<T extends Message> {
-
- /**
- * Updates a message.
- *
- * @param msg message to be updated
- */
- void update(T msg);
- }
-
- /**
- * Function that updates a single field within a message.
- *
- * @param <T> type of Message the function updates
- */
- @FunctionalInterface
- public static interface MessageFieldUpdateFunction<T extends Message> {
-
- /**
- * Updates a field within a message.
- *
- * @param msg message to be updated
- * @param newValue new field value
- */
- void update(T msg, String newValue);
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java
deleted file mode 100644
index bf245feb..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018 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.pooling.message;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Test;
-
-/**
- * Superclass used to test subclasses of {@link MessageWithAssignments}.
- *
- * @param <T> type of {@link MessageWithAssignments} subclass that this tests
- */
-public abstract class SupportMessageWithAssignmentsTester<T extends MessageWithAssignments>
- extends SupportBasicMessageTester<T> {
- // values set by makeValidMessage()
- public static final String[] VALID_ARRAY = {VALID_HOST, VALID_HOST + "_xxx"};
- public static final BucketAssignments VALID_ASGN = new BucketAssignments(VALID_ARRAY);
-
- /**
- * {@code True} if {@code null} assignments are allowed, {@code false}
- * otherwise.
- */
- private boolean nullAssignments;
-
- /**
- * Constructor.
- *
- * @param subclazz subclass of {@link MessageWithAssignments} being tested
- */
- public SupportMessageWithAssignmentsTester(Class<T> subclazz) {
- super(subclazz);
- }
-
- /**
- * Indicates whether or not {@code null} assignments should be used for the
- * remaining tests.
- *
- * @param nullAssignments {@code true} to use {@code null} assignments,
- * {@code false} otherwise
- */
- public void setNullAssignments(boolean nullAssignments) {
- this.nullAssignments = nullAssignments;
- }
-
- public boolean isNullAssignments() {
- return nullAssignments;
- }
-
- @Test
- public void testCheckValidity_InvalidFields() throws Exception {
- // null source (i.e., superclass field)
- expectCheckValidityFailure(msg -> msg.setSource(null));
-
- // empty assignments
- expectCheckValidityFailure(msg -> msg.setAssignments(new BucketAssignments(new String[0])));
-
- // invalid assignment
- String[] invalidAssignment = {"abc", null};
- expectCheckValidityFailure(msg -> msg.setAssignments(new BucketAssignments(invalidAssignment)));
- }
-
- @Test
- public void testGetAssignments_testSetAssignments() {
- MessageWithAssignments msg = makeValidMessage();
-
- // from constructor
- assertEquals(VALID_ASGN, msg.getAssignments());
-
- BucketAssignments asgn = new BucketAssignments();
- msg.setAssignments(asgn);
- assertEquals(asgn, msg.getAssignments());
- }
-
- @Override
- public void testDefaultConstructorFields(T msg) {
- super.testDefaultConstructorFields(msg);
-
- assertNull(msg.getAssignments());
- }
-
- @Override
- public void testValidFields(T msg) {
- super.testValidFields(msg);
-
- if (nullAssignments) {
- assertNull(msg.getAssignments());
-
- } else {
- assertEquals(VALID_ASGN, msg.getAssignments());
- }
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java
deleted file mode 100644
index 771f694e..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.atLeast;
-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 org.apache.commons.lang3.tuple.Pair;
-import org.apache.commons.lang3.tuple.Triple;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class ActiveStateTest extends SupportBasicStateTester {
-
- private ActiveState state;
-
- /**
- * Setup.
- */
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new ActiveState(mgr);
- }
-
- @Test
- public void testStart() {
- state.start();
-
- // ensure the timers were created
- verify(mgr, atLeast(1)).scheduleWithFixedDelay(anyLong(), anyLong(), any(StateTimerTask.class));
-
- // ensure a heart beat was generated
- Pair<String, Heartbeat> msg = capturePublishedMessage(Heartbeat.class);
- assertEquals(MY_HOST, msg.getRight().getSource());
- }
-
- @Test
- public void testProcessHeartbeat_NullHost() {
- assertNull(state.process(new Heartbeat()));
-
- assertFalse(state.isMyHeartbeatSeen());
- assertFalse(state.isPredHeartbeatSeen());
-
- verify(mgr, never()).goInactive();
- verify(mgr, never()).goQuery();
- }
-
- @Test
- public void testProcessHeartbeat_MyHost() {
- assertNull(state.process(new Heartbeat(MY_HOST, 0L)));
-
- assertTrue(state.isMyHeartbeatSeen());
- assertFalse(state.isPredHeartbeatSeen());
-
- verify(mgr, never()).goInactive();
- verify(mgr, never()).goQuery();
- }
-
- @Test
- public void testProcessHeartbeat_Predecessor() {
- assertNull(state.process(new Heartbeat(HOST2, 0L)));
-
- assertFalse(state.isMyHeartbeatSeen());
- assertTrue(state.isPredHeartbeatSeen());
-
- verify(mgr, never()).goInactive();
- verify(mgr, never()).goQuery();
- }
-
- @Test
- public void testProcessHeartbeat_OtherHost() {
- assertNull(state.process(new Heartbeat(HOST3, 0L)));
-
- assertFalse(state.isMyHeartbeatSeen());
- assertFalse(state.isPredHeartbeatSeen());
-
- verify(mgr, never()).goInactive();
- verify(mgr, never()).goQuery();
- }
-
- @Test
- public void testProcessOffline_NullHost() {
- // should be ignored
- assertNull(state.process(new Offline()));
- }
-
- @Test
- public void testProcessOffline_UnassignedHost() {
- // HOST4 is not in the assignment list - should be ignored
- assertNull(state.process(new Offline(HOST4)));
- }
-
- @Test
- public void testProcessOffline_IAmLeader() {
- // configure the next state
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // one of the assigned hosts went offline
- assertEquals(next, state.process(new Offline(HOST1)));
-
- // should have sent a new Leader message
- Leader msg = captureAdminMessage(Leader.class);
-
- assertEquals(MY_HOST, msg.getSource());
-
- // check new bucket assignments
- assertEquals(Arrays.asList(MY_HOST, MY_HOST, HOST2), Arrays.asList(msg.getAssignments().getHostArray()));
- }
-
- @Test
- public void testProcessOffline_PredecessorIsLeaderNowOffline() {
- // configure the next state
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // I am not the leader, but my predecessor was
- mgr.startDistributing(new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST1}));
- state = new ActiveState(mgr);
-
- // my predecessor went offline
- assertEquals(next, state.process(new Offline(PREV_HOST)));
-
- // should have sent a new Leader message
- Leader msg = captureAdminMessage(Leader.class);
-
- assertEquals(MY_HOST, msg.getSource());
-
- // check new bucket assignments
- assertEquals(Arrays.asList(MY_HOST, MY_HOST, HOST1), Arrays.asList(msg.getAssignments().getHostArray()));
- }
-
- @Test
- public void testProcessOffline__PredecessorIsNotLeaderNowOffline() {
- // I am not the leader, and neither is my predecessor
- mgr.startDistributing(new BucketAssignments(new String[] {PREV_HOST, MY_HOST, PREV_HOST2}));
- state = new ActiveState(mgr);
-
- /*
- *
- * PREV_HOST2 has buckets and is my predecessor, but it isn't the leader thus
- * should be ignored.
- */
- assertNull(state.process(new Offline(PREV_HOST2)));
- }
-
- @Test
- public void testProcessOffline_OtherAssignedHostOffline() {
- // I am not the leader
- mgr.startDistributing(new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST1}));
- state = new ActiveState(mgr);
-
- /*
- * HOST1 has buckets, but it isn't the leader and it isn't my predecessor, thus
- * should be ignored.
- */
- assertNull(state.process(new Offline(HOST1)));
- }
-
- @Test
- public void testProcessLeader_Invalid() {
- Leader msg = new Leader(PREV_HOST, null);
-
- // should stay in the same state, and not start distributing
- assertNull(state.process(msg));
- verify(mgr, never()).startDistributing(any());
- verify(mgr, never()).goActive();
- verify(mgr, never()).goInactive();
-
- // info should be unchanged
- assertEquals(MY_HOST, state.getLeader());
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test
- public void testProcessLeader_BadLeader() {
- String[] arr = {HOST2, HOST1};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- // now send a Leader message for that leader
- Leader msg = new Leader(HOST1, asgn);
-
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- // should go Query, but not start distributing
- assertEquals(next, state.process(msg));
- verify(mgr, never()).startDistributing(asgn);
- }
-
- @Test
- public void testProcessLeader_GoodLeader() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- // now send a Leader message for that leader
- Leader msg = new Leader(PREV_HOST, asgn);
-
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // should go Active and start distributing
- assertEquals(next, state.process(msg));
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testActiveState() {
- assertEquals(MY_HOST, state.getLeader());
- assertEquals(ASGN3, state.getAssignments());
-
- // verify that it determined its neighbors
- assertEquals(HOST1, state.getSuccHost());
- assertEquals(HOST2, state.getPredHost());
- }
-
- @Test
- public void testDetmNeighbors() {
- // if only one host (i.e., itself)
- mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST, MY_HOST}));
- state = new ActiveState(mgr);
- assertEquals(null, state.getSuccHost());
- assertEquals("", state.getPredHost());
-
- // two hosts
- mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST, HOST2}));
- state = new ActiveState(mgr);
- assertEquals(HOST2, state.getSuccHost());
- assertEquals(HOST2, state.getPredHost());
-
- // three hosts
- mgr.startDistributing(new BucketAssignments(new String[] {HOST3, MY_HOST, HOST2}));
- state = new ActiveState(mgr);
- assertEquals(HOST2, state.getSuccHost());
- assertEquals(HOST3, state.getPredHost());
-
- // more hosts
- mgr.startDistributing(new BucketAssignments(new String[] {HOST3, MY_HOST, HOST2, HOST4}));
- state = new ActiveState(mgr);
- assertEquals(HOST2, state.getSuccHost());
- assertEquals(HOST4, state.getPredHost());
- }
-
- @Test
- public void testAddTimers_WithPredecessor() {
- // invoke start() to add the timers
- state.start();
-
- assertEquals(3, repeatedSchedules.size());
-
- Triple<Long, Long, StateTimerTask> timer;
-
- // heart beat generator
- timer = repeatedTasks.remove();
- assertEquals(STD_INTER_HEARTBEAT_MS, timer.getLeft().longValue());
- assertEquals(STD_INTER_HEARTBEAT_MS, timer.getMiddle().longValue());
-
- // my heart beat checker
- timer = repeatedTasks.remove();
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getLeft().longValue());
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getMiddle().longValue());
-
- // predecessor's heart beat checker
- timer = repeatedTasks.remove();
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getLeft().longValue());
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getMiddle().longValue());
- }
-
- @Test
- public void testAddTimers_SansPredecessor() {
- // only one host, thus no predecessor
- mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST, MY_HOST}));
- state = new ActiveState(mgr);
-
- // invoke start() to add the timers
- state.start();
-
- assertEquals(2, repeatedSchedules.size());
-
- Triple<Long, Long, StateTimerTask> timer;
-
- // heart beat generator
- timer = repeatedTasks.remove();
- assertEquals(STD_INTER_HEARTBEAT_MS, timer.getLeft().longValue());
- assertEquals(STD_INTER_HEARTBEAT_MS, timer.getMiddle().longValue());
-
- // my heart beat checker
- timer = repeatedTasks.remove();
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getLeft().longValue());
- assertEquals(STD_ACTIVE_HEARTBEAT_MS, timer.getMiddle().longValue());
- }
-
- @Test
- public void testAddTimers_HeartbeatGenerator() {
- // only one host so we only have to look at one heart beat at a time
- mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST}));
- state = new ActiveState(mgr);
-
- // invoke start() to add the timers
- state.start();
-
- Triple<Long, Long, StateTimerTask> task = repeatedTasks.remove();
-
- verify(mgr).publish(anyString(), any(Heartbeat.class));
-
- // fire the task
- assertNull(task.getRight().fire());
-
- // should have generated a second pair of heart beats
- verify(mgr, times(2)).publish(anyString(), any(Heartbeat.class));
-
- Pair<String, Heartbeat> msg = capturePublishedMessage(Heartbeat.class);
- assertEquals(MY_HOST, msg.getLeft());
- assertEquals(MY_HOST, msg.getRight().getSource());
- }
-
- @Test
- public void testAddTimers_MyHeartbeatSeen() {
- // invoke start() to add the timers
- state.start();
-
- Triple<Long, Long, StateTimerTask> task = repeatedTasks.get(1);
-
- // indicate that this host is still alive
- state.process(new Heartbeat(MY_HOST, 0L));
-
- // set up next state
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- // fire the task - should not transition
- assertNull(task.getRight().fire());
-
- verify(mgr, never()).publishAdmin(any(Query.class));
- }
-
- @Test
- public void testAddTimers_MyHeartbeatMissed() {
- // invoke start() to add the timers
- state.start();
-
- Triple<Long, Long, StateTimerTask> task = repeatedTasks.get(1);
-
- // set up next state
- State next = mock(State.class);
- when(mgr.goStart()).thenReturn(next);
-
- // fire the task - should transition
- assertEquals(next, task.getRight().fire());
-
- // should continue to distribute
- verify(mgr, never()).startDistributing(null);
-
- // should publish an offline message
- Offline msg = captureAdminMessage(Offline.class);
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testAddTimers_PredecessorHeartbeatSeen() {
- // invoke start() to add the timers
- state.start();
-
- Triple<Long, Long, StateTimerTask> task = repeatedTasks.get(2);
-
- // indicate that the predecessor is still alive
- state.process(new Heartbeat(HOST2, 0L));
-
- // set up next state, just in case
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- // fire the task - should NOT transition
- assertNull(task.getRight().fire());
-
- verify(mgr, never()).publishAdmin(any(Query.class));
- }
-
- @Test
- public void testAddTimers_PredecessorHeartbeatMissed() {
- // invoke start() to add the timers
- state.start();
-
- Triple<Long, Long, StateTimerTask> task = repeatedTasks.get(2);
-
- // set up next state
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- // fire the task - should transition
- assertEquals(next, task.getRight().fire());
-
- verify(mgr).publishAdmin(any(Query.class));
- }
-
- @Test
- public void testGenHeartbeat_OneHost() {
- // only one host (i.e., itself)
- mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST}));
- state = new ActiveState(mgr);
-
- state.start();
-
- verify(mgr, times(1)).publish(any(), any());
-
- Pair<String, Heartbeat> msg = capturePublishedMessage(Heartbeat.class);
- assertEquals(MY_HOST, msg.getLeft());
- assertEquals(MY_HOST, msg.getRight().getSource());
- }
-
- @Test
- public void testGenHeartbeat_MultipleHosts() {
- state.start();
-
- verify(mgr, times(2)).publish(any(), any());
-
- Pair<String, Heartbeat> msg;
- int index = 0;
-
- // this message should go to itself
- msg = capturePublishedMessage(Heartbeat.class, index++);
- assertEquals(MY_HOST, msg.getLeft());
- assertEquals(MY_HOST, msg.getRight().getSource());
-
- // this message should go to its successor
- msg = capturePublishedMessage(Heartbeat.class, index++);
- assertEquals(HOST1, msg.getLeft());
- assertEquals(MY_HOST, msg.getRight().getSource());
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java
deleted file mode 100644
index 5cc88d3a..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 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.pooling.state;
-
-import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class IdleStateTest extends SupportBasicStateTester {
-
- private IdleState state;
-
- /**
- * Setup.
- */
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new IdleState(mgr);
- }
-
- @Test
- public void testProcessHeartbeat() {
- assertNull(state.process(new Heartbeat(PREV_HOST, 0L)));
- verifyNothingPublished();
- }
-
- @Test
- public void testProcessIdentification() {
- assertNull(state.process(new Identification(PREV_HOST, null)));
- verifyNothingPublished();
- }
-
- @Test
- public void testProcessLeader() {
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST2, PREV_HOST, MY_HOST});
- Leader msg = new Leader(PREV_HOST, asgn);
-
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // should stay in current state, but start distributing
- assertNull(state.process(msg));
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testProcessOffline() {
- assertNull(state.process(new Offline(PREV_HOST)));
- verifyNothingPublished();
- }
-
- @Test
- public void testProcessQuery() {
- assertNull(state.process(new Query()));
- verifyNothingPublished();
- }
-
- /**
- * Verifies that nothing was published on either channel.
- */
- private void verifyNothingPublished() {
- verify(mgr, never()).publish(any(), any());
- verify(mgr, never()).publishAdmin(any());
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java
deleted file mode 100644
index f8f70461..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.apache.commons.lang3.tuple.Pair;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class InactiveStateTest extends SupportBasicStateTester {
-
- private InactiveState state;
-
- /**
- * Setup.
- *
- */
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new InactiveState(mgr);
- }
-
- @Test
- public void testProcessLeader() {
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- String[] arr = {PREV_HOST, MY_HOST, HOST1};
- BucketAssignments asgn = new BucketAssignments(arr);
- Leader msg = new Leader(PREV_HOST, asgn);
-
- assertEquals(next, state.process(msg));
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testProcessLeader_Invalid() {
- Leader msg = new Leader(PREV_HOST, null);
-
- // should stay in the same state, and not start distributing
- assertNull(state.process(msg));
- verify(mgr, never()).startDistributing(any());
- verify(mgr, never()).goActive();
- verify(mgr, never()).goInactive();
- }
-
- @Test
- public void testProcessQuery() {
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- assertEquals(next, state.process(new Query()));
-
- Identification ident = captureAdminMessage(Identification.class);
- assertEquals(MY_HOST, ident.getSource());
- assertEquals(ASGN3, ident.getAssignments());
- }
-
- @Test
- public void testGoInatcive() {
- assertNull(state.goInactive());
- }
-
- @Test
- public void testStart() {
- state.start();
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_REACTIVATE_WAIT_MS, timer.getLeft().longValue());
-
- // invoke the task - it should go to the state returned by the mgr
- State next = mock(State.class);
- when(mgr.goStart()).thenReturn(next);
-
- assertEquals(next, timer.getRight().fire());
- }
-
- @Test
- public void testInactiveState() {
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java
deleted file mode 100644
index 02cbe491..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020-2021 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.pooling.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Message;
-import org.onap.policy.drools.pooling.message.Query;
-import org.onap.policy.drools.pooling.state.ProcessingState.HostBucket;
-
-public class ProcessingStateTest extends SupportBasicStateTester {
-
- private ProcessingState state;
- private HostBucket hostBucket;
-
- /**
- * Setup.
- */
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new ProcessingState(mgr, MY_HOST);
- hostBucket = new HostBucket(MY_HOST);
- }
-
- @Test
- public void testProcessQuery() {
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- assertEquals(next, state.process(new Query()));
-
- Identification ident = captureAdminMessage(Identification.class);
- assertEquals(MY_HOST, ident.getSource());
- assertEquals(ASGN3, ident.getAssignments());
- }
-
- @Test
- public void testProcessingState() {
- /*
- * Null assignments should be OK.
- */
- when(mgr.getAssignments()).thenReturn(null);
- state = new ProcessingState(mgr, LEADER);
-
- /*
- * Empty assignments should be OK.
- */
- when(mgr.getAssignments()).thenReturn(EMPTY_ASGN);
- state = new ProcessingState(mgr, LEADER);
- assertEquals(MY_HOST, state.getHost());
- assertEquals(LEADER, state.getLeader());
- assertEquals(EMPTY_ASGN, state.getAssignments());
-
- /*
- * Now try something with assignments.
- */
- when(mgr.getAssignments()).thenReturn(ASGN3);
- state = new ProcessingState(mgr, LEADER);
-
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
-
- assertEquals(LEADER, state.getLeader());
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testProcessingState_NullLeader() {
- when(mgr.getAssignments()).thenReturn(EMPTY_ASGN);
- state = new ProcessingState(mgr, null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testProcessingState_ZeroLengthHostArray() {
- when(mgr.getAssignments()).thenReturn(new BucketAssignments(new String[] {}));
- state = new ProcessingState(mgr, LEADER);
- }
-
- @Test
- public void testGetAssignments() {
- // assignments from constructor
- assertEquals(ASGN3, state.getAssignments());
-
- // null assignments - no effect
- state.setAssignments(null);
- assertEquals(ASGN3, state.getAssignments());
-
- // empty assignments
- state.setAssignments(EMPTY_ASGN);
- assertEquals(EMPTY_ASGN, state.getAssignments());
-
- // non-empty assignments
- state.setAssignments(ASGN3);
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test
- public void testSetAssignments() {
- state.setAssignments(null);
- verify(mgr, never()).startDistributing(any());
-
- state.setAssignments(ASGN3);
- verify(mgr).startDistributing(ASGN3);
- }
-
- @Test
- public void testGetLeader() {
- // check value from constructor
- assertEquals(MY_HOST, state.getLeader());
-
- state.setLeader(HOST2);
- assertEquals(HOST2, state.getLeader());
-
- state.setLeader(HOST3);
- assertEquals(HOST3, state.getLeader());
- }
-
- @Test
- public void testSetLeader() {
- state.setLeader(MY_HOST);
- assertEquals(MY_HOST, state.getLeader());
- }
-
- @Test(expected = NullPointerException.class)
- public void testSetLeader_Null() {
- state.setLeader(null);
- }
-
- @Test
- public void testIsLeader() {
- state.setLeader(MY_HOST);
- assertTrue(state.isLeader());
-
- state.setLeader(HOST2);
- assertFalse(state.isLeader());
- }
-
- @Test
- public void testBecomeLeader() {
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- assertEquals(next, state.becomeLeader(sortHosts(MY_HOST, HOST2)));
-
- Leader msg = captureAdminMessage(Leader.class);
-
- verify(mgr).startDistributing(msg.getAssignments());
- verify(mgr).goActive();
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testBecomeLeader_NotFirstAlive() {
- // alive list contains something before my host name
- state.becomeLeader(sortHosts(PREV_HOST, MY_HOST));
- }
-
- @Test
- public void testMakeLeader() throws Exception {
- state.becomeLeader(sortHosts(MY_HOST, HOST2));
-
- Leader msg = captureAdminMessage(Leader.class);
-
- // need a channel before invoking checkValidity()
- msg.setChannel(Message.ADMIN);
-
- msg.checkValidity();
-
- assertEquals(MY_HOST, msg.getSource());
- assertNotNull(msg.getAssignments());
- assertTrue(msg.getAssignments().hasAssignment(MY_HOST));
- assertTrue(msg.getAssignments().hasAssignment(HOST2));
-
- // this one wasn't in the list of hosts, so it should have been removed
- assertFalse(msg.getAssignments().hasAssignment(HOST1));
- }
-
- @Test
- public void testMakeAssignments() throws Exception {
- state.becomeLeader(sortHosts(MY_HOST, HOST2));
-
- captureAssignments().checkValidity();
- }
-
- @Test
- public void testMakeBucketArray_NullAssignments() {
- when(mgr.getAssignments()).thenReturn(null);
- state = new ProcessingState(mgr, MY_HOST);
- state.becomeLeader(sortHosts(MY_HOST));
-
- String[] arr = captureHostArray();
-
- assertEquals(BucketAssignments.MAX_BUCKETS, arr.length);
-
- assertTrue(Arrays.asList(arr).stream().allMatch(host -> MY_HOST.equals(host)));
- }
-
- @Test
- public void testMakeBucketArray_ZeroAssignments() {
- // bucket assignment with a zero-length array
- state.setAssignments(new BucketAssignments(new String[0]));
-
- state.becomeLeader(sortHosts(MY_HOST));
-
- String[] arr = captureHostArray();
-
- assertEquals(BucketAssignments.MAX_BUCKETS, arr.length);
-
- assertTrue(Arrays.asList(arr).stream().allMatch(host -> MY_HOST.equals(host)));
- }
-
- @Test
- public void testMakeBucketArray() {
- /*
- * All hosts are still alive, so it should have the exact same assignments as it
- * had to start.
- */
- state.setAssignments(ASGN3);
- state.becomeLeader(sortHosts(HOST_ARR3));
-
- String[] arr = captureHostArray();
-
- assertNotSame(HOST_ARR3, arr);
- assertEquals(Arrays.asList(HOST_ARR3), Arrays.asList(arr));
- }
-
- @Test
- public void testRemoveExcessHosts() {
- /*
- * All hosts are still alive, plus some others.
- */
- state.setAssignments(ASGN3);
- state.becomeLeader(sortHosts(MY_HOST, HOST1, HOST2, HOST3, HOST4));
-
- // assignments should be unchanged
- assertEquals(Arrays.asList(HOST_ARR3), captureHostList());
- }
-
- @Test
- public void testAddIndicesToHostBuckets() {
- // some are null, some hosts are no longer alive
- String[] asgn = {null, MY_HOST, HOST3, null, HOST4, HOST1, HOST2};
-
- state.setAssignments(new BucketAssignments(asgn));
- state.becomeLeader(sortHosts(MY_HOST, HOST1, HOST2));
-
- // every bucket should be assigned to one of the three hosts
- String[] expected = {MY_HOST, MY_HOST, HOST1, HOST2, MY_HOST, HOST1, HOST2};
- assertEquals(Arrays.asList(expected), captureHostList());
- }
-
- @Test
- public void testAssignNullBuckets() {
- /*
- * Ensure buckets are assigned to the host with the fewest buckets.
- */
- String[] asgn = {MY_HOST, HOST1, MY_HOST, null, null, null, null, null, MY_HOST};
-
- state.setAssignments(new BucketAssignments(asgn));
- state.becomeLeader(sortHosts(MY_HOST, HOST1, HOST2));
-
- String[] expected = {MY_HOST, HOST1, MY_HOST, HOST2, HOST1, HOST2, HOST1, HOST2, MY_HOST};
- assertEquals(Arrays.asList(expected), captureHostList());
- }
-
- @Test
- public void testRebalanceBuckets() {
- /*
- * Some are very lopsided.
- */
- String[] asgn = {MY_HOST, HOST1, MY_HOST, MY_HOST, MY_HOST, MY_HOST, HOST1, HOST2, HOST1, HOST3};
-
- state.setAssignments(new BucketAssignments(asgn));
- state.becomeLeader(sortHosts(MY_HOST, HOST1, HOST2, HOST3));
-
- String[] expected = {HOST2, HOST1, HOST3, MY_HOST, MY_HOST, MY_HOST, HOST1, HOST2, HOST1, HOST3};
- assertEquals(Arrays.asList(expected), captureHostList());
- }
-
- @Test
- public void testHostBucketRemove_testHostBucketAdd_testHostBucketSize() {
- assertEquals(0, hostBucket.size());
-
- hostBucket.add(20);
- hostBucket.add(30);
- hostBucket.add(40);
- assertEquals(3, hostBucket.size());
-
- assertEquals(20, hostBucket.remove().intValue());
- assertEquals(30, hostBucket.remove().intValue());
- assertEquals(1, hostBucket.size());
-
- // add more before taking the last item
- hostBucket.add(50);
- hostBucket.add(60);
- assertEquals(3, hostBucket.size());
-
- assertEquals(40, hostBucket.remove().intValue());
- assertEquals(50, hostBucket.remove().intValue());
- assertEquals(60, hostBucket.remove().intValue());
- assertEquals(0, hostBucket.size());
-
- // add more AFTER taking the last item
- hostBucket.add(70);
- assertEquals(70, hostBucket.remove().intValue());
- assertEquals(0, hostBucket.size());
- }
-
- @Test
- public void testHostBucketCompareTo() {
- HostBucket hb1 = new HostBucket(PREV_HOST);
- HostBucket hb2 = new HostBucket(MY_HOST);
-
- assertEquals(0, hb1.compareTo(hb1));
- assertEquals(0, hb1.compareTo(new HostBucket(PREV_HOST)));
-
- // both empty
- assertTrue(hb1.compareTo(hb2) < 0);
- assertTrue(hb2.compareTo(hb1) > 0);
-
- // hb1 has one bucket, so it should not be larger
- hb1.add(100);
- assertTrue(hb1.compareTo(hb2) > 0);
- assertTrue(hb2.compareTo(hb1) < 0);
-
- // hb1 has two buckets, so it should still be larger
- hb1.add(200);
- assertTrue(hb1.compareTo(hb2) > 0);
- assertTrue(hb2.compareTo(hb1) < 0);
-
- // hb1 has two buckets, hb2 has one, so hb1 should still be larger
- hb2.add(1000);
- assertTrue(hb1.compareTo(hb2) > 0);
- assertTrue(hb2.compareTo(hb1) < 0);
-
- // same number of buckets, so hb2 should now be larger
- hb2.add(2000);
- assertTrue(hb1.compareTo(hb2) < 0);
- assertTrue(hb2.compareTo(hb1) > 0);
-
- // hb2 has more buckets, it should still be larger
- hb2.add(3000);
- assertTrue(hb1.compareTo(hb2) < 0);
- assertTrue(hb2.compareTo(hb1) > 0);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testHostBucketHashCode() {
- hostBucket.hashCode();
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void testHostBucketEquals() {
- hostBucket.equals(hostBucket);
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java
deleted file mode 100644
index 70abb96a..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-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 org.apache.commons.lang3.tuple.Pair;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-
-public class QueryStateTest extends SupportBasicStateTester {
-
- private QueryState state;
-
- /**
- * Setup.
- */
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new QueryState(mgr);
- }
-
- @Test
- public void testGoQuery() {
- assertNull(state.goQuery());
- }
-
- @Test
- public void testStart() {
- state.start();
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
- assertNotNull(timer.getRight());
- }
-
- @Test
- public void testProcessIdentification_SameSource() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertNull(state.process(new Identification(MY_HOST, asgn)));
-
- // info should be unchanged
- assertEquals(MY_HOST, state.getLeader());
- verify(mgr, never()).startDistributing(asgn);
- }
-
- @Test
- public void testProcessIdentification_DiffSource() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertNull(state.process(new Identification(HOST2, asgn)));
-
- // leader should be unchanged
- assertEquals(MY_HOST, state.getLeader());
-
- // should have picked up the assignments
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testProcessLeader_Invalid() {
- Leader msg = new Leader(PREV_HOST, null);
-
- // should stay in the same state, and not start distributing
- assertNull(state.process(msg));
- verify(mgr, never()).startDistributing(any());
- verify(mgr, never()).goActive();
- verify(mgr, never()).goInactive();
-
- // info should be unchanged
- assertEquals(MY_HOST, state.getLeader());
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test
- public void testProcessLeader_SameLeader() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- // identify a leader that's better than my host
- assertEquals(null, state.process(new Identification(PREV_HOST, asgn)));
-
- // now send a Leader message for that leader
- Leader msg = new Leader(PREV_HOST, asgn);
-
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // should go Active and start distributing
- assertEquals(next, state.process(msg));
- verify(mgr, never()).goInactive();
-
- // Ident msg + Leader msg = times(2)
- verify(mgr, times(2)).startDistributing(asgn);
- }
-
- @Test
- public void testProcessLeader_BetterLeaderWithAssignment() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
- Leader msg = new Leader(PREV_HOST, asgn);
-
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- // should go Active and start distributing
- assertEquals(next, state.process(msg));
- verify(mgr).startDistributing(asgn);
- verify(mgr, never()).goInactive();
- }
-
- @Test
- public void testProcessLeader_BetterLeaderWithoutAssignment() {
- String[] arr = {HOST2, PREV_HOST, HOST1};
- BucketAssignments asgn = new BucketAssignments(arr);
- Leader msg = new Leader(PREV_HOST, asgn);
-
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- // should go Inactive, but start distributing
- assertEquals(next, state.process(msg));
- verify(mgr).startDistributing(asgn);
- verify(mgr, never()).goActive();
- }
-
- @Test
- public void testProcessLeader_NotABetterLeader() {
- // no assignments yet
- mgr.startDistributing(null);
- state = new QueryState(mgr);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
- Leader msg = new Leader(HOST1, asgn);
-
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- // should stay in the same state
- assertNull(state.process(msg));
- verify(mgr, never()).goActive();
- verify(mgr, never()).goInactive();
-
- // should have started distributing
- verify(mgr).startDistributing(asgn);
-
- // this host should still be the leader
- assertEquals(MY_HOST, state.getLeader());
-
- // new assignments
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testProcessOffline_NullHost() {
- assertNull(state.process(new Offline()));
- assertEquals(MY_HOST, state.getLeader());
- }
-
- @Test
- public void testProcessOffline_SameHost() {
- assertNull(state.process(new Offline(MY_HOST)));
- assertEquals(MY_HOST, state.getLeader());
- }
-
- @Test
- public void testProcessOffline_DiffHost() {
- BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, HOST1});
- mgr.startDistributing(asgn);
- state = new QueryState(mgr);
-
- // tell it that the hosts are alive
- state.process(new Identification(PREV_HOST, asgn));
- state.process(new Identification(HOST1, asgn));
-
- // #2 goes offline
- assertNull(state.process(new Offline(HOST1)));
-
- // #1 should still be the leader
- assertEquals(PREV_HOST, state.getLeader());
-
- // #1 goes offline
- assertNull(state.process(new Offline(PREV_HOST)));
-
- // this should still be the leader now
- assertEquals(MY_HOST, state.getLeader());
- }
-
- @Test
- public void testQueryState() {
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testAwaitIdentification_MissingSelfIdent() {
- state.start();
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
- assertNotNull(timer.getRight());
-
- // should published an Offline message and go inactive
-
- State next = mock(State.class);
- when(mgr.goStart()).thenReturn(next);
-
- assertEquals(next, timer.getRight().fire());
-
- // should continue distributing
- verify(mgr, never()).startDistributing(null);
-
- Offline msg = captureAdminMessage(Offline.class);
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testAwaitIdentification_Leader() {
- state.start();
- state.process(new Identification(MY_HOST, null));
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
- assertNotNull(timer.getRight());
-
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- assertEquals(next, timer.getRight().fire());
-
- // should have published a Leader message
- Leader msg = captureAdminMessage(Leader.class);
- assertEquals(MY_HOST, msg.getSource());
- assertTrue(msg.getAssignments().hasAssignment(MY_HOST));
- }
-
- @Test
- public void testAwaitIdentification_HasAssignment() {
- // not the leader, but has an assignment
- BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
- mgr.startDistributing(asgn);
- state = new QueryState(mgr);
-
- state.start();
- state.process(new Identification(MY_HOST, null));
-
- // tell it the leader is still active
- state.process(new Identification(PREV_HOST, asgn));
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
- assertNotNull(timer.getRight());
-
- // set up active state, as that's what it should return
- State next = mock(State.class);
- when(mgr.goActive()).thenReturn(next);
-
- assertEquals(next, timer.getRight().fire());
-
- // should NOT have published a Leader message
- assertTrue(admin.isEmpty());
-
- // should have gone active with the current assignments
- verify(mgr).goActive();
- }
-
- @Test
- public void testAwaitIdentification_NoAssignment() {
- // not the leader and no assignment
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
- mgr.startDistributing(asgn);
- state = new QueryState(mgr);
-
- state.start();
- state.process(new Identification(MY_HOST, null));
-
- // tell it the leader is still active
- state.process(new Identification(PREV_HOST, asgn));
-
- Pair<Long, StateTimerTask> timer = onceTasks.remove();
-
- assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
- assertNotNull(timer.getRight());
-
- // set up inactive state, as that's what it should return
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- assertEquals(next, timer.getRight().fire());
-
- // should NOT have published a Leader message
- assertTrue(admin.isEmpty());
- }
-
- @Test
- public void testRecordInfo_NullSource() {
- state.setAssignments(ASGN3);
- state.setLeader(MY_HOST);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
- state.process(new Identification(null, asgn));
-
- // leader unchanged
- assertEquals(MY_HOST, state.getLeader());
-
- // assignments still updated
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_SourcePreceedsMyHost() {
- state.setAssignments(ASGN3);
- state.setLeader(MY_HOST);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
- state.process(new Identification(PREV_HOST, asgn));
-
- // new leader
- assertEquals(PREV_HOST, state.getLeader());
-
- // assignments still updated
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_SourceFollowsMyHost() {
- mgr.startDistributing(null);
- state.setLeader(MY_HOST);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
- state.process(new Identification(HOST1, asgn));
-
- // leader unchanged
- assertEquals(MY_HOST, state.getLeader());
-
- // assignments still updated
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_NewIsNull() {
- state.setAssignments(ASGN3);
- state.process(new Identification(HOST1, null));
-
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_NewIsEmpty() {
- state.setAssignments(ASGN3);
- state.process(new Identification(PREV_HOST, new BucketAssignments()));
-
- assertEquals(ASGN3, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_OldIsNull() {
- mgr.startDistributing(null);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
- state.process(new Identification(HOST1, asgn));
-
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_OldIsEmpty() {
- state.setAssignments(new BucketAssignments());
-
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
- state.process(new Identification(HOST1, asgn));
-
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_NewLeaderPreceedsOld() {
- state.setAssignments(ASGN3);
- state.setLeader(MY_HOST);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
- state.process(new Identification(HOST3, asgn));
-
- assertEquals(asgn, state.getAssignments());
- }
-
- @Test
- public void testRecordInfo_NewLeaderSucceedsOld() {
- state.setAssignments(ASGN3);
- state.setLeader(MY_HOST);
-
- BucketAssignments asgn = new BucketAssignments(new String[] {HOST2, HOST3});
- state.process(new Identification(HOST3, asgn));
-
- // should be unchanged
- assertEquals(ASGN3, state.getAssignments());
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java
deleted file mode 100644
index 3d64687f..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling.state;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-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 org.apache.commons.lang3.tuple.Pair;
-import org.apache.commons.lang3.tuple.Triple;
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class StartStateTest extends SupportBasicStateTester {
-
- private StartState state;
-
- /**
- * Setup.
- */
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new StartState(mgr);
- }
-
- @Test
- public void testStart() {
- state.start();
-
- Pair<String, Heartbeat> msg = capturePublishedMessage(Heartbeat.class);
-
- assertEquals(MY_HOST, msg.getLeft());
- assertEquals(state.getHbTimestampMs(), msg.getRight().getTimestampMs());
-
-
- /*
- * Verify heartbeat generator
- */
- Triple<Long, Long, StateTimerTask> generator = repeatedTasks.removeFirst();
-
- assertEquals(STD_INTER_HEARTBEAT_MS, generator.getLeft().longValue());
- assertEquals(STD_INTER_HEARTBEAT_MS, generator.getMiddle().longValue());
-
- // invoke the task - it should generate another heartbeat
- assertEquals(null, generator.getRight().fire());
- verify(mgr, times(2)).publish(MY_HOST, msg.getRight());
-
- // and again
- assertEquals(null, generator.getRight().fire());
- verify(mgr, times(3)).publish(MY_HOST, msg.getRight());
-
-
- /*
- * Verify heartbeat checker
- */
- Pair<Long, StateTimerTask> checker = onceTasks.removeFirst();
-
- assertEquals(STD_HEARTBEAT_WAIT_MS, checker.getLeft().longValue());
-
- // invoke the task - it should go to the state returned by the mgr
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- assertEquals(next, checker.getRight().fire());
-
- verify(mgr).startDistributing(null);
- }
-
- @Test
- public void testStartStatePoolingManager() {
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testStartStateState() {
- // create a new state from the current state
- state = new StartState(mgr);
-
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testProcessHeartbeat() {
- Heartbeat msg = new Heartbeat();
-
- // no matching data in heart beat
- assertNull(state.process(msg));
- verify(mgr, never()).publishAdmin(any());
-
- // same source, different time stamp
- msg.setSource(MY_HOST);
- msg.setTimestampMs(state.getHbTimestampMs() - 1);
- assertNull(state.process(msg));
- verify(mgr, never()).publishAdmin(any());
-
- // same time stamp, different source
- msg.setSource("unknown");
- msg.setTimestampMs(state.getHbTimestampMs());
- assertNull(state.process(msg));
- verify(mgr, never()).publishAdmin(any());
-
- // matching heart beat
- msg.setSource(MY_HOST);
- msg.setTimestampMs(state.getHbTimestampMs());
-
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- assertEquals(next, state.process(msg));
-
- verify(mgr).publishAdmin(any(Query.class));
- }
-
- @Test
- public void testProcessIdentification() {
- assertNull(state.process(new Identification(MY_HOST, null)));
- }
-
- @Test
- public void testProcessLeader() {
- assertNull(state.process(new Leader(MY_HOST, null)));
- }
-
- @Test
- public void testProcessOffline() {
- assertNull(state.process(new Offline(HOST1)));
- }
-
- @Test
- public void testProcessQuery() {
- assertNull(state.process(new Query()));
- }
-
- @Test
- public void testGetHbTimestampMs() {
- long tcurrent = System.currentTimeMillis();
- assertTrue(new StartState(mgr).getHbTimestampMs() >= tcurrent);
-
- tcurrent = System.currentTimeMillis();
- assertTrue(new StartState(mgr).getHbTimestampMs() >= tcurrent);
- }
-
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java
deleted file mode 100644
index 87868a76..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 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.pooling.state;
-
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.onap.policy.drools.pooling.CancellableScheduledTask;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Heartbeat;
-import org.onap.policy.drools.pooling.message.Identification;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Offline;
-import org.onap.policy.drools.pooling.message.Query;
-
-public class StateTest extends SupportBasicStateTester {
-
- private State state;
-
- /**
- * Setup.
- */
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- state = new MyState(mgr);
- }
-
- @Test
- public void testStatePoolingManager() {
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testStateState() {
- // allocate a new state, copying from the old state
- state = new MyState(mgr);
-
- /*
- * Prove the state is attached to the manager by invoking getHost(), which
- * delegates to the manager.
- */
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testCancelTimers() {
- int delay = 100;
- int initDelay = 200;
-
- /*
- * Create three tasks tasks.
- */
-
- StateTimerTask task1 = mock(StateTimerTask.class);
- StateTimerTask task2 = mock(StateTimerTask.class);
- StateTimerTask task3 = mock(StateTimerTask.class);
-
- // two tasks via schedule()
- state.schedule(delay, task1);
- state.schedule(delay, task2);
-
- // one task via scheduleWithFixedDelay()
- state.scheduleWithFixedDelay(initDelay, delay, task3);
-
- // ensure all were scheduled, but not yet canceled
- verify(mgr).schedule(delay, task1);
- verify(mgr).schedule(delay, task2);
- verify(mgr).scheduleWithFixedDelay(initDelay, delay, task3);
-
- CancellableScheduledTask sched1 = onceSchedules.removeFirst();
- CancellableScheduledTask sched2 = onceSchedules.removeFirst();
- CancellableScheduledTask sched3 = repeatedSchedules.removeFirst();
-
- verify(sched1, never()).cancel();
- verify(sched2, never()).cancel();
- verify(sched3, never()).cancel();
-
- /*
- * Cancel the timers.
- */
- state.cancelTimers();
-
- // verify that all were cancelled
- verify(sched1).cancel();
- verify(sched2).cancel();
- verify(sched3).cancel();
- }
-
- @Test
- public void testStart() {
- assertThatCode(() -> state.start()).doesNotThrowAnyException();
- }
-
- @Test
- public void testGoStart() {
- State next = mock(State.class);
- when(mgr.goStart()).thenReturn(next);
-
- State next2 = state.goStart();
- assertEquals(next, next2);
- }
-
- @Test
- public void testGoQuery() {
- State next = mock(State.class);
- when(mgr.goQuery()).thenReturn(next);
-
- State next2 = state.goQuery();
- assertEquals(next, next2);
- }
-
- @Test
- public void testGoActive_WithAssignment() {
- State act = mock(State.class);
- State inact = mock(State.class);
-
- when(mgr.goActive()).thenReturn(act);
- when(mgr.goInactive()).thenReturn(inact);
-
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertEquals(act, state.goActive(asgn));
-
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testGoActive_WithoutAssignment() {
- State act = mock(State.class);
- State inact = mock(State.class);
-
- when(mgr.goActive()).thenReturn(act);
- when(mgr.goInactive()).thenReturn(inact);
-
- String[] arr = {HOST2, PREV_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertEquals(inact, state.goActive(asgn));
-
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testGoActive_NullAssignment() {
- State act = mock(State.class);
- State inact = mock(State.class);
-
- when(mgr.goActive()).thenReturn(act);
- when(mgr.goInactive()).thenReturn(inact);
-
- assertEquals(inact, state.goActive(null));
-
- verify(mgr, never()).startDistributing(any());
- }
-
- @Test
- public void testGoInactive() {
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- State next2 = state.goInactive();
- assertEquals(next, next2);
- }
-
- @Test
- public void testProcessHeartbeat() {
- assertNull(state.process(new Heartbeat()));
- }
-
- @Test
- public void testProcessIdentification() {
- assertNull(state.process(new Identification()));
- }
-
- @Test
- public void testProcessLeader() {
- String[] arr = {HOST2, HOST1};
- BucketAssignments asgn = new BucketAssignments(arr);
- Leader msg = new Leader(HOST1, asgn);
-
- // should ignore it
- assertEquals(null, state.process(msg));
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testProcessLeader_Invalid() {
- Leader msg = new Leader(PREV_HOST, null);
-
- // should stay in the same state, and not start distributing
- assertNull(state.process(msg));
- verify(mgr, never()).startDistributing(any());
- verify(mgr, never()).goActive();
- verify(mgr, never()).goInactive();
- }
-
- @Test
- public void testIsValidLeader_NullAssignment() {
- assertFalse(state.isValid(new Leader(PREV_HOST, null)));
- }
-
- @Test
- public void testIsValidLeader_NullSource() {
- String[] arr = {HOST2, PREV_HOST, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
- assertFalse(state.isValid(new Leader(null, asgn)));
- }
-
- @Test
- public void testIsValidLeader_EmptyAssignment() {
- assertFalse(state.isValid(new Leader(PREV_HOST, new BucketAssignments())));
- }
-
- @Test
- public void testIsValidLeader_FromSelf() {
- String[] arr = {HOST2, MY_HOST};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertFalse(state.isValid(new Leader(MY_HOST, asgn)));
- }
-
- @Test
- public void testIsValidLeader_WrongLeader() {
- String[] arr = {HOST2, HOST3};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertFalse(state.isValid(new Leader(HOST1, asgn)));
- }
-
- @Test
- public void testIsValidLeader() {
- String[] arr = {HOST2, HOST1};
- BucketAssignments asgn = new BucketAssignments(arr);
-
- assertTrue(state.isValid(new Leader(HOST1, asgn)));
- }
-
- @Test
- public void testProcessOffline() {
- assertNull(state.process(new Offline()));
- }
-
- @Test
- public void testProcessQuery() {
- assertNull(state.process(new Query()));
- }
-
- @Test
- public void testPublishIdentification() {
- Identification msg = new Identification();
- state.publish(msg);
-
- verify(mgr).publishAdmin(msg);
- }
-
- @Test
- public void testPublishLeader() {
- Leader msg = new Leader();
- state.publish(msg);
-
- verify(mgr).publishAdmin(msg);
- }
-
- @Test
- public void testPublishOffline() {
- Offline msg = new Offline();
- state.publish(msg);
-
- verify(mgr).publishAdmin(msg);
- }
-
- @Test
- public void testPublishQuery() {
- Query msg = new Query();
- state.publish(msg);
-
- verify(mgr).publishAdmin(msg);
- }
-
- @Test
- public void testPublishStringHeartbeat() {
- String chnl = "channelH";
- Heartbeat msg = new Heartbeat();
-
- state.publish(chnl, msg);
-
- verify(mgr).publish(chnl, msg);
- }
-
- @Test
- public void testStartDistributing() {
- BucketAssignments asgn = new BucketAssignments();
- state.startDistributing(asgn);
-
- verify(mgr).startDistributing(asgn);
- }
-
- @Test
- public void testStartDistributing_NullAssignments() {
- state.startDistributing(null);
-
- verify(mgr, never()).startDistributing(any());
- }
-
- @Test
- public void testSchedule() {
- int delay = 100;
-
- StateTimerTask task = mock(StateTimerTask.class);
-
- state.schedule(delay, task);
-
- CancellableScheduledTask sched = onceSchedules.removeFirst();
-
- // scheduled, but not canceled yet
- verify(mgr).schedule(delay, task);
- verify(sched, never()).cancel();
-
- /*
- * Ensure the state added the timer to its list by telling it to cancel its timers
- * and then seeing if this timer was canceled.
- */
- state.cancelTimers();
- verify(sched).cancel();
- }
-
- @Test
- public void testScheduleWithFixedDelay() {
- int initdel = 100;
- int delay = 200;
-
- StateTimerTask task = mock(StateTimerTask.class);
-
- state.scheduleWithFixedDelay(initdel, delay, task);
-
- CancellableScheduledTask sched = repeatedSchedules.removeFirst();
-
- // scheduled, but not canceled yet
- verify(mgr).scheduleWithFixedDelay(initdel, delay, task);
- verify(sched, never()).cancel();
-
- /*
- * Ensure the state added the timer to its list by telling it to cancel its timers
- * and then seeing if this timer was canceled.
- */
- state.cancelTimers();
- verify(sched).cancel();
- }
-
- @Test
- public void testMissedHeartbeat() {
- State next = mock(State.class);
- when(mgr.goStart()).thenReturn(next);
-
- State next2 = state.missedHeartbeat();
- assertEquals(next, next2);
-
- // should continue to distribute
- verify(mgr, never()).startDistributing(null);
-
- Offline msg = captureAdminMessage(Offline.class);
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testInternalTopicFailed() {
- State next = mock(State.class);
- when(mgr.goInactive()).thenReturn(next);
-
- State next2 = state.internalTopicFailed();
- assertEquals(next, next2);
-
- // should stop distributing
- verify(mgr).startDistributing(null);
-
- Offline msg = captureAdminMessage(Offline.class);
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testMakeHeartbeat() {
- long timestamp = 30000L;
- Heartbeat msg = state.makeHeartbeat(timestamp);
-
- assertEquals(MY_HOST, msg.getSource());
- assertEquals(timestamp, msg.getTimestampMs());
- }
-
- @Test
- public void testMakeIdentification() {
- Identification ident = state.makeIdentification();
- assertEquals(MY_HOST, ident.getSource());
- assertEquals(ASGN3, ident.getAssignments());
- }
-
- @Test
- public void testMakeOffline() {
- Offline msg = state.makeOffline();
-
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testMakeQuery() {
- Query msg = state.makeQuery();
-
- assertEquals(MY_HOST, msg.getSource());
- }
-
- @Test
- public void testGetHost() {
- assertEquals(MY_HOST, state.getHost());
- }
-
- @Test
- public void testGetTopic() {
- assertEquals(MY_TOPIC, state.getTopic());
- }
-
- /**
- * State used for testing purposes, with abstract methods implemented.
- */
- private class MyState extends State {
-
- public MyState(PoolingManager mgr) {
- super(mgr);
- }
- }
-}
diff --git a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java b/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java
deleted file mode 100644
index 18d77ba7..00000000
--- a/feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * ONAP
- * ================================================================================
- * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2020 Nordix Foundation
- * ================================================================================
- * 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.pooling.state;
-
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicReference;
-import org.apache.commons.lang3.tuple.Pair;
-import org.apache.commons.lang3.tuple.Triple;
-import org.onap.policy.drools.pooling.CancellableScheduledTask;
-import org.onap.policy.drools.pooling.PoolingManager;
-import org.onap.policy.drools.pooling.PoolingProperties;
-import org.onap.policy.drools.pooling.message.BucketAssignments;
-import org.onap.policy.drools.pooling.message.Leader;
-import org.onap.policy.drools.pooling.message.Message;
-
-/**
- * Superclass used to test subclasses of {@link State}.
- */
-public class SupportBasicStateTester {
-
- protected static final long STD_HEARTBEAT_WAIT_MS = 10;
- protected static final long STD_REACTIVATE_WAIT_MS = STD_HEARTBEAT_WAIT_MS + 1;
- protected static final long STD_IDENTIFICATION_MS = STD_REACTIVATE_WAIT_MS + 1;
- protected static final long STD_ACTIVE_HEARTBEAT_MS = STD_IDENTIFICATION_MS + 1;
- protected static final long STD_INTER_HEARTBEAT_MS = STD_ACTIVE_HEARTBEAT_MS + 1;
-
- protected static final String MY_TOPIC = "myTopic";
-
- protected static final String PREV_HOST = "prevHost";
- protected static final String PREV_HOST2 = PREV_HOST + "A";
-
- // this follows PREV_HOST, alphabetically
- protected static final String MY_HOST = PREV_HOST + "X";
-
- // these follow MY_HOST, alphabetically
- protected static final String HOST1 = MY_HOST + "1";
- protected static final String HOST2 = MY_HOST + "2";
- protected static final String HOST3 = MY_HOST + "3";
- protected static final String HOST4 = MY_HOST + "4";
-
- protected static final String LEADER = HOST1;
-
- protected static final String[] HOST_ARR3 = {HOST1, MY_HOST, HOST2};
-
- protected static final BucketAssignments EMPTY_ASGN = new BucketAssignments();
- protected static final BucketAssignments ASGN3 = new BucketAssignments(HOST_ARR3);
-
- /**
- * Scheduled tasks returned by schedule().
- */
- protected LinkedList<CancellableScheduledTask> onceSchedules;
-
- /**
- * Tasks captured via schedule().
- */
- protected LinkedList<Pair<Long, StateTimerTask>> onceTasks;
-
- /**
- * Scheduled tasks returned by scheduleWithFixedDelay().
- */
- protected LinkedList<CancellableScheduledTask> repeatedSchedules;
-
- /**
- * Tasks captured via scheduleWithFixedDelay().
- */
- protected LinkedList<Triple<Long, Long, StateTimerTask>> repeatedTasks;
-
- /**
- * Messages captured via publish().
- */
- protected LinkedList<Pair<String, Message>> published;
-
- /**
- * Messages captured via publishAdmin().
- */
- protected LinkedList<Message> admin;
-
- protected PoolingManager mgr;
- protected PoolingProperties props;
- protected State prevState;
-
- public SupportBasicStateTester() {
- super();
- }
-
- /**
- * Setup.
- *
- * @throws Exception throws exception
- */
- public void setUp() throws Exception {
- onceSchedules = new LinkedList<>();
- onceTasks = new LinkedList<>();
-
- repeatedSchedules = new LinkedList<>();
- repeatedTasks = new LinkedList<>();
-
- published = new LinkedList<>();
- admin = new LinkedList<>();
-
- mgr = mock(PoolingManager.class);
- props = mock(PoolingProperties.class);
-
- when(mgr.getHost()).thenReturn(MY_HOST);
- when(mgr.getTopic()).thenReturn(MY_TOPIC);
- when(mgr.getProperties()).thenReturn(props);
-
- when(props.getStartHeartbeatMs()).thenReturn(STD_HEARTBEAT_WAIT_MS);
- when(props.getReactivateMs()).thenReturn(STD_REACTIVATE_WAIT_MS);
- when(props.getIdentificationMs()).thenReturn(STD_IDENTIFICATION_MS);
- when(props.getActiveHeartbeatMs()).thenReturn(STD_ACTIVE_HEARTBEAT_MS);
- when(props.getInterHeartbeatMs()).thenReturn(STD_INTER_HEARTBEAT_MS);
-
- prevState = new State(mgr) {};
-
- // capture publish() arguments
- doAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- published.add(Pair.of((String) args[0], (Message) args[1]));
-
- return null;
- }).when(mgr).publish(anyString(), any(Message.class));
-
- // capture publishAdmin() arguments
- doAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- admin.add((Message) args[0]);
-
- return null;
- }).when(mgr).publishAdmin(any(Message.class));
-
- // capture schedule() arguments, and return a new future
- when(mgr.schedule(anyLong(), any(StateTimerTask.class))).thenAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- onceTasks.add(Pair.of((Long) args[0], (StateTimerTask) args[1]));
-
- CancellableScheduledTask sched = mock(CancellableScheduledTask.class);
- onceSchedules.add(sched);
- return sched;
- });
-
- // capture scheduleWithFixedDelay() arguments, and return a new future
- when(mgr.scheduleWithFixedDelay(anyLong(), anyLong(), any(StateTimerTask.class))).thenAnswer(invocation -> {
- Object[] args = invocation.getArguments();
- repeatedTasks.add(Triple.of((Long) args[0], (Long) args[1], (StateTimerTask) args[2]));
-
- CancellableScheduledTask sched = mock(CancellableScheduledTask.class);
- repeatedSchedules.add(sched);
- return sched;
- });
-
- // get/set assignments in the manager
- AtomicReference<BucketAssignments> asgn = new AtomicReference<>(ASGN3);
-
- when(mgr.getAssignments()).thenAnswer(args -> asgn.get());
-
- doAnswer(args -> {
- asgn.set(args.getArgument(0));
- return null;
- }).when(mgr).startDistributing(any());
- }
-
- /**
- * Makes a sorted set of hosts.
- *
- * @param hosts the hosts to be sorted
- * @return the set of hosts, sorted
- */
- protected SortedSet<String> sortHosts(String... hosts) {
- return new TreeSet<>(Arrays.asList(hosts));
- }
-
- /**
- * Captures the host array from the Leader message published to the admin channel.
- *
- * @return the host array, as a list
- */
- protected List<String> captureHostList() {
- return Arrays.asList(captureHostArray());
- }
-
- /**
- * Captures the host array from the Leader message published to the admin channel.
- *
- * @return the host array
- */
- protected String[] captureHostArray() {
- BucketAssignments asgn = captureAssignments();
-
- String[] arr = asgn.getHostArray();
- assertNotNull(arr);
-
- return arr;
- }
-
- /**
- * Captures the assignments from the Leader message published to the admin channel.
- *
- * @return the bucket assignments
- */
- protected BucketAssignments captureAssignments() {
- Leader msg = captureAdminMessage(Leader.class);
-
- BucketAssignments asgn = msg.getAssignments();
- assertNotNull(asgn);
- return asgn;
- }
-
- /**
- * Captures the message published to the admin channel.
- *
- * @param clazz type of {@link Message} to capture
- * @return the message that was published
- */
- protected <T extends Message> T captureAdminMessage(Class<T> clazz) {
- return captureAdminMessage(clazz, 0);
- }
-
- /**
- * Captures the message published to the admin channel.
- *
- * @param clazz type of {@link Message} to capture
- * @param index index of the item to be captured
- * @return the message that was published
- */
- protected <T extends Message> T captureAdminMessage(Class<T> clazz, int index) {
- return clazz.cast(admin.get(index));
- }
-
- /**
- * Captures the message published to the non-admin channels.
- *
- * @param clazz type of {@link Message} to capture
- * @return the (channel,message) pair that was published
- */
- protected <T extends Message> Pair<String, T> capturePublishedMessage(Class<T> clazz) {
- return capturePublishedMessage(clazz, 0);
- }
-
- /**
- * Captures the message published to the non-admin channels.
- *
- * @param clazz type of {@link Message} to capture
- * @param index index of the item to be captured
- * @return the (channel,message) pair that was published
- */
- protected <T extends Message> Pair<String, T> capturePublishedMessage(Class<T> clazz, int index) {
- Pair<String, Message> msg = published.get(index);
- return Pair.of(msg.getLeft(), clazz.cast(msg.getRight()));
- }
-}
diff --git a/feature-pooling-dmaap/src/test/resources/logback-test.xml b/feature-pooling-dmaap/src/test/resources/logback-test.xml
deleted file mode 100644
index 45d8201d..00000000
--- a/feature-pooling-dmaap/src/test/resources/logback-test.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<!--
- ============LICENSE_START=======================================================
- ONAP
- ================================================================================
- Copyright (C) 2018 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=========================================================
- -->
-<configuration>
-
- <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
- <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
- <Pattern>
- %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n
- </Pattern>
- </encoder>
- </appender>
-
- <logger name="org.onap.policy.drools.http.server.test" level="INFO"/>
-
- <root level="WARN">
- <appender-ref ref="STDOUT"/>
- </root>
-
-</configuration> \ No newline at end of file