From cc1d3d352771d1fa35d297e90663539e34b022f6 Mon Sep 17 00:00:00 2001 From: "adheli.tavares" Date: Fri, 26 Jan 2024 15:28:56 +0000 Subject: Removing deprecated DMAAP library Issue-ID: POLICY-4402 Change-Id: I4ce5b303cb3a775010683d3c7102b0bd065280ea Signed-off-by: adheli.tavares --- .../DistributedLockManagerExceptionTest.java | 9 +- .../locking/DistributedLockManagerTest.java | 335 +++---- .../locking/DistributedLockPropertiesTest.java | 15 +- .../feature/config/feature-healthcheck.properties | 2 +- .../drools/healthcheck/HealthCheckFeatureTest.java | 27 +- .../drools/healthcheck/HealthCheckManagerTest.java | 39 +- .../policy/drools/healthcheck/HealthCheckTest.java | 21 +- .../drools/healthcheck/RestHealthCheckTest.java | 23 +- feature-healthcheck/src/test/resources/echo.drl | 3 +- .../src/test/resources/echo.kmodule | 3 +- .../config/feature-legacy-config.properties | 33 +- .../policy/drools/legacy/config/LegacyConfig.java | 6 +- .../legacy/config/LegacyConfigFeatureTest.java | 23 +- .../drools/legacy/config/LegacyConfigTest.java | 24 +- .../server/restful/RestLegacyConfigTest.java | 19 +- .../feature/config/feature-lifecycle.properties | 41 +- .../onap/policy/drools/lifecycle/LifecycleFsm.java | 8 +- .../drools/lifecycle/LifecycleStateActive.java | 7 +- .../drools/lifecycle/LifecycleStateRunning.java | 2 +- .../PolicyTypeNativeDroolsController.java | 2 +- .../policy/drools/lifecycle/ControllerSupport.java | 23 +- .../policy/drools/lifecycle/LifecycleFsmTest.java | 36 +- .../drools/lifecycle/LifecycleFsmUpdateTest.java | 67 +- .../LifecycleStateActivePoliciesTest.java | 24 +- .../drools/lifecycle/LifecycleStateActiveTest.java | 34 +- .../lifecycle/LifecycleStatePassiveTest.java | 50 +- .../lifecycle/LifecycleStateRunningTest.java | 9 +- .../drools/lifecycle/LifecycleStateSafeTest.java | 9 +- .../lifecycle/LifecycleStateTerminatedTest.java | 44 +- .../drools/lifecycle/LifecycleStateTestTest.java | 9 +- .../lifecycle/LifecycleStateUnsupportedTest.java | 11 +- .../lifecycle/PolicyTypeDroolsControllerTest.java | 19 +- .../PolicyTypeNativeArtifactControllerTest.java | 25 +- .../PolicyTypeNativeDroolsControllerTest.java | 28 +- .../server/restful/RestLifecycleManagerTest.java | 36 +- feature-lifecycle/src/test/resources/echo.kmodule | 3 +- .../src/test/resources/lifecycle.kmodule | 3 +- .../tosca-policy-native-controller-example.json | 4 +- .../onap/policy/no/locking/NoLockManagerTest.java | 34 +- feature-pooling-dmaap/pom.xml | 121 --- .../src/assembly/assemble_zip.xml | 76 -- .../config/feature-pooling-dmaap.properties | 87 -- .../drools/pooling/CancellableScheduledTask.java | 33 - .../onap/policy/drools/pooling/DmaapManager.java | 232 ----- .../onap/policy/drools/pooling/PoolingFeature.java | 396 -------- .../drools/pooling/PoolingFeatureException.java | 50 - .../drools/pooling/PoolingFeatureRtException.java | 50 - .../onap/policy/drools/pooling/PoolingManager.java | 132 --- .../policy/drools/pooling/PoolingManagerImpl.java | 646 ------------ .../policy/drools/pooling/PoolingProperties.java | 149 --- .../org/onap/policy/drools/pooling/Serializer.java | 123 --- .../drools/pooling/message/BucketAssignments.java | 204 ---- .../policy/drools/pooling/message/Heartbeat.java | 51 - .../drools/pooling/message/Identification.java | 40 - .../onap/policy/drools/pooling/message/Leader.java | 69 -- .../policy/drools/pooling/message/Message.java | 78 -- .../pooling/message/MessageWithAssignments.java | 67 -- .../policy/drools/pooling/message/Offline.java | 40 - .../onap/policy/drools/pooling/message/Query.java | 39 - .../policy/drools/pooling/state/ActiveState.java | 269 ----- .../policy/drools/pooling/state/IdleState.java | 33 - .../policy/drools/pooling/state/InactiveState.java | 80 -- .../drools/pooling/state/ProcessingState.java | 399 -------- .../policy/drools/pooling/state/QueryState.java | 204 ---- .../policy/drools/pooling/state/StartState.java | 98 -- .../onap/policy/drools/pooling/state/State.java | 372 ------- .../drools/pooling/state/StateTimerTask.java | 36 - ...licy.drools.features.DroolsControllerFeatureApi | 1 - ...licy.drools.features.PolicyControllerFeatureApi | 1 - ...p.policy.drools.features.PolicyEngineFeatureApi | 1 - .../policy/drools/pooling/DmaapManagerTest.java | 319 ------ .../policy/drools/pooling/EndToEndFeatureTest.java | 809 --------------- .../onap/policy/drools/pooling/FeatureTest.java | 1040 -------------------- .../pooling/PoolingFeatureExceptionTest.java | 35 - .../pooling/PoolingFeatureRtExceptionTest.java | 35 - .../policy/drools/pooling/PoolingFeatureTest.java | 547 ---------- .../drools/pooling/PoolingManagerImplTest.java | 994 ------------------- .../drools/pooling/PoolingPropertiesTest.java | 191 ---- .../onap/policy/drools/pooling/SerializerTest.java | 84 -- .../pooling/feature-pooling-dmaap.properties | 46 - .../pooling/message/BucketAssignmentsTest.java | 360 ------- .../drools/pooling/message/HeartbeatTest.java | 58 -- .../drools/pooling/message/IdentificationTest.java | 73 -- .../policy/drools/pooling/message/LeaderTest.java | 73 -- .../policy/drools/pooling/message/MessageTest.java | 81 -- .../policy/drools/pooling/message/OfflineTest.java | 37 - .../policy/drools/pooling/message/QueryTest.java | 37 - .../pooling/message/SupportBasicMessageTester.java | 250 ----- .../SupportMessageWithAssignmentsTester.java | 113 --- .../drools/pooling/state/ActiveStateTest.java | 470 --------- .../policy/drools/pooling/state/IdleStateTest.java | 97 -- .../drools/pooling/state/InactiveStateTest.java | 121 --- .../drools/pooling/state/ProcessingStateTest.java | 393 -------- .../drools/pooling/state/QueryStateTest.java | 444 --------- .../drools/pooling/state/StartStateTest.java | 184 ---- .../policy/drools/pooling/state/StateTest.java | 465 --------- .../pooling/state/SupportBasicStateTester.java | 282 ------ .../src/test/resources/logback-test.xml | 36 - feature-pooling-messages/pom.xml | 108 ++ .../src/assembly/assemble_zip.xml | 76 ++ .../config/feature-pooling-messages.properties | 89 ++ .../drools/pooling/CancellableScheduledTask.java | 34 + .../onap/policy/drools/pooling/PoolingFeature.java | 397 ++++++++ .../drools/pooling/PoolingFeatureException.java | 54 + .../drools/pooling/PoolingFeatureRtException.java | 54 + .../onap/policy/drools/pooling/PoolingManager.java | 133 +++ .../policy/drools/pooling/PoolingManagerImpl.java | 647 ++++++++++++ .../policy/drools/pooling/PoolingProperties.java | 150 +++ .../org/onap/policy/drools/pooling/Serializer.java | 124 +++ .../policy/drools/pooling/TopicMessageManager.java | 233 +++++ .../drools/pooling/message/BucketAssignments.java | 205 ++++ .../policy/drools/pooling/message/Heartbeat.java | 52 + .../drools/pooling/message/Identification.java | 41 + .../onap/policy/drools/pooling/message/Leader.java | 70 ++ .../policy/drools/pooling/message/Message.java | 79 ++ .../pooling/message/MessageWithAssignments.java | 68 ++ .../policy/drools/pooling/message/Offline.java | 41 + .../onap/policy/drools/pooling/message/Query.java | 40 + .../policy/drools/pooling/state/ActiveState.java | 270 +++++ .../policy/drools/pooling/state/IdleState.java | 34 + .../policy/drools/pooling/state/InactiveState.java | 81 ++ .../drools/pooling/state/ProcessingState.java | 398 ++++++++ .../policy/drools/pooling/state/QueryState.java | 204 ++++ .../policy/drools/pooling/state/StartState.java | 99 ++ .../onap/policy/drools/pooling/state/State.java | 373 +++++++ .../drools/pooling/state/StateTimerTask.java | 37 + ...licy.drools.features.DroolsControllerFeatureApi | 1 + ...licy.drools.features.PolicyControllerFeatureApi | 1 + ...p.policy.drools.features.PolicyEngineFeatureApi | 1 + .../policy/drools/pooling/EndToEndFeatureTest.java | 810 +++++++++++++++ .../onap/policy/drools/pooling/FeatureTest.java | 1033 +++++++++++++++++++ .../pooling/PoolingFeatureExceptionTest.java | 36 + .../pooling/PoolingFeatureRtExceptionTest.java | 36 + .../policy/drools/pooling/PoolingFeatureTest.java | 548 +++++++++++ .../drools/pooling/PoolingManagerImplTest.java | 995 +++++++++++++++++++ .../drools/pooling/PoolingPropertiesTest.java | 190 ++++ .../onap/policy/drools/pooling/SerializerTest.java | 85 ++ .../drools/pooling/TopicMessageManagerTest.java | 322 ++++++ .../pooling/feature-pooling-messages.properties | 47 + .../pooling/message/BucketAssignmentsTest.java | 361 +++++++ .../drools/pooling/message/HeartbeatTest.java | 59 ++ .../drools/pooling/message/IdentificationTest.java | 74 ++ .../policy/drools/pooling/message/LeaderTest.java | 73 ++ .../policy/drools/pooling/message/MessageTest.java | 82 ++ .../policy/drools/pooling/message/OfflineTest.java | 38 + .../policy/drools/pooling/message/QueryTest.java | 38 + .../pooling/message/SupportBasicMessageTester.java | 251 +++++ .../SupportMessageWithAssignmentsTester.java | 103 ++ .../drools/pooling/state/ActiveStateTest.java | 470 +++++++++ .../policy/drools/pooling/state/IdleStateTest.java | 98 ++ .../drools/pooling/state/InactiveStateTest.java | 121 +++ .../drools/pooling/state/ProcessingStateTest.java | 396 ++++++++ .../drools/pooling/state/QueryStateTest.java | 444 +++++++++ .../drools/pooling/state/StartStateTest.java | 184 ++++ .../policy/drools/pooling/state/StateTest.java | 466 +++++++++ .../pooling/state/SupportBasicStateTester.java | 282 ++++++ .../src/test/resources/logback-test.xml | 36 + .../TestTransactionAdditionalTest.java | 41 +- .../TestTransactionFeatureTest.java | 27 +- .../testtransaction/TestTransactionTest.java | 23 +- packages/docker/src/main/docker/pdpd-entrypoint.sh | 8 +- packages/install/pom.xml | 4 +- packages/install/src/files/base.conf | 17 +- .../install/src/files/feature-pooling-dmaap.conf | 20 - .../src/files/feature-pooling-messages.conf | 20 + policy-core/pom.xml | 4 - .../onap/policy/drools/core/PolicyContainer.java | 15 +- .../org/onap/policy/drools/core/PolicySession.java | 11 +- .../org/onap/policy/drools/core/jmx/PdpJmx.java | 3 +- .../policy/drools/core/lock/AlwaysFailLock.java | 3 + .../policy/drools/core/lock/AlwaysSuccessLock.java | 3 + .../policy/drools/util/FeatureEnabledChecker.java | 5 +- .../policy/drools/core/DroolsContainerTest.java | 41 +- .../drools/core/PolicySessionFeatureApiMock.java | 16 +- .../drools/core/PolicySessionFeatureApiTest.java | 16 +- .../onap/policy/drools/core/PolicySessionTest.java | 27 +- .../onap/policy/drools/core/jmx/PdpJmxTest.java | 25 +- .../drools/core/lock/AlwaysFailLockTest.java | 19 +- .../drools/core/lock/AlwaysLockBaseTest.java | 9 +- .../drools/core/lock/AlwaysSuccessLockTest.java | 23 +- .../onap/policy/drools/core/lock/LockImplTest.java | 47 +- .../drools/util/FeatureEnabledCheckerTest.java | 11 +- .../org/onap/policy/drools/util/KieUtilsTest.java | 35 +- .../src/main/resources/META-INF/kmodule.xml | 2 +- .../src/main/resources/META-INF/kmodule.xml | 2 +- .../domain/models/DomainPolicyTypesTest.java | 18 +- .../drools/domain/models/DroolsPolicyTest.java | 13 +- .../domain/models/artifact/ArtifactPolicyTest.java | 9 +- .../models/controller/ControllerPolicyTest.java | 11 +- .../models/operational/OperationalPolicyTest.java | 36 +- .../controller/IndexedDroolsControllerFactory.java | 13 +- .../controller/internal/MavenDroolsController.java | 6 +- .../protocol/configuration/PdpdConfiguration.java | 44 +- .../policy/drools/server/restful/RestManager.java | 42 +- .../policy/drools/server/restful/aaf/AafBase.java | 35 - .../server/restful/aaf/AafTelemetryAuthFilter.java | 41 - .../policy/drools/system/PolicyEngineManager.java | 7 +- .../src/main/resources/openapi/openapi.yaml | 4 +- .../src/main/resources/swagger/swagger.json | 3 - .../main/server-gen/bin/add-secured-participant | 3 +- .../src/main/server-gen/bin/create-api-key | 3 +- .../src/main/server-gen/bin/create-secured-topic | 3 +- .../src/main/server-gen/bin/pdpd-configuration | 5 +- .../src/main/server/config/aaf-cadi.keyfile | 27 - .../src/main/server/config/aaf-system.properties | 43 - .../src/main/server/config/engine.properties | 5 +- .../controller/DroolsControllerFactoryTest.java | 29 +- .../internal/MavenDroolsController2Test.java | 361 +++---- .../internal/MavenDroolsControllerTest.java | 92 +- .../MavenDroolsControllerUpgradesTest.java | 37 +- .../internal/NullDroolsControllerTest.java | 132 +-- .../drools/persistence/SystemPersistenceTest.java | 35 +- .../protocol/coders/EventProtocolCoderTest.java | 9 +- .../protocol/coders/JsonProtocolFilterTest.java | 58 +- .../protocol/coders/ProtocolCoderToolsetTest.java | 27 +- .../configuration/ControllerConfigurationTest.java | 17 +- .../configuration/DroolsConfigurationTest.java | 15 +- .../configuration/PdpdConfigurationTest.java | 16 +- .../server/restful/test/RestManagerTest.java | 122 +-- .../restful/test/TestAafTelemetryAuthFilter.java | 43 - .../drools/stats/PolicyStatsManagerTest.java | 9 +- .../onap/policy/drools/stats/PolicyStatsTest.java | 9 +- .../drools/system/PolicyControllerFactoryTest.java | 58 +- .../PolicyDroolsPdpRuntimeExceptionTest.java | 9 +- .../drools/system/PolicyEngineManagerTest.java | 127 +-- .../policy/drools/system/PolicyEngineTest.java | 55 +- .../internal/AggregatedPolicyControllerTest.java | 127 +-- .../system/internal/FeatureLockImplTest.java | 115 ++- .../drools/system/internal/LockManagerTest.java | 52 +- .../internal/SimpleLockManagerExceptionTest.java | 9 +- .../system/internal/SimpleLockManagerTest.java | 138 +-- policy-management/src/test/resources/echo.kmodule | 3 +- .../policy/drools/system/PolicyEngineTestAdd.json | 1 - .../drools/system/PolicyEngineTestConfig.json | 1 - policy-management/src/test/resources/rules.kmodule | 3 +- .../onap/policy/drools/utils/ReflectionUtil.java | 7 +- .../policy/drools/utils/logging/LoggerUtil.java | 42 - .../org/onap/policy/drools/metrics/MetricTest.java | 43 +- .../policy/drools/models/domains/a/Metadata.java | 5 +- .../policy/drools/models/domains/a/Nested.java | 5 +- .../policy/drools/models/domains/a/Properties.java | 5 +- .../policy/drools/policies/DomainMakerTest.java | 36 +- .../onap/policy/drools/utils/PropertyUtilTest.java | 25 +- .../onap/policy/drools/utils/ReferenceTest.java | 19 +- .../policy/drools/utils/ReflectionUtilTest.java | 36 +- .../drools/utils/logging/LoggerUtilTest.java | 11 +- .../drools/utils/logging/MdcTransactionTest.java | 29 +- pom.xml | 14 +- 248 files changed, 13754 insertions(+), 13913 deletions(-) delete mode 100644 feature-pooling-dmaap/pom.xml delete mode 100644 feature-pooling-dmaap/src/assembly/assemble_zip.xml delete mode 100644 feature-pooling-dmaap/src/main/feature/config/feature-pooling-dmaap.properties delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/DmaapManager.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/Serializer.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Identification.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Leader.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Message.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Offline.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/message/Query.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StartState.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/State.java delete mode 100644 feature-pooling-dmaap/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java delete mode 100644 feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi delete mode 100644 feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi delete mode 100644 feature-pooling-dmaap/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/DmaapManagerTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/feature-pooling-dmaap.properties delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java delete mode 100644 feature-pooling-dmaap/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java delete mode 100644 feature-pooling-dmaap/src/test/resources/logback-test.xml create mode 100644 feature-pooling-messages/pom.xml create mode 100644 feature-pooling-messages/src/assembly/assemble_zip.xml create mode 100644 feature-pooling-messages/src/main/feature/config/feature-pooling-messages.properties create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/Serializer.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/TopicMessageManager.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Identification.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Leader.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Message.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Offline.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Query.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StartState.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/State.java create mode 100644 feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java create mode 100644 feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi create mode 100644 feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi create mode 100644 feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/TopicMessageManagerTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/feature-pooling-messages.properties create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java create mode 100644 feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java create mode 100644 feature-pooling-messages/src/test/resources/logback-test.xml delete mode 100644 packages/install/src/files/feature-pooling-dmaap.conf create mode 100644 packages/install/src/files/feature-pooling-messages.conf delete mode 100644 policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafBase.java delete mode 100644 policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafTelemetryAuthFilter.java delete mode 100644 policy-management/src/main/server/config/aaf-cadi.keyfile delete mode 100644 policy-management/src/main/server/config/aaf-system.properties delete mode 100644 policy-management/src/test/java/org/onap/policy/drools/server/restful/test/TestAafTelemetryAuthFilter.java delete mode 100644 policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerExceptionTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerExceptionTest.java index 9c172545..59833c29 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerExceptionTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerExceptionTest.java @@ -3,6 +3,7 @@ * feature-distributed-locking * ================================================================================ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.distributed.locking; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.test.ExceptionsTester; -public class DistributedLockManagerExceptionTest extends ExceptionsTester { +class DistributedLockManagerExceptionTest extends ExceptionsTester { @Test - public void test() { + void test() { assertEquals(1, test(DistributedLockManagerException.class)); } diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerTest.java index 9646a88c..74a3c761 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockManagerTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,18 +25,19 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 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.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -47,6 +48,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serial; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -66,16 +68,17 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.apache.commons.dbcp2.BasicDataSource; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.kie.api.runtime.KieSession; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.policy.common.utils.services.OrderedServiceImpl; import org.onap.policy.distributed.locking.DistributedLockManager.DistributedLock; import org.onap.policy.drools.core.PolicySession; @@ -88,8 +91,8 @@ import org.onap.policy.drools.system.PolicyEngine; import org.onap.policy.drools.system.PolicyEngineConstants; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(MockitoJUnitRunner.class) -public class DistributedLockManagerTest { +@ExtendWith(MockitoExtension.class) +class DistributedLockManagerTest { private static final long EXPIRE_SEC = 900L; private static final long RETRY_SEC = 60L; private static final String POLICY_ENGINE_EXECUTOR_FIELD = "executorService"; @@ -142,19 +145,20 @@ public class DistributedLockManagerTest { private BasicDataSource datasrc; private DistributedLock lock; - private PolicySession session; private AtomicInteger nactive; private AtomicInteger nsuccesses; private DistributedLockManager feature; + AutoCloseable closeable; + /** * Configures the location of the property files and creates the DB. * * @throws SQLException if the DB cannot be created */ - @BeforeClass - public static void setUpBeforeClass() throws SQLException { + @BeforeAll + static void setUpBeforeClass() throws SQLException { SystemPersistenceConstants.getManager().setConfigurationDir("src/test/resources"); PolicyEngineConstants.getManager().configure(new Properties()); @@ -175,8 +179,8 @@ public class DistributedLockManagerTest { /** * Restores static fields. */ - @AfterClass - public static void tearDownAfterClass() throws SQLException { + @AfterAll + static void tearDownAfterClass() throws SQLException { ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, saveExec); realExec.shutdown(); conn.close(); @@ -188,10 +192,11 @@ public class DistributedLockManagerTest { * * @throws SQLException if the lock records cannot be deleted from the DB */ - @Before - public void setUp() throws SQLException { + @BeforeEach + void setUp() throws SQLException { + closeable = MockitoAnnotations.openMocks(this); // grant() and deny() calls will come through here and be immediately executed - session = new PolicySession(null, null, kieSess) { + PolicySession session = new PolicySession(null, null, kieSess) { @Override public void insertDrools(Object object) { ((Runnable) object).run(); @@ -208,10 +213,11 @@ public class DistributedLockManagerTest { feature = new MyLockingFeature(true); } - @After - public void tearDown() throws SQLException { + @AfterEach + void tearDown() throws Exception { shutdownFeature(); cleanDb(); + closeable.close(); } private void cleanDb() throws SQLException { @@ -231,18 +237,18 @@ public class DistributedLockManagerTest { * Tests that the feature is found in the expected service sets. */ @Test - public void testServiceApis() { + void testServiceApis() { assertTrue(new OrderedServiceImpl<>(PolicyEngineFeatureApi.class).getList().stream() .anyMatch(obj -> obj instanceof DistributedLockManager)); } @Test - public void testGetSequenceNumber() { + void testGetSequenceNumber() { assertEquals(1000, feature.getSequenceNumber()); } @Test - public void testBeforeCreateLockManager() { + void testBeforeCreateLockManager() { assertSame(feature, feature.beforeCreateLockManager(engine, new Properties())); } @@ -250,7 +256,7 @@ public class DistributedLockManagerTest { * Tests beforeCreate(), when getProperties() throws a runtime exception. */ @Test - public void testBeforeCreateLockManagerEx() { + void testBeforeCreateLockManagerEx() { shutdownFeature(); feature = new MyLockingFeature(false) { @@ -266,7 +272,7 @@ public class DistributedLockManagerTest { } @Test - public void testAfterStart() { + void testAfterStart() { // verify that cleanup & expire check are both added to the queue verify(exsvc).execute(any()); verify(exsvc).schedule(any(Runnable.class), anyLong(), any()); @@ -276,7 +282,7 @@ public class DistributedLockManagerTest { * Tests afterStart(), when thread pool throws a runtime exception. */ @Test - public void testAfterStartExInThreadPool() { + void testAfterStartExInThreadPool() { shutdownFeature(); feature = new MyLockingFeature(false); @@ -287,7 +293,7 @@ public class DistributedLockManagerTest { } @Test - public void testDeleteExpiredDbLocks() throws SQLException { + void testDeleteExpiredDbLocks() throws SQLException { // add records: two expired, one not insertRecord(RESOURCE, feature.getUuidString(), -1); insertRecord(RESOURCE2, feature.getUuidString(), HOLD_SEC2); @@ -315,7 +321,7 @@ public class DistributedLockManagerTest { * */ @Test - public void testDeleteExpiredDbLocksEx() { + void testDeleteExpiredDbLocksEx() { feature = new InvalidDbLockingFeature(TRANSIENT); // get the clean-up function and execute it @@ -329,7 +335,7 @@ public class DistributedLockManagerTest { } @Test - public void testAfterStop() { + void testAfterStop() { shutdownFeature(); verify(checker).cancel(anyBoolean()); @@ -345,7 +351,7 @@ public class DistributedLockManagerTest { * */ @Test - public void testAfterStopEx() { + void testAfterStopEx() { shutdownFeature(); // use a data source that throws an exception when closed @@ -355,24 +361,24 @@ public class DistributedLockManagerTest { } @Test - public void testCreateLock() throws SQLException { + void testCreateLock() throws SQLException { verify(exsvc).execute(any()); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); assertTrue(lock.isWaiting()); verify(exsvc, times(PRE_LOCK_EXECS + 1)).execute(any()); // this lock should fail LockCallback callback2 = mock(LockCallback.class); - DistributedLock lock2 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback2, false); + DistributedLock lock2 = getLock(RESOURCE, callback2); assertTrue(lock2.isUnavailable()); verify(callback2, never()).lockAvailable(lock2); verify(callback2).lockUnavailable(lock2); // this should fail, too LockCallback callback3 = mock(LockCallback.class); - DistributedLock lock3 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback3, false); + DistributedLock lock3 = getLock(RESOURCE, callback3); assertTrue(lock3.isUnavailable()); verify(callback3, never()).lockAvailable(lock3); verify(callback3).lockUnavailable(lock3); @@ -395,11 +401,11 @@ public class DistributedLockManagerTest { verify(callback, never()).lockUnavailable(lock); // this should succeed - DistributedLock lock4 = getLock(RESOURCE2, OWNER_KEY, HOLD_SEC, callback, false); + DistributedLock lock4 = getLock(RESOURCE2, callback); assertTrue(lock4.isWaiting()); // after running checker, original records should still remain - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); assertEquals(1, getRecordCount()); verify(callback, never()).lockUnavailable(lock); } @@ -408,7 +414,7 @@ public class DistributedLockManagerTest { * Tests createLock() when the feature is not the latest instance. */ @Test - public void testCreateLockNotLatestInstance() { + void testCreateLockNotLatestInstance() { DistributedLockManager.setLatestInstance(null); Lock lock = feature.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); @@ -418,24 +424,24 @@ public class DistributedLockManagerTest { } @Test - public void testCheckExpired() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testCheckExpired() throws SQLException { + lock = getLock(RESOURCE, callback); runLock(0, 0); LockCallback callback2 = mock(LockCallback.class); - final DistributedLock lock2 = getLock(RESOURCE2, OWNER_KEY, HOLD_SEC, callback2, false); + final DistributedLock lock2 = getLock(RESOURCE2, callback2); runLock(1, 0); LockCallback callback3 = mock(LockCallback.class); - final DistributedLock lock3 = getLock(RESOURCE3, OWNER_KEY, HOLD_SEC, callback3, false); + final DistributedLock lock3 = getLock(RESOURCE3, callback3); runLock(2, 0); LockCallback callback4 = mock(LockCallback.class); - final DistributedLock lock4 = getLock(RESOURCE4, OWNER_KEY, HOLD_SEC, callback4, false); + final DistributedLock lock4 = getLock(RESOURCE4, callback4); runLock(3, 0); LockCallback callback5 = mock(LockCallback.class); - final DistributedLock lock5 = getLock(RESOURCE5, OWNER_KEY, HOLD_SEC, callback5, false); + final DistributedLock lock5 = getLock(RESOURCE5, callback5); runLock(4, 0); assertEquals(5, getRecordCount()); @@ -450,7 +456,7 @@ public class DistributedLockManagerTest { updateRecord(RESOURCE5, feature.getPdpName(), OTHER_OWNER, HOLD_SEC); // run the checker - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); // check lock states assertTrue(lock.isUnavailable()); @@ -471,33 +477,33 @@ public class DistributedLockManagerTest { verify(callback4, never()).lockUnavailable(lock4); // another check should have been scheduled, with the normal interval - runChecker(1, 0, EXPIRE_SEC); + runChecker(1, EXPIRE_SEC); } /** * Tests checkExpired(), when schedule() throws an exception. */ @Test - public void testCheckExpiredExecRejected() { + void testCheckExpiredExecRejected() { // arrange for execution to be rejected when(exsvc.schedule(any(Runnable.class), anyLong(), any())) .thenThrow(new RejectedExecutionException(EXPECTED_EXCEPTION)); - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); } /** * Tests checkExpired(), when getConnection() throws an exception. */ @Test - public void testCheckExpiredSqlEx() { + void testCheckExpiredSqlEx() { // use a data source that throws an exception when getConnection() is called feature = new InvalidDbLockingFeature(TRANSIENT); - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); // it should have scheduled another check, sooner - runChecker(0, 0, RETRY_SEC); + runChecker(0, RETRY_SEC); } /** @@ -505,7 +511,7 @@ public class DistributedLockManagerTest { * no longer alive. */ @Test - public void testCheckExpiredSqlExFeatureStopped() { + void testCheckExpiredSqlExFeatureStopped() { // use a data source that throws an exception when getConnection() is called feature = new InvalidDbLockingFeature(TRANSIENT) { @Override @@ -515,14 +521,14 @@ public class DistributedLockManagerTest { } }; - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); // it should NOT have scheduled another check verify(exsvc, times(1)).schedule(any(Runnable.class), anyLong(), any()); } @Test - public void testExpireLocks() throws SQLException { + void testExpireLocks() throws SQLException { AtomicReference freeLock = new AtomicReference<>(null); feature = new MyLockingFeature(true) { @@ -548,19 +554,19 @@ public class DistributedLockManagerTest { } }; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); runLock(0, 0); LockCallback callback2 = mock(LockCallback.class); - final DistributedLock lock2 = getLock(RESOURCE2, OWNER_KEY, HOLD_SEC, callback2, false); + final DistributedLock lock2 = getLock(RESOURCE2, callback2); runLock(1, 0); LockCallback callback3 = mock(LockCallback.class); - final DistributedLock lock3 = getLock(RESOURCE3, OWNER_KEY, HOLD_SEC, callback3, false); + final DistributedLock lock3 = getLock(RESOURCE3, callback3); // don't run doLock for lock3 - leave it in the waiting state LockCallback callback4 = mock(LockCallback.class); - final DistributedLock lock4 = getLock(RESOURCE4, OWNER_KEY, HOLD_SEC, callback4, false); + final DistributedLock lock4 = getLock(RESOURCE4, callback4); runLock(3, 0); assertEquals(3, getRecordCount()); @@ -572,7 +578,7 @@ public class DistributedLockManagerTest { freeLock.set(lock4); // run the checker - runChecker(0, 0, EXPIRE_SEC); + runChecker(0, EXPIRE_SEC); // check lock states assertTrue(lock.isUnavailable()); @@ -590,7 +596,7 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockNoArgs() { + void testDistributedLockNoArgs() { DistributedLock lock = new DistributedLock(); assertNull(lock.getResourceId()); assertNull(lock.getOwnerKey()); @@ -599,7 +605,7 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLock() { + void testDistributedLock() { assertThatIllegalArgumentException() .isThrownBy(() -> feature.createLock(RESOURCE, OWNER_KEY, -1, callback, false)) .withMessageContaining("holdSec"); @@ -609,8 +615,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockSerializable() throws Exception { - DistributedLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockSerializable() throws Exception { + DistributedLock lock = getLock(RESOURCE, callback); lock = roundTrip(lock); assertTrue(lock.isWaiting()); @@ -622,8 +628,8 @@ public class DistributedLockManagerTest { } @Test - public void testGrant() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testGrant() { + lock = getLock(RESOURCE, callback); assertFalse(lock.isActive()); // execute the doLock() call @@ -636,12 +642,12 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockDeny() { + void testDistributedLockDeny() { // get a lock feature.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); // get another lock - should fail - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); assertTrue(lock.isUnavailable()); @@ -653,8 +659,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockFree() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockFree() { + lock = getLock(RESOURCE, callback); assertTrue(lock.free()); assertTrue(lock.isUnavailable()); @@ -673,7 +679,7 @@ public class DistributedLockManagerTest { verify(exsvc, times(PRE_LOCK_EXECS + 2)).execute(any()); // new lock should succeed - DistributedLock lock2 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + DistributedLock lock2 = getLock(RESOURCE, callback); assertNotSame(lock2, lock); assertTrue(lock2.isWaiting()); } @@ -684,8 +690,8 @@ public class DistributedLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testDistributedLockFreeSerialized() throws Exception { - DistributedLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockFreeSerialized() throws Exception { + DistributedLock lock = getLock(RESOURCE, callback); feature = new MyLockingFeature(true); @@ -700,8 +706,8 @@ public class DistributedLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testDistributedLockFreeNoFeature() throws Exception { - DistributedLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockFreeNoFeature() throws Exception { + DistributedLock lock = getLock(RESOURCE, callback); DistributedLockManager.setLatestInstance(null); @@ -715,10 +721,10 @@ public class DistributedLockManagerTest { * isUnavailable() and the call to compute(). */ @Test - public void testDistributedLockFreeUnlocked() { + void testDistributedLockFreeUnlocked() { feature = new FreeWithFreeLockingFeature(true); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); assertFalse(lock.free()); assertTrue(lock.isUnavailable()); @@ -729,21 +735,21 @@ public class DistributedLockManagerTest { * call to isUnavailable() and the call to compute(). */ @Test - public void testDistributedLockFreeLockFreed() { + void testDistributedLockFreeLockFreed() { feature = new FreeWithFreeLockingFeature(false); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); assertFalse(lock.free()); assertTrue(lock.isUnavailable()); } @Test - public void testDistributedLockExtend() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockExtend() { + lock = getLock(RESOURCE, callback); // lock2 should be denied - called back by this thread - DistributedLock lock2 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + DistributedLock lock2 = getLock(RESOURCE, callback); verify(callback, never()).lockAvailable(lock2); verify(callback).lockUnavailable(lock2); @@ -782,8 +788,8 @@ public class DistributedLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testDistributedLockExtendSerialized() throws Exception { - DistributedLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockExtendSerialized() throws Exception { + DistributedLock lock = getLock(RESOURCE, callback); // run doLock runLock(0, 0); @@ -813,8 +819,8 @@ public class DistributedLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testDistributedLockExtendNoFeature() throws Exception { - DistributedLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockExtendNoFeature() throws Exception { + DistributedLock lock = getLock(RESOURCE, callback); // run doLock runLock(0, 0); @@ -839,10 +845,10 @@ public class DistributedLockManagerTest { * isUnavailable() and the call to compute(). */ @Test - public void testDistributedLockExtendUnlocked() { + void testDistributedLockExtendUnlocked() { feature = new FreeWithFreeLockingFeature(true); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); lock.extend(HOLD_SEC2, callback); assertTrue(lock.isUnavailable()); @@ -854,10 +860,10 @@ public class DistributedLockManagerTest { * call to isUnavailable() and the call to compute(). */ @Test - public void testDistributedLockExtendLockFreed() { + void testDistributedLockExtendLockFreed() { feature = new FreeWithFreeLockingFeature(false); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); lock.extend(HOLD_SEC2, callback); assertTrue(lock.isUnavailable()); @@ -865,20 +871,20 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockScheduleRequest() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockScheduleRequest() { + lock = getLock(RESOURCE, callback); runLock(0, 0); verify(callback).lockAvailable(lock); } @Test - public void testDistributedLockRescheduleRequest() { + void testDistributedLockRescheduleRequest() { // use a data source that throws an exception when getConnection() is called InvalidDbLockingFeature invfeat = new InvalidDbLockingFeature(TRANSIENT); feature = invfeat; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should fail and reschedule runLock(0, 0); @@ -891,7 +897,7 @@ public class DistributedLockManagerTest { invfeat.freeLock = true; // try scheduled request - should just invoke doUnlock - runSchedule(0, 0); + runSchedule(0); // should still be waiting assertTrue(lock.isUnavailable()); @@ -902,8 +908,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockGetNextRequest() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockGetNextRequest() { + lock = getLock(RESOURCE, callback); /* * run doLock. This should cause getNextRequest() to be called twice, once with a @@ -917,11 +923,11 @@ public class DistributedLockManagerTest { * time it's called. */ @Test - public void testDistributedLockGetNextRequestSameRequest() { + void testDistributedLockGetNextRequestSameRequest() { // force reschedule to be invoked feature = new InvalidDbLockingFeature(TRANSIENT); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); /* * run doLock. This should cause getNextRequest() to be called twice, once with a @@ -933,8 +939,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockDoRequest() { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoRequest() { + lock = getLock(RESOURCE, callback); assertTrue(lock.isWaiting()); @@ -948,7 +954,7 @@ public class DistributedLockManagerTest { * Tests doRequest(), when doRequest() is already running within another thread. */ @Test - public void testDistributedLockDoRequestBusy() { + void testDistributedLockDoRequestBusy() { /* * this feature will invoke a request in a background thread while it's being run * in a foreground thread. @@ -961,6 +967,7 @@ public class DistributedLockManagerTest { protected DistributedLock makeLock(LockState state, String resourceId, String ownerKey, int holdSec, LockCallback callback) { return new DistributedLock(state, resourceId, ownerKey, holdSec, callback, feature) { + @Serial private static final long serialVersionUID = 1L; @Override @@ -994,7 +1001,7 @@ public class DistributedLockManagerTest { } }; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // run doLock runLock(0, 0); @@ -1008,7 +1015,7 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoRequestRunExWaiting() throws SQLException { + void testDistributedLockDoRequestRunExWaiting() throws SQLException { // throw run-time exception when(datasrc.getConnection()).thenThrow(new IllegalStateException(EXPECTED_EXCEPTION)); @@ -1020,7 +1027,7 @@ public class DistributedLockManagerTest { } }; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should NOT reschedule runLock(0, 0); @@ -1038,7 +1045,7 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoRequestRunExUnavailable() throws SQLException { + void testDistributedLockDoRequestRunExUnavailable() throws SQLException { // throw run-time exception when(datasrc.getConnection()).thenAnswer(answer -> { lock.free(); @@ -1053,7 +1060,7 @@ public class DistributedLockManagerTest { } }; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should NOT reschedule runLock(0, 0); @@ -1068,11 +1075,11 @@ public class DistributedLockManagerTest { * Tests doRequest() when the retry count gets exhausted. */ @Test - public void testDistributedLockDoRequestRetriesExhaustedWhileLocking() { + void testDistributedLockDoRequestRetriesExhaustedWhileLocking() { // use a data source that throws an exception when getConnection() is called feature = new InvalidDbLockingFeature(TRANSIENT); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should fail and reschedule runLock(0, 0); @@ -1082,14 +1089,14 @@ public class DistributedLockManagerTest { verify(callback, never()).lockUnavailable(lock); // try again, via SCHEDULER - first retry fails - runSchedule(0, 0); + runSchedule(0); // should still be waiting assertTrue(lock.isWaiting()); verify(callback, never()).lockUnavailable(lock); // try again, via SCHEDULER - final retry fails - runSchedule(1, 0); + runSchedule(1); assertTrue(lock.isUnavailable()); // now callback should have been called @@ -1100,14 +1107,14 @@ public class DistributedLockManagerTest { * Tests doRequest() when a non-transient DB exception is thrown. */ @Test - public void testDistributedLockDoRequestNotTransient() { + void testDistributedLockDoRequestNotTransient() { /* * use a data source that throws a PERMANENT exception when getConnection() is * called */ feature = new InvalidDbLockingFeature(PERMANENT); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should fail runLock(0, 0); @@ -1121,8 +1128,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockDoLock() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoLock() throws SQLException { + lock = getLock(RESOURCE, callback); // invoke doLock - should simply do an insert long tbegin = System.currentTimeMillis(); @@ -1139,8 +1146,8 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoLockFreed() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoLockFreed() throws SQLException { + lock = getLock(RESOURCE, callback); lock.setState(LockState.UNAVAILABLE); @@ -1156,11 +1163,11 @@ public class DistributedLockManagerTest { * Tests doLock() when a DB exception is thrown. */ @Test - public void testDistributedLockDoLockEx() { + void testDistributedLockDoLockEx() { // use a data source that throws an exception when getConnection() is called feature = new InvalidDbLockingFeature(PERMANENT); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should simply do an insert runLock(0, 0); @@ -1174,11 +1181,11 @@ public class DistributedLockManagerTest { * to be called. */ @Test - public void testDistributedLockDoLockNeedingUpdate() throws SQLException { + void testDistributedLockDoLockNeedingUpdate() throws SQLException { // insert an expired record insertRecord(RESOURCE, feature.getUuidString(), 0); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock - should simply do an update runLock(0, 0); @@ -1189,11 +1196,11 @@ public class DistributedLockManagerTest { * Tests doLock() when a locked record already exists. */ @Test - public void testDistributedLockDoLockAlreadyLocked() throws SQLException { + void testDistributedLockDoLockAlreadyLocked() throws SQLException { // insert an expired record insertRecord(RESOURCE, OTHER_OWNER, HOLD_SEC); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // invoke doLock runLock(0, 0); @@ -1203,8 +1210,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockDoUnlock() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoUnlock() throws SQLException { + lock = getLock(RESOURCE, callback); // invoke doLock() runLock(0, 0); @@ -1230,10 +1237,10 @@ public class DistributedLockManagerTest { * */ @Test - public void testDistributedLockDoUnlockEx() { + void testDistributedLockDoUnlockEx() { feature = new InvalidDbLockingFeature(PERMANENT); - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); // do NOT invoke doLock() - it will fail without a DB connection @@ -1250,8 +1257,8 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockDoExtend() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoExtend() throws SQLException { + lock = getLock(RESOURCE, callback); runLock(0, 0); LockCallback callback2 = mock(LockCallback.class); @@ -1281,8 +1288,8 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoExtendFreed() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoExtendFreed() throws SQLException { + lock = getLock(RESOURCE, callback); lock.extend(HOLD_SEC2, callback); lock.setState(LockState.UNAVAILABLE); @@ -1302,8 +1309,8 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoExtendInsertNeeded() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoExtendInsertNeeded() throws SQLException { + lock = getLock(RESOURCE, callback); runLock(0, 0); LockCallback callback2 = mock(LockCallback.class); @@ -1335,7 +1342,7 @@ public class DistributedLockManagerTest { * */ @Test - public void testDistributedLockDoExtendNeitherSucceeds() { + void testDistributedLockDoExtendNeitherSucceeds() { /* * this feature will create a lock that returns false when doDbUpdate() is * invoked, or when doDbInsert() is invoked a second time @@ -1345,6 +1352,7 @@ public class DistributedLockManagerTest { protected DistributedLock makeLock(LockState state, String resourceId, String ownerKey, int holdSec, LockCallback callback) { return new DistributedLock(state, resourceId, ownerKey, holdSec, callback, feature) { + @Serial private static final long serialVersionUID = 1L; private int ntimes = 0; @@ -1365,7 +1373,7 @@ public class DistributedLockManagerTest { } }; - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + lock = getLock(RESOURCE, callback); runLock(0, 0); LockCallback callback2 = mock(LockCallback.class); @@ -1391,8 +1399,8 @@ public class DistributedLockManagerTest { * @throws SQLException if an error occurs */ @Test - public void testDistributedLockDoExtendEx() throws SQLException { - lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testDistributedLockDoExtendEx() throws SQLException { + lock = getLock(RESOURCE, callback); runLock(0, 0); /* @@ -1420,14 +1428,14 @@ public class DistributedLockManagerTest { } @Test - public void testDistributedLockToString() { - String text = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false).toString(); + void testDistributedLockToString() { + String text = getLock(RESOURCE, callback).toString(); assertNotNull(text); assertThat(text).doesNotContain("ownerInfo").doesNotContain("callback"); } @Test - public void testMakeThreadPool() { + void testMakeThreadPool() { // use a REAL feature to test this feature = new DistributedLockManager(); @@ -1439,13 +1447,13 @@ public class DistributedLockManagerTest { } /** - * Performs a multi-threaded test of the locking facility. + * Performs a multithreaded test of the locking facility. * * @throws InterruptedException if the current thread is interrupted while waiting for * the background threads to complete */ @Test - public void testMultiThreaded() throws InterruptedException { + void testMultiThreaded() throws InterruptedException { ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, realExec); feature = new DistributedLockManager(); @@ -1473,9 +1481,9 @@ public class DistributedLockManagerTest { assertTrue(nsuccesses.get() > 0); } - private DistributedLock getLock(String resource, String ownerKey, int holdSec, LockCallback callback, - boolean waitForLock) { - return (DistributedLock) feature.createLock(resource, ownerKey, holdSec, callback, waitForLock); + private DistributedLock getLock(String resource, LockCallback callback) { + return (DistributedLock) feature.createLock(resource, DistributedLockManagerTest.OWNER_KEY, + DistributedLockManagerTest.HOLD_SEC, callback, false); } private DistributedLock roundTrip(DistributedLock lock) throws Exception { @@ -1493,14 +1501,12 @@ public class DistributedLockManagerTest { /** * Runs the checkExpired() action. * - * @param nskip number of actions in the work queue to skip - * @param nadditional number of additional actions that appear in the work queue - * after the checkExpired action + * @param nskip number of actions in the work queue to skip * @param schedSec number of seconds for which the checker should have been scheduled */ - private void runChecker(int nskip, int nadditional, long schedSec) { + private void runChecker(int nskip, long schedSec) { ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); - verify(exsvc, times(nskip + nadditional + 1)).schedule(captor.capture(), eq(schedSec), eq(TimeUnit.SECONDS)); + verify(exsvc, times(nskip + 1)).schedule(captor.capture(), eq(schedSec), eq(TimeUnit.SECONDS)); Runnable action = captor.getAllValues().get(nskip); action.run(); } @@ -1524,12 +1530,10 @@ public class DistributedLockManagerTest { * Runs a scheduled action (e.g., "retry" action). * * @param nskip number of actions in the work queue to skip - * @param nadditional number of additional actions that appear in the work queue - * after the desired action */ - void runSchedule(int nskip, int nadditional) { + void runSchedule(int nskip) { ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); - verify(exsvc, times(PRE_SCHED_EXECS + nskip + nadditional + 1)).schedule(captor.capture(), anyLong(), any()); + verify(exsvc, times(PRE_SCHED_EXECS + nskip + 1)).schedule(captor.capture(), anyLong(), any()); Runnable action = captor.getAllValues().get(PRE_SCHED_EXECS + nskip); action.run(); @@ -1645,7 +1649,7 @@ public class DistributedLockManagerTest { shutdownFeature(); exsvc = mock(ScheduledExecutorService.class); - when(exsvc.schedule(any(Runnable.class), anyLong(), any())).thenAnswer(ans -> checker); + lenient().when(exsvc.schedule(any(Runnable.class), anyLong(), any())).thenAnswer(ans -> checker); ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, exsvc); if (init) { @@ -1660,10 +1664,10 @@ public class DistributedLockManagerTest { * Feature whose data source all throws exceptions. */ private class InvalidDbLockingFeature extends MyLockingFeature { - private boolean isTransient; + private final boolean isTransient; private boolean freeLock = false; - public InvalidDbLockingFeature(boolean isTransient) { + InvalidDbLockingFeature(boolean isTransient) { // pass "false" because we have to set the error code BEFORE calling // afterStart() super(false); @@ -1677,7 +1681,7 @@ public class DistributedLockManagerTest { @Override protected BasicDataSource makeDataSource() throws Exception { - when(datasrc.getConnection()).thenAnswer(answer -> { + lenient().when(datasrc.getConnection()).thenAnswer(answer -> { if (freeLock) { freeLock = false; lock.free(); @@ -1705,7 +1709,7 @@ public class DistributedLockManagerTest { * Feature whose locks free themselves while free() is already running. */ private class FreeWithFreeLockingFeature extends MyLockingFeature { - private boolean relock; + private final boolean relock; public FreeWithFreeLockingFeature(boolean relock) { super(true); @@ -1717,6 +1721,7 @@ public class DistributedLockManagerTest { LockCallback callback) { return new DistributedLock(state, resourceId, ownerKey, holdSec, callback, feature) { + @Serial private static final long serialVersionUID = 1L; private boolean checked = false; @@ -1746,7 +1751,7 @@ public class DistributedLockManagerTest { } /** - * Thread used with the multi-threaded test. It repeatedly attempts to get a lock, + * Thread used with the multithreaded test. It repeatedly attempts to get a lock, * extend it, and then unlock it. */ private class MyThread extends Thread { diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockPropertiesTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockPropertiesTest.java index 5abca889..8cfb3eab 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockPropertiesTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockPropertiesTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,22 +21,22 @@ package org.onap.policy.distributed.locking; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.util.Properties; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.properties.exception.PropertyException; -public class DistributedLockPropertiesTest { +class DistributedLockPropertiesTest { private Properties props; /** * Populates {@link #props}. */ - @Before - public void setUp() { + @BeforeEach + void setUp() { props = new Properties(); props.setProperty(DistributedLockProperties.DB_DRIVER, "my driver"); @@ -48,7 +49,7 @@ public class DistributedLockPropertiesTest { } @Test - public void test() throws PropertyException { + void test() throws PropertyException { DistributedLockProperties dlp = new DistributedLockProperties(props); assertEquals("my driver", dlp.getDbDriver()); diff --git a/feature-healthcheck/src/main/feature/config/feature-healthcheck.properties b/feature-healthcheck/src/main/feature/config/feature-healthcheck.properties index 98247a89..d8e22b4f 100644 --- a/feature-healthcheck/src/main/feature/config/feature-healthcheck.properties +++ b/feature-healthcheck/src/main/feature/config/feature-healthcheck.properties @@ -3,6 +3,7 @@ # ONAP # ================================================================================ # Copyright (C) 2017-2019,2022 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,7 +29,6 @@ http.server.services.HEALTHCHECK.swagger=true http.server.services.HEALTHCHECK.userName=${envd:HEALTHCHECK_USER} http.server.services.HEALTHCHECK.password=${envd:HEALTHCHECK_PASSWORD} http.server.services.HEALTHCHECK.https=${envd:HTTP_SERVER_HTTPS:false} -http.server.services.HEALTHCHECK.aaf=${envd:AAF:false} http.server.services.HEALTHCHECK.serialization.provider=org.onap.policy.common.gson.JacksonHandler,org.onap.policy.common.endpoints.http.server.YamlJacksonHandler http.server.services.LIVENESS.host=0.0.0.0 diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java index 0567595f..7cf7ed5f 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckFeatureTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2019,2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +21,9 @@ package org.onap.policy.drools.healthcheck; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; @@ -38,9 +39,9 @@ import java.util.HashMap; import java.util.List; import java.util.Properties; import org.eclipse.jetty.http.HttpStatus; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.kie.api.builder.ReleaseId; import org.mockito.AdditionalAnswers; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; @@ -65,7 +66,7 @@ public class HealthCheckFeatureTest { /** * Set up. */ - @BeforeClass + @BeforeAll public static void setup() throws IOException { SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); @@ -92,7 +93,7 @@ public class HealthCheckFeatureTest { /** * Tear down. */ - @AfterClass + @AfterAll public static void teardown() { PolicyControllerConstants.getFactory().destroy(); HttpClientFactoryInstance.getClientFactory().destroy(); @@ -100,7 +101,7 @@ public class HealthCheckFeatureTest { } @Test - public void test() throws InterruptedException { + void test() throws InterruptedException { var manager = spy(HealthCheckManager.class); var feature = new HealthCheckFeatureImpl(manager); when(manager.isEngineAlive()).thenReturn(true); @@ -167,12 +168,12 @@ public class HealthCheckFeatureTest { } @Test - public void testGetSequenceNumber() { + void testGetSequenceNumber() { assertEquals(1000, new HealthCheckFeature().getSequenceNumber()); } @Test - public void testAfterStart() { + void testAfterStart() { HealthCheck checker = mock(HealthCheck.class); HealthCheckFeature feature = new HealthCheckFeatureImpl(checker); @@ -187,7 +188,7 @@ public class HealthCheckFeatureTest { } @Test - public void testAfterOpen() { + void testAfterOpen() { HealthCheck checker = mock(HealthCheck.class); HealthCheckFeature feature = new HealthCheckFeatureImpl(checker); @@ -203,7 +204,7 @@ public class HealthCheckFeatureTest { } @Test - public void testAfterShutdown() { + void testAfterShutdown() { HealthCheck checker = mock(HealthCheck.class); HealthCheckFeature feature = new HealthCheckFeatureImpl(checker); diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckManagerTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckManagerTest.java index 9e081015..8553301f 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckManagerTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckManagerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +21,11 @@ package org.onap.policy.drools.healthcheck; -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.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -41,8 +42,8 @@ import java.util.Map; import java.util.Properties; import java.util.stream.Collectors; import org.eclipse.jetty.http.HttpStatus; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.AdditionalAnswers; import org.onap.policy.common.endpoints.http.client.HttpClient; import org.onap.policy.common.endpoints.http.client.HttpClientFactory; @@ -57,7 +58,7 @@ import org.onap.policy.drools.system.PolicyEngine; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class HealthCheckManagerTest { +class HealthCheckManagerTest { private static final Logger logger = LoggerFactory.getLogger(HealthCheckManagerTest.class); @@ -101,7 +102,7 @@ public class HealthCheckManagerTest { /** * Initializes the object to be tested. */ - @Before + @BeforeEach public void setUp() throws Exception { properties = new Properties(); mocks(); @@ -186,7 +187,7 @@ public class HealthCheckManagerTest { } @Test - public void testHealthcheck() { + void testHealthcheck() { /* engine not alive */ when(engineMgr.isAlive()).thenReturn(false); @@ -210,7 +211,7 @@ public class HealthCheckManagerTest { } @Test - public void testControllerHealthcheck() { + void testControllerHealthcheck() { /* engine not alive */ when(engineMgr.isAlive()).thenReturn(false); @@ -248,7 +249,7 @@ public class HealthCheckManagerTest { } @Test - public void testClientHealthcheck() { + void testClientHealthcheck() { /* engine not alive */ when(engineMgr.isAlive()).thenReturn(false); @@ -278,7 +279,7 @@ public class HealthCheckManagerTest { } @Test - public void reportOnController() { + void reportOnController() { /* controller not alive */ @@ -336,7 +337,7 @@ public class HealthCheckManagerTest { } @Test - public void testReportOnUnknown() { + void testReportOnUnknown() { var reports = monitor.summary(monitor.engineHealthcheck(), monitor.futures(List.of(1))); logger.info("{}", reports); @@ -346,7 +347,7 @@ public class HealthCheckManagerTest { } @Test - public void testStart() { + void testStart() { // good start when(server1.start()).thenReturn(true); @@ -381,7 +382,7 @@ public class HealthCheckManagerTest { } @Test - public void testOpen() { + void testOpen() { /* nothing done */ @@ -412,7 +413,7 @@ public class HealthCheckManagerTest { } @Test - public void testShutdown() { + void testShutdown() { monitor.healthcheckServer = server1; monitor.livenessServer = server2; monitor.clients = List.of(client1, client2, client3); @@ -429,12 +430,12 @@ public class HealthCheckManagerTest { } @Test - public void testIsAlive() { + void testIsAlive() { assertFalse(monitor.isAlive()); } @Test - public void testToString() { + void testToString() { assertTrue(monitor.toString().contains("HealthCheckManager")); } diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java index 01f5063d..375c1622 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/HealthCheckTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018, 2021-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,27 +21,27 @@ package org.onap.policy.drools.healthcheck; -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.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collections; import java.util.List; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.healthcheck.HealthCheck.Report; import org.onap.policy.drools.healthcheck.HealthCheck.Reports; -public class HealthCheckTest { +class HealthCheckTest { private static final long RPT_CODE = 100; private static final String RPT_MSG = "report-message"; private static final String RPT_NAME = "report-name"; private static final String RPT_URL = "report-url"; @Test - public void testReport() { + void testReport() { Report rpt = new Report(); assertNotNull(rpt.toString()); @@ -73,7 +74,7 @@ public class HealthCheckTest { } @Test - public void testReports() { + void testReports() { Reports reports = new Reports(); // toString should work with un-populated data diff --git a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/RestHealthCheckTest.java b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/RestHealthCheckTest.java index 2ab1fe82..63825fa8 100644 --- a/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/RestHealthCheckTest.java +++ b/feature-healthcheck/src/test/java/org/onap/policy/drools/healthcheck/RestHealthCheckTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.healthcheck; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import jakarta.ws.rs.core.Response; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; import org.onap.policy.common.endpoints.http.client.HttpClient; import org.onap.policy.common.endpoints.http.client.HttpClientFactory; @@ -60,7 +61,7 @@ public class RestHealthCheckTest { * Set up. */ - @BeforeClass + @BeforeAll public static void setUp() throws Exception { LoggerUtils.setLevel("org.onap.policy.common.endpoints", "WARN"); LoggerUtils.setLevel("org.eclipse", "ERROR"); @@ -103,26 +104,26 @@ public class RestHealthCheckTest { * Tear down. */ - @AfterClass + @AfterAll public static void tearDown() { HttpClientFactoryInstance.getClientFactory().destroy(); HttpServletServerFactoryInstance.getServerFactory().destroy(); } @Test - public void healthcheck() { + void healthcheck() { when(healthcheckManager.healthCheck()).thenReturn(summary); assertHttp("/"); } @Test - public void engine() { + void engine() { when(healthcheckManager.engineHealthcheck()).thenReturn(summary); assertHttp("engine"); } @Test - public void controllers() { + void controllers() { when(healthcheckManager.controllerHealthcheck()).thenReturn(summary); assertHttp("controllers"); @@ -140,7 +141,7 @@ public class RestHealthCheckTest { } @Test - public void clients() { + void clients() { when(healthcheckManager.clientHealthcheck()).thenReturn(summary); assertHttp("clients"); diff --git a/feature-healthcheck/src/test/resources/echo.drl b/feature-healthcheck/src/test/resources/echo.drl index 54847da9..189c8a51 100644 --- a/feature-healthcheck/src/test/resources/echo.drl +++ b/feature-healthcheck/src/test/resources/echo.drl @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +30,7 @@ end rule "ECHO" when - $o : Object(); + $o : Object() then System.out.println("ECHO: " + $o.toString()); end diff --git a/feature-healthcheck/src/test/resources/echo.kmodule b/feature-healthcheck/src/test/resources/echo.kmodule index 7a1acc70..fd972ab0 100644 --- a/feature-healthcheck/src/test/resources/echo.kmodule +++ b/feature-healthcheck/src/test/resources/echo.kmodule @@ -4,6 +4,7 @@ ONAP ================================================================================ Copyright (C) 2022 AT&T Intellectual Property. All rights reserved. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,7 @@ ============LICENSE_END========================================================= --> - + diff --git a/feature-legacy-config/src/main/feature/config/feature-legacy-config.properties b/feature-legacy-config/src/main/feature/config/feature-legacy-config.properties index 15a35b8b..47a4e229 100644 --- a/feature-legacy-config/src/main/feature/config/feature-legacy-config.properties +++ b/feature-legacy-config/src/main/feature/config/feature-legacy-config.properties @@ -2,6 +2,7 @@ # ONAP # ================================================================================ # Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,25 +17,13 @@ # limitations under the License. # ============LICENSE_END========================================================= -dmaap.source.topics=PDPD-CONFIGURATION - -dmaap.source.topics.PDPD-CONFIGURATION.servers=${envd:DMAAP_SERVERS} -dmaap.source.topics.PDPD-CONFIGURATION.effectiveTopic=${envd:PDPD_CONFIGURATION_TOPIC} -dmaap.source.topics.PDPD-CONFIGURATION.apiKey=${envd:PDPD_CONFIGURATION_API_KEY} -dmaap.source.topics.PDPD-CONFIGURATION.apiSecret=${envd:PDPD_CONFIGURATION_API_SECRET} -dmaap.source.topics.PDPD-CONFIGURATION.consumerGroup=${envd:PDPD_CONFIGURATION_CONSUMER_GROUP} -dmaap.source.topics.PDPD-CONFIGURATION.consumerInstance=${envd:PDPD_CONFIGURATION_CONSUMER_INSTANCE} -dmaap.source.topics.PDPD-CONFIGURATION.managed=false -dmaap.source.topics.PDPD-CONFIGURATION.https=${envd:DMAAP_HTTPS:true} - -#Replace the properties with the following to use kafka message broker -#kafka.source.topics=pdpd-configuration -#kafka.source.topics.fetchTimeout=15000 -#kafka.source.topics.pdpd-configuration.servers=${envd:DMAAP_SERVERS} -#kafka.source.topics.pdpd-configuration.effectiveTopic=${envd:PDPD_CONFIGURATION_TOPIC} -#kafka.source.topics.pdpd-configuration.apiKey=${envd:PDPD_CONFIGURATION_API_KEY} -#kafka.source.topics.pdpd-configuration.apiSecret=${envd:PDPD_CONFIGURATION_API_SECRET} -#kafka.source.topics.pdpd-configuration.consumerGroup=${envd:PDPD_CONFIGURATION_CONSUMER_GROUP} -#kafka.source.topics.pdpd-configuration.consumerInstance=${envd:PDPD_CONFIGURATION_CONSUMER_INSTANCE} -#kafka.source.topics.pdpd-configuration.managed=false -#kafka.source.topics.pdpd-configuration.https=${envd:DMAAP_HTTPS:true} +kafka.source.topics=pdpd-configuration +kafka.source.topics.fetchTimeout=15000 +kafka.source.topics.pdpd-configuration.servers=${envd:KAFKA_SERVERS} +kafka.source.topics.pdpd-configuration.effectiveTopic=${envd:PDPD_CONFIGURATION_TOPIC} +kafka.source.topics.pdpd-configuration.apiKey=${envd:PDPD_CONFIGURATION_API_KEY} +kafka.source.topics.pdpd-configuration.apiSecret=${envd:PDPD_CONFIGURATION_API_SECRET} +kafka.source.topics.pdpd-configuration.consumerGroup=${envd:PDPD_CONFIGURATION_CONSUMER_GROUP} +kafka.source.topics.pdpd-configuration.consumerInstance=${envd:PDPD_CONFIGURATION_CONSUMER_INSTANCE} +kafka.source.topics.pdpd-configuration.managed=false +kafka.source.topics.pdpd-configuration.https=${envd:KAFKA_HTTPS:true} diff --git a/feature-legacy-config/src/main/java/org/onap/policy/drools/legacy/config/LegacyConfig.java b/feature-legacy-config/src/main/java/org/onap/policy/drools/legacy/config/LegacyConfig.java index 01cc3b34..7ca4632c 100644 --- a/feature-legacy-config/src/main/java/org/onap/policy/drools/legacy/config/LegacyConfig.java +++ b/feature-legacy-config/src/main/java/org/onap/policy/drools/legacy/config/LegacyConfig.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,16 +37,15 @@ import org.slf4j.LoggerFactory; /** * Legacy Configurator. */ +@Getter public class LegacyConfig implements Startable, TopicListener { private static final Logger logger = LoggerFactory.getLogger(LegacyConfig.class); private static final String CONFIGURATION_PROPERTIES_NAME = "feature-legacy-config"; - @Getter private final Properties properties; - @Getter - private TopicSource source; + private final TopicSource source; /** * Constructor. diff --git a/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigFeatureTest.java b/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigFeatureTest.java index d73817b8..c8371895 100644 --- a/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigFeatureTest.java +++ b/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigFeatureTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,25 +21,25 @@ package org.onap.policy.drools.legacy.config; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; import org.onap.policy.drools.persistence.SystemPersistenceConstants; import org.onap.policy.drools.system.PolicyEngineConstants; -public class LegacyConfigFeatureTest { +class LegacyConfigFeatureTest { private LegacyConfigFeature configF; /** * Set up. */ - @Before + @BeforeEach public void setUp() { SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); configF = new LegacyConfigFeature(); @@ -47,7 +48,7 @@ public class LegacyConfigFeatureTest { /** * Tear down. */ - @After + @AfterEach public void tearDown() { NoopTopicFactories.getSourceFactory().destroy(); NoopTopicFactories.getSinkFactory().destroy(); @@ -55,12 +56,12 @@ public class LegacyConfigFeatureTest { } @Test - public void getSequenceNumber() { + void getSequenceNumber() { assertEquals(LegacyConfigFeature.SEQNO, new LegacyConfigFeature().getSequenceNumber()); } @Test - public void afterOpenBeforeShutdown() { + void afterOpenBeforeShutdown() { assertFalse(LegacyConfigFeature.getLegacyConfig().isAlive()); configF.afterOpen(PolicyEngineConstants.getManager()); assertTrue(LegacyConfigFeature.getLegacyConfig().isAlive()); diff --git a/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigTest.java b/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigTest.java index eb8860d2..09e03b3e 100644 --- a/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigTest.java +++ b/feature-legacy-config/src/test/java/org/onap/policy/drools/legacy/config/LegacyConfigTest.java @@ -22,26 +22,26 @@ package org.onap.policy.drools.legacy.config; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.Topic; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; import org.onap.policy.drools.persistence.SystemPersistenceConstants; -public class LegacyConfigTest { +class LegacyConfigTest { private static final String PDPD_CONFIGURATION_TOPIC = "pdpd-configuration"; /** * Set up. */ - @Before + @BeforeEach public void setUp() { SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); } @@ -49,7 +49,7 @@ public class LegacyConfigTest { /** * Tear down. */ - @After + @AfterEach public void tearDown() { NoopTopicFactories.getSourceFactory().destroy(); NoopTopicFactories.getSinkFactory().destroy(); @@ -57,7 +57,7 @@ public class LegacyConfigTest { } @Test - public void testStartStop() { + void testStartStop() { LegacyConfig config = new LegacyConfig(); assertFalse(config.isAlive()); @@ -75,7 +75,7 @@ public class LegacyConfigTest { } @Test - public void testConstructors() { + void testConstructors() { LegacyConfig config = new LegacyConfig(); assertNotNull(config.getProperties()); assertEquals(PDPD_CONFIGURATION_TOPIC, config.getSource().getTopic()); diff --git a/feature-legacy-config/src/test/java/org/onap/policy/drools/server/restful/RestLegacyConfigTest.java b/feature-legacy-config/src/test/java/org/onap/policy/drools/server/restful/RestLegacyConfigTest.java index 46bdb0f8..5180c486 100644 --- a/feature-legacy-config/src/test/java/org/onap/policy/drools/server/restful/RestLegacyConfigTest.java +++ b/feature-legacy-config/src/test/java/org/onap/policy/drools/server/restful/RestLegacyConfigTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,14 +19,14 @@ package org.onap.policy.drools.server.restful; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import jakarta.ws.rs.core.Response; import java.util.Properties; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; import org.onap.policy.common.endpoints.http.client.HttpClient; import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; @@ -45,7 +46,7 @@ public class RestLegacyConfigTest { /** * Set up. */ - @BeforeClass + @BeforeAll public static void setUp() throws Exception { SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); @@ -79,7 +80,7 @@ public class RestLegacyConfigTest { /** * Tear down. */ - @AfterClass + @AfterAll public static void tearDown() { LegacyConfigFeature.getLegacyConfig().shutdown(); HttpClientFactoryInstance.getClientFactory().destroy(); @@ -88,7 +89,7 @@ public class RestLegacyConfigTest { } @Test - public void properties() { + void properties() { Response response = client.get("properties"); assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); assertEquals(LegacyConfigFeature.getLegacyConfig().getProperties(), @@ -96,7 +97,7 @@ public class RestLegacyConfigTest { } @Test - public void topic() { + void topic() { Response response = client.get("source"); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); } diff --git a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties index 27799543..06fa87e5 100644 --- a/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties +++ b/feature-lifecycle/src/main/feature/config/feature-lifecycle.properties @@ -2,6 +2,7 @@ # ONAP # ================================================================================ # Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -22,33 +23,17 @@ lifecycle.pdp.type=${envd:POLICY_PDP_PAP_TYPE:drools} # Mandatory policy types that this PDP-D must support at a minimum lifecycle.pdp.policytypes=${envd:POLICY_PDP_PAP_POLICYTYPES} -dmaap.source.topics=POLICY-PDP-PAP -dmaap.sink.topics=POLICY-PDP-PAP +kafka.source.topics=POLICY-PDP-PAP +kafka.sink.topics=POLICY-PDP-PAP -dmaap.source.topics.POLICY-PDP-PAP.servers=${envd:DMAAP_SERVERS} -dmaap.source.topics.POLICY-PDP-PAP.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} -dmaap.source.topics.POLICY-PDP-PAP.apiKey=${envd:POLICY_PDP_PAP_API_KEY} -dmaap.source.topics.POLICY-PDP-PAP.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} -dmaap.source.topics.POLICY-PDP-PAP.https=${envd:DMAAP_HTTPS:true} +kafka.source.topics.POLICY-PDP-PAP.servers=${envd:KAFKA_SERVERS} +kafka.source.topics.POLICY-PDP-PAP.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} +kafka.source.topics.POLICY-PDP-PAP.apiKey=${envd:POLICY_PDP_PAP_API_KEY} +kafka.source.topics.POLICY-PDP-PAP.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} +kafka.source.topics.POLICY-PDP-PAP.https=${envd:KAFKA_HTTPS:true} -dmaap.sink.topics.POLICY-PDP-PAP.servers=${envd:DMAAP_SERVERS} -dmaap.sink.topics.POLICY-PDP-PAP.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} -dmaap.sink.topics.POLICY-PDP-PAP.apiKey=${envd:POLICY_PDP_PAP_API_KEY} -dmaap.sink.topics.POLICY-PDP-PAP.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} -dmaap.sink.topics.POLICY-PDP-PAP.https=${envd:DMAAP_HTTPS:true} - -#Replace the properties with the following to use kafka message broker -#kafka.source.topics=policy-pdp-pap -#kafka.source.topics.fetchTimeout=15000 -#kafka.sink.topics=policy-pdp-pap -#kafka.source.topics.policy-pdp-pap.servers=${envd:DMAAP_SERVERS} -#kafka.source.topics.policy-pdp-pap.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} -#kafka.source.topics.policy-pdp-pap.apiKey=${envd:POLICY_PDP_PAP_API_KEY} -#kafka.source.topics.policy-pdp-pap.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} -#kafka.source.topics.policy-pdp-pap.https=${envd:DMAAP_HTTPS:true} - -#kafka.sink.topics.policy-pdp-pap.servers=${envd:DMAAP_SERVERS} -#kafka.sink.topics.policy-pdp-pap.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} -#kafka.sink.topics.policy-pdp-pap.apiKey=${envd:POLICY_PDP_PAP_API_KEY} -#kafka.sink.topics.policy-pdp-pap.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} -#kafka.sink.topics.policy-pdp-pap.https=${envd:DMAAP_HTTPS:true} +kafka.sink.topics.POLICY-PDP-PAP.servers=${envd:KAFKA_SERVERS} +kafka.sink.topics.POLICY-PDP-PAP.effectiveTopic=${envd:POLICY_PDP_PAP_TOPIC} +kafka.sink.topics.POLICY-PDP-PAP.apiKey=${envd:POLICY_PDP_PAP_API_KEY} +kafka.sink.topics.POLICY-PDP-PAP.apiSecret=${envd:POLICY_PDP_PAP_API_SECRET} +kafka.sink.topics.POLICY-PDP-PAP.https=${envd:KAFKA_HTTPS:true} diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java index c67367e0..e7656ae6 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021,2023 Nordix Foundation. + * Modifications Copyright (C) 2021, 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,8 +23,6 @@ package org.onap.policy.drools.lifecycle; import com.google.re2j.Pattern; import io.prometheus.client.Counter; -import java.lang.reflect.InvocationTargetException; -import java.time.Instant; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -42,7 +40,6 @@ import java.util.stream.Collectors; import lombok.Getter; import lombok.NonNull; import lombok.Setter; -import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang3.StringUtils; import org.onap.policy.common.capabilities.Startable; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; @@ -286,8 +283,7 @@ public class LifecycleFsm implements Startable { policyTypesMap.values().stream() .filter(PolicyTypeDroolsController.class::isInstance) .map(PolicyTypeDroolsController.class::cast) - .filter(opController -> opController.getControllers().containsKey(controller.getName())) - .collect(Collectors.toList()); + .filter(opController -> opController.getControllers().containsKey(controller.getName())).toList(); for (PolicyTypeDroolsController opController : opControllers) { opController.remove(controller); diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java index 202eb98b..02fc7a93 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateActive.java @@ -4,7 +4,7 @@ * ================================================================================ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2019 Bell Canada. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,6 @@ package org.onap.policy.drools.lifecycle; import java.util.Collections; import lombok.NonNull; import lombok.ToString; -import org.jetbrains.annotations.NotNull; import org.onap.policy.models.pdp.concepts.PdpStateChange; import org.onap.policy.models.pdp.enums.PdpResponseStatus; import org.onap.policy.models.pdp.enums.PdpState; @@ -46,12 +45,12 @@ public class LifecycleStateActive extends LifecycleStateRunning { } @Override - protected boolean stateChangeToActive(@NotNull PdpStateChange change) { + protected boolean stateChangeToActive(@NonNull PdpStateChange change) { return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS, null)); } @Override - protected boolean stateChangeToPassive(@NotNull PdpStateChange change) { + protected boolean stateChangeToPassive(@NonNull PdpStateChange change) { undeployPolicies(Collections.emptyList()); fsm.transitionToAction(new LifecycleStatePassive(fsm)); return fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS, null)); diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java index fc62b947..2d5c66b3 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java @@ -217,7 +217,7 @@ public abstract class LifecycleStateRunning extends LifecycleStateDefault { } protected List reApplyNonNativePolicies(Map> preActivePoliciesMap) { - // only need to re-apply non native policies if there are new native artifact policies + // only need to re-apply non-native policies if there are new native artifact policies Map> activePoliciesByType = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); List activeNativeArtifactPolicies = fsm.getNativeArtifactPolicies(activePoliciesByType); diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java index 6973745c..6e248e8d 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsController.java @@ -179,7 +179,7 @@ public class PolicyTypeNativeDroolsController implements PolicyTypeController { List sinks = TopicEndpointManager.getManager().getTopicSinks(List.of(configSinkTopic.getTopicName())); if (sinks.size() != 1) { - logger.warn("Topic {} is not present or ambigous {}", configSinkTopic.getTopicName(), sinks); + logger.warn("Topic {} is not present or ambiguous {}", configSinkTopic.getTopicName(), sinks); return false; } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java index 4e0b4bf7..858e8495 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +24,6 @@ package org.onap.policy.drools.lifecycle; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.nio.file.Paths; import java.util.List; import java.util.Properties; @@ -39,6 +39,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Controller Test Support. */ +@Getter public class ControllerSupport { protected static final String JUNIT_KMODULE_DRL_PATH = "src/test/resources/lifecycle.drl"; @@ -52,7 +53,6 @@ public class ControllerSupport { protected static final String SESSION_NAME = "junits"; - @Getter private final String name; public ControllerSupport(@NonNull String name) { @@ -73,21 +73,26 @@ public class ControllerSupport { ReleaseId coordinates = installArtifact(); + Properties controllerProps = getControllerProps(coordinates); + + return PolicyControllerConstants.getFactory().build(name, controllerProps); + } + + private Properties getControllerProps(ReleaseId coordinates) { Properties controllerProps = new Properties(); controllerProps.put(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, name); controllerProps.put(DroolsPropertyConstants.PROPERTY_CONTROLLER_POLICY_TYPES, getPolicyType()); controllerProps.put(DroolsPropertyConstants.RULES_GROUPID, coordinates.getGroupId()); controllerProps.put(DroolsPropertyConstants.RULES_ARTIFACTID, coordinates.getArtifactId()); controllerProps.put(DroolsPropertyConstants.RULES_VERSION, coordinates.getVersion()); - - return PolicyControllerConstants.getFactory().build(name, controllerProps); + return controllerProps; } /** * Install a maven artifact. */ public static ReleaseId installArtifact(File kmodule, File pom, - String drlKjarPath, List drls) throws IOException { + String drlKjarPath, List drls) throws IOException { return KieUtils.installArtifact(kmodule, pom, drlKjarPath, drls); } @@ -96,9 +101,9 @@ public class ControllerSupport { */ public ReleaseId installArtifact() throws IOException { return ControllerSupport.installArtifact(Paths.get(JUNIT_KMODULE_PATH).toFile(), - Paths.get(JUNIT_KMODULE_POM_PATH).toFile(), - JUNIT_KJAR_DRL_PATH, - List.of(Paths.get(JUNIT_KMODULE_DRL_PATH).toFile())); + Paths.get(JUNIT_KMODULE_POM_PATH).toFile(), + JUNIT_KJAR_DRL_PATH, + List.of(Paths.get(JUNIT_KMODULE_DRL_PATH).toFile())); } /** @@ -146,7 +151,7 @@ public class ControllerSupport { * Reassign static field. */ public static void setStaticField(Class clazz, String fieldName, E newValue) - throws NoSuchFieldException, IllegalAccessException { + throws NoSuchFieldException, IllegalAccessException { unsetFinalStaticAccess(clazz, fieldName).set(null, newValue); } } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java index e5fc13a8..cae3bb3b 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2021-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,7 +21,7 @@ package org.onap.policy.drools.lifecycle; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.nio.file.Files; @@ -32,9 +32,9 @@ import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.concurrent.ScheduledExecutorService; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.logging.LoggerUtils; @@ -98,7 +98,7 @@ public class LifecycleFsmTest { /** * Test initialization. */ - @Before + @BeforeEach public void beforeTest() throws CoderException, IOException { LoggerUtils.setLevel(LoggerUtils.ROOT_LOGGER, "INFO"); LoggerUtils.setLevel("org.onap.policy.common.endpoints", "WARN"); @@ -130,7 +130,7 @@ public class LifecycleFsmTest { resetExecutionStats(); } - @AfterClass + @AfterAll public static void afterClass() { resetExecutionStats(); } @@ -141,14 +141,8 @@ public class LifecycleFsmTest { PolicyEngineConstants.getManager().getStats().getGroupStat().setPolicyExecutedSuccessCount(0L); } - private void setExecutionCounts() { - PolicyEngineConstants.getManager().getStats().getGroupStat().setPolicyExecutedCount(7L); - PolicyEngineConstants.getManager().getStats().getGroupStat().setPolicyExecutedFailCount(2L); - PolicyEngineConstants.getManager().getStats().getGroupStat().setPolicyExecutedSuccessCount(5L); - } - @Test - public void testGetDeployableActions() { + void testGetDeployableActions() { List expectedDeployOrder = List.of(controllerPolicy, controller2Policy, artifact2Policy, artifactPolicy, op2Policy, opPolicy, unvalPolicy, valPolicy); @@ -165,7 +159,7 @@ public class LifecycleFsmTest { } @Test - public void testGetUndeployableActions() { + void testGetUndeployableActions() { deployAllPolicies(); List expectedUndeployOrder = List.of(opPolicy, op2Policy, unvalPolicy, valPolicy, artifactPolicy, @@ -177,7 +171,7 @@ public class LifecycleFsmTest { } @Test - public void testGetNativeArtifactPolicies() { + void testGetNativeArtifactPolicies() { deployAllPolicies(); Map> deployedPolicies = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); @@ -186,24 +180,24 @@ public class LifecycleFsmTest { } @Test - public void testSetGroup() { + void testSetGroup() { fsm.setGroup("bar"); assertEquals("bar", fsm.getGroup()); } @Test - public void testSetSubGroup() { + void testSetSubGroup() { fsm.setSubGroup("foo"); assertEquals("foo", fsm.getSubGroup()); } @Test - public void testPdpType() { + void testPdpType() { assertEquals("foo", fsm.getPdpType()); } @Test - public void testMergePolicies() { + void testMergePolicies() { assertEquals(List.of(), fsm.getActivePolicies()); assertEquals(List.of(), fsm.mergePolicies(List.of(), List.of())); @@ -229,7 +223,7 @@ public class LifecycleFsmTest { } @Test - public void testGetPolicyIdsMessages() { + void testGetPolicyIdsMessages() { assertEquals("[operational.modifyconfig 1.0.0, example.controller 1.0.0]", fsm.getPolicyIds(List.of(opPolicy, controllerPolicy)).toString()); } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java index 0ab9f888..8f0c19db 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java @@ -22,9 +22,9 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.base.Strings; import java.io.IOException; @@ -37,10 +37,10 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.ScheduledExecutorService; import java.util.stream.Collectors; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; @@ -116,7 +116,7 @@ public class LifecycleFsmUpdateTest { /** * Set up. */ - @BeforeClass + @BeforeAll public static void setUp() throws IOException { LoggerUtils.setLevel(LoggerUtils.ROOT_LOGGER, "INFO"); LoggerUtils.setLevel("org.onap.policy.common.endpoints", "WARN"); @@ -149,7 +149,7 @@ public class LifecycleFsmUpdateTest { /** * Tear Down. */ - @AfterClass + @AfterAll public static void tearDown() throws NoSuchFieldException, IllegalAccessException { PolicyControllerConstants.getFactory().destroy(); @@ -170,7 +170,7 @@ public class LifecycleFsmUpdateTest { /** * Test initialization. */ - @Before + @BeforeEach public void init() throws CoderException, IOException, NoSuchFieldException, IllegalAccessException { fsm = new LifecycleFsm() { @Override @@ -208,7 +208,7 @@ public class LifecycleFsmUpdateTest { } @Test - public void testUpdate() throws CoderException { + void testUpdate() throws CoderException { verifyInitState(); // native controller policy - deploy @@ -369,8 +369,8 @@ public class LifecycleFsmUpdateTest { protected void verifyExists(boolean exists, String controller, List policies) { assertTrue(PolicyControllerConstants.getFactory().get(controller).getDrools().isBrained()); for (ToscaPolicy policy : policies) { - assertEquals("ID: " + controller + ":" + policy.getIdentifier(), exists, - PolicyControllerConstants.getFactory().get(controller).getDrools().exists(policy)); + assertEquals(exists, PolicyControllerConstants.getFactory().get(controller).getDrools().exists(policy), + "ID: " + controller + ":" + policy.getIdentifier()); } } @@ -383,10 +383,10 @@ public class LifecycleFsmUpdateTest { // verify that each policy is tracked in the active lists for (ToscaPolicy policy : testPolicies) { - assertTrue(policy.getIdentifier().toString(), fsm.getActivePolicies().contains(policy)); + assertTrue(fsm.getActivePolicies().contains(policy), policy.getIdentifier().toString()); if (!nativeDisables.contains(policy.getIdentifier())) { - assertTrue(policy.getIdentifier().toString(), - fsm.getPolicyTypesMap().containsKey(policy.getTypeIdentifier())); + assertTrue(fsm.getPolicyTypesMap().containsKey(policy.getTypeIdentifier()), + policy.getIdentifier().toString()); } } assertEquals(testPolicies.size(), fsm.getActivePolicies().size()); @@ -451,17 +451,19 @@ public class LifecycleFsmUpdateTest { String artifactControllerName = artifactPolicy.getProperties().getController().getName(); // brained controller check - assertTrue(artifactControllerName + ":" + testPolicy.getIdentifier(), - PolicyControllerConstants.getFactory().get(artifactControllerName).getDrools().isBrained()); + assertTrue(PolicyControllerConstants.getFactory().get(artifactControllerName).getDrools().isBrained(), + artifactControllerName + ":" + testPolicy.getIdentifier()); - // non native tosca policy as a fact in drools + // non-native tosca policy as a fact in drools if (PolicyControllerConstants.getFactory().get(artifactControllerName).getPolicyTypes() .contains(testPolicy.getTypeIdentifier())) { - assertTrue(artifactControllerName + ":" + testPolicy.getIdentifier(), PolicyControllerConstants - .getFactory().get(artifactControllerName).getDrools().exists(testPolicy)); + assertTrue(PolicyControllerConstants.getFactory() + .get(artifactControllerName).getDrools().exists(testPolicy), + artifactControllerName + ":" + testPolicy.getIdentifier()); } else { - assertFalse(artifactControllerName + ":" + testPolicy.getIdentifier(), PolicyControllerConstants - .getFactory().get(artifactControllerName).getDrools().exists(testPolicy)); + assertFalse(PolicyControllerConstants.getFactory() + .get(artifactControllerName).getDrools().exists(testPolicy), + artifactControllerName + ":" + testPolicy.getIdentifier()); } // there should always be a controller policy for each artifact policy @@ -489,10 +491,10 @@ public class LifecycleFsmUpdateTest { getNativeArtifactPolicies(nativeArtifactPolicies, controllerName); if (candidateNativeArtifactPolicies.size() == 1) { - assertTrue(controllerName + ":" + testPolicy.getIdentifier(), - PolicyControllerConstants.getFactory().get(controllerName).getDrools().isBrained()); - assertTrue(controllerName + ":" + testPolicy.getIdentifier(), - PolicyControllerConstants.getFactory().get(controllerName).getDrools().exists(testPolicy)); + assertTrue(PolicyControllerConstants.getFactory().get(controllerName).getDrools().isBrained(), + controllerName + ":" + testPolicy.getIdentifier()); + assertTrue(PolicyControllerConstants.getFactory().get(controllerName).getDrools().exists(testPolicy), + controllerName + ":" + testPolicy.getIdentifier()); // verify that the other brained controllers don't have this non-native policy @@ -502,10 +504,9 @@ public class LifecycleFsmUpdateTest { assertTrue(PolicyControllerConstants.getFactory() .get(nativePolicy.getProperties().getController().getName()) .getDrools().isBrained()); - assertFalse(controllerName + ":" + testPolicy.getIdentifier(), - PolicyControllerConstants.getFactory() - .get(nativePolicy.getProperties().getController().getName()) - .getDrools().exists(testPolicy)); + assertFalse(PolicyControllerConstants.getFactory() + .get(nativePolicy.getProperties().getController().getName()).getDrools().exists(testPolicy), + controllerName + ":" + testPolicy.getIdentifier()); } // @formatter:on @@ -514,8 +515,8 @@ public class LifecycleFsmUpdateTest { // at this point the only valid possibility is that there is no native artifact policies - assertTrue("There is more than 1 native artifact policy for " + controllerName, - candidateNativeArtifactPolicies.isEmpty()); + assertTrue(candidateNativeArtifactPolicies.isEmpty(), + "There is more than 1 native artifact policy for " + controllerName); } protected List getNativeArtifactPoliciesBut(List nativePolicies, diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java index 653a4694..2ed368d4 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActivePoliciesTest.java @@ -22,20 +22,20 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.common.utils.coder.CoderException; @@ -51,7 +51,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Lifecycle State Active Test. */ -public class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest { +class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest { private static final String EXAMPLE_NATIVE_DROOLS_CONTROLLER_POLICY_NAME = "example.controller"; private static final String EXAMPLE_NATIVE_DROOLS_ARTIFACT_POLICY_NAME = "example.artifact"; @@ -67,7 +67,7 @@ public class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest /** * Start tests in the Active state. */ - @Before + @BeforeEach public void startActive() throws CoderException { fsm = makeFsmWithPseudoTime(); @@ -86,7 +86,7 @@ public class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest } @Test - public void testMandatoryPolicyTypes() { + void testMandatoryPolicyTypes() { assertEquals(Set.of("onap.policies.native.drools.Artifact", "onap.policies.native.drools.Controller"), fsm.getMandatoryPolicyTypes()); assertEquals(fsm.getMandatoryPolicyTypes(), fsm.getCurrentPolicyTypes()); @@ -102,7 +102,7 @@ public class LifecycleStateActivePoliciesTest extends LifecycleStateRunningTest } @Test - public void testUpdatePolicies() throws IOException, CoderException { + void testUpdatePolicies() throws IOException, CoderException { assertEquals(2, fsm.policyTypesMap.size()); assertNotNull(fsm.getPolicyTypesMap().get( new ToscaConceptIdentifier("onap.policies.native.drools.Controller", "1.0.0"))); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java index d00c8a41..86e6ce3c 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateActiveTest.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,11 +22,11 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -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.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -36,8 +36,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.drools.system.PolicyEngineConstants; @@ -51,7 +51,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Lifecycle State Active Test. */ -public class LifecycleStateActiveTest extends LifecycleStateRunningTest { +class LifecycleStateActiveTest extends LifecycleStateRunningTest { private static final String POLICY_COMPLIANT_VCPE_BAD_INTEGER_JSON = "src/test/resources/tosca-policy-compliant-vcpe-bad-integer.json"; @@ -59,7 +59,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { /** * Start tests in the Active state. */ - @Before + @BeforeEach public void startActive() throws CoderException { fsm = makeFsmWithPseudoTime(); @@ -83,13 +83,13 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void constructor() { + void constructor() { assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStateActive(null)); fsm.shutdown(); } @Test - public void testStart() { + void testStart() { assertActive(); assertFalse(fsm.start()); assertActive(); @@ -106,7 +106,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void testStop() { + void testStop() { assertTrue(fsm.stop()); assertBasicTerminated(); @@ -121,7 +121,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void testShutdown() { + void testShutdown() { fsm.shutdown(); assertBasicTerminated(); @@ -131,7 +131,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void testStatus() { + void testStatus() { waitUntil(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS, isStatus(PdpState.ACTIVE)); int preCount = fsm.client.getSink().getRecentEvents().length; @@ -147,7 +147,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void testStateChange() throws CoderException { + void testStateChange() throws CoderException { assertActive(); /* no name and mismatching group info */ @@ -184,7 +184,7 @@ public class LifecycleStateActiveTest extends LifecycleStateRunningTest { } @Test - public void testUpdate() throws IOException, CoderException { + void testUpdate() throws IOException, CoderException { // TODO: extract repeated similar assertion blocks into their own helper methods diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java index d6c94996..01fb90b5 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,17 +22,17 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import java.util.concurrent.TimeUnit; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.drools.system.PolicyEngineConstants; @@ -48,12 +48,12 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Lifecycle State Passive Tests. */ -public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { +class LifecycleStatePassiveTest extends LifecycleStateRunningTest { /** * Start tests in the Passive state. */ - @Before + @BeforeEach public void startPassive() { /* start every test in passive mode */ fsm = makeFsmWithPseudoTime(); @@ -62,13 +62,13 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void constructor() { + void constructor() { assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStatePassive(null)); fsm.shutdown(); } @Test - public void testController() { + void testController() { fsm.start(controllerSupport.getController()); assertSame(controllerSupport.getController(), ((PolicyTypeDroolsController) fsm.getController( @@ -84,7 +84,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void testStart() { + void testStart() { assertEquals(0, fsm.client.getSink().getRecentEvents().length); assertFalse(fsm.start()); assertBasicPassive(); @@ -93,7 +93,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void stop() { + void stop() { simpleStop(); assertBasicTerminated(); } @@ -109,7 +109,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void testShutdown() throws Exception { + void testShutdown() throws Exception { simpleStop(); fsm.shutdown(); @@ -117,28 +117,28 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void testStatus() { + void testStatus() { assertTrue(fsm.client.getSink().isAlive()); assertTrue(fsm.status()); assertSame(1, fsm.client.getSink().getRecentEvents().length); fsm.start(controllerSupport.getController()); - status(PdpState.PASSIVE, 1); + status(); fsm.stop(controllerSupport.getController()); fsm.shutdown(); } - private void status(PdpState state, int initial) { - waitUntil(5, TimeUnit.SECONDS, isStatus(state, initial)); - waitUntil(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS, isStatus(state, initial + 1)); - waitUntil(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS, isStatus(state, initial + 2)); + private void status() { + waitUntil(5, TimeUnit.SECONDS, isStatus(PdpState.PASSIVE, 1)); + waitUntil(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS, isStatus(PdpState.PASSIVE, 1 + 1)); + waitUntil(fsm.statusTimerSeconds + 2, TimeUnit.SECONDS, isStatus(PdpState.PASSIVE, 1 + 2)); assertTrue(fsm.status()); - waitUntil(200, TimeUnit.MILLISECONDS, isStatus(state, initial + 3)); + waitUntil(200, TimeUnit.MILLISECONDS, isStatus(PdpState.PASSIVE, 1 + 3)); } @Test - public void testUpdate() throws CoderException { + void testUpdate() throws CoderException { controllerSupport.getController().getDrools().delete(ToscaPolicy.class); assertEquals(0, controllerSupport.getController().getDrools().factCount("junits")); @@ -253,7 +253,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void testStateChange() throws CoderException { + void testStateChange() throws CoderException { /* no name */ PdpStateChange change = new PdpStateChange(); change.setPdpGroup("A"); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java index 7b210db8..c9d12165 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateRunningTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +27,8 @@ import java.nio.file.Paths; import java.util.concurrent.Callable; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.junit.AfterClass; -import org.junit.BeforeClass; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; @@ -54,7 +55,7 @@ public abstract class LifecycleStateRunningTest { /** * Set up. */ - @BeforeClass + @BeforeAll public static void setUp() throws IOException { LoggerUtils.setLevel(LoggerUtils.ROOT_LOGGER, "INFO"); LoggerUtils.setLevel("org.onap.policy.common.endpoints", "WARN"); @@ -66,7 +67,7 @@ public abstract class LifecycleStateRunningTest { /** * Tear Down. */ - @AfterClass + @AfterAll public static void tearDown() { controllerSupport.destroyController(); NoopTopicFactories.getSourceFactory().destroy(); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java index 81ce85f1..4c292b42 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateSafeTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.lifecycle; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.models.pdp.enums.PdpState; /** * TEST State Junits. */ -public class LifecycleStateSafeTest extends LifecycleStateUnsupportedTest { +class LifecycleStateSafeTest extends LifecycleStateUnsupportedTest { public LifecycleStateSafeTest() { super(new LifecycleStateSafe(new LifecycleFsm())); @@ -46,7 +47,7 @@ public class LifecycleStateSafeTest extends LifecycleStateUnsupportedTest { } @Test - public void state() { + void state() { assertEquals(PdpState.SAFE, state.state()); } } \ No newline at end of file diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java index 23643302..bd7561fd 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTerminatedTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,17 +22,17 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Collections; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.logging.LoggerUtils; import org.onap.policy.drools.persistence.SystemPersistenceConstants; import org.onap.policy.drools.system.PolicyEngineConstants; @@ -46,19 +46,19 @@ import org.onap.policy.models.pdp.enums.PdpState; public class LifecycleStateTerminatedTest { private LifecycleFsm fsm = new LifecycleFsm(); - @BeforeClass + @BeforeAll public static void setUp() { SystemPersistenceConstants.getManager().setConfigurationDir("src/test/resources"); LoggerUtils.setLevel("org.onap.policy.common.endpoints", "WARN"); } - @AfterClass + @AfterAll public static void tearDown() { SystemPersistenceConstants.getManager().setConfigurationDir(null); } @Test - public void testConstructor() { + void testConstructor() { assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStateTerminated(null)); LifecycleState state = new LifecycleStateTerminated(new LifecycleFsm()); @@ -72,7 +72,7 @@ public class LifecycleStateTerminatedTest { } @Test - public void testStop() { + void testStop() { assertEquals(PdpState.TERMINATED, fsm.state.state()); assertFalse(fsm.isAlive()); @@ -90,7 +90,7 @@ public class LifecycleStateTerminatedTest { } @Test - public void testBounce() { + void testBounce() { assertBasicTerminated(); simpleStart(); simpleStop(); @@ -101,13 +101,13 @@ public class LifecycleStateTerminatedTest { } @Test - public void doubleBounce() { + void doubleBounce() { testBounce(); testBounce(); } @Test - public void testDoubleStartBounce() { + void testDoubleStartBounce() { simpleStart(); assertFalse(fsm.start()); assertBasicPassive(); @@ -115,7 +115,7 @@ public class LifecycleStateTerminatedTest { } @Test - public void testShutdown() { + void testShutdown() { assertBasicTerminated(); fsm.shutdown(); assertBasicTerminated(); @@ -124,20 +124,20 @@ public class LifecycleStateTerminatedTest { } @Test - public void testStatus() { + void testStatus() { assertBasicTerminated(); assertFalse(fsm.status()); assertBasicTerminated(); } @Test - public void changeState() { + void changeState() { assertFalse(fsm.state.transitionToState(new LifecycleStateTerminated(fsm))); assertEquals(PdpState.TERMINATED, fsm.state.state()); } @Test - public void testUpdate() { + void testUpdate() { PdpUpdate update = new PdpUpdate(); update.setName(PolicyEngineConstants.getManager().getPdpName()); update.setPdpGroup("A"); @@ -152,7 +152,7 @@ public class LifecycleStateTerminatedTest { } @Test - public void testStateChange() { + void testStateChange() { PdpStateChange change = new PdpStateChange(); change.setPdpGroup("A"); change.setPdpSubgroup("a"); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java index c086dfb4..89aae201 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateTestTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.lifecycle; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.models.pdp.enums.PdpState; /** * TEST State Junits. */ -public class LifecycleStateTestTest extends LifecycleStateUnsupportedTest { +class LifecycleStateTestTest extends LifecycleStateUnsupportedTest { public LifecycleStateTestTest() { super(new LifecycleStateTest(new LifecycleFsm())); @@ -46,7 +47,7 @@ public class LifecycleStateTestTest extends LifecycleStateUnsupportedTest { } @Test - public void state() { + void state() { assertEquals(PdpState.TEST, state.state()); } } \ No newline at end of file diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java index 400aa169..b5ec6aca 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStateUnsupportedTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,9 +24,9 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.persistence.SystemPersistenceConstants; import org.onap.policy.models.pdp.concepts.PdpStateChange; import org.onap.policy.models.pdp.concepts.PdpUpdate; @@ -37,12 +38,12 @@ public abstract class LifecycleStateUnsupportedTest { protected final LifecycleState state; - @BeforeClass + @BeforeAll public static void setUp() { SystemPersistenceConstants.getManager().setConfigurationDir("src/test/resources"); } - @AfterClass + @AfterAll public static void tearDown() { SystemPersistenceConstants.getManager().setConfigurationDir(null); } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java index a3b8d8c9..999860a0 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +21,13 @@ package org.onap.policy.drools.lifecycle; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.drools.domain.models.operational.OperationalPolicy; import org.onap.policy.drools.system.PolicyControllerConstants; @@ -35,7 +36,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Drools Controller Policy Test. */ -public class PolicyTypeDroolsControllerTest extends LifecycleStateRunningTest { +class PolicyTypeDroolsControllerTest extends LifecycleStateRunningTest { // Operational vCPE Policies private static final String OP_POLICY_NAME_VCPE = "operational.restart"; @@ -48,7 +49,7 @@ public class PolicyTypeDroolsControllerTest extends LifecycleStateRunningTest { /** * Test initialization. */ - @Before + @BeforeEach public void init() throws CoderException { fsm = makeFsmWithPseudoTime(); policy = getExamplesPolicy(VCPE_OPERATIONAL_DROOLS_POLICY_JSON, OP_POLICY_NAME_VCPE); @@ -71,7 +72,7 @@ public class PolicyTypeDroolsControllerTest extends LifecycleStateRunningTest { } @Test - public void testDeployUndeploy() { + void testDeployUndeploy() { /* non-existing controller */ assertFalse(controller.undeploy(policy)); assertFalse(controller.deploy(policy)); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactControllerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactControllerTest.java index 05ed41a4..26e6bbe4 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactControllerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeArtifactControllerTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,14 +22,15 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.drools.controller.DroolsControllerConstants; import org.onap.policy.drools.controller.internal.MavenDroolsController; @@ -42,7 +43,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Rules Controller Test. */ -public class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunningTest { +class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunningTest { // Native Drools Policy private static final String EXAMPLE_NATIVE_DROOLS_POLICY_NAME = "example.artifact"; private static final String EXAMPLE_NATIVE_DROOLS_POLICY_JSON = @@ -55,7 +56,7 @@ public class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunnin /** * Test Set initialization. */ - @Before + @BeforeEach public void init() throws IOException, CoderException { fsm = makeFsmWithPseudoTime(); policy = getPolicyFromFile(EXAMPLE_NATIVE_DROOLS_POLICY_JSON, EXAMPLE_NATIVE_DROOLS_POLICY_NAME); @@ -88,7 +89,7 @@ public class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunnin } @Test - public void testUndeployDeploy() { + void testUndeployDeploy() { undeploy(); deploy(); @@ -128,7 +129,7 @@ public class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunnin nativePolicy.getProperties() .getRulesArtifact() .getArtifactId())); - assertTrue(controllerSupport.getController().getDrools() instanceof NullDroolsController); + assertInstanceOf(NullDroolsController.class, controllerSupport.getController().getDrools()); assertEquals(DroolsControllerConstants.NO_GROUP_ID, controllerSupport.getController().getDrools().getGroupId()); assertEquals(DroolsControllerConstants.NO_ARTIFACT_ID, controllerSupport.getController().getDrools().getArtifactId()); @@ -144,7 +145,7 @@ public class PolicyTypeNativeArtifactControllerTest extends LifecycleStateRunnin PolicyControllerConstants.getFactory().get( nativePolicy.getProperties().getRulesArtifact().getGroupId(), nativePolicy.getProperties().getRulesArtifact().getArtifactId())); - assertTrue(controllerSupport.getController().getDrools() instanceof MavenDroolsController); + assertInstanceOf(MavenDroolsController.class, controllerSupport.getController().getDrools()); } } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java index 95f0ff55..a964d134 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeNativeDroolsControllerTest.java @@ -22,16 +22,16 @@ package org.onap.policy.drools.lifecycle; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.util.Properties; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.common.utils.coder.CoderException; @@ -43,7 +43,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; /** * Native Controller Policy Test. */ -public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningTest { +class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningTest { private static final String EXAMPLE_NATIVE_DROOLS_POLICY_NAME = "example.controller"; private static final String EXAMPLE_NATIVE_DROOLS_POLICY_JSON = "src/test/resources/tosca-policy-native-controller-example.json"; @@ -51,13 +51,13 @@ public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningT /** * Test initialization. */ - @Before + @BeforeEach public void init() { fsm = makeFsmWithPseudoTime(); } @Test - public void testDeployUndeploy() throws IOException, CoderException { + void testDeployUndeploy() throws IOException, CoderException { fsm = makeFsmWithPseudoTime(); assertTrue(controllerSupport.getController().getDrools().isBrained()); @@ -91,7 +91,7 @@ public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningT } @Test - public void testControllerProperties() throws CoderException { + void testControllerProperties() throws CoderException { Properties noopTopicProperties = new Properties(); String noopSources = String.join(",", TestConstants.DCAE_TOPIC, TestConstants.APPC_CL_TOPIC, TestConstants.APPC_LCM_WRITE_TOPIC, TestConstants.SDNR_CL_RSP_TOPIC); @@ -139,12 +139,12 @@ public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningT assertEquals("org.onap.policy.appc.util.Serialization,gsonPretty", properties.getProperty("noop.source.topics.appc-cl.events.custom.gson")); - assertEquals("org.onap.policy.appclcm.AppcLcmDmaapWrapper", + assertEquals("org.onap.policy.appclcm.AppcLcmMessageWrapper", properties.getProperty("noop.source.topics.appc-lcm-write.events")); assertEquals("[?($.type == 'response')]", properties .getProperty("noop.source.topics.appc-lcm-write.events." - + "org.onap.policy.appclcm.AppcLcmDmaapWrapper.filter")); + + "org.onap.policy.appclcm.AppcLcmMessageWrapper.filter")); assertEquals("org.onap.policy.appclcm.util.Serialization,gson", properties.getProperty("noop.source.topics.appc-lcm-write.events.custom.gson")); @@ -161,7 +161,7 @@ public class PolicyTypeNativeDroolsControllerTest extends LifecycleStateRunningT assertEquals("org.onap.policy.appc.util.Serialization,gsonPretty", properties.getProperty("noop.sink.topics.appc-cl.events.custom.gson")); - assertEquals("org.onap.policy.appclcm.AppcLcmDmaapWrapper", + assertEquals("org.onap.policy.appclcm.AppcLcmMessageWrapper", properties.getProperty("noop.sink.topics.appc-lcm-read.events")); assertEquals("org.onap.policy.appclcm.util.Serialization,gson", properties.getProperty("noop.sink.topics.appc-lcm-read.events.custom.gson")); diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java index 37c1e8d8..23d3e24a 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java @@ -21,9 +21,9 @@ package org.onap.policy.drools.server.restful; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.Response; @@ -35,9 +35,9 @@ import java.util.Collections; import java.util.List; import java.util.Properties; import org.apache.commons.lang3.StringUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; @@ -107,7 +107,7 @@ public class RestLifecycleManagerTest { /** * Set up. */ - @Before + @BeforeEach public void setUp() throws Exception { SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); @@ -158,7 +158,7 @@ public class RestLifecycleManagerTest { /** * Tear down. */ - @After + @AfterEach public void tearDown() { fsm.shutdown(); @@ -174,7 +174,7 @@ public class RestLifecycleManagerTest { } @Test - public void testMultiPolicyFlow() throws IOException, CoderException { + void testMultiPolicyFlow() throws IOException, CoderException { /* group assignments */ group(); @@ -204,7 +204,7 @@ public class RestLifecycleManagerTest { assertTrue(fsm.start()); - booleanPut("state/ACTIVE", "", Status.OK.getStatusCode(), Boolean.TRUE); + booleanPut(Status.OK.getStatusCode()); assertEquals(PdpState.ACTIVE, HttpClient.getBody(get("state", Status.OK.getStatusCode()), PdpState.class)); @@ -270,7 +270,7 @@ public class RestLifecycleManagerTest { ToscaPolicy toscaPolicyValError = getPolicyFromFile(EXAMPLE_OTHER_VAL_ERROR_POLICY_JSON, EXAMPLE_OTHER_VAL_ERROR_POLICY_NAME); assertThat( - listPost("policies/operations/validation", toString(toscaPolicyValError), + listPost(toString(toscaPolicyValError), Status.NOT_ACCEPTABLE.getStatusCode())).isNotEmpty(); booleanPost("policies", toString(toscaPolicyValError), @@ -338,7 +338,7 @@ public class RestLifecycleManagerTest { assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle")); opPolicy.getMetadata().remove("policy-id"); assertThat( - listPost("policies/operations/validation", toString(opPolicy), + listPost(toString(opPolicy), Status.NOT_ACCEPTABLE.getStatusCode())).isNotEmpty(); metrics(); @@ -346,7 +346,7 @@ public class RestLifecycleManagerTest { private void testNotNativePolicy(ToscaPolicy toscaPolicy) throws CoderException { assertThat( - listPost("policies/operations/validation", toString(toscaPolicy), + listPost(toString(toscaPolicy), Status.OK.getStatusCode())).isEmpty(); booleanPost("policies", toString(toscaPolicy), Status.OK.getStatusCode(), Boolean.TRUE); @@ -384,13 +384,13 @@ public class RestLifecycleManagerTest { assertEquals(bool, HttpClient.getBody(response, Boolean.class)); } - private void booleanPut(String contextPath, String body, int statusCode, Boolean bool) { - Response response = client.put(contextPath, Entity.json(body), Collections.emptyMap()); - booleanResponse(response, statusCode, bool); + private void booleanPut(int statusCode) { + Response response = client.put("state/ACTIVE", Entity.json(""), Collections.emptyMap()); + booleanResponse(response, statusCode, Boolean.TRUE); } - private List listPost(String contextPath, String body, int statusCode) { - Response response = client.post(contextPath, Entity.json(body), Collections.emptyMap()); + private List listPost(String body, int statusCode) { + Response response = client.post("policies/operations/validation", Entity.json(body), Collections.emptyMap()); assertEquals(statusCode, response.getStatus()); return HttpClient.getBody(response, List.class); } diff --git a/feature-lifecycle/src/test/resources/echo.kmodule b/feature-lifecycle/src/test/resources/echo.kmodule index 98d80a90..c0cb5078 100644 --- a/feature-lifecycle/src/test/resources/echo.kmodule +++ b/feature-lifecycle/src/test/resources/echo.kmodule @@ -4,6 +4,7 @@ ONAP ================================================================================ Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,7 @@ ============LICENSE_END========================================================= --> - + diff --git a/feature-lifecycle/src/test/resources/lifecycle.kmodule b/feature-lifecycle/src/test/resources/lifecycle.kmodule index 9ea1670a..9e77501f 100644 --- a/feature-lifecycle/src/test/resources/lifecycle.kmodule +++ b/feature-lifecycle/src/test/resources/lifecycle.kmodule @@ -4,6 +4,7 @@ ONAP ================================================================================ Copyright (C) 2019-2020, 2022 AT&T Intellectual Property. All rights reserved. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,7 @@ ============LICENSE_END========================================================= --> - + diff --git a/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json b/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json index 642ecc0e..65279859 100644 --- a/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json +++ b/feature-lifecycle/src/test/resources/tosca-policy-native-controller-example.json @@ -15,7 +15,7 @@ "controllerName": "lifecycle", "sourceTopics": [ { - "topicName": "DCAE_TOPIC", + "topicName": "dcae_topic", "events": [ { "eventClass": "java.util.HashMap", @@ -30,7 +30,7 @@ ], "sinkTopics": [ { - "topicName": "APPC-CL", + "topicName": "appc-cl", "events": [ { "eventClass": "java.util.HashMap", diff --git a/feature-no-locking/src/test/java/org/onap/policy/no/locking/NoLockManagerTest.java b/feature-no-locking/src/test/java/org/onap/policy/no/locking/NoLockManagerTest.java index 376fc04e..5b5e0964 100644 --- a/feature-no-locking/src/test/java/org/onap/policy/no/locking/NoLockManagerTest.java +++ b/feature-no-locking/src/test/java/org/onap/policy/no/locking/NoLockManagerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,17 +22,18 @@ package org.onap.policy.no.locking; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.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 java.util.List; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.core.lock.AlwaysSuccessLock; import org.onap.policy.drools.core.lock.Lock; import org.onap.policy.drools.core.lock.LockCallback; @@ -46,7 +48,7 @@ public class NoLockManagerTest { /** * Set up Junits. */ - @BeforeClass + @BeforeAll public static void setUp() { List engineServices = PolicyEngineFeatureApiConstants.getProviders().getList(); assertThat(engineServices).hasSize(1); @@ -55,50 +57,50 @@ public class NoLockManagerTest { } @Test - public void testLock() { + void testLock() { assertTrue(nlm.lock()); } @Test - public void testUnlock() { + void testUnlock() { assertTrue(nlm.unlock()); } @Test - public void testIsLocked() { + void testIsLocked() { assertFalse(nlm.isLocked()); } @Test - public void testStart() { + void testStart() { assertTrue(nlm.start()); } @Test - public void testStop() { + void testStop() { assertTrue(nlm.stop()); } @Test - public void testIsAlive() { + void testIsAlive() { assertTrue(nlm.isAlive()); } @Test - public void testGetSeqNo() { + void testGetSeqNo() { assertEquals(NoLockManager.SEQNO, nlm.getSequenceNumber()); } @Test - public void testBeforeCreateLockManager() { + void testBeforeCreateLockManager() { assertEquals(nlm, nlm.beforeCreateLockManager(null, null)); } @Test - public void testCreateLock() { + void testCreateLock() { Lock lock = nlm.createLock("x", "y", 1, callback, false); assertTrue(lock.isActive()); - assertTrue(lock instanceof AlwaysSuccessLock); + assertInstanceOf(AlwaysSuccessLock.class, lock); verify(callback).lockAvailable(lock); verify(callback, never()).lockUnavailable(any()); } diff --git a/feature-pooling-dmaap/pom.xml b/feature-pooling-dmaap/pom.xml deleted file mode 100644 index 5252c445..00000000 --- a/feature-pooling-dmaap/pom.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - 4.0.0 - - - org.onap.policy.drools-pdp - drools-pdp - 2.1.1-SNAPSHOT - - - feature-pooling-dmaap - - feature-pooling-dmaap - Endpoints - - - - - maven-assembly-plugin - - - zipfile - - single - - package - - true - ${project.artifactId}-${project.version} - - src/assembly/assemble_zip.xml - - false - - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - - copy-dependencies - - prepare-package - - ${project.build.directory}/assembly/lib - false - true - true - false - false - false - runtime - true - - - - - - - - - - com.att.nsa - cambriaClient - - - org.slf4j - slf4j-log4j12 - - - com.att.nsa - saClientLibrary - - - provided - - - ch.qos.logback - logback-classic - provided - - - org.onap.policy.drools-pdp - policy-core - ${project.version} - provided - - - org.onap.policy.drools-pdp - policy-management - ${project.version} - provided - - - - 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 @@ - - - - - - feature-pooling-dmaap - - zip - - - - false - - - - target - lib/feature - - feature-pooling-dmaap-${project.version}.jar - - - - target/assembly/lib - lib/dependencies - - *.jar - - - - src/main/feature/config - config - 0644 - - - - src/main/feature/bin - bin - 0744 - - - - src/main/feature/db - db - 0744 - - - - src/main/feature/install - install - 0744 - - - - 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.", 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..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..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 getTopicSources() { - return TopicEndpointManager.getManager().getTopicSources(); - } - - /** - * Get topic sinks. - * - * @return the topic sinks - */ - protected List 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. - * - *

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 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 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 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 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 not 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. - * - *

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. - * - *

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, String> class2type = new HashMap<>(); - - /** - * Maps a message type to the appropriate subclass. - */ - private static final Map> 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 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 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 getAllHosts() { - Set 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 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 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 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 alive) { - - // make a working array from the CURRENT assignments - String[] bucket2host = makeBucketArray(); - - TreeSet 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 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 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 host2data) { - LinkedList 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 buckets, Collection coll) { - // assign null buckets to the hosts with the fewest buckets - TreeSet 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 coll, String[] bucket2host) { - if (coll.size() <= 1) { - // only one hosts - nothing to rebalance - return; - } - - TreeSet 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 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 { - /** - * Host to which the buckets have been assigned. - */ - private String host; - - /** - * Buckets that have been assigned to this host. - */ - private Queue 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 become 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 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. - * - *

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 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 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 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 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 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 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 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 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:

PolicyEngine, PolicyController, DroolsController
mocked
- *
- * - *

The following fields must be set before executing this:

  • UEB_SERVERS
  • - *
  • INTERNAL_TOPIC
  • EXTERNAL_TOPIC
- */ -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 currentHost = new ThreadLocal(); - - /** - * 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 hosts = new LinkedList<>(); - - /** - * Maps a drools controller to its policy controller. - */ - private final IdentityHashMap 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 - * AggregatedPolicyController.onTopicEvent. - */ - private static class MyExternalTopicListener implements Answer { - - 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 getTopicSources() { - Host host = currentHost.get(); - return Arrays.asList(host.internalSource, host.externalSource); - } - - @Override - protected List 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: - *
- *
DMaaP sources and sinks
- *
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
- *
PolicyEngine, PolicyController, DroolsController
- *
mocked
- *
- * - *

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 currentContext = new ThreadLocal(); - /** - * 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 hosts = new LinkedList<>(); - /** - * Maps a drools controller to its policy controller. - */ - private final IdentityHashMap drools2policy = new IdentityHashMap<>(); - /** - * Maps a channel to its queue. Does not include the "admin" channel. - */ - private final ConcurrentMap> 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 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 msgQueue = new LinkedBlockingQueue<>(); - - /** - * Queue for the external "DMaaP" topic. - */ - @Getter - private final BlockingQueue externalTopic = new LinkedBlockingQueue(); - - /** - * 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 getInternalQueue() { - return msgQueue; - } - } - - /** - * Listener for the external topic. Simulates the actions taken by - * AggregatedPolicyController.onTopicEvent. - */ - - private static class MyExternalTopicListener implements Answer { - 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 - * channel 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 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 by - * the thread when it completes. - */ - private AtomicReference> pair = new AtomicReference<>(null); - - /** - * Constructor. - * - * @param type topic type - * @param queue topic from which to read - */ - - public TopicSourceImpl(String type, BlockingQueue 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 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 any 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 newPair) { - try { - Pair 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 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 getTopicSources() { - return Arrays.asList(new TopicSourceImpl(INTERNAL_TOPIC, - currentContext.get().getCurrentHost().getInternalQueue())); - } - - @Override - protected List 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> 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 initTopicSources(Properties props) { - return Collections.emptyList(); - } - - @Override - protected List 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> 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 timeCap = ArgumentCaptor.forClass(Long.class); - ArgumentCaptor 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 taskCap = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor timeCap = ArgumentCaptor.forClass(Long.class); - ArgumentCaptor 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 taskCap = ArgumentCaptor.forClass(Runnable.class); - ArgumentCaptor initCap = ArgumentCaptor.forClass(Long.class); - ArgumentCaptor timeCap = ArgumentCaptor.forClass(Long.class); - ArgumentCaptor 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 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 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 void doTest(String propnm, T specValue, T dfltValue, Function 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 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 seen = new TreeSet<>(); - for (int x = -1; x < arr.length + 2; ++x) { - seen.add(asgn.getAssignedHost(x)); - } - - TreeSet 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 { - - /** - * 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 { - - 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 { - - 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 { - - 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 { - - 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 { - - 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 type of {@link Message} subclass that this tests - */ -public abstract class SupportBasicMessageTester { - // 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 subclazz; - - /** - * Constructor. - * - * @param subclazz subclass of {@link Message} being tested - */ - public SupportBasicMessageTester(Class 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 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 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 type of Message the function updates - */ - @FunctionalInterface - public static interface MessageUpdateFunction { - - /** - * Updates a message. - * - * @param msg message to be updated - */ - void update(T msg); - } - - /** - * Function that updates a single field within a message. - * - * @param type of Message the function updates - */ - @FunctionalInterface - public static interface MessageFieldUpdateFunction { - - /** - * 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 type of {@link MessageWithAssignments} subclass that this tests - */ -public abstract class SupportMessageWithAssignmentsTester - extends SupportBasicMessageTester { - // 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 msg = capturePublishedMessage(Heartbeat.class); - - assertEquals(MY_HOST, msg.getLeft()); - assertEquals(state.getHbTimestampMs(), msg.getRight().getTimestampMs()); - - - /* - * Verify heartbeat generator - */ - Triple 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 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 onceSchedules; - - /** - * Tasks captured via schedule(). - */ - protected LinkedList> onceTasks; - - /** - * Scheduled tasks returned by scheduleWithFixedDelay(). - */ - protected LinkedList repeatedSchedules; - - /** - * Tasks captured via scheduleWithFixedDelay(). - */ - protected LinkedList> repeatedTasks; - - /** - * Messages captured via publish(). - */ - protected LinkedList> published; - - /** - * Messages captured via publishAdmin(). - */ - protected LinkedList 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 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 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 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 captureAdminMessage(Class 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 captureAdminMessage(Class 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 Pair capturePublishedMessage(Class 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 Pair capturePublishedMessage(Class clazz, int index) { - Pair 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 @@ - - - - - - - %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n - - - - - - - - - - - \ No newline at end of file diff --git a/feature-pooling-messages/pom.xml b/feature-pooling-messages/pom.xml new file mode 100644 index 00000000..756abcab --- /dev/null +++ b/feature-pooling-messages/pom.xml @@ -0,0 +1,108 @@ + + + + + 4.0.0 + + + org.onap.policy.drools-pdp + drools-pdp + 2.1.1-SNAPSHOT + + + feature-pooling-messages + + feature-pooling-messages + Endpoints + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + zipfile + + single + + package + + true + ${project.artifactId}-${project.version} + + src/assembly/assemble_zip.xml + + false + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + + copy-dependencies + + prepare-package + + ${project.build.directory}/assembly/lib + false + true + true + false + false + false + runtime + true + + + + + + + + + + ch.qos.logback + logback-classic + provided + + + org.onap.policy.drools-pdp + policy-core + ${project.version} + provided + + + org.onap.policy.drools-pdp + policy-management + ${project.version} + provided + + + + diff --git a/feature-pooling-messages/src/assembly/assemble_zip.xml b/feature-pooling-messages/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..67424116 --- /dev/null +++ b/feature-pooling-messages/src/assembly/assemble_zip.xml @@ -0,0 +1,76 @@ + + + + + + feature-pooling-messages + + zip + + + + false + + + + target + lib/feature + + feature-pooling-messages-${project.version}.jar + + + + target/assembly/lib + lib/dependencies + + *.jar + + + + src/main/feature/config + config + 0644 + + + + src/main/feature/bin + bin + 0744 + + + + src/main/feature/db + db + 0744 + + + + src/main/feature/install + install + 0744 + + + + diff --git a/feature-pooling-messages/src/main/feature/config/feature-pooling-messages.properties b/feature-pooling-messages/src/main/feature/config/feature-pooling-messages.properties new file mode 100644 index 00000000..925d1698 --- /dev/null +++ b/feature-pooling-messages/src/main/feature/config/feature-pooling-messages.properties @@ -0,0 +1,89 @@ +### +# ============LICENSE_START======================================================= +# feature-pooling-messages +# ================================================================================ +# Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 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========================================================= +### + +# In general, the feature-specific properties begin with "pooling", +# and they may be made specific to a controller by prepending with +# "pooling.", instead. +# +# The available properties and their default values are shown below. + +# Whether the feature is enabled. +#pooling.enabled=false + +# The internal kafka topic used by a controller. Note: the controller +# name is required for this property. +#pooling..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 topic manager 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 topic. +#pooling.start.heartbeat.milliseconds=100000 + +# Time, in milliseconds, to wait before attempting to reactivate 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..topic=XXX + +# Each controller that is enabled should have its own topic and the +# corresponding ${topicManager}.xxx properties (using kafka as default). +# 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 +kafka.source.topics=POOLING_TOPIC +kafka.sink.topics=POOLING_TOPIC + +kafka.source.topics.POOLING_TOPIC.servers=${env:KAFKA_SERVERS} +kafka.source.topics.POOLING_TOPIC.effectiveTopic=${env:POOLING_TOPIC} +kafka.source.topics.POOLING_TOPIC.apiKey= +kafka.source.topics.POOLING_TOPIC.apiSecret= + +kafka.sink.topics.POOLING_TOPIC.servers=${env:kafka_SERVERS} +kafka.sink.topics.POOLING_TOPIC.effectiveTopic=${env:POOLING_TOPIC} +kafka.sink.topics.POOLING_TOPIC.apiKey= +kafka.sink.topics.POOLING_TOPIC.apiSecret= diff --git a/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java new file mode 100644 index 00000000..4e9112e6 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/CancellableScheduledTask.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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; + +/** + * A scheduled task that can be cancelled. + */ +@FunctionalInterface +public interface CancellableScheduledTask { + + /** + * Cancels the scheduled task. + */ + void cancel(); +} diff --git a/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java new file mode 100644 index 00000000..6411dd81 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeature.java @@ -0,0 +1,397 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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. + * + *

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 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 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-messages 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-pooling-messages 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 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 initTopicSinks(Properties props) { + return TopicEndpointManager.getManager().addTopicSinks(props); + } +} diff --git a/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java new file mode 100644 index 00000000..5d7b9f76 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureException.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 java.io.Serial; + +/** + * Exception thrown by the pooling feature. + */ +public class PoolingFeatureException extends Exception { + @Serial + 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-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java new file mode 100644 index 00000000..5d0a2755 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingFeatureRtException.java @@ -0,0 +1,54 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 java.io.Serial; + +/** + * A runtime exception thrown by the pooling feature. + */ +public class PoolingFeatureRtException extends RuntimeException { + @Serial + 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-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java new file mode 100644 index 00000000..5e358e61 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManager.java @@ -0,0 +1,133 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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 not 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-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java new file mode 100644 index 00000000..7c0436eb --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingManagerImpl.java @@ -0,0 +1,647 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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 TopicMessageManager topicMessageManager; + + /** + * 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. + * + *

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 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.topicMessageManager = makeTopicMessagesManager(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) { + topicMessageManager.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) { + topicMessageManager.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)); + topicMessageManager.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 + */ + topicMessageManager.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); + topicMessageManager.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. + * + *

On the other hand, if the controller is not locked, then we just return immediately + * and let {@link #beforeInsert(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 topic messages manager + * @throws PoolingFeatureException if an error occurs + */ + protected TopicMessageManager makeTopicMessagesManager(String topic) throws PoolingFeatureException { + return new TopicMessageManager(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 + * @throws 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-messages/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java new file mode 100644 index 00000000..fd1c3d3d --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/PoolingProperties.java @@ -0,0 +1,150 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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-messages"; + + /** + * 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 topic. + */ + @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 reactivate 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-messages/src/main/java/org/onap/policy/drools/pooling/Serializer.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/Serializer.java new file mode 100644 index 00000000..2894b1da --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/Serializer.java @@ -0,0 +1,124 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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 topic. + */ + private final Gson gson = new Gson(); + + /** + * Maps a message subclass to its type. + */ + private static final Map, String> class2type = new HashMap<>(); + + /** + * Maps a message type to the appropriate subclass. + */ + private static final Map> 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 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 clazz = type2class.get(typeEl.getAsString()); + if (clazz == null) { + throw new JsonParseException("cannot deserialize " + typeEl); + } + + return gson.fromJson(jsonEl, clazz); + } +} diff --git a/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/TopicMessageManager.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/TopicMessageManager.java new file mode 100644 index 00000000..4c9b3f34 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/TopicMessageManager.java @@ -0,0 +1,233 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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 topic. Assumes all topics are managed by + * {@link TopicEndpoint}. + */ +public class TopicMessageManager { + + private static final Logger logger = LoggerFactory.getLogger(TopicMessageManager.class); + + /** + * Name of the 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 topic + * @throws PoolingFeatureException if an error occurs + */ + public TopicMessageManager(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 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 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 getTopicSources() { + return TopicEndpointManager.getManager().getTopicSources(); + } + + /** + * Get topic sinks. + * + * @return the topic sinks + */ + protected List getTopicSinks() { + return TopicEndpointManager.getManager().getTopicSinks(); + } +} diff --git a/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java new file mode 100644 index 00000000..485a9d2e --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/BucketAssignments.java @@ -0,0 +1,205 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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 the hosts that have an assignment. + * + * @return all the hosts that have an assignment + */ + public Set getAllHosts() { + Set 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-messages/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java new file mode 100644 index 00000000..4a8bdc3b --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Heartbeat.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/message/Identification.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Identification.java new file mode 100644 index 00000000..b8fd8414 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Identification.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/message/Leader.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Leader.java new file mode 100644 index 00000000..10c33382 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Leader.java @@ -0,0 +1,70 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/message/Message.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Message.java new file mode 100644 index 00000000..bb973142 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Message.java @@ -0,0 +1,79 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java new file mode 100644 index 00000000..b8521dd8 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/MessageWithAssignments.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.onap.policy.drools.pooling.PoolingFeatureException; + +/** + * A Message that includes bucket assignments. + */ +@Setter +@Getter +@NoArgsConstructor +public class MessageWithAssignments extends Message { + + /** + * Bucket assignments, as known by the source host. + */ + private BucketAssignments assignments; + + + /** + * Constructor. + * + * @param source host on which the message originated + * @param assignments assignments + */ + 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-messages/src/main/java/org/onap/policy/drools/pooling/message/Offline.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Offline.java new file mode 100644 index 00000000..3ff7bf1e --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Offline.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/message/Query.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Query.java new file mode 100644 index 00000000..4c856bb7 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/message/Query.java @@ -0,0 +1,40 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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-messages/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java new file mode 100644 index 00000000..cafcb45b --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ActiveState.java @@ -0,0 +1,270 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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 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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java new file mode 100644 index 00000000..06418280 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/IdleState.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java new file mode 100644 index 00000000..7fc220a0 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/InactiveState.java @@ -0,0 +1,81 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java new file mode 100644 index 00000000..76914b75 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/ProcessingState.java @@ -0,0 +1,398 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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. + */ +@Setter +@Getter +public class ProcessingState extends State { + + private static final Logger logger = LoggerFactory.getLogger(ProcessingState.class); + + /** + * Current known leader, never {@code null}. + */ + @NonNull + 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, @NonNull String leader) { + super(mgr); + + 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 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 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 alive) { + + // make a working array from the CURRENT assignments + String[] bucket2host = makeBucketArray(); + + TreeSet 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 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 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 host2data) { + LinkedList 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 buckets, Collection coll) { + // assign null buckets to the hosts with the fewest buckets + TreeSet assignments = new TreeSet<>(coll); + + for (Integer index : buckets) { + // add it to the host with the shortest bucket list + HostBucket newhb = assignments.pollFirst(); + assert newhb != null; + 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 coll, String[] bucket2host) { + if (coll.size() <= 1) { + // only one hosts - nothing to rebalance + return; + } + + TreeSet assignments = new TreeSet<>(coll); + + for (;;) { + HostBucket smaller = assignments.pollFirst(); + HostBucket larger = assignments.pollLast(); + + assert larger != null && smaller != null; + 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 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 { + /** + * Host to which the buckets have been assigned. + */ + private String host; + + /** + * Buckets that have been assigned to this host. + */ + private Queue 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-messages/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java new file mode 100644 index 00000000..ef401dcb --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/QueryState.java @@ -0,0 +1,204 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 become 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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/StartState.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StartState.java new file mode 100644 index 00000000..73717d7c --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StartState.java @@ -0,0 +1,99 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/State.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/State.java new file mode 100644 index 00000000..e2cf9586 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/State.java @@ -0,0 +1,373 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.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. + * + *

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 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-messages/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java new file mode 100644 index 00000000..892a1767 --- /dev/null +++ b/feature-pooling-messages/src/main/java/org/onap/policy/drools/pooling/state/StateTimerTask.java @@ -0,0 +1,37 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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; + +/** + * 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-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi new file mode 100644 index 00000000..cd59e469 --- /dev/null +++ b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.DroolsControllerFeatureApi @@ -0,0 +1 @@ +org.onap.policy.drools.pooling.PoolingFeature diff --git a/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi new file mode 100644 index 00000000..cd59e469 --- /dev/null +++ b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyControllerFeatureApi @@ -0,0 +1 @@ +org.onap.policy.drools.pooling.PoolingFeature diff --git a/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi new file mode 100644 index 00000000..cd59e469 --- /dev/null +++ b/feature-pooling-messages/src/main/resources/META-INF/services/org.onap.policy.drools.features.PolicyEngineFeatureApi @@ -0,0 +1 @@ +org.onap.policy.drools.pooling.PoolingFeature diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java new file mode 100644 index 00000000..31ad207c --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/EndToEndFeatureTest.java @@ -0,0 +1,810 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.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:

PolicyEngine, PolicyController, DroolsController
mocked
+ *
+ * + *

The following fields must be set before executing this:

  • UEB_SERVERS
  • + *
  • INTERNAL_TOPIC
  • EXTERNAL_TOPIC
+ */ +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 = "ueb-server"; + + /** + * Name of the topic used for inter-host communication. + */ + private static final String INTERNAL_TOPIC = "internal-topic"; + + /** + * Name of the topic from which "external" events "arrive". + */ + private static final String EXTERNAL_TOPIC = "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 currentHost = new ThreadLocal(); + + /** + * 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. + * + */ + @BeforeAll + 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. + * + */ + @AfterAll + public static void tearDownAfterClass() { + externalSink.stop(); + internalSink.stop(); + } + + /** + * Setup. + */ + @BeforeEach + public void setUp() { + ctx = null; + } + + /** + * Tear down. + */ + @AfterEach + public void tearDown() { + if (ctx != null) { + ctx.destroy(); + } + } + + /* + * This test should only be run manually, after configuring all the fields, + * thus it is ignored. + */ + @Disabled + @Test + public void test_SingleHost() throws Exception { // NOSONAR + run(70, 1); + } + + /* + * This test should only be run manually, after configuring all the fields, + * thus it is ignored. + */ + @Disabled + @Test + public void test_TwoHosts() throws Exception { // NOSONAR + run(200, 2); + } + + /* + * This test should only be run manually, after configuring all the fields, + * thus it is ignored. + */ + @Disabled + @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 hosts = new LinkedList<>(); + + /** + * Maps a drools controller to its policy controller. + */ + private final IdentityHashMap 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(host.messageSeen(), "msgs=" + msgs); + ++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 + * AggregatedPolicyController.onTopicEvent. + */ + private static class MyExternalTopicListener implements Answer { + + 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 TopicMessageManager makeTopicMessagesManager(String topic) throws PoolingFeatureException { + return new TopicMessageManagerImpl(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 TopicMessageManagerImpl extends TopicMessageManager { + + /** + * Constructor. + * + * @param topic the topic + * @throws PoolingFeatureException if an error occurs + */ + public TopicMessageManagerImpl(String topic) throws PoolingFeatureException { + super(topic); + } + + @Override + protected List getTopicSources() { + Host host = currentHost.get(); + return Arrays.asList(host.internalSource, host.externalSource); + } + + @Override + protected List 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-messages/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java new file mode 100644 index 00000000..e9bd3cb5 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/FeatureTest.java @@ -0,0 +1,1033 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.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.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.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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: + *
+ *
DMaaP sources and sinks
+ *
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
+ *
PolicyEngine, PolicyController, DroolsController
+ *
mocked
+ *
+ * + *

Invoke {@link #runSlow()}, before the test, to slow things down. + */ + +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 currentContext = new ThreadLocal(); + /** + * Context for the current test case. + */ + private Context ctx; + + /** + * Setup. + */ + + @BeforeEach + public void setUp() { + ctx = null; + } + + /** + * Tear down. + */ + + @AfterEach + public void tearDown() { + if (ctx != null) { + ctx.destroy(); + } + } + + @Test + void test_SingleHost() throws Exception { + run(70, 1); + } + + @Test + void test_TwoHosts() throws Exception { + run(200, 2); + } + + @Test + 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 hosts = new LinkedList<>(); + /** + * Maps a drools controller to its policy controller. + */ + private final IdentityHashMap drools2policy = new IdentityHashMap<>(); + /** + * Maps a channel to its queue. Does not include the "admin" channel. + */ + private final ConcurrentMap> 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()}. + */ + @Getter + 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(host.messageSeen(), "msgs=" + msgs); + ++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 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); + } + + } + + /** + * 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 msgQueue = new LinkedBlockingQueue<>(); + + /** + * Queue for the external "DMaaP" topic. + */ + @Getter + private final BlockingQueue externalTopic = new LinkedBlockingQueue(); + + /** + * 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 getInternalQueue() { + return msgQueue; + } + } + + /** + * Listener for the external topic. Simulates the actions taken by + * AggregatedPolicyController.onTopicEvent. + */ + + private static class MyExternalTopicListener implements Answer { + 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 + * channel 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 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 by + * the thread when it completes. + */ + private AtomicReference> pair = new AtomicReference<>(null); + + /** + * Constructor. + * + * @param type topic type + * @param queue topic from which to read + */ + + public TopicSourceImpl(String type, BlockingQueue 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 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 any 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 newPair) { + try { + Pair 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 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 TopicMessageManager makeTopicMessagesManager(String topic) throws PoolingFeatureException { + return new TopicMessageManagerImpl(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 TopicMessageManagerImpl extends TopicMessageManager { + + /** + * Constructor. + * + * @param topic the topic + * @throws PoolingFeatureException if an error occurs + */ + + public TopicMessageManagerImpl(String topic) throws PoolingFeatureException { + super(topic); + } + + @Override + protected List getTopicSources() { + return List.of( + new TopicSourceImpl(INTERNAL_TOPIC, currentContext.get().getCurrentHost().getInternalQueue())); + } + + @Override + protected List getTopicSinks() { + return List.of(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-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java new file mode 100644 index 00000000..1bfba19c --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureExceptionTest.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.onap.policy.common.utils.test.ExceptionsTester; + +class PoolingFeatureExceptionTest extends ExceptionsTester { + + @Test + void test() { + assertEquals(5, test(PoolingFeatureException.class)); + } + +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java new file mode 100644 index 00000000..a4305a7f --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureRtExceptionTest.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.Test; +import org.onap.policy.common.utils.test.ExceptionsTester; + +class PoolingFeatureRtExceptionTest extends ExceptionsTester { + + @Test + void test() { + assertEquals(5, test(PoolingFeatureRtException.class)); + } + +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java new file mode 100644 index 00000000..1b05e021 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingFeatureTest.java @@ -0,0 +1,548 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +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> managers; + private PoolingManagerImpl mgr1; + private PoolingManagerImpl mgr2; + + private PoolingFeature pool; + + /** + * Setup. + * + * @throws Exception exception + */ + @BeforeEach + 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 + void test() { + assertEquals(2, managers.size()); + } + + @Test + 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 + void testGetSequenceNumber() { + assertEquals(0, pool.getSequenceNumber()); + } + + @Test + void testBeforeStartEngine() { + pool = new PoolingFeatureImpl(); + + assertFalse(pool.beforeStart(engine)); + } + + @Test + 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 + void testAfterCreate_NotEnabled() { + managers.clear(); + pool = new PoolingFeatureImpl(); + pool.beforeStart(engine); + + assertFalse(pool.afterCreate(controllerDisabled)); + assertTrue(managers.isEmpty()); + } + + @Test + void testAfterCreate_PropertyEx() { + managers.clear(); + pool = new PoolingFeatureImpl(); + pool.beforeStart(engine); + + assertThrows(PoolingFeatureRtException.class, () -> pool.afterCreate(controllerException)); + } + + @Test + void testAfterCreate_NoProps() { + pool = new PoolingFeatureImpl(); + + // did not perform globalInit, which is an error + + assertThrows(PoolingFeatureRtException.class, () -> pool.afterCreate(controller1)); + } + + @Test + void testAfterCreate_NoFeatProps() { + managers.clear(); + pool = new PoolingFeatureImpl(); + pool.beforeStart(engine); + + assertFalse(pool.afterCreate(controllerUnknown)); + assertTrue(managers.isEmpty()); + } + + @Test + 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 + 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 + 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 + void testAfterStop() { + assertFalse(pool.afterStop(controller1)); + verify(mgr1).afterStop(); + + assertFalse(pool.afterStop(controllerDisabled)); + + // count should be unchanged + verify(mgr1).afterStop(); + } + + @Test + void testAfterHalt() { + assertFalse(pool.afterHalt(controller1)); + assertFalse(pool.afterHalt(controller1)); + + verify(mgr1, never()).afterStop(); + + assertFalse(pool.afterStop(controllerDisabled)); + } + + @Test + void testAfterShutdown() { + assertFalse(pool.afterShutdown(controller1)); + assertFalse(pool.afterShutdown(controller1)); + + verify(mgr1, never()).afterStop(); + + assertFalse(pool.afterStop(controllerDisabled)); + } + + @Test + 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 + 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 + 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 + void testBeforeOffer_NotFound() { + assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1)); + } + + @Test + 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 + 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 + 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 + 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 + 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 + 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 + void testBeforeInsert_NotFound() { + + pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2); + assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1)); + } + + @Test + 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 + void testDoManager() { + 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 + void testDoManager_NotFound() { + assertFalse(pool.beforeStart(controllerDisabled)); + } + + @Test + void testDoManager_Ex() { + + // generate exception + doThrow(new RuntimeException()).when(mgr1).beforeStart(); + + assertThrows(RuntimeException.class, () -> 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 initTopicSources(Properties props) { + return Collections.emptyList(); + } + + @Override + protected List initTopicSinks(Properties props) { + return Collections.emptyList(); + } + } +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java new file mode 100644 index 00000000..ac60ae27 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingManagerImplTest.java @@ -0,0 +1,995 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +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 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> futures; + + private PoolingProperties poolProps; + private ListeningController controller; + private TopicMessageManager topicMessageManager; + private boolean gotManager; + private ScheduledThreadPoolExecutor sched; + private int schedCount; + private DroolsController drools; + private Serializer ser; + private CountDownLatch active; + + private PoolingManagerImpl mgr; + + /** + * Setup. + * + * @throws Exception throws exception + */ + @BeforeEach + 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); + + topicMessageManager = mock(TopicMessageManager.class); + gotManager = 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 + void testPoolingManagerImpl() { + assertTrue(gotManager); + + State st = mgr.getCurrent(); + assertInstanceOf(IdleState.class, st); + + // ensure the state is attached to the manager + assertEquals(mgr.getHost(), st.getHost()); + } + + @Test + void testPoolingManagerImpl_PoolEx() { + // throw an exception when we try to create the topic messages manager + PoolingFeatureException ex = new PoolingFeatureException(); + + assertThatThrownBy(() -> new PoolingManagerTest(MY_HOST, controller, poolProps, active) { + @Override + protected TopicMessageManager makeTopicMessagesManager(String topic) throws PoolingFeatureException { + throw ex; + } + }).isInstanceOf(PoolingFeatureRtException.class).hasCause(ex); + } + + @Test + void testGetCurrent() throws Exception { + assertEquals(IdleState.class, mgr.getCurrent().getClass()); + + startMgr(); + + assertEquals(StartState.class, mgr.getCurrent().getClass()); + } + + @Test + void testGetHost() { + assertEquals(MY_HOST, mgr.getHost()); + + mgr = new PoolingManagerTest(HOST2, controller, poolProps, active); + assertEquals(HOST2, mgr.getHost()); + } + + @Test + void testGetTopic() { + assertEquals(MY_TOPIC, mgr.getTopic()); + } + + @Test + void testGetProperties() { + assertEquals(poolProps, mgr.getProperties()); + } + + @Test + void testBeforeStart() { + // not running yet + mgr.beforeStart(); + + verify(topicMessageManager).startPublisher(); + + assertEquals(1, schedCount); + verify(sched).setMaximumPoolSize(1); + verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false); + + + // try again - nothing should happen + mgr.beforeStart(); + + verify(topicMessageManager).startPublisher(); + + assertEquals(1, schedCount); + verify(sched).setMaximumPoolSize(1); + verify(sched).setContinueExistingPeriodicTasksAfterShutdownPolicy(false); + } + + @Test + void testAfterStart() throws Exception { + startMgr(); + + verify(topicMessageManager).startConsumer(mgr); + + State st = mgr.getCurrent(); + assertInstanceOf(StartState.class, st); + + // ensure the state is attached to the manager + assertEquals(mgr.getHost(), st.getHost()); + + ArgumentCaptor timeCap = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor 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(topicMessageManager).startConsumer(mgr); + + assertInstanceOf(StartState.class, mgr.getCurrent()); + + verify(sched).schedule(any(Runnable.class), any(Long.class), any(TimeUnit.class)); + } + + @Test + void testBeforeStop() throws Exception { + startMgr(); + mgr.startDistributing(makeAssignments(false)); + + verify(topicMessageManager, times(START_PUB)).publish(any()); + + mgr.beforeStop(); + + verify(topicMessageManager).stopConsumer(mgr); + verify(sched).shutdownNow(); + verify(topicMessageManager, times(START_PUB + 1)).publish(any()); + verify(topicMessageManager).publish(contains("offline")); + + assertInstanceOf(IdleState.class, mgr.getCurrent()); + + // verify that next message is handled locally + assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT)); + verify(topicMessageManager, times(START_PUB + 1)).publish(any()); + } + + @Test + void testBeforeStop_NotRunning() { + final State st = mgr.getCurrent(); + + mgr.beforeStop(); + + verify(topicMessageManager, never()).stopConsumer(any()); + verify(sched, never()).shutdownNow(); + + // hasn't changed states either + assertEquals(st, mgr.getCurrent()); + } + + @Test + void testBeforeStop_AfterPartialStart() { + // call beforeStart but not afterStart + mgr.beforeStart(); + + final State st = mgr.getCurrent(); + + mgr.beforeStop(); + + // should still shut the scheduler down + verify(sched).shutdownNow(); + + verify(topicMessageManager, never()).stopConsumer(any()); + + // hasn't changed states + assertEquals(st, mgr.getCurrent()); + } + + @Test + void testAfterStop() throws Exception { + startMgr(); + mgr.beforeStop(); + + mgr.afterStop(); + + verify(topicMessageManager).stopPublisher(STD_OFFLINE_PUB_WAIT_MS); + } + + @Test + void testBeforeLock() throws Exception { + startMgr(); + + mgr.beforeLock(); + + assertInstanceOf(IdleState.class, mgr.getCurrent()); + } + + @Test + void testAfterUnlock_AliveIdle() { + // this really shouldn't happen + + lockMgr(); + + mgr.afterUnlock(); + + // stays in idle state, because it has no scheduler + assertInstanceOf(IdleState.class, mgr.getCurrent()); + } + + @Test + void testAfterUnlock_AliveStarted() throws Exception { + startMgr(); + lockMgr(); + + mgr.afterUnlock(); + + assertInstanceOf(StartState.class, mgr.getCurrent()); + } + + @Test + void testAfterUnlock_StoppedIdle() throws Exception { + startMgr(); + lockMgr(); + + // controller is stopped + when(controller.isAlive()).thenReturn(false); + + mgr.afterUnlock(); + + assertInstanceOf(IdleState.class, mgr.getCurrent()); + } + + @Test + void testAfterUnlock_StoppedStarted() throws Exception { + startMgr(); + + // Note: don't lockMgr() + + // controller is stopped + when(controller.isAlive()).thenReturn(false); + + mgr.afterUnlock(); + + assertInstanceOf(StartState.class, mgr.getCurrent()); + } + + @Test + 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 + 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 taskCap = ArgumentCaptor.forClass(Runnable.class); + ArgumentCaptor timeCap = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor 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 + 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 taskCap = ArgumentCaptor.forClass(Runnable.class); + ArgumentCaptor initCap = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor timeCap = ArgumentCaptor.forClass(Long.class); + ArgumentCaptor 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 + void testPublishAdmin() throws Exception { + Offline msg = new Offline(mgr.getHost()); + mgr.publishAdmin(msg); + + assertEquals(Message.ADMIN, msg.getChannel()); + + verify(topicMessageManager).publish(any()); + } + + @Test + void testPublish() throws Exception { + Offline msg = new Offline(mgr.getHost()); + mgr.publish("my.channel", msg); + + assertEquals("my.channel", msg.getChannel()); + + verify(topicMessageManager).publish(any()); + } + + @Test + void testPublish_InvalidMsg() throws Exception { + // message is missing data + mgr.publish(Message.ADMIN, new Offline()); + + // should not have attempted to publish it + verify(topicMessageManager, never()).publish(any()); + } + + @Test + void testPublish_TopicMessageMngEx() throws Exception { + + // generate exception + doThrow(new PoolingFeatureException()).when(topicMessageManager).publish(any()); + + assertThatCode(() -> mgr.publish(Message.ADMIN, new Offline(mgr.getHost()))).doesNotThrowAnyException(); + } + + @Test + 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); + + assertInstanceOf(QueryState.class, mgr.getCurrent()); + } + + @Test + void testOnTopicEvent_NullEvent() throws Exception { + startMgr(); + + assertThatCode(() -> mgr.onTopicEvent(CommInfrastructure.UEB, TOPIC2, null)).doesNotThrowAnyException(); + } + + @Test + void testBeforeOffer_Unlocked() throws Exception { + startMgr(); + + // route the message to another host + mgr.startDistributing(makeAssignments(false)); + + assertFalse(mgr.beforeOffer(TOPIC2, THE_EVENT)); + } + + @Test + void testBeforeOffer_Locked() throws Exception { + startMgr(); + lockMgr(); + + // route the message to another host + mgr.startDistributing(makeAssignments(false)); + + assertTrue(mgr.beforeOffer(TOPIC2, THE_EVENT)); + } + + @Test + void testBeforeInsert() throws Exception { + startMgr(); + lockMgr(); + + // route the message to this host + mgr.startDistributing(makeAssignments(true)); + + assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT)); + } + + @Test + void testHandleExternalCommInfrastructureStringStringString_NullReqId() throws Exception { + validateHandleReqId(null); + } + + @Test + void testHandleExternalCommInfrastructureStringStringString_EmptyReqId() throws Exception { + validateHandleReqId(""); + } + + @Test + void testHandleExternalCommInfrastructureStringStringString_InvalidMsg() throws Exception { + startMgr(); + + assertFalse(mgr.beforeInsert(TOPIC2, "invalid message")); + } + + @Test + void testHandleExternalCommInfrastructureStringStringString() throws Exception { + validateUnhandled(); + } + + @Test + void testHandleExternalForward_NoAssignments() throws Exception { + validateUnhandled(); + } + + @Test + void testHandleExternalForward() throws Exception { + validateNoForward(); + } + + @Test + void testHandleEvent_NullTarget() throws Exception { + // buckets have null targets + validateDiscarded(new BucketAssignments(new String[] {null, null})); + } + + @Test + void testHandleEvent_SameHost() throws Exception { + validateNoForward(); + } + + @Test + void testHandleEvent_DiffHost() throws Exception { + // route the message to the *OTHER* host + validateDiscarded(makeAssignments(false)); + } + + @Test + 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 + 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 + 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 + 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 + 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 + 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); + + assertInstanceOf(QueryState.class, mgr.getCurrent()); + } + + @Test + void testHandleInternal_IoEx() throws Exception { + startMgr(); + + mgr.onTopicEvent(CommInfrastructure.UEB, MY_TOPIC, "invalid message"); + + assertInstanceOf(StartState.class, mgr.getCurrent()); + } + + @Test + 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); + + assertInstanceOf(StartState.class, mgr.getCurrent()); + } + + @Test + void testStartDistributing() throws Exception { + validateNoForward(); + + + // null assignments should cause message to be processed locally + mgr.startDistributing(null); + assertFalse(mgr.beforeInsert(TOPIC2, DECODED_EVENT)); + verify(topicMessageManager, 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 + void testGoStart() { + State st = mgr.goStart(); + assertInstanceOf(StartState.class, st); + assertEquals(mgr.getHost(), st.getHost()); + } + + @Test + void testGoQuery() { + BucketAssignments asgn = new BucketAssignments(new String[] {HOST2}); + mgr.startDistributing(asgn); + + State st = mgr.goQuery(); + + assertInstanceOf(QueryState.class, st); + assertEquals(mgr.getHost(), st.getHost()); + assertEquals(asgn, mgr.getAssignments()); + } + + @Test + void testGoActive() { + BucketAssignments asgn = new BucketAssignments(new String[] {HOST2}); + mgr.startDistributing(asgn); + + State st = mgr.goActive(); + + assertInstanceOf(ActiveState.class, st); + assertEquals(mgr.getHost(), st.getHost()); + assertEquals(asgn, mgr.getAssignments()); + assertEquals(0, active.getCount()); + } + + @Test + void testGoInactive() { + State st = mgr.goInactive(); + assertInstanceOf(InactiveState.class, st); + assertEquals(mgr.getHost(), st.getHost()); + assertEquals(1, active.getCount()); + } + + @Test + 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 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 + 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 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); + + assertInstanceOf(QueryState.class, mgr.getCurrent()); + + // 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(topicMessageManager, 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 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. + * + */ + private void startMgr() { + 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 TopicMessageManager makeTopicMessagesManager(String topic) throws PoolingFeatureException { + gotManager = true; + return topicMessageManager; + } + + @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-messages/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java new file mode 100644 index 00000000..383e0071 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/PoolingPropertiesTest.java @@ -0,0 +1,190 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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_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 + */ + @BeforeEach + public void setUp() throws Exception { + plain = makeProperties(); + + pooling = new PoolingProperties(CONTROLLER, plain); + } + + @Test + void testPoolingProperties() { + // ensure no exceptions + assertThatCode(() -> new PoolingProperties(CONTROLLER, plain)).doesNotThrowAnyException(); + } + + @Test + void testGetSource() { + assertEquals(plain, pooling.getSource()); + } + + @Test + void testGetPoolingTopic() { + assertEquals(STD_POOLING_TOPIC, pooling.getPoolingTopic()); + } + + @Test + void testGetOfflineLimit() throws PropertyException { + doTest(OFFLINE_LIMIT, STD_OFFLINE_LIMIT, 1000, xxx -> pooling.getOfflineLimit()); + } + + @Test + void testGetOfflineAgeMs() throws PropertyException { + doTest(OFFLINE_AGE_MS, STD_OFFLINE_AGE_MS, 60000L, xxx -> pooling.getOfflineAgeMs()); + } + + @Test + void testGetOfflinePubWaitMs() throws PropertyException { + doTest(OFFLINE_PUB_WAIT_MS, STD_OFFLINE_PUB_WAIT_MS, 3000L, xxx -> pooling.getOfflinePubWaitMs()); + } + + @Test + void testGetStartHeartbeatMs() throws PropertyException { + doTest(START_HEARTBEAT_MS, STD_START_HEARTBEAT_MS, 100000L, xxx -> pooling.getStartHeartbeatMs()); + } + + @Test + void testGetReactivateMs() throws PropertyException { + doTest(REACTIVATE_MS, STD_REACTIVATE_MS, 50000L, xxx -> pooling.getReactivateMs()); + } + + @Test + void testGetIdentificationMs() throws PropertyException { + doTest(IDENTIFICATION_MS, STD_IDENTIFICATION_MS, 50000L, xxx -> pooling.getIdentificationMs()); + } + + @Test + void testGetActiveHeartbeatMs() throws PropertyException { + doTest(ACTIVE_HEARTBEAT_MS, STD_ACTIVE_HEARTBEAT_MS, 50000L, xxx -> pooling.getActiveHeartbeatMs()); + } + + @Test + 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 void doTest(String propnm, T specValue, T dfltValue, Function func) throws PropertyException { + /* + * With specialized property + */ + pooling = new PoolingProperties(CONTROLLER, plain); + assertEquals(specValue, func.apply(null), "special " + propnm); + + /* + * Without the property - should use the default value. + */ + plain.remove(specialize(propnm)); + plain.remove(propnm); + pooling = new PoolingProperties(CONTROLLER, plain); + assertEquals(dfltValue, func.apply(null), "default " + propnm); + } + + /** + * Makes a set of properties, where all the properties are specialized for the + * controller. + * + * @return a new property set + */ + private Properties makeProperties() { + Properties props = new Properties(); + + props.setProperty(specialize(POOLING_TOPIC), STD_POOLING_TOPIC); + props.setProperty(specialize(FEATURE_ENABLED), "" + STD_FEATURE_ENABLED); + props.setProperty(specialize(OFFLINE_LIMIT), "" + STD_OFFLINE_LIMIT); + props.setProperty(specialize(OFFLINE_AGE_MS), "" + STD_OFFLINE_AGE_MS); + props.setProperty(specialize(OFFLINE_PUB_WAIT_MS), "" + STD_OFFLINE_PUB_WAIT_MS); + props.setProperty(specialize(START_HEARTBEAT_MS), "" + STD_START_HEARTBEAT_MS); + props.setProperty(specialize(REACTIVATE_MS), "" + STD_REACTIVATE_MS); + props.setProperty(specialize(IDENTIFICATION_MS), "" + STD_IDENTIFICATION_MS); + props.setProperty(specialize(ACTIVE_HEARTBEAT_MS), "" + STD_ACTIVE_HEARTBEAT_MS); + props.setProperty(specialize(INTER_HEARTBEAT_MS), "" + 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 + * @return the property name, with the specializer embedded within it + */ + private String specialize(String propnm) { + String suffix = propnm.substring(PREFIX.length()); + return PREFIX + PoolingPropertiesTest.CONTROLLER + "." + suffix; + } +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java new file mode 100644 index 00000000..a81ea68b --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/SerializerTest.java @@ -0,0 +1,85 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import com.google.gson.JsonParseException; +import org.junit.jupiter.api.Test; +import org.onap.policy.drools.pooling.message.Message; +import org.onap.policy.drools.pooling.message.Query; + +class SerializerTest { + + @Test + void testSerializer() { + assertThatCode(Serializer::new).doesNotThrowAnyException(); + } + + @Test + void testEncodeMsg_testDecodeMsg() { + 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-messages/src/test/java/org/onap/policy/drools/pooling/TopicMessageManagerTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/TopicMessageManagerTest.java new file mode 100644 index 00000000..74098487 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/TopicMessageManagerTest.java @@ -0,0 +1,322 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class TopicMessageManagerTest { + + 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 TopicMessageManager mgr; + + /** + * Setup. + * + * @throws Exception throws an exception + */ + @BeforeEach + 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 TopicMessageManagerImpl(MY_TOPIC); + } + + @Test + void testTopicMessageManager() { + // verify that the init methods were called + assertTrue(gotSources); + assertTrue(gotSinks); + } + + @Test + void testTopicMessageManager_PoolingEx() { + // force error by having no topics match + when(source.getTopic()).thenReturn(""); + + assertThrows(PoolingFeatureException.class, () -> new TopicMessageManagerImpl(MY_TOPIC)); + } + + @Test + void testTopicMessageManager_IllegalArgEx() { + // force error + assertThrows(PoolingFeatureException.class, () -> + new TopicMessageManagerImpl(MY_TOPIC) { + @Override + protected List getTopicSources() { + throw new IllegalArgumentException(EXPECTED); + } + }); + } + + @Test + void testGetTopic() { + assertEquals(MY_TOPIC, mgr.getTopic()); + } + + @Test + void testFindTopicSource_NotFound() { + // one item in list, and its topic doesn't match + assertThrows(PoolingFeatureException.class, () -> new TopicMessageManagerImpl(MY_TOPIC) { + @Override + protected List getTopicSources() { + return Collections.singletonList(mock(TopicSource.class)); + } + }); + } + + @Test + void testFindTopicSource_EmptyList() { + // empty list + assertThrows(PoolingFeatureException.class, () -> new TopicMessageManagerImpl(MY_TOPIC) { + @Override + protected List getTopicSources() { + return Collections.emptyList(); + } + }); + } + + @Test + void testFindTopicSink_NotFound() { + // one item in list, and its topic doesn't match + assertThrows(PoolingFeatureException.class, () -> new TopicMessageManagerImpl(MY_TOPIC) { + @Override + protected List getTopicSinks() { + return Collections.singletonList(mock(TopicSink.class)); + } + }); + } + + @Test + void testFindTopicSink_EmptyList() { + // empty list + assertThrows(PoolingFeatureException.class, () -> new TopicMessageManagerImpl(MY_TOPIC) { + @Override + protected List getTopicSinks() { + return Collections.emptyList(); + } + }); + } + + @Test + 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 + void testStopPublisher() { + // 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 + void testStopPublisher_WithDelay() { + + mgr.startPublisher(); + + long tbeg = System.currentTimeMillis(); + + mgr.stopPublisher(100L); + + assertTrue(System.currentTimeMillis() >= tbeg + 100L); + } + + @Test + 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 + 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 + 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 + 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 + void testPublish_SendFailed() { + mgr.startPublisher(); + + // arrange for send() to fail + when(sink.send(MSG)).thenReturn(false); + + assertThrows(PoolingFeatureException.class, () -> mgr.publish(MSG)); + } + + @Test + void testPublish_SendEx() { + mgr.startPublisher(); + + // arrange for send() to throw an exception + doThrow(new IllegalStateException(EXPECTED)).when(sink).send(MSG); + + assertThrows(PoolingFeatureException.class, () -> mgr.publish(MSG)); + } + + /** + * Manager with overrides. + */ + private class TopicMessageManagerImpl extends TopicMessageManager { + + public TopicMessageManagerImpl(String topic) throws PoolingFeatureException { + super(topic); + } + + @Override + protected List 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 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-messages/src/test/java/org/onap/policy/drools/pooling/feature-pooling-messages.properties b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/feature-pooling-messages.properties new file mode 100644 index 00000000..b89e4062 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/feature-pooling-messages.properties @@ -0,0 +1,47 @@ +# Copyright 2018 AT&T Intellectual Property. All rights reserved +# Modifications Copyright (C) 2024 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. + +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-messages/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java new file mode 100644 index 00000000..ca47f9c1 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/BucketAssignmentsTest.java @@ -0,0 +1,361 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.Arrays; +import java.util.SortedSet; +import java.util.TreeSet; +import org.junit.jupiter.api.Test; +import org.onap.policy.drools.pooling.PoolingFeatureException; + +class BucketAssignmentsTest { + + @Test + void testBucketAssignments() { + assertThatCode(BucketAssignments::new).doesNotThrowAnyException(); + } + + @Test + void testBucketAssignmentsStringArray() { + String[] arr = {"abc", "def"}; + BucketAssignments asgn = new BucketAssignments(arr); + + assertNotNull(asgn.getHostArray()); + assertEquals(Arrays.toString(arr), Arrays.toString(asgn.getHostArray())); + } + + @Test + void testGetHostArray_testSetHostArray() { + + String[] arr = {"abc", "def"}; + BucketAssignments asgn = new BucketAssignments(arr); + + assertNotNull(asgn.getHostArray()); + assertEquals(Arrays.toString(arr), Arrays.toString(asgn.getHostArray())); + + String[] arr2 = {"xyz"}; + asgn.setHostArray(arr2); + + assertNotNull(asgn.getHostArray()); + assertEquals(Arrays.toString(arr2), Arrays.toString(asgn.getHostArray())); + } + + @Test + 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 + 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 + 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 getSortedHosts(BucketAssignments asgn) { + return new TreeSet<>(asgn.getAllHosts()); + } + + @Test + 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 seen = new TreeSet<>(); + for (int x = -1; x < arr.length + 2; ++x) { + seen.add(asgn.getAssignedHost(x)); + } + + TreeSet expected = new TreeSet<>(Arrays.asList(arr)); + assertEquals(expected, seen); + + // try a much bigger number + assertNotNull(asgn.getAssignedHost(arr.length * 1000)); + } + + @Test + 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 + 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 + 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 + void testEquals() { + // null object + BucketAssignments asgn = new BucketAssignments(); + assertNotEquals(null, asgn); + + // same object + asgn = new BucketAssignments(); + assertEquals(asgn, asgn); + + // different class of object + asgn = new BucketAssignments(); + assertNotEquals("not an assignment object", asgn); + + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java new file mode 100644 index 00000000..142ebbca --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/HeartbeatTest.java @@ -0,0 +1,59 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HeartbeatTest extends SupportBasicMessageTester { + + /** + * 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-messages/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java new file mode 100644 index 00000000..dced372d --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/IdentificationTest.java @@ -0,0 +1,74 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class IdentificationTest extends SupportMessageWithAssignmentsTester { + + public IdentificationTest() { + super(Identification.class); + } + + @BeforeEach + 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 + 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 + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java new file mode 100644 index 00000000..15d9d338 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/LeaderTest.java @@ -0,0 +1,73 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class LeaderTest extends SupportMessageWithAssignmentsTester { + + public LeaderTest() { + super(Leader.class); + } + + @BeforeEach + 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. + * + */ + @Test + void testCheckValidity_InvalidFields_NullAssignments() { + // null assignments are invalid + expectCheckValidityFailure(msg -> msg.setAssignments(null)); + } + + @Test + void testCheckValidity_SourceIsNotLeader() { + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java new file mode 100644 index 00000000..cf2cb695 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/MessageTest.java @@ -0,0 +1,82 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; + +class MessageTest extends SupportBasicMessageTester { + + public MessageTest() { + super(Message.class); + } + + @Test + 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 + 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 + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java new file mode 100644 index 00000000..29a7fad1 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/OfflineTest.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +public class OfflineTest extends SupportBasicMessageTester { + + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java new file mode 100644 index 00000000..737bcc19 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/QueryTest.java @@ -0,0 +1,38 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +public class QueryTest extends SupportBasicMessageTester { + + 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-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java new file mode 100644 index 00000000..2fe905a9 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportBasicMessageTester.java @@ -0,0 +1,251 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Test; +import org.onap.policy.drools.pooling.PoolingFeatureException; +import org.onap.policy.drools.pooling.Serializer; + +/** + * Superclass used to test subclasses of {@link Message}. + * + * @param type of {@link Message} subclass that this tests + */ +public abstract class SupportBasicMessageTester { + // 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 subclazz; + + /** + * Constructor. + * + * @param subclazz subclass of {@link Message} being tested + */ + public SupportBasicMessageTester(Class 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 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 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 + * VALID_HOST and 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 type of Message the function updates + */ + @FunctionalInterface + public static interface MessageUpdateFunction { + + /** + * Updates a message. + * + * @param msg message to be updated + */ + void update(T msg); + } + + /** + * Function that updates a single field within a message. + * + * @param type of Message the function updates + */ + @FunctionalInterface + public static interface MessageFieldUpdateFunction { + + /** + * 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-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java new file mode 100644 index 00000000..3814553f --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/message/SupportMessageWithAssignmentsTester.java @@ -0,0 +1,103 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.message; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import lombok.Getter; +import lombok.Setter; +import org.junit.jupiter.api.Test; + +/** + * Superclass used to test subclasses of {@link MessageWithAssignments}. + * + * @param type of {@link MessageWithAssignments} subclass that this tests + */ +@Setter +@Getter +public abstract class SupportMessageWithAssignmentsTester + extends SupportBasicMessageTester { + // 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 subclazz) { + super(subclazz); + } + + @Test + public void testCheckValidity_InvalidFields() { + // 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-messages/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java new file mode 100644 index 00000000..ce9adb9f --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ActiveStateTest.java @@ -0,0 +1,470 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class ActiveStateTest extends SupportBasicStateTester { + + private ActiveState state; + + /** + * Setup. + */ + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new ActiveState(mgr); + } + + @Test + 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 msg = capturePublishedMessage(Heartbeat.class); + assertEquals(MY_HOST, msg.getRight().getSource()); + } + + @Test + void testProcessHeartbeat_NullHost() { + assertNull(state.process(new Heartbeat())); + + assertFalse(state.isMyHeartbeatSeen()); + assertFalse(state.isPredHeartbeatSeen()); + + verify(mgr, never()).goInactive(); + verify(mgr, never()).goQuery(); + } + + @Test + 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 + 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 + 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 + void testProcessOffline_NullHost() { + // should be ignored + assertNull(state.process(new Offline())); + } + + @Test + void testProcessOffline_UnassignedHost() { + // HOST4 is not in the assignment list - should be ignored + assertNull(state.process(new Offline(HOST4))); + } + + @Test + 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + void testDetmNeighbors() { + // if only one host (i.e., itself) + mgr.startDistributing(new BucketAssignments(new String[] {MY_HOST, MY_HOST})); + state = new ActiveState(mgr); + assertNull(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 + void testAddTimers_WithPredecessor() { + // invoke start() to add the timers + state.start(); + + assertEquals(3, repeatedSchedules.size()); + + Triple 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 + 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 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 + 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 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 msg = capturePublishedMessage(Heartbeat.class); + assertEquals(MY_HOST, msg.getLeft()); + assertEquals(MY_HOST, msg.getRight().getSource()); + } + + @Test + void testAddTimers_MyHeartbeatSeen() { + // invoke start() to add the timers + state.start(); + + Triple 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 + void testAddTimers_MyHeartbeatMissed() { + // invoke start() to add the timers + state.start(); + + Triple 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 + void testAddTimers_PredecessorHeartbeatSeen() { + // invoke start() to add the timers + state.start(); + + Triple 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 + void testAddTimers_PredecessorHeartbeatMissed() { + // invoke start() to add the timers + state.start(); + + Triple 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 + 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 msg = capturePublishedMessage(Heartbeat.class); + assertEquals(MY_HOST, msg.getLeft()); + assertEquals(MY_HOST, msg.getRight().getSource()); + } + + @Test + void testGenHeartbeat_MultipleHosts() { + state.start(); + + verify(mgr, times(2)).publish(any(), any()); + + Pair 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-messages/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java new file mode 100644 index 00000000..51e27738 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/IdleStateTest.java @@ -0,0 +1,98 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class IdleStateTest extends SupportBasicStateTester { + + private IdleState state; + + /** + * Setup. + */ + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new IdleState(mgr); + } + + @Test + void testProcessHeartbeat() { + assertNull(state.process(new Heartbeat(PREV_HOST, 0L))); + verifyNothingPublished(); + } + + @Test + void testProcessIdentification() { + assertNull(state.process(new Identification(PREV_HOST, null))); + verifyNothingPublished(); + } + + @Test + 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 + void testProcessOffline() { + assertNull(state.process(new Offline(PREV_HOST))); + verifyNothingPublished(); + } + + @Test + 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-messages/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java new file mode 100644 index 00000000..a5ee2d06 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/InactiveStateTest.java @@ -0,0 +1,121 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class InactiveStateTest extends SupportBasicStateTester { + + private InactiveState state; + + /** + * Setup. + * + */ + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new InactiveState(mgr); + } + + @Test + 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 + 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 + 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 + void testGoInatcive() { + assertNull(state.goInactive()); + } + + @Test + void testStart() { + state.start(); + + Pair 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 + 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-messages/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java new file mode 100644 index 00000000..dbac7619 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/ProcessingStateTest.java @@ -0,0 +1,396 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class ProcessingStateTest extends SupportBasicStateTester { + + private ProcessingState state; + private HostBucket hostBucket; + + /** + * Setup. + */ + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new ProcessingState(mgr, MY_HOST); + hostBucket = new HostBucket(MY_HOST); + } + + @Test + 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 + 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 + void testProcessingState_NullLeader() { + when(mgr.getAssignments()).thenReturn(EMPTY_ASGN); + assertThrows(NullPointerException.class, () -> state = new ProcessingState(mgr, null)); + } + + @Test + void testProcessingState_ZeroLengthHostArray() { + when(mgr.getAssignments()).thenReturn(new BucketAssignments(new String[] {})); + assertThrows(IllegalArgumentException.class, () -> state = new ProcessingState(mgr, LEADER)); + } + + @Test + 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 + void testSetAssignments() { + state.setAssignments(null); + verify(mgr, never()).startDistributing(any()); + + state.setAssignments(ASGN3); + verify(mgr).startDistributing(ASGN3); + } + + @Test + 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 + void testSetLeader() { + state.setLeader(MY_HOST); + assertEquals(MY_HOST, state.getLeader()); + } + + @Test + void testSetLeader_Null() { + assertThrows(NullPointerException.class, () -> state.setLeader(null)); + } + + @Test + void testIsLeader() { + state.setLeader(MY_HOST); + assertTrue(state.isLeader()); + + state.setLeader(HOST2); + assertFalse(state.isLeader()); + } + + @Test + 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 + void testBecomeLeader_NotFirstAlive() { + // alive list contains something before my host name + var sortedHosts = sortHosts(PREV_HOST, MY_HOST); + assertThrows(IllegalArgumentException.class, () -> state.becomeLeader(sortedHosts)); + } + + @Test + 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 + void testMakeAssignments() throws Exception { + state.becomeLeader(sortHosts(MY_HOST, HOST2)); + + captureAssignments().checkValidity(); + } + + @Test + 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.stream(arr).allMatch(MY_HOST::equals)); + } + + @Test + 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.stream(arr).allMatch(MY_HOST::equals)); + } + + @Test + 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 + 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 + 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 + 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 + 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 + 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 + 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 + void testHostBucketHashCode() { + assertThrows(UnsupportedOperationException.class, () -> hostBucket.hashCode()); + } + + @Test + void testHostBucketEquals() { + assertThrows(UnsupportedOperationException.class, () -> hostBucket.equals(hostBucket)); + } +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java new file mode 100644 index 00000000..aae6e056 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/QueryStateTest.java @@ -0,0 +1,444 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class QueryStateTest extends SupportBasicStateTester { + + private QueryState state; + + /** + * Setup. + */ + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new QueryState(mgr); + } + + @Test + void testGoQuery() { + assertNull(state.goQuery()); + } + + @Test + void testStart() { + state.start(); + + Pair timer = onceTasks.remove(); + + assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue()); + assertNotNull(timer.getRight()); + } + + @Test + 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 + 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 + 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 + void testProcessLeader_SameLeader() { + String[] arr = {HOST2, PREV_HOST, MY_HOST}; + BucketAssignments asgn = new BucketAssignments(arr); + + // identify a leader that's better than my host + assertNull(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 + 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 + 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 + 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 + void testProcessOffline_NullHost() { + assertNull(state.process(new Offline())); + assertEquals(MY_HOST, state.getLeader()); + } + + @Test + void testProcessOffline_SameHost() { + assertNull(state.process(new Offline(MY_HOST))); + assertEquals(MY_HOST, state.getLeader()); + } + + @Test + 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 + void testQueryState() { + /* + * Prove the state is attached to the manager by invoking getHost(), which + * delegates to the manager. + */ + assertEquals(MY_HOST, state.getHost()); + } + + @Test + void testAwaitIdentification_MissingSelfIdent() { + state.start(); + + Pair 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 + void testAwaitIdentification_Leader() { + state.start(); + state.process(new Identification(MY_HOST, null)); + + Pair 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 + 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 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 + 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 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 + 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 + 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 + 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 + void testRecordInfo_NewIsNull() { + state.setAssignments(ASGN3); + state.process(new Identification(HOST1, null)); + + assertEquals(ASGN3, state.getAssignments()); + } + + @Test + void testRecordInfo_NewIsEmpty() { + state.setAssignments(ASGN3); + state.process(new Identification(PREV_HOST, new BucketAssignments())); + + assertEquals(ASGN3, state.getAssignments()); + } + + @Test + 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 + 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 + 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 + 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-messages/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java new file mode 100644 index 00000000..1a85304f --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StartStateTest.java @@ -0,0 +1,184 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class StartStateTest extends SupportBasicStateTester { + + private StartState state; + + /** + * Setup. + */ + @Override + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new StartState(mgr); + } + + @Test + void testStart() { + state.start(); + + Pair msg = capturePublishedMessage(Heartbeat.class); + + assertEquals(MY_HOST, msg.getLeft()); + assertEquals(state.getHbTimestampMs(), msg.getRight().getTimestampMs()); + + + /* + * Verify heartbeat generator + */ + Triple 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 + assertNull(generator.getRight().fire()); + verify(mgr, times(2)).publish(MY_HOST, msg.getRight()); + + // and again + assertNull(generator.getRight().fire()); + verify(mgr, times(3)).publish(MY_HOST, msg.getRight()); + + + /* + * Verify heartbeat checker + */ + Pair 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 + void testStartStatePoolingManager() { + /* + * Prove the state is attached to the manager by invoking getHost(), which + * delegates to the manager. + */ + assertEquals(MY_HOST, state.getHost()); + } + + @Test + 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 + 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 + void testProcessIdentification() { + assertNull(state.process(new Identification(MY_HOST, null))); + } + + @Test + void testProcessLeader() { + assertNull(state.process(new Leader(MY_HOST, null))); + } + + @Test + void testProcessOffline() { + assertNull(state.process(new Offline(HOST1))); + } + + @Test + void testProcessQuery() { + assertNull(state.process(new Query())); + } + + @Test + 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-messages/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java new file mode 100644 index 00000000..cfae6f3c --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/StateTest.java @@ -0,0 +1,466 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 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.assertj.core.api.Assertions.assertThatCode; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.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.jupiter.api.BeforeEach; +import org.junit.jupiter.api.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; + +class StateTest extends SupportBasicStateTester { + + private State state; + + /** + * Setup. + */ + @BeforeEach + public void setUp() throws Exception { + super.setUp(); + + state = new MyState(mgr); + } + + @Test + void testStatePoolingManager() { + /* + * Prove the state is attached to the manager by invoking getHost(), which + * delegates to the manager. + */ + assertEquals(MY_HOST, state.getHost()); + } + + @Test + 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 + 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 + void testStart() { + assertThatCode(() -> state.start()).doesNotThrowAnyException(); + } + + @Test + void testGoStart() { + State next = mock(State.class); + when(mgr.goStart()).thenReturn(next); + + State next2 = state.goStart(); + assertEquals(next, next2); + } + + @Test + void testGoQuery() { + State next = mock(State.class); + when(mgr.goQuery()).thenReturn(next); + + State next2 = state.goQuery(); + assertEquals(next, next2); + } + + @Test + 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 + 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 + 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 + void testGoInactive() { + State next = mock(State.class); + when(mgr.goInactive()).thenReturn(next); + + State next2 = state.goInactive(); + assertEquals(next, next2); + } + + @Test + void testProcessHeartbeat() { + assertNull(state.process(new Heartbeat())); + } + + @Test + void testProcessIdentification() { + assertNull(state.process(new Identification())); + } + + @Test + void testProcessLeader() { + String[] arr = {HOST2, HOST1}; + BucketAssignments asgn = new BucketAssignments(arr); + Leader msg = new Leader(HOST1, asgn); + + // should ignore it + assertNull(state.process(msg)); + verify(mgr).startDistributing(asgn); + } + + @Test + 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 + void testIsValidLeader_NullAssignment() { + assertFalse(state.isValid(new Leader(PREV_HOST, null))); + } + + @Test + void testIsValidLeader_NullSource() { + String[] arr = {HOST2, PREV_HOST, MY_HOST}; + BucketAssignments asgn = new BucketAssignments(arr); + assertFalse(state.isValid(new Leader(null, asgn))); + } + + @Test + void testIsValidLeader_EmptyAssignment() { + assertFalse(state.isValid(new Leader(PREV_HOST, new BucketAssignments()))); + } + + @Test + void testIsValidLeader_FromSelf() { + String[] arr = {HOST2, MY_HOST}; + BucketAssignments asgn = new BucketAssignments(arr); + + assertFalse(state.isValid(new Leader(MY_HOST, asgn))); + } + + @Test + void testIsValidLeader_WrongLeader() { + String[] arr = {HOST2, HOST3}; + BucketAssignments asgn = new BucketAssignments(arr); + + assertFalse(state.isValid(new Leader(HOST1, asgn))); + } + + @Test + void testIsValidLeader() { + String[] arr = {HOST2, HOST1}; + BucketAssignments asgn = new BucketAssignments(arr); + + assertTrue(state.isValid(new Leader(HOST1, asgn))); + } + + @Test + void testProcessOffline() { + assertNull(state.process(new Offline())); + } + + @Test + void testProcessQuery() { + assertNull(state.process(new Query())); + } + + @Test + void testPublishIdentification() { + Identification msg = new Identification(); + state.publish(msg); + + verify(mgr).publishAdmin(msg); + } + + @Test + void testPublishLeader() { + Leader msg = new Leader(); + state.publish(msg); + + verify(mgr).publishAdmin(msg); + } + + @Test + void testPublishOffline() { + Offline msg = new Offline(); + state.publish(msg); + + verify(mgr).publishAdmin(msg); + } + + @Test + void testPublishQuery() { + Query msg = new Query(); + state.publish(msg); + + verify(mgr).publishAdmin(msg); + } + + @Test + void testPublishStringHeartbeat() { + String chnl = "channelH"; + Heartbeat msg = new Heartbeat(); + + state.publish(chnl, msg); + + verify(mgr).publish(chnl, msg); + } + + @Test + void testStartDistributing() { + BucketAssignments asgn = new BucketAssignments(); + state.startDistributing(asgn); + + verify(mgr).startDistributing(asgn); + } + + @Test + void testStartDistributing_NullAssignments() { + state.startDistributing(null); + + verify(mgr, never()).startDistributing(any()); + } + + @Test + 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 + 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 + 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 + 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 + void testMakeHeartbeat() { + long timestamp = 30000L; + Heartbeat msg = state.makeHeartbeat(timestamp); + + assertEquals(MY_HOST, msg.getSource()); + assertEquals(timestamp, msg.getTimestampMs()); + } + + @Test + void testMakeIdentification() { + Identification ident = state.makeIdentification(); + assertEquals(MY_HOST, ident.getSource()); + assertEquals(ASGN3, ident.getAssignments()); + } + + @Test + void testMakeOffline() { + Offline msg = state.makeOffline(); + + assertEquals(MY_HOST, msg.getSource()); + } + + @Test + void testMakeQuery() { + Query msg = state.makeQuery(); + + assertEquals(MY_HOST, msg.getSource()); + } + + @Test + void testGetHost() { + assertEquals(MY_HOST, state.getHost()); + } + + @Test + void testGetTopic() { + assertEquals(MY_TOPIC, state.getTopic()); + } + + /** + * State used for testing purposes, with abstract methods implemented. + */ + private static class MyState extends State { + + public MyState(PoolingManager mgr) { + super(mgr); + } + } +} diff --git a/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java new file mode 100644 index 00000000..8f2c9160 --- /dev/null +++ b/feature-pooling-messages/src/test/java/org/onap/policy/drools/pooling/state/SupportBasicStateTester.java @@ -0,0 +1,282 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2020, 2024 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.jupiter.api.Assertions.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 onceSchedules; + + /** + * Tasks captured via schedule(). + */ + protected LinkedList> onceTasks; + + /** + * Scheduled tasks returned by scheduleWithFixedDelay(). + */ + protected LinkedList repeatedSchedules; + + /** + * Tasks captured via scheduleWithFixedDelay(). + */ + protected LinkedList> repeatedTasks; + + /** + * Messages captured via publish(). + */ + protected LinkedList> published; + + /** + * Messages captured via publishAdmin(). + */ + protected LinkedList 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 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 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 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 captureAdminMessage(Class 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 captureAdminMessage(Class 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 Pair capturePublishedMessage(Class 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 Pair capturePublishedMessage(Class clazz, int index) { + Pair msg = published.get(index); + return Pair.of(msg.getLeft(), clazz.cast(msg.getRight())); + } +} diff --git a/feature-pooling-messages/src/test/resources/logback-test.xml b/feature-pooling-messages/src/test/resources/logback-test.xml new file mode 100644 index 00000000..45d8201d --- /dev/null +++ b/feature-pooling-messages/src/test/resources/logback-test.xml @@ -0,0 +1,36 @@ + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}.%M\(%line\) - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionAdditionalTest.java b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionAdditionalTest.java index 7a32e549..f567c593 100644 --- a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionAdditionalTest.java +++ b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionAdditionalTest.java @@ -3,6 +3,7 @@ * feature-test-transaction * ================================================================================ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +21,10 @@ package org.onap.policy.drools.testtransaction; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; @@ -40,13 +41,13 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.core.PolicyContainer; import org.onap.policy.drools.system.PolicyController; -public class TestTransactionAdditionalTest { +class TestTransactionAdditionalTest { private static final int MAX_SLEEP_COUNT = 3; private static final String EXPECTED = "expected exception"; @@ -56,7 +57,7 @@ public class TestTransactionAdditionalTest { private static final String SESSION1 = "session-a"; private static final String SESSION2 = "session-b"; private static final List sessions = Arrays.asList(SESSION1, SESSION2); - private static final List facts = Arrays.asList(0L); + private static final List facts = List.of(0L); private Thread theThread; private PolicyController controller; @@ -76,7 +77,7 @@ public class TestTransactionAdditionalTest { /** * Initialize objects for each test. */ - @Before + @BeforeEach public void setUp() { theThread = mock(Thread.class); controller = mock(PolicyController.class); @@ -118,12 +119,12 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionImpl() { + void testTestTransactionImpl() { assertNotNull(TestTransactionConstants.getManager()); } @Test - public void testTestTransactionImplRegister_testTestTransactionImplUnregister() { + void testTestTransactionImplRegister_testTestTransactionImplUnregister() { task = mock(TtControllerTask.class); when(task.isAlive()).thenReturn(true); name2task.put(CONTROLLER1, task); @@ -162,7 +163,7 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTaskFactory() throws Exception { + void testTestTransactionControllerTaskFactory() throws Exception { task = new TtControllerTask(controller) { @Override protected Thread makeThread(Runnable action) { @@ -170,7 +171,7 @@ public class TestTransactionAdditionalTest { } @Override - protected void joinThread(long waitTimeMs) throws InterruptedException { + protected void joinThread(long waitTimeMs) { // do nothing } }; @@ -180,7 +181,7 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTask() { + void testTestTransactionControllerTask() { assertEquals(task, theAction); assertTrue(task.isAlive()); assertEquals(controller, task.getController()); @@ -190,17 +191,17 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTaskGetController() { + void testTestTransactionControllerTaskGetController() { assertEquals(controller, task.getController()); } @Test - public void testTestTransactionControllerTaskGetThread() { + void testTestTransactionControllerTaskGetThread() { assertEquals(theThread, task.getThread()); } @Test - public void testTestTransactionControllerTaskStop() throws Exception { + void testTestTransactionControllerTaskStop() { task.stop(); assertFalse(task.isAlive()); verify(theThread).interrupt(); @@ -222,7 +223,7 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTaskRun() { + void testTestTransactionControllerTaskRun() { task.run(); assertFalse(task.isAlive()); verify(theThread, never()).interrupt(); @@ -338,7 +339,7 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTaskInjectTxIntoSessions() { + void testTestTransactionControllerTaskInjectTxIntoSessions() { task.run(); verify(container, times(MAX_SLEEP_COUNT * sessions.size())).insert(anyString(), any(EventObject.class)); @@ -356,7 +357,7 @@ public class TestTransactionAdditionalTest { } @Test - public void testTestTransactionControllerTaskToString() { + void testTestTransactionControllerTaskToString() { assertTrue(task.toString().startsWith("TTControllerTask [")); } diff --git a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java index 6bb09903..a7b213bb 100644 --- a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java +++ b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionFeatureTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,21 +21,21 @@ package org.onap.policy.drools.testtransaction; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.system.PolicyController; -public class TestTransactionFeatureTest { +class TestTransactionFeatureTest { private AtomicInteger regCount; private AtomicInteger unregCount; @@ -46,7 +47,7 @@ public class TestTransactionFeatureTest { /** * Initialize objects for each test. */ - @Before + @BeforeEach public void setUp() { regCount = new AtomicInteger(0); unregCount = new AtomicInteger(0); @@ -75,34 +76,34 @@ public class TestTransactionFeatureTest { } @Test - public void testAfterStart() { + void testAfterStart() { // try each combination of alive, locked, and brained checkCombos(regCount, ctlr -> feat.afterStart(ctlr)); } @Test - public void testAfterLock() { + void testAfterLock() { checkSimple(unregCount, ctlr -> feat.afterLock(ctlr)); } @Test - public void testAfterUnlock() { + void testAfterUnlock() { // try each combination of alive, locked, and brained checkCombos(regCount, ctlr -> feat.afterUnlock(ctlr)); } @Test - public void testBeforeStop() { + void testBeforeStop() { checkSimple(unregCount, ctlr -> feat.beforeStop(ctlr)); } @Test - public void testGetSequenceNumber() { + void testGetSequenceNumber() { assertEquals(1000, feat.getSequenceNumber()); } @Test - public void testGetTestTransMgr() { + void testGetTestTransMgr() { assertNotNull(new TestTransactionFeature().getTestTransMgr()); } diff --git a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionTest.java b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionTest.java index f8a8cc20..a1fd2738 100644 --- a/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionTest.java +++ b/feature-test-transaction/src/test/java/org/onap/policy/drools/testtransaction/TestTransactionTest.java @@ -3,6 +3,7 @@ * feature-test-transaction * ================================================================================ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +21,9 @@ package org.onap.policy.drools.testtransaction; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import java.io.IOException; import java.nio.file.Files; @@ -31,8 +33,8 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.persistence.SystemPersistenceConstants; import org.onap.policy.drools.properties.DroolsPropertyConstants; import org.onap.policy.drools.system.PolicyController; @@ -52,15 +54,14 @@ public class TestTransactionTest { TEST_CONTROLLER_NAME + "-controller.properties.bak"; /** logger. */ - private static Logger logger = LoggerFactory.getLogger(TestTransactionTest.class); + private static final Logger logger = LoggerFactory.getLogger(TestTransactionTest.class); /** * Start up. * - * @throws IOException exception */ - @BeforeClass - public static void startUp() throws IOException { + @BeforeAll + public static void startUp() { logger.info("enter"); cleanUpWorkingDir(); @@ -70,7 +71,7 @@ public class TestTransactionTest { } @Test - public void testRegisterUnregister() throws InterruptedException { + void testRegisterUnregister() throws InterruptedException { final Properties controllerProperties = new Properties(); controllerProperties.put(DroolsPropertyConstants.PROPERTY_CONTROLLER_NAME, TEST_CONTROLLER_NAME); final PolicyController controller = @@ -80,7 +81,7 @@ public class TestTransactionTest { CountDownLatch latch = new CountDownLatch(1); - // use our own impl so we can decrement the latch when run() completes + // use our own impl, so we can decrement the latch when run() completes TtImpl impl = new TtImpl() { @Override protected TtControllerTask makeControllerTask(PolicyController controller) { @@ -104,7 +105,7 @@ public class TestTransactionTest { impl.unregister(controller); Thread ttThread = getThread(latch, "tt-controller-task-" + TEST_CONTROLLER_NAME); - assertEquals(null, ttThread); + assertNull(ttThread); } /** diff --git a/packages/docker/src/main/docker/pdpd-entrypoint.sh b/packages/docker/src/main/docker/pdpd-entrypoint.sh index 112d3cb4..2caca628 100644 --- a/packages/docker/src/main/docker/pdpd-entrypoint.sh +++ b/packages/docker/src/main/docker/pdpd-entrypoint.sh @@ -2,6 +2,7 @@ # ######################################################################## # Copyright 2019-2021 AT&T Intellectual Property. All rights reserved +# Modifications Copyright (C) 2024 Nordix Foundation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -117,13 +118,6 @@ function security { cp -f "${POLICY_INSTALL_INIT}"/policy-truststore "${POLICY_HOME}"/etc/ssl fi fi - - if [ -f "${POLICY_INSTALL_INIT}"/aaf-cadi.keyfile ]; then - if ! cmp -s "${POLICY_INSTALL_INIT}"/aaf-cadi.keyfile "${POLICY_HOME}"/config/aaf-cadi.keyfile; then - echo "overriding aaf-cadi.keyfile" - cp -f "${POLICY_INSTALL_INIT}"/aaf-cadi.keyfile "${POLICY_HOME}"/config/aaf-cadi.keyfile - fi - fi } function serverConfig { diff --git a/packages/install/pom.xml b/packages/install/pom.xml index 45f15b72..a79aa0ee 100644 --- a/packages/install/pom.xml +++ b/packages/install/pom.xml @@ -4,6 +4,7 @@ ================================================================================ Copyright (C) 2017, 2022 AT&T Intellectual Property. All rights reserved. Modifications Copyright (C) 2020 Bell Canada. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -40,6 +41,7 @@ + org.apache.maven.plugins maven-assembly-plugin @@ -93,7 +95,7 @@ org.onap.policy.drools-pdp - feature-pooling-dmaap + feature-pooling-messages ${project.version} zip diff --git a/packages/install/src/files/base.conf b/packages/install/src/files/base.conf index 24d95a76..3b447647 100644 --- a/packages/install/src/files/base.conf +++ b/packages/install/src/files/base.conf @@ -4,7 +4,7 @@ # ================================================================================ # Copyright (C) 2017-2022 AT&T Intellectual Property. All rights reserved. # Modifications Copyright (C) 2020 Bell Canada. -# Modifications Copyright (C) 2022 Nordix Foundation. +# Modifications Copyright (C) 2022, 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -87,13 +87,6 @@ JDBC_URL= # add optional JDBC options for the connector to use JDBC_OPTS= -# AAF - -AAF=false -AAF_NAMESPACE=org.onap.policy -AAF_HOST=aaf-onap-test.osaaf.org -CADI_KEYFILE=/opt/app/policy/config/aaf-cadi.keyfile - # Prometheus PROMETHEUS=false @@ -102,7 +95,7 @@ PROMETHEUS=false HTTP_SERVER_HTTPS=false -# PDP-D DMaaP configuration channel +# PDP-D Message Broker configuration channel PDPD_CONFIGURATION_TOPIC=PDPD-CONFIGURATION PDPD_CONFIGURATION_API_KEY= @@ -139,7 +132,7 @@ PDP_CLIENT_USERNAME= PDP_CLIENT_PASSWORD= PDP_ENVIRONMENT= -# DCAE DMaaP +# DCAE Message Broker DCAE_TOPIC= DCAE_SERVERS= @@ -147,8 +140,8 @@ DCAE_CONSUMER_GROUP= # Open DMaaP -DMAAP_SERVERS= -DMAAP_HTTPS=true +# DMAAP_SERVERS= +# DMAAP_HTTPS=true # AAI diff --git a/packages/install/src/files/feature-pooling-dmaap.conf b/packages/install/src/files/feature-pooling-dmaap.conf deleted file mode 100644 index 0ef81951..00000000 --- a/packages/install/src/files/feature-pooling-dmaap.conf +++ /dev/null @@ -1,20 +0,0 @@ -### -# ============LICENSE_START======================================================= -# ONAP POLICY -# ================================================================================ -# 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========================================================= -### -POOLING_TOPIC=POLICY-PDP-POOLING diff --git a/packages/install/src/files/feature-pooling-messages.conf b/packages/install/src/files/feature-pooling-messages.conf new file mode 100644 index 00000000..0ef81951 --- /dev/null +++ b/packages/install/src/files/feature-pooling-messages.conf @@ -0,0 +1,20 @@ +### +# ============LICENSE_START======================================================= +# ONAP POLICY +# ================================================================================ +# 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========================================================= +### +POOLING_TOPIC=POLICY-PDP-POOLING diff --git a/policy-core/pom.xml b/policy-core/pom.xml index a9f47311..0a743e86 100644 --- a/policy-core/pom.xml +++ b/policy-core/pom.xml @@ -60,10 +60,6 @@ and vice versa. --> - - org.codehaus.plexus - plexus-utils - org.apache.ant ant diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java b/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java index 1eab676f..ec5ceb21 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/PolicyContainer.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,12 +47,12 @@ import org.slf4j.LoggerFactory; */ public class PolicyContainer implements Startable { // get an instance of logger - private static Logger logger = LoggerFactory.getLogger(PolicyContainer.class); + private static final Logger logger = LoggerFactory.getLogger(PolicyContainer.class); // 'KieServices' singleton private static KieServices kieServices = KieServices.Factory.get(); // set of all 'PolicyContainer' instances - private static HashSet containers = new HashSet<>(); + private static final HashSet containers = new HashSet<>(); // maps feature objects to per-PolicyContainer data private ConcurrentHashMap adjuncts = new ConcurrentHashMap<>(); @@ -65,7 +66,7 @@ public class PolicyContainer implements Startable { private volatile boolean isStarted = false; // maps session name into the associated 'PolicySession' instance - private HashMap sessions = new HashMap<>(); + private final HashMap sessions = new HashMap<>(); // if not null, this is a 'KieScanner' looking for updates private KieScanner scanner = null; @@ -171,7 +172,7 @@ public class PolicyContainer implements Startable { } } if (exception != null) { - // all of the 'newKieContainer' invocations failed -- throw the + // all the 'newKieContainer' invocations failed -- throw the // most recent exception throw exception; } @@ -263,7 +264,7 @@ public class PolicyContainer implements Startable { PolicySession session = null; KieSession kieSession = null; - // loop through all of the features, and give each one + // loop through all the features, and give each one // a chance to create the 'KieSession' for (PolicySessionFeatureApi feature : PolicySessionFeatureApiConstants.getImpl().getList()) { try { @@ -432,7 +433,7 @@ public class PolicyContainer implements Startable { /** * Get policy sessions. * - * @return all of the 'PolicySession' instances + * @return all the 'PolicySession' instances */ public Collection getPolicySessions() { // KLUDGE WARNING: this is a temporary workaround -- if there are @@ -703,7 +704,7 @@ public class PolicyContainer implements Startable { var configDir = "config"; logger.info("PolicyContainer.main: configDir={}", configDir); - // invoke 'globalInit' on all of the features + // invoke 'globalInit' on all the features for (PolicySessionFeatureApi feature : PolicySessionFeatureApiConstants.getImpl().getList()) { try { feature.globalInit(args, configDir); diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java index 1f8a61c6..0c10e984 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/PolicySession.java @@ -4,6 +4,7 @@ * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2018 Samsung Electronics Co., Ltd. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,14 +50,12 @@ import org.slf4j.LoggerFactory; * 2) Access to UEB * 3) Logging of events */ -public class PolicySession - implements AgendaEventListener, RuleRuntimeEventListener { +public class PolicySession implements AgendaEventListener, RuleRuntimeEventListener { // get an instance of logger - private static Logger logger = LoggerFactory.getLogger(PolicySession.class); + private static final Logger logger = LoggerFactory.getLogger(PolicySession.class); // supports 'getCurrentSession()' method - private static ThreadLocal policySess = - new ThreadLocal<>(); + private static ThreadLocal policySess = new ThreadLocal<>(); // name of the 'PolicySession' and associated 'KieSession' @Getter @@ -115,7 +114,7 @@ public class PolicySession return; } - // loop through all of the features, and give each one + // loop through all the features, and give each one // a chance to create the 'ThreadModel' for (PolicySessionFeatureApi feature : PolicySessionFeatureApiConstants.getImpl().getList()) { diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java index 0f4add77..4356d111 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/jmx/PdpJmx.java @@ -3,6 +3,7 @@ * policy-core * ================================================================================ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,7 +42,7 @@ public class PdpJmx implements PdpJmxMBean { return actions.longValue(); } - public void updateOccured() { + public void updateOccurred() { updates.incrementAndGet(); } diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysFailLock.java b/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysFailLock.java index dbb20883..df0ac151 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysFailLock.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysFailLock.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +21,7 @@ package org.onap.policy.drools.core.lock; +import java.io.Serial; import lombok.NoArgsConstructor; /** @@ -27,6 +29,7 @@ import lombok.NoArgsConstructor; */ @NoArgsConstructor public class AlwaysFailLock extends LockImpl { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysSuccessLock.java b/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysSuccessLock.java index 6b1e1494..ced6c4c9 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysSuccessLock.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/lock/AlwaysSuccessLock.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,12 +21,14 @@ package org.onap.policy.drools.core.lock; +import java.io.Serial; import lombok.NonNull; /** * Lock implementation whose operations always succeed. */ public class AlwaysSuccessLock extends LockImpl { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/policy-core/src/main/java/org/onap/policy/drools/util/FeatureEnabledChecker.java b/policy-core/src/main/java/org/onap/policy/drools/util/FeatureEnabledChecker.java index 755e7a18..285a9a0a 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/util/FeatureEnabledChecker.java +++ b/policy-core/src/main/java/org/onap/policy/drools/util/FeatureEnabledChecker.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +26,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; /** - * Checks whether or not a feature is enabled. + * Checks whether a feature is enabled. */ @NoArgsConstructor(access = AccessLevel.PRIVATE) public class FeatureEnabledChecker { @@ -40,6 +41,6 @@ public class FeatureEnabledChecker { */ public static boolean isFeatureEnabled(Properties props, String propName) { String val = props.getProperty(propName); - return (val != null && Boolean.valueOf(val)); + return (Boolean.parseBoolean(val)); } } diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java index 81ca3407..abed9727 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/DroolsContainerTest.java @@ -3,6 +3,7 @@ * policy-core * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +21,11 @@ package org.onap.policy.drools.core; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,11 +33,13 @@ import static org.mockito.Mockito.when; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collection; +import java.util.List; +import java.util.Objects; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; import org.drools.core.WorkingMemory; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.util.KieUtils; /** @@ -54,7 +57,7 @@ public class DroolsContainerTest { * and 'PolicySession', and the updating of that container to a new * version. */ - @BeforeClass + @BeforeAll public static void setUp() throws Exception { KieUtils.installArtifact( Paths.get("src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml").toFile(), @@ -75,13 +78,13 @@ public class DroolsContainerTest { * version. */ @Test - public void createAndUpdate() throws Exception { + void createAndUpdate() throws Exception { // make sure feature log starts out clean PolicySessionFeatureApiMock.getLog(); // run 'globalInit', and verify expected feature hook fired PolicyContainer.globalInit(new String[0]); - assertEquals(Arrays.asList("globalInit"), + assertEquals(List.of("globalInit"), PolicySessionFeatureApiMock.getLog()); // initial conditions -- there should be no containers @@ -139,15 +142,15 @@ public class DroolsContainerTest { session.getKieSession().insert(result); // the Drools rules should add 3 + 8 + 2, and store 13 in a[0] - assertEquals(13, result.poll(TIMEOUT_SEC, TimeUnit.SECONDS).intValue()); + assertEquals(13, Objects.requireNonNull(result.poll(TIMEOUT_SEC, TimeUnit.SECONDS)).intValue()); // update the container to a new version -- // the rules will then multiply values rather than add them assertEquals("[]", - container.updateToVersion("17.2.0-SNAPSHOT").toString()); + container.updateToVersion("17.2.0-SNAPSHOT")); // verify expected feature hooks fired - assertEquals(Arrays.asList("selectThreadModel"), + assertEquals(List.of("selectThreadModel"), PolicySessionFeatureApiMock.getLog()); // verify new container attributes @@ -169,7 +172,7 @@ public class DroolsContainerTest { container.insert("session1", Arrays.asList(3, 8, 2)); container.insert("session1", result); - assertEquals(48, result.poll(TIMEOUT_SEC, TimeUnit.SECONDS).intValue()); + assertEquals(48, Objects.requireNonNull(result.poll(TIMEOUT_SEC, TimeUnit.SECONDS)).intValue()); /* * verify that default KiePackages have been added by testing that @@ -198,7 +201,7 @@ public class DroolsContainerTest { assertFalse(container.isAlive()); // verify expected feature hooks fired - assertEquals(Arrays.asList("disposeKieSession"), + assertEquals(List.of("disposeKieSession"), PolicySessionFeatureApiMock.getLog()); } @@ -213,7 +216,7 @@ public class DroolsContainerTest { * test, also to increase code coverage. */ @Test - public void versionList() throws Exception { + void versionList() throws Exception { // make sure feature log starts out clean PolicySessionFeatureApiMock.getLog(); @@ -222,7 +225,7 @@ public class DroolsContainerTest { // run 'globalInit', and verify expected feature hook fired PolicyContainer.globalInit(new String[0]); - assertEquals(Arrays.asList("globalInit-exception"), + assertEquals(List.of("globalInit-exception"), PolicySessionFeatureApiMock.getLog()); // initial conditions -- there should be no containers @@ -317,7 +320,7 @@ public class DroolsContainerTest { container.insertAll(result); // the Drools rules should add 7 + 3 + 4, and store 14 in a[0] - assertEquals(14, result.poll(TIMEOUT_SEC, TimeUnit.SECONDS).intValue()); + assertEquals(14, Objects.requireNonNull(result.poll(TIMEOUT_SEC, TimeUnit.SECONDS)).intValue()); // exercise some more API methods assertEquals(container.getClassLoader(), @@ -328,7 +331,7 @@ public class DroolsContainerTest { assertFalse(container.isAlive()); // verify expected feature hooks fired - assertEquals(Arrays.asList("destroyKieSession-exception"), + assertEquals(List.of("destroyKieSession-exception"), PolicySessionFeatureApiMock.getLog()); // clear exception trigger diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java index fbd81391..d8257067 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiMock.java @@ -3,6 +3,7 @@ * policy-core * ================================================================================ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ package org.onap.policy.drools.core; import java.util.ArrayList; +import lombok.Setter; import org.kie.api.runtime.KieSession; /** @@ -30,10 +32,11 @@ import org.kie.api.runtime.KieSession; */ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi { // contains the log entries since the most recent 'getLog()' call - private static ArrayList log = new ArrayList<>(); + private static final ArrayList log = new ArrayList<>(); // if 'true', trigger an exception right after doing the log, // to verify that exceptions are handled + @Setter private static boolean exceptionTrigger = false; /** @@ -49,17 +52,6 @@ public class PolicySessionFeatureApiMock implements PolicySessionFeatureApi { } } - /** - * This method controls whether these hooks trigger an exception after - * being invoked. - * - * @param indicator if 'true', subsequent hook method calls will trigger - * an exception; if 'false', no exception is triggered - */ - public static void setExceptionTrigger(boolean indicator) { - exceptionTrigger = indicator; - } - /** * This method adds an entry to the log, and possibly triggers an exception. * diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiTest.java index 1d1ca0ff..9e5643f1 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionFeatureApiTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +21,15 @@ package org.onap.policy.drools.core; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class PolicySessionFeatureApiTest { +class PolicySessionFeatureApiTest { @Test - public void test() { - PolicySessionFeatureApi api = new PolicySessionFeatureApi() { - @Override - public int getSequenceNumber() { - return 0; - } - }; + void test() { + PolicySessionFeatureApi api = () -> 0; // test default methods api.globalInit(null, null); diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionTest.java index e937bb30..6f07a34f 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/PolicySessionTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018, 2020-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,22 +22,22 @@ package org.onap.policy.drools.core; import static org.assertj.core.api.Assertions.assertThatCode; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.concurrent.Semaphore; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.kie.api.event.rule.AgendaEventListener; import org.kie.api.event.rule.RuleRuntimeEventListener; import org.kie.api.runtime.KieSession; import org.onap.policy.drools.core.PolicySession.ThreadModel; -public class PolicySessionTest { +class PolicySessionTest { private static final String MY_NAME = "my-name"; private static final String CONTAINER = "my-container"; @@ -49,7 +50,7 @@ public class PolicySessionTest { /** * Initialize test objects. */ - @Before + @BeforeEach public void setUp() { container = mock(PolicyContainer.class); kie = mock(KieSession.class); @@ -60,7 +61,7 @@ public class PolicySessionTest { } @Test - public void test_Simple() { + void test_Simple() { // verify constructor operations AgendaEventListener agenda = session; verify(kie).addEventListener(agenda); @@ -92,7 +93,7 @@ public class PolicySessionTest { } @Test - public void testStartThread() { + void testStartThread() { session.startThread(); // re-start @@ -102,7 +103,7 @@ public class PolicySessionTest { } @Test - public void testSetPolicySession_testGetCurrentSession_testRemovePolicySession() { + void testSetPolicySession_testGetCurrentSession_testRemovePolicySession() { PolicySession sess2 = new PolicySession(MY_NAME + "-b", container, kie); session.setPolicySession(); @@ -121,7 +122,7 @@ public class PolicySessionTest { } @Test - public void testGetAdjunct_testSetAdjunct() { + void testGetAdjunct_testSetAdjunct() { Object adjnm1 = "adjunct-a"; Object adjval1 = "value-a"; session.setAdjunct(adjnm1, adjval1); @@ -136,7 +137,7 @@ public class PolicySessionTest { } @Test - public void testThreadModel() { + void testThreadModel() { ThreadModel model = new PolicySession.ThreadModel() { @Override public void stop() { @@ -149,11 +150,11 @@ public class PolicySessionTest { } }; - assertThatCode(() -> model.updated()).doesNotThrowAnyException(); + assertThatCode(model::updated).doesNotThrowAnyException(); } @Test - public void testDefaultThreadModelRun() throws Exception { + void testDefaultThreadModelRun() throws Exception { testDefaultThreadModelRun_Ex(() -> { throw new RuntimeException(EXPECTED); }); diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxTest.java index e585a4b6..6bd994be 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/jmx/PdpJmxTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,45 +21,45 @@ package org.onap.policy.drools.core.jmx; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -public class PdpJmxTest { +class PdpJmxTest { private PdpJmx jmx; - @Before + @BeforeEach public void setUp() { jmx = new PdpJmx(); } @Test - public void testGetInstance() { + void testGetInstance() { jmx = PdpJmx.getInstance(); assertNotNull(jmx); assertSame(jmx, PdpJmx.getInstance()); } @Test - public void testGetUpdates_testUpdateOccured() { + void testGetUpdates_testUpdateOccurred() { assertEquals(0, jmx.getUpdates()); assertEquals(0, jmx.getRulesFired()); - jmx.updateOccured(); + jmx.updateOccurred(); assertEquals(1, jmx.getUpdates()); assertEquals(0, jmx.getRulesFired()); - jmx.updateOccured(); + jmx.updateOccurred(); assertEquals(2, jmx.getUpdates()); assertEquals(0, jmx.getRulesFired()); } @Test - public void testGetRulesFired_testRuleFired() { + void testGetRulesFired_testRuleFired() { assertEquals(0, jmx.getUpdates()); assertEquals(0, jmx.getRulesFired()); diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java index 178ef0af..51273d7d 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysFailLockTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,33 +22,33 @@ package org.onap.policy.drools.core.lock; import static org.assertj.core.api.Assertions.assertThatCode; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -public class AlwaysFailLockTest extends AlwaysLockBaseTest { +class AlwaysFailLockTest extends AlwaysLockBaseTest { - @Before + @BeforeEach public void setUp() { callback = mock(LockCallback.class); lock = new AlwaysFailLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback); } @Test - public void testAlwaysFailLockNoArgs() { + void testAlwaysFailLockNoArgs() { assertThatCode(AlwaysFailLock::new).doesNotThrowAnyException(); } @Test - public void testUnavailableLock() { + void testUnavailableLock() { assertTrue(lock.isUnavailable()); } @Test - public void testFree() { + void testFree() { assertFalse(lock.free()); assertTrue(lock.isUnavailable()); } diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysLockBaseTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysLockBaseTest.java index b5f7a64c..347ff874 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysLockBaseTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysLockBaseTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.core.lock; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import org.junit.Test; +import org.junit.jupiter.api.Test; public abstract class AlwaysLockBaseTest { protected static final String RESOURCE = "hello"; diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java index 32889484..80f81f92 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/AlwaysSuccessLockTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,24 +23,24 @@ package org.onap.policy.drools.core.lock; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.mock; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -public class AlwaysSuccessLockTest extends AlwaysLockBaseTest { +class AlwaysSuccessLockTest extends AlwaysLockBaseTest { - @Before + @BeforeEach public void setUp() { callback = mock(LockCallback.class); lock = new AlwaysSuccessLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback); } @Test - public void testAlwaysSuccessLockConstructors() { + void testAlwaysSuccessLockConstructors() { assertThatCode(AlwaysSuccessLock::new).doesNotThrowAnyException(); assertThatCode(() -> new AlwaysSuccessLock(LockState.ACTIVE, RESOURCE, OWNER_KEY, HOLD_SEC, callback)) .doesNotThrowAnyException(); @@ -48,18 +49,18 @@ public class AlwaysSuccessLockTest extends AlwaysLockBaseTest } @Test - public void testActiveLock() { + void testActiveLock() { assertTrue(lock.isActive()); } @Test - public void testFree() { + void testFree() { assertTrue(lock.free()); assertTrue(lock.isActive()); } @Test - public void testExtend() { + void testExtend() { LockCallback callback2 = mock(LockCallback.class); lock.extend(HOLD_SEC2, callback2); diff --git a/policy-core/src/test/java/org/onap/policy/drools/core/lock/LockImplTest.java b/policy-core/src/test/java/org/onap/policy/drools/core/lock/LockImplTest.java index 56cd5090..f16d9c4e 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/core/lock/LockImplTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/core/lock/LockImplTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +25,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 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.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -40,10 +41,10 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -public class LockImplTest { +class LockImplTest { private static final LockState STATE = LockState.WAITING; private static final String RESOURCE = "hello"; private static final String OWNER_KEY = "world"; @@ -57,7 +58,7 @@ public class LockImplTest { /** * Populates {@link #lock}. */ - @Before + @BeforeEach public void setUp() { callback = mock(LockCallback.class); @@ -65,7 +66,7 @@ public class LockImplTest { } @Test - public void testSerializable() throws Exception { + void testSerializable() throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (ObjectOutputStream oos = new ObjectOutputStream(baos)) { oos.writeObject(lock); @@ -86,7 +87,7 @@ public class LockImplTest { } @Test - public void testLockImplNoArgs() { + void testLockImplNoArgs() { // use no-arg constructor lock = new LockImpl(); assertEquals(LockState.UNAVAILABLE, lock.getState()); @@ -97,7 +98,7 @@ public class LockImplTest { } @Test - public void testLockImpl_testGetters() { + void testLockImpl_testGetters() { assertEquals(STATE, lock.getState()); assertEquals(RESOURCE, lock.getResourceId()); assertEquals(OWNER_KEY, lock.getOwnerKey()); @@ -118,7 +119,7 @@ public class LockImplTest { } @Test - public void testFree() { + void testFree() { assertTrue(lock.free()); assertTrue(lock.isUnavailable()); @@ -132,7 +133,7 @@ public class LockImplTest { } @Test - public void testExtend() { + void testExtend() { lock.setState(LockState.WAITING); LockCallback callback2 = mock(LockCallback.class); @@ -181,7 +182,7 @@ public class LockImplTest { } @Test - public void testNotifyAvailable() { + void testNotifyAvailable() { lock.notifyAvailable(); verify(callback).lockAvailable(any()); @@ -189,7 +190,7 @@ public class LockImplTest { } @Test - public void testNotifyAvailable_Ex() { + void testNotifyAvailable_Ex() { doThrow(new IllegalArgumentException(EXPECTED_EXCEPTION)).when(callback).lockAvailable(any()); doThrow(new IllegalArgumentException(EXPECTED_EXCEPTION)).when(callback).lockUnavailable(any()); @@ -198,7 +199,7 @@ public class LockImplTest { } @Test - public void testNotifyUnavailable() { + void testNotifyUnavailable() { lock.notifyUnavailable(); verify(callback, never()).lockAvailable(any()); @@ -206,7 +207,7 @@ public class LockImplTest { } @Test - public void testNotifyUnavailable_Ex() { + void testNotifyUnavailable_Ex() { doThrow(new IllegalArgumentException(EXPECTED_EXCEPTION)).when(callback).lockAvailable(any()); doThrow(new IllegalArgumentException(EXPECTED_EXCEPTION)).when(callback).lockUnavailable(any()); @@ -215,7 +216,7 @@ public class LockImplTest { } @Test - public void testSetState_testIsActive_testIsWaiting_testIsUnavailable() { + void testSetState_testIsActive_testIsWaiting_testIsUnavailable() { lock.setState(LockState.WAITING); assertEquals(LockState.WAITING, lock.getState()); assertFalse(lock.isActive()); @@ -236,7 +237,7 @@ public class LockImplTest { } @Test - public void testSetHoldSec() { + void testSetHoldSec() { assertEquals(HOLD_SEC, lock.getHoldSec()); lock.setHoldSec(HOLD_SEC2); @@ -244,7 +245,7 @@ public class LockImplTest { } @Test - public void testSetCallback() { + void testSetCallback() { assertSame(callback, lock.getCallback()); LockCallback callback2 = mock(LockCallback.class); @@ -253,7 +254,7 @@ public class LockImplTest { } @Test - public void testToString() { + void testToString() { String text = lock.toString(); assertNotNull(text); diff --git a/policy-core/src/test/java/org/onap/policy/drools/util/FeatureEnabledCheckerTest.java b/policy-core/src/test/java/org/onap/policy/drools/util/FeatureEnabledCheckerTest.java index c118b897..454544a6 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/util/FeatureEnabledCheckerTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/util/FeatureEnabledCheckerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,18 +21,18 @@ package org.onap.policy.drools.util; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Properties; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class FeatureEnabledCheckerTest { +class FeatureEnabledCheckerTest { private static final String PROP_NAME = "enable.it"; @Test - public void test() { + void test() { assertFalse(check(null)); assertTrue(check(true)); assertFalse(check(false)); diff --git a/policy-core/src/test/java/org/onap/policy/drools/util/KieUtilsTest.java b/policy-core/src/test/java/org/onap/policy/drools/util/KieUtilsTest.java index 1622a2b9..7089fdad 100644 --- a/policy-core/src/test/java/org/onap/policy/drools/util/KieUtilsTest.java +++ b/policy-core/src/test/java/org/onap/policy/drools/util/KieUtilsTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +21,9 @@ package org.onap.policy.drools.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import java.io.IOException; import java.net.URL; @@ -32,8 +33,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.stream.Collectors; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.kie.api.builder.ReleaseId; import org.kie.api.definition.KiePackage; import org.kie.api.definition.rule.Rule; @@ -51,7 +52,7 @@ public class KieUtilsTest { /** * Test class initialization. */ - @BeforeClass + @BeforeAll public static void createArtifact() throws Exception { ReleaseId releaseId = KieUtils.installArtifact( @@ -65,7 +66,7 @@ public class KieUtilsTest { } @Test - public void testInstallArtifact() throws IOException { + void testInstallArtifact() throws IOException { ReleaseId releaseId = KieUtils.installArtifact( Paths.get("src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml").toFile(), @@ -77,7 +78,7 @@ public class KieUtilsTest { } @Test - public void testInstallArtifactList() throws IOException { + void testInstallArtifactList() throws IOException { ReleaseId releaseId = KieUtils.installArtifact( Paths.get("src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml").toFile(), @@ -90,41 +91,41 @@ public class KieUtilsTest { } @Test - public void getBases() { + void getBases() { assertEquals(Collections.singletonList("rules"), KieUtils.getBases(container)); } @Test - public void getPackages() { + void getPackages() { assertEquals(Arrays.asList("java.util", "java.util.concurrent", "org.onap.policy.drools.core.test"), KieUtils.getPackages(container).stream().map(KiePackage::getName).collect(Collectors.toList())); } @Test - public void getPackageNames() { + void getPackageNames() { assertEquals(Arrays.asList("java.util", "java.util.concurrent", "org.onap.policy.drools.core.test"), new ArrayList<>(KieUtils.getPackageNames(container))); } @Test - public void getRules() { + void getRules() { assertEquals(Arrays.asList("Initialization", "Add elements of an int list"), KieUtils.getRules(container).stream().map(Rule::getName).collect(Collectors.toList())); } @Test - public void getRuleNames() { + void getRuleNames() { assertEquals(Arrays.asList("Initialization", "Add elements of an int list"), - KieUtils.getRuleNames(container).stream().collect(Collectors.toList())); + new ArrayList<>(KieUtils.getRuleNames(container))); } @Test - public void getFacts() { + void getFacts() { assertEquals(0, KieUtils.getFacts(session).size()); } @Test - public void testResourceToPackages() { + void testResourceToPackages() { // Some minimal logging -- it would be nice to verify the 'KieUtils' logger messages StringBuffer log; @@ -156,7 +157,7 @@ public class KieUtilsTest { @Override public Enumeration getResources(String name) throws IOException { if ("BogusUrl".equals(name)) { - return new Enumeration() { + return new Enumeration<>() { @Override public boolean hasMoreElements() { return true; diff --git a/policy-core/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml b/policy-core/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml index 22319689..2ab03fcf 100644 --- a/policy-core/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml +++ b/policy-core/src/test/resources/drools-artifact-1.1/src/main/resources/META-INF/kmodule.xml @@ -1,5 +1,5 @@ - + diff --git a/policy-core/src/test/resources/drools-artifact-1.2/src/main/resources/META-INF/kmodule.xml b/policy-core/src/test/resources/drools-artifact-1.2/src/main/resources/META-INF/kmodule.xml index 22319689..2ab03fcf 100644 --- a/policy-core/src/test/resources/drools-artifact-1.2/src/main/resources/META-INF/kmodule.xml +++ b/policy-core/src/test/resources/drools-artifact-1.2/src/main/resources/META-INF/kmodule.xml @@ -1,5 +1,5 @@ - + diff --git a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DomainPolicyTypesTest.java b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DomainPolicyTypesTest.java index d7692fc0..3d1e8490 100644 --- a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DomainPolicyTypesTest.java +++ b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DomainPolicyTypesTest.java @@ -22,16 +22,16 @@ package org.onap.policy.drools.domain.models; 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.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.worldturner.medeia.api.ValidationFailedException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.ResourceUtils; @@ -45,7 +45,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -public class DomainPolicyTypesTest { +class DomainPolicyTypesTest { // Policy Types private static final String NATIVE_DROOLS_POLICY_TYPE = "onap.policies.native.drools.Artifact"; @@ -63,14 +63,14 @@ public class DomainPolicyTypesTest { private DomainMaker domainMaker; private StandardCoder nonValCoder; - @Before + @BeforeEach public void setUp() { domainMaker = new DomainMaker(); nonValCoder = new StandardCoder(); } @Test - public void testToscaNativeDroolsPolicy() throws CoderException, IOException { + void testToscaNativeDroolsPolicy() throws CoderException, IOException { String rawNativeDroolsPolicy = getPolicyFromFileString(); ToscaPolicy toscaPolicy = @@ -122,7 +122,7 @@ public class DomainPolicyTypesTest { } @Test - public void testToscaControllerPolicy() throws CoderException { + void testToscaControllerPolicy() throws CoderException { ToscaPolicy toscaPolicy = getExamplesPolicy(EXAMPLE_CONTROLLER_DROOLS_POLICY_JSON, EXAMPLE_CONTROLLER_DROOLS_POLICY_NAME); diff --git a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DroolsPolicyTest.java b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DroolsPolicyTest.java index 98ddd4c8..99494d71 100644 --- a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DroolsPolicyTest.java +++ b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/DroolsPolicyTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,26 +30,28 @@ import com.openpojo.validation.Validator; import com.openpojo.validation.ValidatorBuilder; import com.openpojo.validation.test.impl.GetterTester; import com.openpojo.validation.test.impl.SetterTester; +import java.io.Serial; import java.io.Serializable; import java.util.List; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class DroolsPolicyTest { +class DroolsPolicyTest { @Data @SuperBuilder @NoArgsConstructor @EqualsAndHashCode(callSuper = true) public static class DerivedDomainPolicy extends DroolsPolicy implements Serializable { + @Serial private static final long serialVersionUID = -1027974819756498893L; } @Test - public void testDerivedClass() { + void testDerivedClass() { /* validate model pojos */ Validator validator = ValidatorBuilder.create() .with(new SetterTester(), new GetterTester()).build(); @@ -57,7 +60,7 @@ public class DroolsPolicyTest { } @Test - public void testPackage() { + void testPackage() { /* validate model pojos */ List pojoClasses = PojoClassFactory diff --git a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/artifact/ArtifactPolicyTest.java b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/artifact/ArtifactPolicyTest.java index b4c71f0d..16a91b67 100644 --- a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/artifact/ArtifactPolicyTest.java +++ b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/artifact/ArtifactPolicyTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.domain.models.artifact; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.domain.models.Metadata; -public class ArtifactPolicyTest { +class ArtifactPolicyTest { @Test - public void testBuildDomainPolicyNativeArtifact() { + void testBuildDomainPolicyNativeArtifact() { /* manually create a native drools policy */ // @formatter:off diff --git a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/controller/ControllerPolicyTest.java b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/controller/ControllerPolicyTest.java index d24a8f70..05e85b84 100644 --- a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/controller/ControllerPolicyTest.java +++ b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/controller/ControllerPolicyTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +21,16 @@ package org.onap.policy.drools.domain.models.controller; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.util.ArrayList; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.domain.models.Metadata; -public class ControllerPolicyTest { +class ControllerPolicyTest { @Test - public void testBuildDomainPolicyController() { + void testBuildDomainPolicyController() { /* manually create a controller policy */ // @formatter:off diff --git a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/operational/OperationalPolicyTest.java b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/operational/OperationalPolicyTest.java index 91e8acc1..8168e75a 100644 --- a/policy-domains/src/test/java/org/onap/policy/drools/domain/models/operational/OperationalPolicyTest.java +++ b/policy-domains/src/test/java/org/onap/policy/drools/domain/models/operational/OperationalPolicyTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,12 +21,12 @@ package org.onap.policy.drools.domain.models.operational; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.resources.ResourceUtils; @@ -36,7 +36,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -public class OperationalPolicyTest { +class OperationalPolicyTest { // Policy Types private static final String OPERATIONAL_DROOLS_POLICY_TYPE = "onap.policies.controlloop.operational.common.Drools"; @@ -48,15 +48,15 @@ public class OperationalPolicyTest { private DomainMaker domainMaker; private StandardCoder nonValCoder; - @Before + @BeforeEach public void setUp() { domainMaker = new DomainMaker(); nonValCoder = new StandardCoder(); } @Test - public void testToscaCompliantOperationalPolicyType() throws CoderException { - String rawVcpeToscaPolicy = getExamplesPolicyString(VCPE_OPERATIONAL_DROOLS_POLICY_JSON, OP_POLICY_NAME_VCPE); + void testToscaCompliantOperationalPolicyType() throws CoderException { + String rawVcpeToscaPolicy = getExamplesPolicyString(); // valid "known" policy type with implicit schema ToscaConceptIdentifier operationalCompliantType = @@ -66,7 +66,7 @@ public class OperationalPolicyTest { } @Test - public void testOperationalCompliantModel() { + void testOperationalCompliantModel() { // @formatter:off OperationalPolicy policy = OperationalPolicy.builder() @@ -100,17 +100,15 @@ public class OperationalPolicyTest { assertNotNull(policy); } - private String getJsonFromResource(String resourcePath) { - return ResourceUtils.getResourceAsString(resourcePath); - } - - private ToscaPolicy getExamplesPolicy(String resourcePath, String policyName) throws CoderException { - String policyJson = getJsonFromResource(resourcePath); + private ToscaPolicy getExamplesPolicy() throws CoderException { + String policyJson = ResourceUtils + .getResourceAsString(OperationalPolicyTest.VCPE_OPERATIONAL_DROOLS_POLICY_JSON); ToscaServiceTemplate serviceTemplate = new StandardCoder().decode(policyJson, ToscaServiceTemplate.class); - return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName); + return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get( + OperationalPolicyTest.OP_POLICY_NAME_VCPE); } - private String getExamplesPolicyString(String resourcePath, String policyName) throws CoderException { - return nonValCoder.encode(getExamplesPolicy(resourcePath, policyName)); + private String getExamplesPolicyString() throws CoderException { + return nonValCoder.encode(getExamplesPolicy()); } } diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java index 0c732246..1965e22f 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/IndexedDroolsControllerFactory.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -59,6 +59,11 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { */ protected Map droolsControllers = new HashMap<>(); + /** + * Null Drools Controller. + */ + protected NullDroolsController nullDroolsController = new NullDroolsController(); + /** * Constructs the object. */ @@ -259,12 +264,6 @@ class IndexedDroolsControllerFactory implements DroolsControllerFactory { } else { return PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + "."; } - } else if (commInfra == CommInfrastructure.DMAAP) { - if (isSource) { - return PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "."; - } else { - return PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + "."; - } } else if (commInfra == CommInfrastructure.NOOP) { if (isSource) { return PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS + "."; diff --git a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java index e93adec5..68a69159 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java +++ b/policy-management/src/main/java/org/onap/policy/drools/controller/internal/MavenDroolsController.java @@ -119,8 +119,6 @@ public class MavenDroolsController implements DroolsController { /** * original Drools Model/Rules classloader hash. - * -- GETTER -- - * Get model class loader hash. */ @Getter protected int modelClassLoaderHash; @@ -208,7 +206,7 @@ public class MavenDroolsController implements DroolsController { logger.warn("{} UPGRADE results: {}", this, messages); /* - * If all sucessful (can load new container), now we can remove all coders from previous sessions + * If all successful (can load new container), now we can remove all coders from previous sessions */ this.removeCoders(); @@ -533,7 +531,7 @@ public class MavenDroolsController implements DroolsController { this.recentSourceEvents.add(event); } - PdpJmx.getInstance().updateOccured(); + PdpJmx.getInstance().updateOccurred(); // Broadcast diff --git a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java index f3a422e7..76836ba2 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java +++ b/policy-management/src/main/java/org/onap/policy/drools/protocol/configuration/PdpdConfiguration.java @@ -3,6 +3,7 @@ * policy-management * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -56,7 +57,8 @@ public class PdpdConfiguration { @GsonJsonProperty("controllers") private List controllers = new ArrayList<>(); - @GsonJsonIgnore private Map additionalProperties = new HashMap<>(); + @GsonJsonIgnore + private final Map additionalProperties = new HashMap<>(); /** * Constructor. @@ -163,32 +165,30 @@ public class PdpdConfiguration { } protected boolean declaredProperty(String name, Object value) { - switch (name) { - case "requestID": + return switch (name) { + case "requestID" -> { callSetRequestId(value); - return true; - case "entity": + yield true; + } + case "entity" -> { callSetEntity(value); - return true; - case "controllers": + yield true; + } + case "controllers" -> { callSetControllers(value); - return true; - default: - return false; - } + yield true; + } + default -> false; + }; } protected Object declaredPropertyOrNotFound(String name, Object notFoundValue) { - switch (name) { - case "requestID": - return getRequestId(); - case "entity": - return getEntity(); - case "controllers": - return getControllers(); - default: - return notFoundValue; - } + return switch (name) { + case "requestID" -> getRequestId(); + case "entity" -> getEntity(); + case "controllers" -> getControllers(); + default -> notFoundValue; + }; } /** @@ -273,7 +273,7 @@ public class PdpdConfiguration { "property \"controllers\" is of type " + "\"java.util.List\", " + "but got " - + value.getClass().toString()); + + value.getClass()); } } } diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java index ad23ff3a..ecc6c083 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java +++ b/policy-management/src/main/java/org/onap/policy/drools/server/restful/RestManager.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021,2023 Nordix Foundation. + * Modifications Copyright (C) 2021, 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1392,7 +1392,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}") public Response commSources( @PathParam("comm") String comm) { if (!checkValidNameInput(comm)) { @@ -1408,9 +1408,6 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA case UEB: sources.addAll(TopicEndpointManager.getManager().getUebTopicSources()); break; - case DMAAP: - sources.addAll(TopicEndpointManager.getManager().getDmaapTopicSources()); - break; case NOOP: sources.addAll(TopicEndpointManager.getManager().getNoopTopicSources()); break; @@ -1430,7 +1427,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}") public Response commSinks( @PathParam("comm") String comm) { if (!checkValidNameInput(comm)) { @@ -1446,9 +1443,6 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA case UEB: sinks.addAll(TopicEndpointManager.getManager().getUebTopicSinks()); break; - case DMAAP: - sinks.addAll(TopicEndpointManager.getManager().getDmaapTopicSinks()); - break; case NOOP: sinks.addAll(TopicEndpointManager.getManager().getNoopTopicSinks()); break; @@ -1468,7 +1462,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}") public Response sourceTopic( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1484,7 +1478,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}") public Response sinkTopic( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1500,7 +1494,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/events") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/events") public Response sourceEvents( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1516,7 +1510,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/events") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/events") public Response sinkEvents( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1532,7 +1526,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/switches") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/switches") public Response commSourceTopicSwitches( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1544,7 +1538,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @GET - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/switches") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/switches") public Response commSinkTopicSwitches( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1556,7 +1550,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @PUT - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/switches/lock") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/switches/lock") public Response commSourceTopicLock( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1570,7 +1564,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @DELETE - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/switches/lock") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/switches/lock") public Response commSourceTopicUnlock( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1584,7 +1578,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @PUT - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/switches/activation") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/switches/activation") public Response commSourceTopicActivation( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1598,7 +1592,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @DELETE - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/switches/activation") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/switches/activation") public Response commSourceTopicDeactivation( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1612,7 +1606,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @PUT - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/switches/lock") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/switches/lock") public Response commSinkTopicLock( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1626,7 +1620,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @DELETE - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/switches/lock") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/switches/lock") public Response commSinkTopicUnlock( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1640,7 +1634,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @PUT - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/switches/activation") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/switches/activation") public Response commSinkTopicActivation( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1654,7 +1648,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @DELETE - @Path("engine/topics/sinks/{comm: ueb|dmaap|noop}/{topic}/switches/activation") + @Path("engine/topics/sinks/{comm: ueb|kafka|noop}/{topic}/switches/activation") public Response commSinkTopicDeactivation( @PathParam("comm") String comm, @PathParam("topic") String topic) { @@ -1682,7 +1676,7 @@ public class RestManager implements SwaggerApi, DefaultApi, FeaturesApi, InputsA */ @Override @PUT - @Path("engine/topics/sources/{comm: ueb|dmaap|noop}/{topic}/events") + @Path("engine/topics/sources/{comm: ueb|kafka|noop}/{topic}/events") @Consumes(MediaType.TEXT_PLAIN) public Response commEventOffer( @PathParam("comm") String comm, diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafBase.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafBase.java deleted file mode 100644 index 67725955..00000000 --- a/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafBase.java +++ /dev/null @@ -1,35 +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.server.restful.aaf; - -import org.onap.policy.common.endpoints.http.server.aaf.AafAuthFilter; -import org.onap.policy.drools.system.PolicyEngineConstants; - -/** - * AAF Base Class. - */ -public abstract class AafBase extends AafAuthFilter { - public static final String AAF_NODETYPE = "pdpd"; - public static final String AAF_ROOT_PERMISSION_PROPERTY = "aaf.root.permission"; - public static final String AAF_ROOT_PERMISSION = - PolicyEngineConstants.getManager().getProperties().getProperty( - AAF_ROOT_PERMISSION_PROPERTY, DEFAULT_NAMESPACE + "." + AAF_NODETYPE); -} diff --git a/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafTelemetryAuthFilter.java b/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafTelemetryAuthFilter.java deleted file mode 100644 index 1f7ef8c3..00000000 --- a/policy-management/src/main/java/org/onap/policy/drools/server/restful/aaf/AafTelemetryAuthFilter.java +++ /dev/null @@ -1,41 +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.server.restful.aaf; - -import jakarta.servlet.http.HttpServletRequest; -import org.onap.policy.common.utils.network.NetworkUtil; - -/** - * AAF Telemetry Authorization. - */ -public class AafTelemetryAuthFilter extends AafBase { - private static final String RESOURCE_TYPE = AAF_ROOT_PERMISSION + "." + "telemetry"; - - @Override - protected String getPermissionType(HttpServletRequest request) { - return RESOURCE_TYPE; - } - - @Override - protected String getPermissionInstance(HttpServletRequest request) { - return NetworkUtil.getHostname(); - } -} diff --git a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java index 43ab5e47..0bc2318b 100644 --- a/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java +++ b/policy-management/src/main/java/org/onap/policy/drools/system/PolicyEngineManager.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -85,7 +86,6 @@ import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants; import org.onap.policy.drools.protocol.configuration.ControllerConfiguration; import org.onap.policy.drools.protocol.configuration.PdpdConfiguration; import org.onap.policy.drools.server.restful.RestManager; -import org.onap.policy.drools.server.restful.aaf.AafTelemetryAuthFilter; import org.onap.policy.drools.stats.PolicyStatsManager; import org.onap.policy.drools.system.internal.SimpleLockManager; import org.onap.policy.drools.utils.PropertyUtil; @@ -408,11 +408,6 @@ class PolicyEngineManager implements PolicyEngine { try { this.httpServers = getServletFactory().build(properties); - for (HttpServletServer server : this.httpServers) { - if (server.isAaf()) { - server.addFilterClass(null, AafTelemetryAuthFilter.class.getName()); - } - } } catch (final IllegalArgumentException e) { logger.error("{}: add-http-servers failed", this, e); } diff --git a/policy-management/src/main/resources/openapi/openapi.yaml b/policy-management/src/main/resources/openapi/openapi.yaml index a763150b..80a3ae63 100644 --- a/policy-management/src/main/resources/openapi/openapi.yaml +++ b/policy-management/src/main/resources/openapi/openapi.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2023 Nordix Foundation +# Copyright (C) 2023-2024 Nordix Foundation # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -3207,8 +3207,6 @@ components: properties: prometheus: type: boolean - aaf: - type: boolean name: type: string port: diff --git a/policy-management/src/main/resources/swagger/swagger.json b/policy-management/src/main/resources/swagger/swagger.json index f26a1bfe..9fb709b9 100644 --- a/policy-management/src/main/resources/swagger/swagger.json +++ b/policy-management/src/main/resources/swagger/swagger.json @@ -4593,9 +4593,6 @@ "prometheus" : { "type" : "boolean" }, - "aaf" : { - "type" : "boolean" - }, "name" : { "type" : "string" }, diff --git a/policy-management/src/main/server-gen/bin/add-secured-participant b/policy-management/src/main/server-gen/bin/add-secured-participant index edd92e10..3ddc120f 100644 --- a/policy-management/src/main/server-gen/bin/add-secured-participant +++ b/policy-management/src/main/server-gen/bin/add-secured-participant @@ -5,6 +5,7 @@ # policy-management # ================================================================================ # Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -72,7 +73,7 @@ until [ -z "$1" ]; do done if [ -z "${BUS_HOST}" ]; then - echo "An UEB/DMAAP server must be provided." + echo "An UEB/KAFKA server must be provided." echo usage exit 1 diff --git a/policy-management/src/main/server-gen/bin/create-api-key b/policy-management/src/main/server-gen/bin/create-api-key index 7870265e..e57c1e92 100644 --- a/policy-management/src/main/server-gen/bin/create-api-key +++ b/policy-management/src/main/server-gen/bin/create-api-key @@ -5,6 +5,7 @@ # policy-management # ================================================================================ # Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -52,7 +53,7 @@ until [ -z "$1" ]; do done if [ -z "${BUS_HOST}" ]; then - echo "An UEB/DMAAP server must be provided." + echo "An UEB/KAFKA server must be provided." echo usage exit 1 diff --git a/policy-management/src/main/server-gen/bin/create-secured-topic b/policy-management/src/main/server-gen/bin/create-secured-topic index f906bb55..2aed99ae 100644 --- a/policy-management/src/main/server-gen/bin/create-secured-topic +++ b/policy-management/src/main/server-gen/bin/create-secured-topic @@ -5,6 +5,7 @@ # policy-management # ================================================================================ # Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -71,7 +72,7 @@ until [ -z "$1" ]; do done if [ -z "${BUS_HOST}" ]; then - echo "An UEB/DMAAP server must be provided." + echo "An UEB/KAFKA server must be provided." echo usage exit 1 diff --git a/policy-management/src/main/server-gen/bin/pdpd-configuration b/policy-management/src/main/server-gen/bin/pdpd-configuration index c3fb43b5..5182f3ad 100644 --- a/policy-management/src/main/server-gen/bin/pdpd-configuration +++ b/policy-management/src/main/server-gen/bin/pdpd-configuration @@ -4,6 +4,7 @@ # ONAP # ================================================================================ # Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -37,7 +38,7 @@ function usage() { echo "" } -BUS_PORT=3904 +BUS_PORT=9092 REQUEST_ID="7f5474ca-16a9-42ac-abc0-d86f62296fbc" TOPIC="PDPD-CONFIGURATION" @@ -87,7 +88,7 @@ until [ -z "$1" ]; do done if [ -z "${BUS_HOST}" ]; then - echo "An UEB/DMAAP server must be provided." + echo "An UEB/KAFKA server must be provided." echo usage exit 1 diff --git a/policy-management/src/main/server/config/aaf-cadi.keyfile b/policy-management/src/main/server/config/aaf-cadi.keyfile deleted file mode 100644 index 59d544f3..00000000 --- a/policy-management/src/main/server/config/aaf-cadi.keyfile +++ /dev/null @@ -1,27 +0,0 @@ -N3INM2bAlQ8cNODnjR3Fuvo5z4GeID0KnRYlELmt-oHCFxq_XYVyepBVR591CIbJI9prNd_LLuv7 -tQD8xX_ypcNA-jQsecTwtw4GxvpqkZPhq6Q8BWNQaCegtXGDVTQ8gG2biKiQ7v-2C6Qhx4zj62b6 -bRPS5j1bfxqcAZu7082V00oQjbn40T2zFcLwCuBChZfx5DXTW49bwtLbkCbGqJSzFcIJpbGQ8gLg -ussIoL8VE2Vee7bPJmUAdT4x9B1wrMIuvKlUMppeq0Bj-6ZJgxhM9F0WT8eEBh6NFANdK3LUgZrk -D3kY3LrK-MT9u1TOMx13nOU7vOaVjl7_rkp5Q65gFd9VYbnJBYvJcc7asOQMsrugiSiRIoXH0Fyy --f9L3ROGae042J4M8qxcoOihMbcjVkEXqn6eRIFbDe0eIAlkSRYfaxg9v4tf8GbBjQcShBjzGaI2 -g6QxTA5G6Aa7p63aVRGv3ZODCHcbsbxnkyByXgmkON4cTk9vR0RbT6YYhT5t8xTU3rhqV3jeE0Bz -KbU0c4188xTnhdq_bje2TuuLvtEvevdvDsbtAj7chQmWMOW7GMF3MnqdEpcw1NCoNRdN8wpAdE-5 -mkG-jlYHljSRh9qZK5wdEoO4IXgpFktdGj50XuzcskqqURNfDGHGb29fHznL1-ssdQK6EXcKN0AU -nYyGLAie3VfFxWKj5dGODBs5RttvkX4PHyLcLD3kOrVgtQrz7d0PWWYCxDRqKT6qnJkLB1CUwghn -XweEiDfoQmuUmwFEQNRDp0NGLnde5nsw7NYgLrv5VafGK8EyT4GeVhuu5Tnb6T-HalxCq2p5JaIA -SG8zlDmRx_TykrhfQEJe7sr0pRcAMwgxEhwunG2oBiKnzdRx5jxMfqnVC8xGirumhmOQNterfnd5 -0pIsfvIuntyxRQ48yzIb2gb5kaSkfSzCaVnlqK-_jpj1T74qO86eaKVee4faQAbXDPYF2z5w06nD -WS2dd54wBjGmkFNzi13ejTrAJeA6UzOd1CF_WSpc9XSJJPTPUGxmnfLjmGThErFBYuQxjhpH7vKN -uZgokkIXX78rVcO3zpfa5kTYWjE8lk9y3WA7sGNtTWfG8bR3WLWNLPCnrzxtKZdhq2JsQYC0gwW7 -ZgJSXhgPoaC_RrtCn7haj1_601G_MkD-jcUEsO-4XOBVicsCgG8hn7B-SpgKspqv8gulbeKoORqa -CkrtiFPlXEqdNuaBSHcQ0MWJ3tpXzWtIPM3ouEFOR32xVfptfz4sRPOkM_PNiVXxQtLOn_z3uC7K -VVJCKZxVaavQ6QiZvRRANS9_GD3kDILX15EnbEvh-2DfycDrEo330vMwvNJP7i9eM5vo0YADe--G -r5UDqctmFjl1ulc1yAQkDBGWGxT92x-hhLqCnCXcYPu_aeWssfDpRj573PHPaTiM0SYxJixjszRD -6-AMC1DqugkjiGA5_enQORn-G_H4ZVtoQ_zebizEfIxKv5-8uRdyZDHGG3mDu6_nasEffry-UyVu -STU3oJMycZ1qf5GR1evRJ7gxkrtPXHWKNnVgxfrBC72ON6wJnr7KaY-l9L44epIsk1pEmXm3YQu1 -N0NxiAwdus9OnCXQ7GgZPRXCpxjJPNs7EIKFrYjKJfdtSzT85ZrTpHQtjim2L1ZP9iIlq2QVKD1v -bKSjCwjtb9ztjrV-Bw1BHcAApPcfpXHLhYkJ7iL1XUhxjXp_DGUkD7ZN9S5tuyrsMXz5hh6wMfcq -NPR_XqHaS2ur-ONNrHuFFCmY7Ehc5FArFzb_Xn1JTpOQJTcy6_3r3u3B_euT8GmXHahtVN1Rv8RM -kAD5m_UBx-nHoZDVDYZkfR9k4hF2Sz5rfrWs6Zrl0r8FBrVFtU1j2vOTvTGwrkO9yZvgIqOkX_eq -TnGIpM4paHxEGTP8H8A3Y0ZpsvLttmh0rT_OwzBPa1Mof3RQKhyTzfbptxuUJyVxU0Ln-9f--5Mk -wEFqhuSrgssI6b1iMqm97PqFQMYrWX3SV8l0V-PKxFxDM1bguHq4mOXEtmZBUtMBepwSsI96 \ No newline at end of file diff --git a/policy-management/src/main/server/config/aaf-system.properties b/policy-management/src/main/server/config/aaf-system.properties deleted file mode 100644 index 9e64017f..00000000 --- a/policy-management/src/main/server/config/aaf-system.properties +++ /dev/null @@ -1,43 +0,0 @@ -# -# ============LICENSE_START======================================================= -# ONAP -# ================================================================================ -# Copyright (C) 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========================================================= -# - -# AAF related system properties - -aaf_locate_url=https://${env:AAF_HOST}:8095 -aaf_oauth2_introspect_url=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.introspect:2.1/introspect -aaf_oauth2_token_url=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.token:2.1/token -aaf_url=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.service:2.1 -aaf_env=DEV - -cadi_protocols=TLSv1.1,TLSv1.2 -cadi_latitude=38.000 -cadi_longitude=-72.000 -cadi_loglevel=DEBUG - -cadi_x509_issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US -cadi_keyfile=${envd:CADI_KEYFILE:/opt/app/policy/config/aaf-cadi.keyfile} -cadi_keystore=${envd:KEYSTORE:/opt/app/policy/etc/ssl/policy-keystore} -cadi_keystore_password=${envd:KEYSTORE_PASSWD:Pol1cy_0nap} -cadi_key_password=${envd:KEYSTORE_PASSWD:Pol1cy_0nap} -cadi_alias=policy@policy.onap.org -cadi_truststore=${envd:TRUSTSTORE:/opt/app/policy/etc/ssl/policy-truststore} -cadi_truststore_password=${envd:TRUSTSTORE_PASSWD:Pol1cy_0nap} - -cm_url=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.cm:2.1 diff --git a/policy-management/src/main/server/config/engine.properties b/policy-management/src/main/server/config/engine.properties index e30682f4..aa368fe9 100644 --- a/policy-management/src/main/server/config/engine.properties +++ b/policy-management/src/main/server/config/engine.properties @@ -3,6 +3,7 @@ # ONAP # ================================================================================ # Copyright (C) 2019, 2021-2022 AT&T Intellectual Property. All rights reserved. +# Modifications Copyright (C) 2024 Nordix Foundation. # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -30,11 +31,7 @@ http.server.services.CONFIG.restPackages=org.onap.policy.drools.server.restful http.server.services.CONFIG.managed=false http.server.services.CONFIG.swagger=true http.server.services.CONFIG.https=${envd:HTTP_SERVER_HTTPS:false} -http.server.services.CONFIG.aaf=${envd:AAF:false} http.server.services.CONFIG.prometheus=${envd:PROMETHEUS:true} http.server.services.CONFIG.serialization.provider=org.onap.policy.common.gson.JacksonHandler,org.onap.policy.common.endpoints.http.server.YamlJacksonHandler -aaf.namespace=${envd:AAF_NAMESPACE:false} -aaf.root.permission=${envd:AAF_NAMESPACE:org.onap.policy}.pdpd - engine.cluster=${envd:CLUSTER_NAME} diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java index 03301470..93d5ee43 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/DroolsControllerFactoryTest.java @@ -3,6 +3,7 @@ * policy-management * ================================================================================ * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,16 +21,16 @@ package org.onap.policy.drools.controller; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE; import java.util.List; import java.util.Properties; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.controller.internal.NullDroolsController; import org.onap.policy.drools.features.DroolsControllerFeatureApi; import org.onap.policy.drools.properties.DroolsPropertyConstants; @@ -43,7 +44,7 @@ public class DroolsControllerFactoryTest { public static final String TEST_VERSION = "testVersion"; @Test - public void testBuildNullController() { + void testBuildNullController() { Properties droolsProps = new Properties(); DroolsController droolsController = DroolsControllerConstants.getFactory().build(droolsProps, null, null); @@ -53,7 +54,7 @@ public class DroolsControllerFactoryTest { } @Test - public void testGetNullController() { + void testGetNullController() { DroolsController controller = DroolsControllerConstants.getFactory().get(DroolsControllerConstants.NO_GROUP_ID, DroolsControllerConstants.NO_ARTIFACT_ID, DroolsControllerConstants.NO_VERSION); @@ -65,26 +66,26 @@ public class DroolsControllerFactoryTest { } @Test - public void testInventory() { + void testInventory() { List controllers = DroolsControllerConstants.getFactory().inventory(); assertNotNull(controllers); - for (int i = 0; i < controllers.size(); i++) { - if (!isNullController(controllers.get(i)) && !isActualController(controllers.get(i))) { + for (DroolsController controller : controllers) { + if (!isNullController(controller) && !isActualController(controller)) { fail("drools controller is not a null controller"); } } } @Test - public void testShutdown() { + void testShutdown() { DroolsControllerFactory droolsFactory = new IndexedDroolsControllerFactory(); droolsFactory.shutdown(); assertTrue(droolsFactory.inventory().isEmpty()); } @Test - public void testDestroy() { + void testDestroy() { DroolsControllerFactory droolsFactory = new IndexedDroolsControllerFactory(); droolsFactory.destroy(); assertTrue(droolsFactory.inventory().isEmpty()); @@ -107,7 +108,7 @@ public class DroolsControllerFactoryTest { } @Test - public void testControllerType() { + void testControllerType() { DroolsControllerFactory droolsFactory = new IndexedDroolsControllerFactory(); Properties props = new Properties(); diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsController2Test.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsController2Test.java index f91c437a..fdbfab8f 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsController2Test.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsController2Test.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,13 +24,14 @@ package org.onap.policy.drools.controller.internal; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; @@ -41,9 +42,10 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.TreeMap; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.kie.api.KieBase; import org.kie.api.definition.KiePackage; import org.kie.api.definition.rule.Query; @@ -54,7 +56,8 @@ import org.kie.api.runtime.rule.QueryResults; import org.kie.api.runtime.rule.QueryResultsRow; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.utils.services.OrderedServiceImpl; import org.onap.policy.drools.core.PolicyContainer; @@ -69,8 +72,8 @@ import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.CustomGsonCoder; import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration.PotentialCoderFilter; -@RunWith(MockitoJUnitRunner.class) -public class MavenDroolsController2Test { +@ExtendWith(MockitoExtension.class) +class MavenDroolsController2Test { private static final int FACT1_OBJECT = 1000; private static final int FACT3_OBJECT = 1001; @@ -186,113 +189,121 @@ public class MavenDroolsController2Test { private MavenDroolsController drools; + AutoCloseable autoCloseable; + /** * Initializes objects, including the drools controller. */ - @Before + @BeforeEach public void setUp() { - when(droolsProviders.getList()).thenReturn(List.of(prov1, prov2)); + autoCloseable = MockitoAnnotations.openMocks(this); + lenient().when(droolsProviders.getList()).thenReturn(List.of(prov1, prov2)); - when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(true); - when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenReturn(EVENT); + lenient().when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(true); + lenient().when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenReturn(EVENT); - when(kieSess.getFactCount()).thenReturn(FACT_COUNT); - when(kieSess.getFactHandles()).thenReturn(List.of(fact1, fact2, factex, fact3)); - when(kieSess.getFactHandles(any())).thenReturn(List.of(fact1, fact3)); - when(kieSess.getKieBase()).thenReturn(kieBase); - when(kieSess.getQueryResults(QUERY, PARM1, PARM2)).thenReturn(queryResults); + lenient().when(kieSess.getFactCount()).thenReturn(FACT_COUNT); + lenient().when(kieSess.getFactHandles()).thenReturn(List.of(fact1, fact2, factex, fact3)); + lenient().when(kieSess.getFactHandles(any())).thenReturn(List.of(fact1, fact3)); + lenient().when(kieSess.getKieBase()).thenReturn(kieBase); + lenient().when(kieSess.getQueryResults(QUERY, PARM1, PARM2)).thenReturn(queryResults); - when(kieSess.getFactHandle(FACT3_OBJECT)).thenReturn(fact3); + lenient().when(kieSess.getFactHandle(FACT3_OBJECT)).thenReturn(fact3); - when(kieSess.getObject(fact1)).thenReturn(FACT1_OBJECT); - when(kieSess.getObject(fact2)).thenReturn(""); - when(kieSess.getObject(fact3)).thenReturn(FACT3_OBJECT); - when(kieSess.getObject(factex)).thenThrow(RUNTIME_EX); + lenient().when(kieSess.getObject(fact1)).thenReturn(FACT1_OBJECT); + lenient().when(kieSess.getObject(fact2)).thenReturn(""); + lenient().when(kieSess.getObject(fact3)).thenReturn(FACT3_OBJECT); + lenient().when(kieSess.getObject(factex)).thenThrow(RUNTIME_EX); - when(kieBase.getKiePackages()).thenReturn(List.of(pkg1, pkg2)); + lenient().when(kieBase.getKiePackages()).thenReturn(List.of(pkg1, pkg2)); - when(pkg1.getQueries()).thenReturn(List.of(query3)); - when(pkg2.getQueries()).thenReturn(List.of(query2, query1)); + lenient().when(pkg1.getQueries()).thenReturn(List.of(query3)); + lenient().when(pkg2.getQueries()).thenReturn(List.of(query2, query1)); - when(query1.getName()).thenReturn(QUERY); - when(query2.getName()).thenReturn(QUERY2); + lenient().when(query1.getName()).thenReturn(QUERY); + lenient().when(query2.getName()).thenReturn(QUERY2); - when(queryResults.iterator()).thenReturn(List.of(row1, row2).iterator()); + lenient().when(queryResults.iterator()).thenReturn(List.of(row1, row2).iterator()); - when(row1.get(ENTITY)).thenReturn(FACT1_OBJECT); - when(row2.get(ENTITY)).thenReturn(FACT3_OBJECT); + lenient().when(row1.get(ENTITY)).thenReturn(FACT1_OBJECT); + lenient().when(row2.get(ENTITY)).thenReturn(FACT3_OBJECT); - when(row1.getFactHandle(ENTITY)).thenReturn(fact1); - when(row2.getFactHandle(ENTITY)).thenReturn(fact3); + lenient().when(row1.getFactHandle(ENTITY)).thenReturn(fact1); + lenient().when(row2.getFactHandle(ENTITY)).thenReturn(fact3); - when(sess1.getKieSession()).thenReturn(kieSess); - when(sess2.getKieSession()).thenReturn(kieSess2); + lenient().when(sess1.getKieSession()).thenReturn(kieSess); + lenient().when(sess2.getKieSession()).thenReturn(kieSess2); - when(sess1.getName()).thenReturn(SESSION1); - when(sess2.getName()).thenReturn(SESSION2); + lenient().when(sess1.getName()).thenReturn(SESSION1); + lenient().when(sess2.getName()).thenReturn(SESSION2); - when(sess1.getFullName()).thenReturn(FULL_SESSION1); - when(sess2.getFullName()).thenReturn(FULL_SESSION2); + lenient().when(sess1.getFullName()).thenReturn(FULL_SESSION1); + lenient().when(sess2.getFullName()).thenReturn(FULL_SESSION2); - when(container.getClassLoader()).thenReturn(CLASS_LOADER); - when(container.getPolicySessions()).thenReturn(List.of(sess1, sess2)); - when(container.insertAll(EVENT)).thenReturn(true); + lenient().when(container.getClassLoader()).thenReturn(CLASS_LOADER); + lenient().when(container.getPolicySessions()).thenReturn(List.of(sess1, sess2)); + lenient().when(container.insertAll(EVENT)).thenReturn(true); - when(decoder1.getTopic()).thenReturn(TOPIC); - when(decoder2.getTopic()).thenReturn(TOPIC2); + lenient().when(decoder1.getTopic()).thenReturn(TOPIC); + lenient().when(decoder2.getTopic()).thenReturn(TOPIC2); - when(encoder1.getTopic()).thenReturn(TOPIC); - when(encoder2.getTopic()).thenReturn(TOPIC2); + lenient().when(encoder1.getTopic()).thenReturn(TOPIC); + lenient().when(encoder2.getTopic()).thenReturn(TOPIC2); decoders = List.of(decoder1, decoder2); encoders = List.of(encoder1, encoder2); - when(decoder1.getCustomGsonCoder()).thenReturn(gson1); - when(encoder2.getCustomGsonCoder()).thenReturn(gson2); + lenient().when(decoder1.getCustomGsonCoder()).thenReturn(gson1); + lenient().when(encoder2.getCustomGsonCoder()).thenReturn(gson2); - when(filter1a.getCodedClass()).thenReturn(Object.class.getName()); - when(filter1a.getFilter()).thenReturn(jsonFilter1a); + lenient().when(filter1a.getCodedClass()).thenReturn(Object.class.getName()); + lenient().when(filter1a.getFilter()).thenReturn(jsonFilter1a); - when(filter1b.getCodedClass()).thenReturn(String.class.getName()); - when(filter1b.getFilter()).thenReturn(jsonFilter1b); + lenient().when(filter1b.getCodedClass()).thenReturn(String.class.getName()); + lenient().when(filter1b.getFilter()).thenReturn(jsonFilter1b); - when(filter2.getCodedClass()).thenReturn(Integer.class.getName()); - when(filter2.getFilter()).thenReturn(jsonFilter2); + lenient().when(filter2.getCodedClass()).thenReturn(Integer.class.getName()); + lenient().when(filter2.getFilter()).thenReturn(jsonFilter2); - when(decoder1.getCoderFilters()).thenReturn(List.of(filter1a, filter1b)); - when(decoder2.getCoderFilters()).thenReturn(Collections.emptyList()); + lenient().when(decoder1.getCoderFilters()).thenReturn(List.of(filter1a, filter1b)); + lenient().when(decoder2.getCoderFilters()).thenReturn(Collections.emptyList()); - when(encoder1.getCoderFilters()).thenReturn(Collections.emptyList()); - when(encoder2.getCoderFilters()).thenReturn(List.of(filter2)); + lenient().when(encoder1.getCoderFilters()).thenReturn(Collections.emptyList()); + lenient().when(encoder2.getCoderFilters()).thenReturn(List.of(filter2)); - when(sink.getTopic()).thenReturn(TOPIC); - when(sink.send(EVENT_TEXT)).thenReturn(true); + lenient().when(sink.getTopic()).thenReturn(TOPIC); + lenient().when(sink.send(EVENT_TEXT)).thenReturn(true); drools = new MyDrools(GROUP, ARTIFACT, VERSION, null, null); - when(coderMgr.encode(TOPIC, EVENT, drools)).thenReturn(EVENT_TEXT); + lenient().when(coderMgr.encode(TOPIC, EVENT, drools)).thenReturn(EVENT_TEXT); + } + + @AfterEach + void closeMocks() throws Exception { + autoCloseable.close(); } @Test - public void testMavenDroolsController_InvalidArgs() { + void testMavenDroolsController_InvalidArgs() { assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(null, ARTIFACT, VERSION, null, null)) - .withMessageContaining("group"); + .withMessageContaining("group"); assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools("", ARTIFACT, VERSION, null, null)) - .withMessageContaining("group"); + .withMessageContaining("group"); assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, null, VERSION, null, null)) - .withMessageContaining("artifact"); + .withMessageContaining("artifact"); assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, "", VERSION, null, null)) - .withMessageContaining("artifact"); + .withMessageContaining("artifact"); assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, null, null, null)) - .withMessageContaining("version"); + .withMessageContaining("version"); assertThatIllegalArgumentException().isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, "", null, null)) - .withMessageContaining("version"); + .withMessageContaining("version"); } @Test - public void testUpdateToVersion() { + void testUpdateToVersion() { // add coders drools.updateToVersion(GROUP, ARTIFACT, VERSION2, decoders, encoders); @@ -320,7 +331,7 @@ public class MavenDroolsController2Test { } @Test - public void testUpdateToVersion_Unchanged() { + void testUpdateToVersion_Unchanged() { drools.updateToVersion(GROUP, ARTIFACT, VERSION, decoders, encoders); verify(coderMgr, never()).addDecoder(any()); @@ -328,53 +339,53 @@ public class MavenDroolsController2Test { } @Test - public void testUpdateToVersion_InvalidArgs() { + void testUpdateToVersion_InvalidArgs() { assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion(null, ARTIFACT, VERSION, null, null)) - .withMessageContaining("group"); + .isThrownBy(() -> drools.updateToVersion(null, ARTIFACT, VERSION, null, null)) + .withMessageContaining("group"); assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion("", ARTIFACT, VERSION, null, null)) - .withMessageContaining("group"); + .withMessageContaining("group"); assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, null, VERSION, null, null)) - .withMessageContaining("artifact"); + .withMessageContaining("artifact"); assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, "", VERSION, null, null)) - .withMessageContaining("artifact"); + .withMessageContaining("artifact"); assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, null, null, null)) - .withMessageContaining("version"); + .withMessageContaining("version"); assertThatIllegalArgumentException().isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "", null, null)) - .withMessageContaining("version"); + .withMessageContaining("version"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion("no-group-id", ARTIFACT, VERSION, null, null)) - .withMessageContaining("BRAINLESS"); + .isThrownBy(() -> drools.updateToVersion("no-group-id", ARTIFACT, VERSION, null, null)) + .withMessageContaining("BRAINLESS"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion(GROUP, "no-artifact-id", VERSION, null, null)) - .withMessageContaining("BRAINLESS"); + .isThrownBy(() -> drools.updateToVersion(GROUP, "no-artifact-id", VERSION, null, null)) + .withMessageContaining("BRAINLESS"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "no-version", null, null)) - .withMessageContaining("BRAINLESS"); + .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT, "no-version", null, null)) + .withMessageContaining("BRAINLESS"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion(GROUP2, ARTIFACT, VERSION, null, null)) - .withMessageContaining("coordinates must be identical"); + .isThrownBy(() -> drools.updateToVersion(GROUP2, ARTIFACT, VERSION, null, null)) + .withMessageContaining("coordinates must be identical"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT2, VERSION, null, null)) - .withMessageContaining("coordinates must be identical"); + .isThrownBy(() -> drools.updateToVersion(GROUP, ARTIFACT2, VERSION, null, null)) + .withMessageContaining("coordinates must be identical"); } @Test - public void testInitCoders_NullCoders() { + void testInitCoders_NullCoders() { // already constructed with null coders verify(coderMgr, never()).addDecoder(any()); verify(coderMgr, never()).addEncoder(any()); } @Test - public void testInitCoders_NullOrEmptyFilters() { + void testInitCoders_NullOrEmptyFilters() { when(decoder1.getCoderFilters()).thenReturn(Collections.emptyList()); when(decoder2.getCoderFilters()).thenReturn(null); @@ -388,7 +399,7 @@ public class MavenDroolsController2Test { } @Test - public void testInitCoders_GsonClass() { + void testInitCoders_GsonClass() { when(gson1.getClassContainer()).thenReturn(""); when(gson2.getClassContainer()).thenReturn(Long.class.getName()); @@ -400,25 +411,25 @@ public class MavenDroolsController2Test { } @Test - public void testInitCoders_InvalidGsonClass() { + void testInitCoders_InvalidGsonClass() { when(gson1.getClassContainer()).thenReturn(UNKNOWN_CLASS); assertThatIllegalArgumentException() - .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders)) - .withMessageContaining("cannot be retrieved"); + .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders)) + .withMessageContaining("cannot be retrieved"); } @Test - public void testInitCoders_InvalidFilterClass() { + void testInitCoders_InvalidFilterClass() { when(filter2.getCodedClass()).thenReturn(UNKNOWN_CLASS); assertThatIllegalArgumentException() - .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders)) - .withMessageContaining("cannot be retrieved"); + .isThrownBy(() -> new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders)) + .withMessageContaining("cannot be retrieved"); } @Test - public void testInitCoders_Filters() { + void testInitCoders_Filters() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); @@ -458,7 +469,7 @@ public class MavenDroolsController2Test { } @Test - public void testOwnsCoder() { + void testOwnsCoder() { int hc = CLASS_LOADER_HASHCODE; // wrong hash code @@ -478,7 +489,7 @@ public class MavenDroolsController2Test { } @Test - public void testStart_testStop_testIsAlive() { + void testStart_testStop_testIsAlive() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); when(container.start()).thenReturn(true); @@ -525,7 +536,7 @@ public class MavenDroolsController2Test { } @Test - public void testShutdown() { + void testShutdown() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); // start it @@ -546,7 +557,7 @@ public class MavenDroolsController2Test { } @Test - public void testShutdown_Ex() { + void testShutdown_Ex() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); // start it @@ -564,7 +575,7 @@ public class MavenDroolsController2Test { } @Test - public void testHalt() { + void testHalt() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); // start it @@ -584,7 +595,7 @@ public class MavenDroolsController2Test { } @Test - public void testHalt_Ex() { + void testHalt_Ex() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders); // start it @@ -601,7 +612,7 @@ public class MavenDroolsController2Test { } @Test - public void testRemoveCoders_Ex() { + void testRemoveCoders_Ex() { drools = new MyDrools(GROUP, ARTIFACT, VERSION, decoders, encoders) { @Override protected void removeDecoders() { @@ -618,7 +629,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferStringString() { + void testOfferStringString() { drools.start(); assertTrue(drools.offer(TOPIC, EVENT_TEXT)); @@ -626,7 +637,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferStringString_NoDecode() { + void testOfferStringString_NoDecode() { when(coderMgr.isDecodingSupported(GROUP, ARTIFACT, TOPIC)).thenReturn(false); drools.start(); @@ -636,9 +647,9 @@ public class MavenDroolsController2Test { } @Test - public void testOfferStringString_DecodeUnsupported() { + void testOfferStringString_DecodeUnsupported() { when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)) - .thenThrow(new UnsupportedOperationException(EXPECTED_EXCEPTION)); + .thenThrow(new UnsupportedOperationException(EXPECTED_EXCEPTION)); drools.start(); assertTrue(drools.offer(TOPIC, EVENT_TEXT)); @@ -647,7 +658,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferStringString_DecodeEx() { + void testOfferStringString_DecodeEx() { when(coderMgr.decode(GROUP, ARTIFACT, TOPIC, EVENT_TEXT)).thenThrow(RUNTIME_EX); drools.start(); @@ -657,7 +668,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferStringString_Ignored() { + void testOfferStringString_Ignored() { drools.start(); drools.lock(); @@ -677,7 +688,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT() { + void testOfferT() { drools.start(); assertTrue(drools.offer(EVENT)); assertEquals(1, drools.getRecentSourceEvents().length); @@ -692,7 +703,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT_Ex() { + void testOfferT_Ex() { when(prov1.beforeInsert(drools, EVENT)).thenThrow(RUNTIME_EX); when(prov1.afterInsert(drools, EVENT, true)).thenThrow(RUNTIME_EX); @@ -709,7 +720,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT_NotInserted() { + void testOfferT_NotInserted() { when(container.insertAll(EVENT)).thenReturn(false); drools.start(); @@ -726,7 +737,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT_BeforeInsertIntercept() { + void testOfferT_BeforeInsertIntercept() { drools.start(); when(prov1.beforeInsert(drools, EVENT)).thenReturn(true); @@ -744,7 +755,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT_AfterInsertIntercept() { + void testOfferT_AfterInsertIntercept() { drools.start(); when(prov1.afterInsert(drools, EVENT, true)).thenReturn(true); @@ -764,7 +775,7 @@ public class MavenDroolsController2Test { } @Test - public void testOfferT_Ignored() { + void testOfferT_Ignored() { drools.start(); drools.lock(); @@ -784,7 +795,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeliver() { + void testDeliver() { drools.start(); assertTrue(drools.deliver(sink, EVENT)); assertEquals(1, drools.getRecentSinkEvents().length); @@ -800,14 +811,14 @@ public class MavenDroolsController2Test { } @Test - public void testDeliver_InvalidArgs() { + void testDeliver_InvalidArgs() { drools.start(); assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(null, EVENT)) - .withMessageContaining("sink"); + .withMessageContaining("sink"); assertThatIllegalArgumentException().isThrownBy(() -> drools.deliver(sink, null)) - .withMessageContaining("event"); + .withMessageContaining("event"); drools.lock(); assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT)).withMessageContaining("locked"); @@ -815,14 +826,14 @@ public class MavenDroolsController2Test { drools.stop(); assertThatIllegalStateException().isThrownBy(() -> drools.deliver(sink, EVENT)) - .withMessageContaining("stopped"); + .withMessageContaining("stopped"); drools.start(); assertEquals(0, drools.getRecentSinkEvents().length); } @Test - public void testDeliver_BeforeIntercept() { + void testDeliver_BeforeIntercept() { when(prov1.beforeDeliver(drools, sink, EVENT)).thenReturn(true); drools.start(); @@ -839,7 +850,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeliver_AfterIntercept() { + void testDeliver_AfterIntercept() { when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenReturn(true); drools.start(); @@ -859,7 +870,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeliver_InterceptEx() { + void testDeliver_InterceptEx() { when(prov1.beforeDeliver(drools, sink, EVENT)).thenThrow(RUNTIME_EX); when(prov1.afterDeliver(drools, sink, EVENT, EVENT_TEXT, true)).thenThrow(RUNTIME_EX); @@ -874,7 +885,7 @@ public class MavenDroolsController2Test { } @Test - public void testGetXxx() { + void testGetXxx() { assertEquals(VERSION, drools.getVersion()); assertEquals(ARTIFACT, drools.getArtifactId()); assertEquals(GROUP, drools.getGroupId()); @@ -895,7 +906,7 @@ public class MavenDroolsController2Test { } @Test - public void testLock_testUnlock_testIsLocked() { + void testLock_testUnlock_testIsLocked() { assertFalse(drools.isLocked()); assertTrue(drools.lock()); @@ -913,7 +924,7 @@ public class MavenDroolsController2Test { } @Test - public void testGetSessionNames_testGetCanonicalSessionNames() { + void testGetSessionNames_testGetCanonicalSessionNames() { assertEquals("[session-A, session-B]", drools.getSessionNames(true).toString()); assertEquals("[full-A, full-B]", drools.getSessionNames(false).toString()); @@ -927,7 +938,7 @@ public class MavenDroolsController2Test { } @Test - public void testGetBaseDomainNames() { + void testGetBaseDomainNames() { KieContainer kiecont = mock(KieContainer.class); when(kiecont.getKieBaseNames()).thenReturn(List.of("kieA", "kieB")); when(container.getKieContainer()).thenReturn(kiecont); @@ -936,12 +947,12 @@ public class MavenDroolsController2Test { } @Test - public void testGetSession() { + void testGetSession() { assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession(null)) - .withMessageContaining("must be provided"); + .withMessageContaining("must be provided"); assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession("")) - .withMessageContaining("must be provided"); + .withMessageContaining("must be provided"); assertSame(sess1, drools.getSession(SESSION1)); assertSame(sess1, drools.getSession(FULL_SESSION1)); @@ -949,35 +960,35 @@ public class MavenDroolsController2Test { assertSame(sess2, drools.getSession(SESSION2)); assertThatIllegalArgumentException().isThrownBy(() -> drools.getSession("unknown session")) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); } @Test - public void testFactClassNames() { + void testFactClassNames() { // copy to a sorted map so the order remains unchanged Map map = new TreeMap<>(drools.factClassNames(SESSION1)); assertEquals("{java.lang.Integer=2, java.lang.String=1}", map.toString()); assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames(null)) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.factClassNames("")) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); } @Test - public void testFactCount() { + void testFactCount() { assertEquals(FACT_COUNT, drools.factCount(SESSION1)); assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount(null)) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.factCount("")) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); } @Test - public void testFactsStringStringBoolean() { + void testFactsStringStringBoolean() { assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), false).toString()); verify(kieSess, never()).delete(fact1); verify(kieSess, never()).delete(fact2); @@ -992,23 +1003,23 @@ public class MavenDroolsController2Test { verify(kieSess, never()).delete(factex); assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(null, Integer.class.getName(), false)) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.facts("", Integer.class.getName(), false)) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, null, false)) - .withMessageContaining("Invalid Class Name"); + .withMessageContaining("Invalid Class Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, "", false)) - .withMessageContaining("Invalid Class Name"); + .withMessageContaining("Invalid Class Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.facts(SESSION1, UNKNOWN_CLASS, false)) - .withMessageContaining("classloader"); + .withMessageContaining("classloader"); } @Test - public void testFactsStringStringBoolean_DeleteEx() { + void testFactsStringStringBoolean_DeleteEx() { doThrow(RUNTIME_EX).when(kieSess).delete(fact1); assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class.getName(), true).toString()); @@ -1018,47 +1029,47 @@ public class MavenDroolsController2Test { } @Test - public void testFactsStringClassOfT() { + void testFactsStringClassOfT() { assertEquals("[1000, 1001]", drools.facts(SESSION1, Integer.class).toString()); } @Test - public void testFactQuery() { + void testFactQuery() { assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, false, PARM1, PARM2).toString()); verify(kieSess, never()).delete(fact1); verify(kieSess, never()).delete(fact3); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.factQuery(null, QUERY, ENTITY, false, PARM1, PARM2)) - .withMessageContaining("Invalid Session Name"); + .isThrownBy(() -> drools.factQuery(null, QUERY, ENTITY, false, PARM1, PARM2)) + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException().isThrownBy(() -> drools.factQuery("", QUERY, ENTITY, false, PARM1, PARM2)) - .withMessageContaining("Invalid Session Name"); + .withMessageContaining("Invalid Session Name"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.factQuery(SESSION1, null, ENTITY, false, PARM1, PARM2)) - .withMessageContaining("Invalid Query Name"); + .isThrownBy(() -> drools.factQuery(SESSION1, null, ENTITY, false, PARM1, PARM2)) + .withMessageContaining("Invalid Query Name"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.factQuery(SESSION1, "", ENTITY, false, PARM1, PARM2)) - .withMessageContaining("Invalid Query Name"); + .isThrownBy(() -> drools.factQuery(SESSION1, "", ENTITY, false, PARM1, PARM2)) + .withMessageContaining("Invalid Query Name"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, null, false, PARM1, PARM2)) - .withMessageContaining("Invalid Queried Entity"); + .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, null, false, PARM1, PARM2)) + .withMessageContaining("Invalid Queried Entity"); assertThatIllegalArgumentException() - .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, "", false, PARM1, PARM2)) - .withMessageContaining("Invalid Queried Entity"); + .isThrownBy(() -> drools.factQuery(SESSION1, QUERY, "", false, PARM1, PARM2)) + .withMessageContaining("Invalid Queried Entity"); assertThatIllegalArgumentException().isThrownBy( - () -> drools.factQuery(SESSION1, QUERY + "-unknown-query", ENTITY, false, PARM1, PARM2)) + () -> drools.factQuery(SESSION1, QUERY + "-unknown-query", ENTITY, false, PARM1, PARM2)) .withMessageContaining("Invalid Query Name"); } @Test - public void testFactQuery_Delete() { + void testFactQuery_Delete() { doThrow(RUNTIME_EX).when(kieSess).delete(fact1); assertEquals("[1000, 1001]", drools.factQuery(SESSION1, QUERY, ENTITY, true, PARM1, PARM2).toString()); @@ -1068,7 +1079,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeleteStringT() { + void testDeleteStringT() { assertTrue(drools.delete(SESSION1, FACT3_OBJECT)); verify(kieSess, never()).delete(fact1); @@ -1087,14 +1098,14 @@ public class MavenDroolsController2Test { } @Test - public void testDeleteT() { + void testDeleteT() { assertTrue(drools.delete(FACT3_OBJECT)); verify(kieSess).delete(fact3); } @Test - public void testDeleteStringClassOfT() { + void testDeleteStringClassOfT() { assertTrue(drools.delete(SESSION1, Integer.class)); verify(kieSess).delete(fact1); @@ -1102,7 +1113,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeleteStringClassOfT_Ex() { + void testDeleteStringClassOfT_Ex() { doThrow(RUNTIME_EX).when(kieSess).delete(fact1); assertFalse(drools.delete(SESSION1, Integer.class)); @@ -1112,7 +1123,7 @@ public class MavenDroolsController2Test { } @Test - public void testDeleteClassOfT() { + void testDeleteClassOfT() { assertTrue(drools.delete(Integer.class)); verify(kieSess).delete(fact1); @@ -1120,17 +1131,17 @@ public class MavenDroolsController2Test { } @Test - public void testFetchModelClass() { + void testFetchModelClass() { assertSame(Long.class, drools.fetchModelClass(Long.class.getName())); } @Test - public void testIsBrained() { + void testIsBrained() { assertTrue(drools.isBrained()); } @Test - public void testToString() { + void testToString() { assertNotNull(drools.toString()); } @@ -1155,9 +1166,9 @@ public class MavenDroolsController2Test { @Override protected PolicyContainer makePolicyContainer(String groupId, String artifactId, String version) { - when(container.getGroupId()).thenReturn(groupId); - when(container.getArtifactId()).thenReturn(artifactId); - when(container.getVersion()).thenReturn(version); + lenient().when(container.getGroupId()).thenReturn(groupId); + lenient().when(container.getArtifactId()).thenReturn(artifactId); + lenient().when(container.getVersion()).thenReturn(version); return container; } diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest.java index a2f41bc6..fbaf8433 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,14 +21,17 @@ package org.onap.policy.drools.controller.internal; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import java.io.IOException; import java.nio.file.Paths; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.kie.api.builder.ReleaseId; import org.onap.policy.common.utils.gson.GsonTestUtils; import org.onap.policy.drools.controller.DroolsController; @@ -49,7 +53,7 @@ public class MavenDroolsControllerTest { * * @throws IOException throws an IO exception */ - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws IOException { releaseId = KieUtils.installArtifact(Paths.get(JUNIT_ECHO_KMODULE_PATH).toFile(), @@ -58,7 +62,7 @@ public class MavenDroolsControllerTest { Paths.get(JUNIT_ECHO_KMODULE_DRL_PATH).toFile()); } - @Before + @BeforeEach public void setUp() { running = new CountDownLatch(1); } @@ -68,58 +72,58 @@ public class MavenDroolsControllerTest { } @Test - public void stop() throws InterruptedException { + void stop() throws InterruptedException { createDroolsController(10000L).stop(); } @Test - public void shutdown() throws InterruptedException { + void shutdown() throws InterruptedException { createDroolsController(10000L).shutdown(); } @Test - public void testLock() throws InterruptedException { + void testLock() throws InterruptedException { DroolsController controller = createDroolsController(30000L); controller.lock(); - Assert.assertTrue(controller.isLocked()); + assertTrue(controller.isLocked()); controller.unlock(); - Assert.assertFalse(controller.isLocked()); + assertFalse(controller.isLocked()); controller.halt(); - Assert.assertFalse(controller.isAlive()); + assertFalse(controller.isAlive()); new GsonTestUtils().compareGson(controller, MavenDroolsControllerTest.class); } @Test - public void testFact() throws InterruptedException { + void testFact() throws InterruptedException { DroolsController controller = createDroolsController(30000L); Integer one = 1; Integer two = 2; - Assert.assertTrue(controller.offer(one)); - Assert.assertTrue(controller.exists(one)); - Assert.assertFalse(controller.exists(two)); + assertTrue(controller.offer(one)); + assertTrue(controller.exists(one)); + assertFalse(controller.exists(two)); - Assert.assertTrue(controller.offer(two)); - Assert.assertTrue(controller.exists(one)); - Assert.assertTrue(controller.exists(two)); + assertTrue(controller.offer(two)); + assertTrue(controller.exists(one)); + assertTrue(controller.exists(two)); Integer three = 3; - Assert.assertFalse(controller.delete(three)); - Assert.assertTrue(controller.exists(one)); - Assert.assertTrue(controller.exists(two)); + assertFalse(controller.delete(three)); + assertTrue(controller.exists(one)); + assertTrue(controller.exists(two)); - Assert.assertTrue(controller.delete(two)); - Assert.assertTrue(controller.exists(one)); - Assert.assertFalse(controller.exists(two)); + assertTrue(controller.delete(two)); + assertTrue(controller.exists(one)); + assertFalse(controller.exists(two)); - Assert.assertTrue(controller.delete(one)); - Assert.assertFalse(controller.exists(one)); - Assert.assertFalse(controller.exists(two)); + assertTrue(controller.delete(one)); + assertFalse(controller.exists(one)); + assertFalse(controller.exists(two)); } private DroolsController createDroolsController(long courtesyStartTimeMs) throws InterruptedException { @@ -130,31 +134,31 @@ public class MavenDroolsControllerTest { DroolsController controller = new MavenDroolsController(releaseId.getGroupId(), releaseId.getArtifactId(), releaseId.getVersion(), null, null); - Assert.assertFalse(controller.isAlive()); - Assert.assertTrue(controller.isBrained()); + assertFalse(controller.isAlive()); + assertTrue(controller.isBrained()); controller.start(); - Assert.assertTrue(controller.isAlive()); - Assert.assertTrue(controller.isBrained()); + assertTrue(controller.isAlive()); + assertTrue(controller.isBrained()); - Assert.assertEquals(releaseId.getGroupId(), controller.getGroupId()); - Assert.assertEquals(releaseId.getArtifactId(), controller.getArtifactId()); - Assert.assertEquals(releaseId.getVersion(), controller.getVersion()); + assertEquals(releaseId.getGroupId(), controller.getGroupId()); + assertEquals(releaseId.getArtifactId(), controller.getArtifactId()); + assertEquals(releaseId.getVersion(), controller.getVersion()); - Assert.assertEquals(releaseId.getGroupId(), controller.getContainer().getGroupId()); - Assert.assertEquals(releaseId.getArtifactId(), controller.getContainer().getArtifactId()); - Assert.assertEquals(releaseId.getVersion(), controller.getContainer().getVersion()); + assertEquals(releaseId.getGroupId(), controller.getContainer().getGroupId()); + assertEquals(releaseId.getArtifactId(), controller.getContainer().getArtifactId()); + assertEquals(releaseId.getVersion(), controller.getContainer().getVersion()); /* allow full initialization from local maven repository */ - Assert.assertTrue(running.await(courtesyStartTimeMs, TimeUnit.MILLISECONDS)); + assertTrue(running.await(courtesyStartTimeMs, TimeUnit.MILLISECONDS)); - Assert.assertEquals(1, controller.getSessionNames().size()); - Assert.assertEquals(JUNIT_ECHO_KSESSION, controller.getSessionNames().get(0)); - Assert.assertEquals(1, controller.getCanonicalSessionNames().size()); - Assert.assertTrue(controller.getCanonicalSessionNames().get(0).contains(JUNIT_ECHO_KSESSION)); + assertEquals(1, controller.getSessionNames().size()); + assertEquals(JUNIT_ECHO_KSESSION, controller.getSessionNames().get(0)); + assertEquals(1, controller.getCanonicalSessionNames().size()); + assertTrue(controller.getCanonicalSessionNames().get(0).contains(JUNIT_ECHO_KSESSION)); - Assert.assertEquals(JUNIT_ECHO_KBASE, String.join(",", controller.getBaseDomainNames())); + assertEquals(JUNIT_ECHO_KBASE, String.join(",", controller.getBaseDomainNames())); return controller; } diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java index b71403e7..38b38a8c 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/MavenDroolsControllerUpgradesTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +21,12 @@ package org.onap.policy.drools.controller.internal; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; @@ -33,10 +35,10 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.kie.api.builder.ReleaseId; import org.kie.api.event.rule.AfterMatchFiredEvent; import org.kie.api.event.rule.AgendaEventListener; @@ -93,15 +95,16 @@ public class MavenDroolsControllerUpgradesTest { /** * Test Class Initialization. */ - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws IOException { + Path path = Paths.get(DROOLS_RESOURCES_DIR + "rules1" + DRL_EXT); rulesDescriptor1 = install("rules1", - Stream.of(Paths.get(DROOLS_RESOURCES_DIR + "rules1" + DRL_EXT).toFile()).collect(Collectors.toList())); + Stream.of(path.toFile()).collect(Collectors.toList())); rulesDescriptor2 = install("rules2", - Stream.of(Paths.get(DROOLS_RESOURCES_DIR + "rules1" + DRL_EXT).toFile(), + Stream.of(path.toFile(), Paths.get(DROOLS_RESOURCES_DIR + "rules2" + DRL_EXT).toFile()) .collect(Collectors.toList())); @@ -112,7 +115,7 @@ public class MavenDroolsControllerUpgradesTest { /** * Creates a controller before each test. */ - @Before + @BeforeEach public void beforeTest() { controller = new MavenDroolsController( @@ -123,7 +126,7 @@ public class MavenDroolsControllerUpgradesTest { /** * Shuts down the controller after each test. */ - @After + @AfterEach public void afterTest() { if (controller != null) { controller.halt(); @@ -134,13 +137,13 @@ public class MavenDroolsControllerUpgradesTest { * Upgrades test. */ @Test - public void upgrades() throws InterruptedException { + void upgrades() throws InterruptedException { assertTrue(controller.start()); logKieEvents(); assertTrue(running1a.await(30, TimeUnit.SECONDS)); summary(); - assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12"), 1); + assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12")); controller.updateToVersion( rulesDescriptor2.getGroupId(), @@ -152,7 +155,7 @@ public class MavenDroolsControllerUpgradesTest { assertTrue(running2b.await(30, TimeUnit.SECONDS)); assertTrue(running1b.await(30, TimeUnit.SECONDS)); summary(); - assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12", "SETUP.2", "VERSION.2"), 1); + assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12", "SETUP.2", "VERSION.2")); controller.updateToVersion( rulesDescriptor1.getGroupId(), @@ -161,7 +164,7 @@ public class MavenDroolsControllerUpgradesTest { null, null); summary(); - assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12"), 1); + assertKie(Arrays.asList("run-drools-runnable", "SETUP.1", "VERSION.12")); } private void summary() { @@ -176,11 +179,11 @@ public class MavenDroolsControllerUpgradesTest { logger.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } - private void assertKie(List expectedRuleNames, long expectedFactCount) { + private void assertKie(List expectedRuleNames) { assertEquals(Collections.singletonList("kbRules"), KieUtils.getBases(controller.getContainer().getKieContainer())); assertEquals(expectedRuleNames, KieUtils.getRuleNames(controller.getContainer().getKieContainer())); - assertEquals(expectedFactCount, controller.factCount(controller.getSessionNames().get(0))); + assertEquals(1, controller.factCount(controller.getSessionNames().get(0))); } private void logKieEvents() { diff --git a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/NullDroolsControllerTest.java b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/NullDroolsControllerTest.java index 010056bb..f61412d9 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/controller/internal/NullDroolsControllerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/controller/internal/NullDroolsControllerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,147 +22,158 @@ package org.onap.policy.drools.controller.internal; import static org.assertj.core.api.Assertions.assertThatCode; - -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.controller.DroolsControllerConstants; -public class NullDroolsControllerTest { +class NullDroolsControllerTest { @Test - public void testStart() { + void testStart() { DroolsController controller = new NullDroolsController(); controller.start(); - Assert.assertFalse(controller.isAlive()); + assertFalse(controller.isAlive()); controller.stop(); - Assert.assertFalse(controller.isAlive()); + assertFalse(controller.isAlive()); controller.shutdown(); - Assert.assertFalse(controller.isAlive()); + assertFalse(controller.isAlive()); controller.halt(); - Assert.assertFalse(controller.isAlive()); + assertFalse(controller.isAlive()); } @Test - public void testSerialize() { + void testSerialize() { assertThatCode(() -> new GsonTestUtils().compareGson(new NullDroolsController(), NullDroolsControllerTest.class)).doesNotThrowAnyException(); } @Test - public void testLock() { + void testLock() { DroolsController controller = new NullDroolsController(); controller.lock(); - Assert.assertFalse(controller.isLocked()); + assertFalse(controller.isLocked()); controller.unlock(); - Assert.assertFalse(controller.isLocked()); + assertFalse(controller.isLocked()); } @Test - public void getGroupId() { - Assert.assertEquals(DroolsControllerConstants.NO_GROUP_ID, new NullDroolsController().getGroupId()); + void getGroupId() { + assertEquals(DroolsControllerConstants.NO_GROUP_ID, new NullDroolsController().getGroupId()); } @Test - public void getArtifactId() { - Assert.assertEquals(DroolsControllerConstants.NO_ARTIFACT_ID, new NullDroolsController().getArtifactId()); + void getArtifactId() { + assertEquals(DroolsControllerConstants.NO_ARTIFACT_ID, new NullDroolsController().getArtifactId()); } @Test - public void getVersion() { - Assert.assertEquals(DroolsControllerConstants.NO_VERSION, new NullDroolsController().getVersion()); + void getVersion() { + assertEquals(DroolsControllerConstants.NO_VERSION, new NullDroolsController().getVersion()); } @Test - public void getSessionNames() { - Assert.assertTrue(new NullDroolsController().getSessionNames().isEmpty()); + void getSessionNames() { + assertTrue(new NullDroolsController().getSessionNames().isEmpty()); } @Test - public void getCanonicalSessionNames() { - Assert.assertTrue(new NullDroolsController().getCanonicalSessionNames().isEmpty()); + void getCanonicalSessionNames() { + assertTrue(new NullDroolsController().getCanonicalSessionNames().isEmpty()); } @Test - public void offer() { - Assert.assertFalse(new NullDroolsController().offer(null, null)); + void offer() { + assertFalse(new NullDroolsController().offer(null, null)); } - @Test(expected = IllegalStateException.class) - public void deliver() { - new NullDroolsController().deliver(null, null); + @Test + void deliver() { + var controller = new NullDroolsController(); + assertThrows(IllegalStateException.class, () -> controller.deliver(null, null)); } @Test - public void getRecentSourceEvents() { - Assert.assertEquals(0, new NullDroolsController().getRecentSourceEvents().length); + void getRecentSourceEvents() { + assertEquals(0, new NullDroolsController().getRecentSourceEvents().length); } @Test - public void getRecentSinkEvents() { - Assert.assertEquals(0, new NullDroolsController().getRecentSinkEvents().length); + void getRecentSinkEvents() { + assertEquals(0, new NullDroolsController().getRecentSinkEvents().length); } @Test - public void getContainer() { - Assert.assertNull(new NullDroolsController().getContainer()); + void getContainer() { + assertNull(new NullDroolsController().getContainer()); } @Test - public void getDomains() { - Assert.assertTrue(new NullDroolsController().getBaseDomainNames().isEmpty()); + void getDomains() { + assertTrue(new NullDroolsController().getBaseDomainNames().isEmpty()); } - @Test(expected = IllegalStateException.class) - public void ownsCoder() { - new NullDroolsController().ownsCoder(null, 0); + @Test + void ownsCoder() { + var controller = new NullDroolsController(); + assertThrows(IllegalStateException.class, () -> controller.ownsCoder(null, 0)); } - @Test(expected = IllegalArgumentException.class) - public void fetchModelClass() { - new NullDroolsController().fetchModelClass(this.getClass().getName()); + @Test + void fetchModelClass() { + var controller = new NullDroolsController(); + var className = this.getClass().getName(); + assertThrows(IllegalArgumentException.class, () -> controller.fetchModelClass(className)); } @Test - public void isBrained() { - Assert.assertFalse(new NullDroolsController().isBrained()); + void isBrained() { + assertFalse(new NullDroolsController().isBrained()); } @Test - public void stringify() { - Assert.assertNotNull(new NullDroolsController().toString()); + void stringify() { + assertNotNull(new NullDroolsController().toString()); } - @Test(expected = IllegalArgumentException.class) - public void updateToVersion() { - new NullDroolsController().updateToVersion(null, null, null, null, null); + @Test + void updateToVersion() { + var controller = new NullDroolsController(); + assertThrows(IllegalArgumentException.class, () -> + controller.updateToVersion(null, null, null, null, null)); } @Test - public void factClassNames() { - Assert.assertTrue(new NullDroolsController().factClassNames(null).isEmpty()); + void factClassNames() { + assertTrue(new NullDroolsController().factClassNames(null).isEmpty()); } @Test - public void factCount() { - Assert.assertEquals(0, new NullDroolsController().factCount(null)); + void factCount() { + assertEquals(0, new NullDroolsController().factCount(null)); } @Test - public void facts() { - Assert.assertTrue(new NullDroolsController().facts(null, null, true).isEmpty()); + void facts() { + assertTrue(new NullDroolsController().facts(null, null, true).isEmpty()); } @Test - public void factQuery() { - Assert.assertTrue(new NullDroolsController().factQuery(null, null, null, false).isEmpty()); + void factQuery() { + assertTrue(new NullDroolsController().factQuery(null, null, null, false).isEmpty()); } @Test - public void exists() { + void exists() { Object o1 = new Object(); - Assert.assertFalse(new NullDroolsController().exists("blah", o1)); - Assert.assertFalse(new NullDroolsController().exists(o1)); + assertFalse(new NullDroolsController().exists("blah", o1)); + assertFalse(new NullDroolsController().exists(o1)); } } diff --git a/policy-management/src/test/java/org/onap/policy/drools/persistence/SystemPersistenceTest.java b/policy-management/src/test/java/org/onap/policy/drools/persistence/SystemPersistenceTest.java index 15a0b18f..b6a9ce52 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/persistence/SystemPersistenceTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/persistence/SystemPersistenceTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +21,9 @@ package org.onap.policy.drools.persistence; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.FileOutputStream; import java.io.IOException; @@ -32,17 +33,17 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Properties; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.onap.policy.drools.properties.DroolsPropertyConstants; /** * (File) System Persistence Tests. */ -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.MethodName.class) public class SystemPersistenceTest { /** * sample configuration dir. @@ -124,18 +125,18 @@ public class SystemPersistenceTest { private static final String SYSTEM_PROPS = TEST_CONTROLLER_NAME; private static final String SYSTEM_PROPS_FILE = SYSTEM_PROPS + "-system.properties"; - @BeforeClass + @BeforeAll public static void setUp() throws IOException { cleanUpWorkingDirs(); } - @AfterClass + @AfterAll public static void tearDown() throws IOException { cleanUpWorkingDirs(); } @Test - public void test1NonDefaultConfigDir() { + void test1NonDefaultConfigDir() { SystemPersistenceConstants.getManager().setConfigurationDir(OTHER_CONFIG_DIR); assertEquals(OTHER_CONFIG_DIR, SystemPersistenceConstants.getManager().getConfigurationPath().toString()); @@ -149,7 +150,7 @@ public class SystemPersistenceTest { } @Test - public void test2Engine_Environment_System() throws IOException { + void test2Engine_Environment_System() throws IOException { SystemPersistenceConstants.getManager().setConfigurationDir(OTHER_CONFIG_DIR); final Path policyEnginePropsPath = @@ -191,7 +192,7 @@ public class SystemPersistenceTest { } @Test - public void test3Topic() { + void test3Topic() { SystemPersistenceConstants.getManager().setConfigurationDir(null); Path topicPath = Paths @@ -221,7 +222,7 @@ public class SystemPersistenceTest { } @Test - public void test4HttpServer() { + void test4HttpServer() { SystemPersistenceConstants.getManager().setConfigurationDir(null); Path httpServerPath = Paths @@ -251,7 +252,7 @@ public class SystemPersistenceTest { } @Test - public void test5HttpClient() { + void test5HttpClient() { SystemPersistenceConstants.getManager().setConfigurationDir(null); Path httpClientPath = Paths @@ -281,7 +282,7 @@ public class SystemPersistenceTest { } @Test - public void test6Controller() { + void test6Controller() { SystemPersistenceConstants.getManager().setConfigurationDir(null); Path controllerPath = Paths diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java index b6168a2e..6d461eef 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/EventProtocolCoderTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,12 +22,12 @@ package org.onap.policy.drools.protocol.coders; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Properties; import lombok.AllArgsConstructor; import lombok.Getter; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; @@ -34,7 +35,7 @@ import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; /** * Tests Coders. */ -public class EventProtocolCoderTest { +class EventProtocolCoderTest { /** * Coder Group. @@ -66,7 +67,7 @@ public class EventProtocolCoderTest { } @Test - public void test() { + void test() { final Properties noopSinkProperties = new Properties(); noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, NOOP_TOPIC); diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java index e0baeb6d..28b3e040 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/JsonProtocolFilterTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +21,14 @@ package org.onap.policy.drools.protocol.coders; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class JsonProtocolFilterTest { +class JsonProtocolFilterTest { private static final String JSON = "{\"requestID\":\"38adde30-cc22-11e8-a8d5-f2801f1b9fd1\",\"entity\":\"controller\"," @@ -38,7 +40,7 @@ public class JsonProtocolFilterTest { * Tests getting the rule expression of the filter. */ @Test - public void getRuleTest() { + void getRuleTest() { assertEquals("$.test", new JsonProtocolFilter("$.test").getRule()); } @@ -46,7 +48,7 @@ public class JsonProtocolFilterTest { * Tests setting the rule expression of the filter. */ @Test - public void setRuleTest() { + void setRuleTest() { JsonProtocolFilter filter = new JsonProtocolFilter(); assertEquals(JsonProtocolFilter.MATCH_ANY, filter.getRule()); filter.setRule("$.test"); @@ -57,7 +59,7 @@ public class JsonProtocolFilterTest { * Tests that the rule expression will be set to match anything if an empty string is passed. */ @Test - public void setRuleEmptyTest() { + void setRuleEmptyTest() { assertEquals(JsonProtocolFilter.MATCH_ANY, new JsonProtocolFilter("").getRule()); } @@ -65,7 +67,7 @@ public class JsonProtocolFilterTest { * Tests that the rule expression will be set to match anything if a null string is passed. */ @Test - public void setRuleNullTest() { + void setRuleNullTest() { assertEquals(JsonProtocolFilter.MATCH_ANY, new JsonProtocolFilter(null).getRule()); } @@ -73,7 +75,7 @@ public class JsonProtocolFilterTest { * Tests accepting a message if all filter rules pass. */ @Test - public void acceptPassTest() { + void acceptPassTest() { assertTrue(new JsonProtocolFilter( "$.controllers[?(@.drools.version =~ /\\d\\.\\d\\.\\d/ && @.operation == 'update')]") .accept(JSON)); @@ -83,7 +85,7 @@ public class JsonProtocolFilterTest { * Tests accepting a message without having to filter if the rule is set to match anything. */ @Test - public void acceptAnyTest() { + void acceptAnyTest() { assertTrue(new JsonProtocolFilter(null).accept(JSON)); } @@ -91,7 +93,7 @@ public class JsonProtocolFilterTest { * Tests rejecting a message if one or more of the filter rules fail. */ @Test - public void acceptFailTest() { + void acceptFailTest() { assertFalse( new JsonProtocolFilter("$.controllers[?(@.drools.version =~ /\\\\d\\\\.\\\\d\\\\.2/)]") .accept(JSON)); @@ -101,7 +103,7 @@ public class JsonProtocolFilterTest { * Tests finding field matches for a filter rule corresponding to a topic. */ @Test - public void filterPassTest() { + void filterPassTest() { assertEquals("38adde30-cc22-11e8-a8d5-f2801f1b9fd1", new JsonProtocolFilter("$.requestID").filter(JSON).get(0)); } @@ -109,7 +111,7 @@ public class JsonProtocolFilterTest { * Tests that an empty list is returned when no matches are found. */ @Test - public void filterFailTest() { + void filterFailTest() { assertTrue(new JsonProtocolFilter("$.test").filter(JSON).isEmpty()); } @@ -117,7 +119,7 @@ public class JsonProtocolFilterTest { * Tests static method for filtering a JSON string with an arbitrary expression. */ @Test - public void staticFilterPassTest() { + void staticFilterPassTest() { assertEquals("controller", JsonProtocolFilter.filter(JSON, "$.entity").get(0)); } @@ -125,39 +127,39 @@ public class JsonProtocolFilterTest { * Tests that an empty list is returned when the static filter() method does not find any matches. */ @Test - public void staticFilterFailTest() { + void staticFilterFailTest() { assertTrue(JsonProtocolFilter.filter(JSON, "$.test").isEmpty()); } /** * Tests that an exception is thrown if a null JSON string is passed. */ - @Test(expected = IllegalArgumentException.class) - public void staticFilterNullJsonTest() { - JsonProtocolFilter.filter(null, "[?($ =~ /.*/"); + @Test + void staticFilterNullJsonTest() { + assertThrows(IllegalArgumentException.class, () -> JsonProtocolFilter.filter(null, "[?($ =~ /.*/")); } /** * Tests that an exception is thrown if an empty JSON string is passed. */ - @Test(expected = IllegalArgumentException.class) - public void staticFilterEmptyJsonTest() { - JsonProtocolFilter.filter("", "[?($ =~ /.*/"); + @Test + void staticFilterEmptyJsonTest() { + assertThrows(IllegalArgumentException.class, () -> JsonProtocolFilter.filter("", "[?($ =~ /.*/")); } /** * Tests that an exception is thrown if a null expression string is passed. */ - @Test(expected = IllegalArgumentException.class) - public void staticFilterNullExpressionTest() { - JsonProtocolFilter.filter("{\"hello\":\"world\"}", null); + @Test + void staticFilterNullExpressionTest() { + assertThrows(IllegalArgumentException.class, () -> JsonProtocolFilter.filter("{\"hello\":\"world\"}", null)); } /** * Tests that an exception is thrown if an empty expression string is passed. */ - @Test(expected = IllegalArgumentException.class) - public void staticFilterEmptyExpressionTest() { - JsonProtocolFilter.filter("{\"hello\":\"world\"}", ""); + @Test + void staticFilterEmptyExpressionTest() { + assertThrows(IllegalArgumentException.class, () -> JsonProtocolFilter.filter("{\"hello\":\"world\"}", "")); } } \ No newline at end of file diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java index 6d1ec3d3..659965f8 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/coders/ProtocolCoderToolsetTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2021-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,11 +22,11 @@ package org.onap.policy.drools.protocol.coders; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -35,10 +36,10 @@ import java.util.List; import java.util.Properties; import lombok.AllArgsConstructor; import lombok.Getter; -import org.junit.After; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.kie.api.builder.ReleaseId; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -73,7 +74,7 @@ public class ProtocolCoderToolsetTest { /** * Test Class Initialization. */ - @BeforeClass + @BeforeAll public static void setUpClass() throws IOException { releaseId = KieUtils.installArtifact(Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_PATH).toFile(), Paths.get(MavenDroolsControllerTest.JUNIT_ECHO_KMODULE_POM_PATH).toFile(), @@ -84,7 +85,7 @@ public class ProtocolCoderToolsetTest { /** * Test Set Up. */ - @Before + @BeforeEach public void setUp() { controller = createController(); } @@ -92,7 +93,7 @@ public class ProtocolCoderToolsetTest { /** * Test Termination. */ - @After + @AfterEach public void tearDown() { if (controller != null) { DroolsControllerConstants.getFactory().destroy(controller); @@ -100,7 +101,7 @@ public class ProtocolCoderToolsetTest { } @Test - public void testToolsets() { + void testToolsets() { testGsonToolset(createFilterSet()); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/ControllerConfigurationTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/ControllerConfigurationTest.java index 7248f11e..f251f9bf 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/ControllerConfigurationTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/ControllerConfigurationTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,16 +22,16 @@ package org.onap.policy.drools.protocol.configuration; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Properties; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; -public class ControllerConfigurationTest { +class ControllerConfigurationTest { private static final String NAME = "name"; private static final String OPERATION = "operation"; @@ -60,7 +61,7 @@ public class ControllerConfigurationTest { * Test. */ @Test - public void test() { + void test() { Properties additionalProperties = new Properties(); additionalProperties.put(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE); @@ -104,7 +105,7 @@ public class ControllerConfigurationTest { } @Test - public void testSerialize() { + void testSerialize() { ControllerConfiguration controllerConfig = new ControllerConfiguration(NAME, OPERATION, DROOLS_CONFIG); controllerConfig.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE); controllerConfig.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY2, ADDITIONAL_PROPERTY_VALUE2); diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/DroolsConfigurationTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/DroolsConfigurationTest.java index 2d1ed7e2..e693d000 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/DroolsConfigurationTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/DroolsConfigurationTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,15 +22,15 @@ package org.onap.policy.drools.protocol.configuration; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Properties; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; -public class DroolsConfigurationTest { +class DroolsConfigurationTest { private static final String ARTIFACT_ID_STRING = "artifactId"; private static final String GROUP_ID_STRING = "groupId"; private static final String VERSION_STRING = "version"; @@ -51,7 +52,7 @@ public class DroolsConfigurationTest { private static final String ADDITIONAL_PROPERTY_VALUE2 = "world"; @Test - public void test() { + void test() { final Properties additionalProperties = new Properties(); additionalProperties.put(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE); @@ -96,7 +97,7 @@ public class DroolsConfigurationTest { } @Test - public void testSerialize() { + void testSerialize() { final DroolsConfiguration droolsConfig = new DroolsConfiguration(ARTIFACT, GROUPID, VERSION); droolsConfig.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY, ADDITIONAL_PROPERTY_VALUE); droolsConfig.setAdditionalProperty(ADDITIONAL_PROPERTY_KEY2, ADDITIONAL_PROPERTY_VALUE2); diff --git a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/PdpdConfigurationTest.java b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/PdpdConfigurationTest.java index a8a0a2ac..f8f542c8 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/PdpdConfigurationTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/protocol/configuration/PdpdConfigurationTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +21,19 @@ package org.onap.policy.drools.protocol.configuration; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class PdpdConfigurationTest { +class PdpdConfigurationTest { private static final Logger logger = LoggerFactory.getLogger(PdpdConfigurationTest.class); @@ -64,7 +64,7 @@ public class PdpdConfigurationTest { private static final String OPERATION2 = "operation2"; @Test - public void test() { + void test() { // // Empty constructor test // @@ -246,14 +246,14 @@ public class PdpdConfigurationTest { } @Test - public void testConstructor() { + void testConstructor() { PdpdConfiguration config = new PdpdConfiguration(REQUEST_ID, ENTITY, null); assertEquals(REQUEST_ID, config.getRequestId()); assertEquals(ENTITY, config.getEntity()); } @Test - public void testSerialize() throws IOException { + void testSerialize() { List controllers = Arrays.asList(new ControllerConfiguration(NAME, OPERATION, null), new ControllerConfiguration(NAME2, OPERATION2, null)); PdpdConfiguration pdpConfig = new PdpdConfiguration(REQUEST_ID, ENTITY, controllers); diff --git a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java index ad0d1afc..65447d80 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/RestManagerTest.java @@ -21,7 +21,7 @@ package org.onap.policy.drools.server.restful.test; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.io.IOException; import java.nio.file.Files; @@ -44,11 +44,11 @@ import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.http.server.YamlJacksonHandler; import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; @@ -60,7 +60,7 @@ import org.onap.policy.drools.system.PolicyEngineConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@FixMethodOrder(MethodSorters.NAME_ASCENDING) +@TestMethodOrder(MethodOrderer.DisplayName.class) public class RestManagerTest { private static final int DEFAULT_TELEMETRY_PORT = 7887; private static final String HOST = "localhost"; @@ -71,31 +71,19 @@ public class RestManagerTest { private static final String FOO_CONTROLLER = "foo"; private static final String UEB_TOPIC = "ueb-topic-test"; - private static final String DMAAP_TOPIC = "dmaap-topic-test"; + private static final String KAFKA_TOPIC = "kafka-topic-test"; private static final String NOOP_TOPIC = "noop_topic"; private static final String UEB_SOURCE_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS + "." + UEB_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; private static final String UEB_SINK_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS + "." + UEB_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; - private static final String DMAAP_SOURCE_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS - + "." + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; - private static final String DMAAP_SINK_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + "." - + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; + private static final String KAFKA_SOURCE_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_KAFKA_SOURCE_TOPICS + + "." + KAFKA_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; + private static final String KAFKA_SINK_SERVER_PROPERTY = PolicyEndPointProperties.PROPERTY_KAFKA_SINK_TOPICS + "." + + KAFKA_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_SERVERS_SUFFIX; private static final String UEB_SERVER = "localhost"; - private static final String DMAAP_SERVER = "localhost"; - private static final String DMAAP_MECHID = "blah"; - private static final String DMAAP_PASSWD = "blah"; - - private static final String DMAAP_SOURCE_MECHID_KEY = PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "." - + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_AAF_MECHID_SUFFIX; - private static final String DMAAP_SOURCE_PASSWD_KEY = PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS + "." - + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_AAF_PASSWORD_SUFFIX; - - private static final String DMAAP_SINK_MECHID_KEY = PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + "." - + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_AAF_MECHID_SUFFIX; - private static final String DMAAP_SINK_PASSWD_KEY = PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS + "." - + DMAAP_TOPIC + PolicyEndPointProperties.PROPERTY_TOPIC_AAF_PASSWORD_SUFFIX; + private static final String KAFKA_SERVER = "localhost:9092"; private static final String FOO_CONTROLLER_FILE = FOO_CONTROLLER + "-controller.properties"; private static final String FOO_CONTROLLER_FILE_BAK = FOO_CONTROLLER_FILE + ".bak"; @@ -111,7 +99,7 @@ public class RestManagerTest { * * @throws IOException throws an IO exception */ - @BeforeClass + @BeforeAll public static void setUp() throws IOException, InterruptedException { cleanUpWorkingDirs(); @@ -122,10 +110,6 @@ public class RestManagerTest { engineProps.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + PolicyEngineConstants.TELEMETRY_SERVER_DEFAULT_NAME + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, "" + DEFAULT_TELEMETRY_PORT); - engineProps.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." - + PolicyEngineConstants.TELEMETRY_SERVER_DEFAULT_NAME - + PolicyEndPointProperties.PROPERTY_HTTP_FILTER_CLASSES_SUFFIX, - TestAafTelemetryAuthFilter.class.getName()); engineProps.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + PolicyEngineConstants.TELEMETRY_SERVER_DEFAULT_NAME + PolicyEndPointProperties.PROPERTY_HTTP_AUTH_USERNAME_SUFFIX, @@ -142,16 +126,12 @@ public class RestManagerTest { /* other properties */ engineProps.put(PolicyEndPointProperties.PROPERTY_UEB_SOURCE_TOPICS, UEB_TOPIC); engineProps.put(PolicyEndPointProperties.PROPERTY_UEB_SINK_TOPICS, UEB_TOPIC); - engineProps.put(PolicyEndPointProperties.PROPERTY_DMAAP_SOURCE_TOPICS, DMAAP_TOPIC); - engineProps.put(PolicyEndPointProperties.PROPERTY_DMAAP_SINK_TOPICS, DMAAP_TOPIC); + engineProps.put(PolicyEndPointProperties.PROPERTY_KAFKA_SOURCE_TOPICS, KAFKA_TOPIC); + engineProps.put(PolicyEndPointProperties.PROPERTY_KAFKA_SINK_TOPICS, KAFKA_TOPIC); engineProps.put(UEB_SOURCE_SERVER_PROPERTY, UEB_SERVER); engineProps.put(UEB_SINK_SERVER_PROPERTY, UEB_SERVER); - engineProps.put(DMAAP_SOURCE_SERVER_PROPERTY, DMAAP_SERVER); - engineProps.put(DMAAP_SINK_SERVER_PROPERTY, DMAAP_SERVER); - engineProps.put(DMAAP_SOURCE_MECHID_KEY, DMAAP_MECHID); - engineProps.put(DMAAP_SOURCE_PASSWD_KEY, DMAAP_PASSWD); - engineProps.put(DMAAP_SINK_MECHID_KEY, DMAAP_MECHID); - engineProps.put(DMAAP_SINK_PASSWD_KEY, DMAAP_PASSWD); + engineProps.put(KAFKA_SOURCE_SERVER_PROPERTY, KAFKA_SERVER); + engineProps.put(KAFKA_SINK_SERVER_PROPERTY, KAFKA_SERVER); PolicyEngineConstants.getManager().configure(engineProps); PolicyEngineConstants.getManager().start(); @@ -181,7 +161,7 @@ public class RestManagerTest { * * @throws IOException IO exception */ - @AfterClass + @AfterAll public static void tearDown() throws IOException { try { client.close(); @@ -198,7 +178,7 @@ public class RestManagerTest { @Test - public void testPutDelete() throws IOException { + void testPutDelete() throws IOException { putTest(HOST_URL + "/engine/switches/lock", 406); deleteTest(HOST_URL + "/engine/switches/lock", 406); @@ -218,24 +198,24 @@ public class RestManagerTest { private void putDeleteTopicSwitches() throws IOException { putDeleteSwitch("/engine/topics/sources/ueb/", UEB_TOPIC, "lock"); - putDeleteSwitch("/engine/topics/sources/dmaap/", DMAAP_TOPIC, "lock"); + putDeleteSwitch("/engine/topics/sources/kafka/", KAFKA_TOPIC, "lock"); putDeleteSwitch("/engine/topics/sources/noop/", NOOP_TOPIC, "lock"); putDeleteSwitch("/engine/topics/sinks/ueb/", UEB_TOPIC, "lock"); - putDeleteSwitch("/engine/topics/sinks/dmaap/", DMAAP_TOPIC, "lock"); + putDeleteSwitch("/engine/topics/sinks/kafka/", KAFKA_TOPIC, "lock"); putDeleteSwitch("/engine/topics/sinks/noop/", NOOP_TOPIC, "lock"); putDeleteSwitch("/engine/topics/sources/ueb/", UEB_TOPIC, "activation"); - putDeleteSwitch("/engine/topics/sources/dmaap/", DMAAP_TOPIC, "activation"); + putDeleteSwitch("/engine/topics/sources/kafka/", KAFKA_TOPIC, "activation"); putDeleteSwitch("/engine/topics/sources/noop/", NOOP_TOPIC, "activation"); putDeleteSwitch("/engine/topics/sinks/ueb/", UEB_TOPIC, "activation"); - putDeleteSwitch("/engine/topics/sinks/dmaap/", DMAAP_TOPIC, "activation"); + putDeleteSwitch("/engine/topics/sinks/kafka/", KAFKA_TOPIC, "activation"); putDeleteSwitch("/engine/topics/sinks/noop/", NOOP_TOPIC, "activation"); putSwitch("/engine/topics/sources/ueb/", UEB_TOPIC, "activation"); - putSwitch("/engine/topics/sources/dmaap/", DMAAP_TOPIC, "activation"); + putSwitch("/engine/topics/sources/kafka/", KAFKA_TOPIC, "activation"); putSwitch("/engine/topics/sources/noop/", NOOP_TOPIC, "activation"); putSwitch("/engine/topics/sinks/ueb/", UEB_TOPIC, "activation"); - putSwitch("/engine/topics/sinks/dmaap/", DMAAP_TOPIC, "activation"); + putSwitch("/engine/topics/sinks/kafka/", KAFKA_TOPIC, "activation"); putSwitch("/engine/topics/sinks/noop/", NOOP_TOPIC, "activation"); } @@ -244,15 +224,15 @@ public class RestManagerTest { "{x:y}", ContentType.TEXT_PLAIN); putTest(HOST_URL + "/engine/topics/sources/noop/" + NOOP_TOPIC + "/events", 200, "{x:y}", ContentType.TEXT_PLAIN); - putTest(HOST_URL + "/engine/topics/sources/dmaap/" + DMAAP_TOPIC + "/events", 200, + putTest(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/events", 200, "FOOOO", ContentType.TEXT_PLAIN); putTest(HOST_URL + "/engine/topics/sources/ueb/fiznits/events", 406, "FOOOO", ContentType.TEXT_PLAIN); - putTest(HOST_URL + "/engine/topics/sources/dmaap/fiznits/events", 406, + putTest(HOST_URL + "/engine/topics/sources/kafka/fiznits/events", 406, "FOOOO", ContentType.TEXT_PLAIN); putTest(HOST_URL + "/engine/topics/switches/lock", 200); putTest(HOST_URL + "/engine/topics/sources/ueb/" + UEB_TOPIC + "/events", 406, "FOOOO", ContentType.TEXT_PLAIN); - putTest(HOST_URL + "/engine/topics/sources/dmaap/" + DMAAP_TOPIC + "/events", + putTest(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/events", 406, "FOOOO", ContentType.TEXT_PLAIN); deleteTest(HOST_URL + "/engine/topics/switches/lock", 200); } @@ -311,7 +291,7 @@ public class RestManagerTest { } @Test - public void testPost() throws IOException { + void testPost() throws IOException { postTest(HOST_URL + "/engine/inputs/configuration", 406, Files.readString(Paths.get(PDP_CONFIGURATION_JSON)), ContentType.APPLICATION_JSON); @@ -338,7 +318,7 @@ public class RestManagerTest { } @Test - public void testGetSwagger() throws IOException { + void testGetSwagger() throws IOException { HttpGet httpGet; CloseableHttpResponse response; httpGet = new HttpGet(HOST_URL + "/engine/swagger"); @@ -349,7 +329,7 @@ public class RestManagerTest { } @Test - public void testGet() throws IOException { + void testGet() throws IOException { HttpGet httpGet; CloseableHttpResponse response; @@ -630,13 +610,13 @@ public class RestManagerTest { /* * GET: /engine/topics /engine/topics/switches /engine/topics/sources /engine/topics/sinks - * /engine/topics/sinks/ueb /engine/topics/sources/ueb /engine/topics/sinks/dmaap - * /engine/topics/sources/dmaap /engine/topics/sinks/ueb/topic - * /engine/topics/sources/ueb/topic /engine/topics/sinks/dmaap/topic - * /engine/topics/sources/dmaap/topic /engine/topics/sinks/ueb/topic/events - * /engine/topics/sources/ueb/topic/events /engine/topics/sinks/dmaap/topic/events - * /engine/topics/sources/dmaap/topic/events /engine/topics/sources/ueb/topic/switches - * /engine/topics/sources/dmaap/topic/switches + * /engine/topics/sinks/ueb /engine/topics/sources/ueb /engine/topics/sinks/kafka + * /engine/topics/sources/kafka /engine/topics/sinks/ueb/topic + * /engine/topics/sources/ueb/topic /engine/topics/sinks/kafka/topic + * /engine/topics/sources/kafka/topic /engine/topics/sinks/ueb/topic/events + * /engine/topics/sources/ueb/topic/events /engine/topics/sinks/kafka/topic/events + * /engine/topics/sources/kafka/topic/events /engine/topics/sources/ueb/topic/switches + * /engine/topics/sources/kafka/topic/switches */ httpGet = new HttpGet(HOST_URL + "/engine/topics"); response = client.execute(httpGet); @@ -674,13 +654,13 @@ public class RestManagerTest { assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); @@ -722,25 +702,25 @@ public class RestManagerTest { assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap/" + DMAAP_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap/" + DMAAP_TOPIC); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap/foobar"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); @@ -794,25 +774,25 @@ public class RestManagerTest { assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap/" + DMAAP_TOPIC + "/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/events"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/foobar/events"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap/" + DMAAP_TOPIC + "/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/events"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap/foobar/events"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/foobar/events"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(500, response.getStatusLine().getStatusCode()); @@ -848,7 +828,7 @@ public class RestManagerTest { assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/dmaap/" + DMAAP_TOPIC + "/switches"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sources/kafka/" + KAFKA_TOPIC + "/switches"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); @@ -866,7 +846,7 @@ public class RestManagerTest { assertEquals(200, response.getStatusLine().getStatusCode()); httpGet.releaseConnection(); - httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/dmaap/" + DMAAP_TOPIC + "/switches"); + httpGet = new HttpGet(HOST_URL + "/engine/topics/sinks/kafka/" + KAFKA_TOPIC + "/switches"); response = client.execute(httpGet); logger.info(httpGet.getRequestLine() + " response code: {}", response.getStatusLine().getStatusCode()); assertEquals(200, response.getStatusLine().getStatusCode()); diff --git a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/TestAafTelemetryAuthFilter.java b/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/TestAafTelemetryAuthFilter.java deleted file mode 100644 index 6a9be8a2..00000000 --- a/policy-management/src/test/java/org/onap/policy/drools/server/restful/test/TestAafTelemetryAuthFilter.java +++ /dev/null @@ -1,43 +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.server.restful.test; - -import jakarta.servlet.http.HttpServletRequest; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.drools.server.restful.aaf.AafTelemetryAuthFilter; - -/** - * Test AAF Telemetry Authorization Filter for Junits. - */ -public class TestAafTelemetryAuthFilter extends AafTelemetryAuthFilter { - - @Override - protected String getRole(HttpServletRequest request) { - String expectedPerm = "org.onap.policy.pdpd.telemetry|" - + NetworkUtil.getHostname() + "|" - + request.getMethod().toLowerCase(); - if (!expectedPerm.equals(super.getRole(request))) { - throw new IllegalStateException("unexpected permission"); - } else { - return "user"; - } - } -} diff --git a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java index a12fb50a..118c4d7e 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsManagerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.stats; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.metrics.Metric; -public class PolicyStatsManagerTest { +class PolicyStatsManagerTest { @Test - public void testStat() { + void testStat() { PolicyStatsManager stats = new PolicyStatsManager(); assertEquals(0, stats.getGroupStat().getPolicyExecutedCount()); diff --git a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java index 631e85b8..3f26e82e 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/stats/PolicyStatsTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,15 +22,15 @@ package org.onap.policy.drools.stats; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.drools.metrics.Metric; -public class PolicyStatsTest { +class PolicyStatsTest { @Test - public void testStat() { + void testStat() { Metric trans1 = createTrans(); trans1.setSuccess(true); diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java index 818f8fc1..615ffe2b 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +23,9 @@ package org.onap.policy.drools.system; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -35,10 +36,11 @@ import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Properties; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.gson.GsonTestUtils; import org.onap.policy.drools.controller.DroolsController; import org.onap.policy.drools.controller.internal.NullDroolsController; @@ -48,7 +50,7 @@ import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration; import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; import org.onap.policy.drools.system.internal.AggregatedPolicyController; -public class PolicyControllerFactoryTest { +class PolicyControllerFactoryTest { private static final String POLICY_CONTROLLER_BUILDER_TAG = "PolicyControllerFactoryTest"; private static final String MY_NAME = "my-name-a"; @@ -79,7 +81,7 @@ public class PolicyControllerFactoryTest { /** * Initializes the object to be tested. */ - @Before + @BeforeEach public void setUp() { controller = mock(PolicyController.class); controller2 = mock(PolicyController.class); @@ -114,14 +116,14 @@ public class PolicyControllerFactoryTest { } @Test - public void testFactory() { + void testFactory() { // use a REAL object instead of an Impl ipc = new IndexedPolicyControllerFactory(); assertNotNull(ipc.getProviders()); } @Test - public void testBuild() { + void testBuild() { assertEquals(controller, ipc.build(MY_NAME, properties)); // re-build - should not create another one @@ -134,14 +136,14 @@ public class PolicyControllerFactoryTest { } @Test - public void testSerialize() { + void testSerialize() { assertEquals(controller, ipc.build(MY_NAME, properties)); new GsonTestUtils().compareGson(ipc, PolicyControllerFactoryTest.class); } @Test - public void testPatchStringDroolsConfiguration() { + void testPatchStringDroolsConfiguration() { // unknown controller assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(MY_NAME, config)); @@ -173,7 +175,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testPatchPolicyControllerDroolsConfiguration() { + void testPatchPolicyControllerDroolsConfiguration() { ipc.patch(controller, config); verify(controller).updateDrools(config); @@ -194,7 +196,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testShutdownString() { + void testShutdownString() { // null name String nullName = null; assertThatIllegalArgumentException().isThrownBy(() -> ipc.shutdown(nullName)); @@ -213,7 +215,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testShutdownPolicyController() { + void testShutdownPolicyController() { ipc.build(MY_NAME, properties); ipc.shutdown(controller); @@ -225,7 +227,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testShutdown() { + void testShutdown() { ipc.build(MY_NAME, properties); ipc.build(MY_NAME2, properties); @@ -240,7 +242,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testUnmanage() { + void testUnmanage() { ipc.build(MY_NAME, properties); ipc.build(MY_NAME2, properties); @@ -265,7 +267,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testDestroyString() { + void testDestroyString() { // null name String nullName = null; assertThatIllegalArgumentException().isThrownBy(() -> ipc.destroy(nullName)); @@ -284,7 +286,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testDestroyPolicyController() { + void testDestroyPolicyController() { ipc.build(MY_NAME, properties); ipc.destroy(controller); @@ -296,7 +298,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testDestroy() { + void testDestroy() { ipc.build(MY_NAME, properties); ipc.build(MY_NAME2, properties); @@ -311,7 +313,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testGetString() { + void testGetString() { // unknown name assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME)); @@ -330,7 +332,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testGetStringString_testToKey() { + void testGetStringString_testToKey() { // unknown controller assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(GROUP1, ARTIFACT1)); @@ -357,7 +359,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testGetDroolsController() { + void testGetDroolsController() { // unknown controller assertThatIllegalStateException().isThrownBy(() -> ipc.get(drools)); @@ -376,27 +378,27 @@ public class PolicyControllerFactoryTest { } @Test - public void testInventory() { + void testInventory() { ipc.build(MY_NAME, properties); ipc.build(MY_NAME2, properties); List lst = ipc.inventory(); - Collections.sort(lst, (left, right) -> left.getName().compareTo(right.getName())); + lst.sort(Comparator.comparing(PolicyController::getName)); assertEquals(Arrays.asList(controller, controller2), lst); } @Test - public void testGetFeatures() { + void testGetFeatures() { assertEquals(Arrays.asList(FEATURE1, FEATURE2), ipc.getFeatures()); } @Test - public void testGetFeatureProviders() { + void testGetFeatureProviders() { assertEquals(providers, ipc.getFeatureProviders()); } @Test - public void testGetFeatureProvider() { + void testGetFeatureProvider() { // null name assertThatIllegalArgumentException().isThrownBy(() -> ipc.getFeatureProvider(null)); @@ -411,7 +413,7 @@ public class PolicyControllerFactoryTest { } @Test - public void testControllerType() { + void testControllerType() { PolicyControllerFactory factory = new IndexedPolicyControllerFactory(); Properties props = new Properties(); diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyDroolsPdpRuntimeExceptionTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyDroolsPdpRuntimeExceptionTest.java index 64595178..f4b26307 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyDroolsPdpRuntimeExceptionTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyDroolsPdpRuntimeExceptionTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,15 +23,15 @@ package org.onap.policy.drools.system; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.test.ExceptionsTester; -public class PolicyDroolsPdpRuntimeExceptionTest { +class PolicyDroolsPdpRuntimeExceptionTest { @Test - public void test() { + void test() { assertEquals(2, new ExceptionsTester().test(PolicyDroolsPdpRuntimeException.class)); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java index 93c0f348..4006c9ed 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineManagerTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2022 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,13 @@ import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; 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.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doThrow; @@ -50,9 +51,9 @@ import java.util.Properties; import java.util.concurrent.ScheduledExecutorService; import java.util.function.BiConsumer; import java.util.function.Consumer; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -80,7 +81,7 @@ import org.onap.policy.drools.system.internal.SimpleLockManager; import org.onap.policy.drools.system.internal.SimpleLockProperties; import org.onap.policy.models.pdp.enums.PdpResponseStatus; -public class PolicyEngineManagerTest { +class PolicyEngineManagerTest { private static final String EXPECTED = "expected exception"; private static final String NOOP_STR = CommInfrastructure.NOOP.name(); @@ -158,7 +159,7 @@ public class PolicyEngineManagerTest { * * @throws Exception if an error occurs */ - @Before + @BeforeEach public void setUp() throws Exception { CollectorRegistry.defaultRegistry.clear(); properties = new Properties(); @@ -324,13 +325,13 @@ public class PolicyEngineManagerTest { mgr = new PolicyEngineManagerImpl(); } - @After + @AfterEach public void tearDown() { CollectorRegistry.defaultRegistry.clear(); } @Test - public void testSerialize() { + void testSerialize() { mgr.setHostName("foo"); mgr.setClusterName("bar"); mgr.configure(properties); @@ -338,7 +339,7 @@ public class PolicyEngineManagerTest { } @Test - public void testFactory() { + void testFactory() { mgr = new PolicyEngineManager(); assertNotNull(mgr.getEngineProviders()); @@ -353,7 +354,7 @@ public class PolicyEngineManagerTest { } @Test - public void testBoot() throws Exception { + void testBoot() throws Exception { String[] args = {"boot-a", "boot-b"}; // arrange for first provider to throw exceptions @@ -392,7 +393,7 @@ public class PolicyEngineManagerTest { } @Test - public void testSetEnvironment_testGetEnvironment_testGetEnvironmentProperty_setEnvironmentProperty() { + void testSetEnvironment_testGetEnvironment_testGetEnvironmentProperty_setEnvironmentProperty() { Properties props1 = new Properties(); props1.put("prop1-a", "value1-a"); props1.put("prop1-b", "value1-b"); @@ -440,14 +441,14 @@ public class PolicyEngineManagerTest { } @Test - public void testDefaultTelemetryConfig() { + void testDefaultTelemetryConfig() { Properties config = mgr.defaultTelemetryConfig(); assertNotNull(config); assertFalse(config.isEmpty()); } @Test - public void testGetPdpName() { + void testGetPdpName() { properties.setProperty(PolicyEngineManager.CLUSTER_NAME_PROP, "east1"); mgr.configure(properties); @@ -480,7 +481,7 @@ public class PolicyEngineManagerTest { * property. */ @Test - public void testMakeExecutorServicePropertyProvided() { + void testMakeExecutorServicePropertyProvided() { PolicyEngineManager mgrspy = spy(mgr); properties.setProperty(PolicyEngineManager.EXECUTOR_THREAD_PROP, "3"); @@ -494,7 +495,7 @@ public class PolicyEngineManagerTest { * property is provided. */ @Test - public void testMakeExecutorServiceNoProperty() { + void testMakeExecutorServiceNoProperty() { PolicyEngineManager mgrspy = spy(mgr); mgrspy.configure(properties); @@ -507,7 +508,7 @@ public class PolicyEngineManagerTest { * property is invalid. */ @Test - public void testMakeExecutorServiceInvalidProperty() { + void testMakeExecutorServiceInvalidProperty() { PolicyEngineManager mgrspy = spy(mgr); properties.setProperty(PolicyEngineManager.EXECUTOR_THREAD_PROP, "abc"); @@ -521,7 +522,7 @@ public class PolicyEngineManagerTest { * manager. */ @Test - public void testCreateLockManagerHaveProvider() { + void testCreateLockManagerHaveProvider() { // first provider throws an exception when(prov1.beforeCreateLockManager(any(), any())).thenThrow(new RuntimeException(EXPECTED)); @@ -533,7 +534,7 @@ public class PolicyEngineManagerTest { * Tests createLockManager() when SimpleLockManager throws an exception. */ @Test - public void testCreateLockManagerSimpleEx() { + void testCreateLockManagerSimpleEx() { when(prov2.beforeCreateLockManager(any(), any())).thenReturn(null); // invalid property for SimpleLockManager @@ -541,22 +542,22 @@ public class PolicyEngineManagerTest { mgr.configure(properties); // should create a manager using default properties - assertTrue(mgr.getLockManager() instanceof SimpleLockManager); + assertInstanceOf(SimpleLockManager.class, mgr.getLockManager()); } /** * Tests createLockManager() when SimpleLockManager is returned. */ @Test - public void testCreateLockManagerSimple() { + void testCreateLockManagerSimple() { when(prov2.beforeCreateLockManager(any(), any())).thenReturn(null); mgr.configure(properties); - assertTrue(mgr.getLockManager() instanceof SimpleLockManager); + assertInstanceOf(SimpleLockManager.class, mgr.getLockManager()); } @Test - public void testConfigureProperties() throws Exception { + void testConfigureProperties() throws Exception { // arrange for first provider to throw exceptions when(prov1.beforeConfigure(mgr, properties)).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterConfigure(mgr)).thenThrow(new RuntimeException(EXPECTED)); @@ -605,7 +606,7 @@ public class PolicyEngineManagerTest { } @Test - public void testConfigurePdpdConfiguration() throws Exception { + void testConfigurePdpdConfiguration() throws Exception { mgr.configure(properties); assertTrue(mgr.configure(pdpConfig)); @@ -630,7 +631,7 @@ public class PolicyEngineManagerTest { } @Test - public void testCreatePolicyController() throws Exception { + void testCreatePolicyController() throws Exception { assertEquals(controller, mgr.createPolicyController(MY_NAME, properties)); verify(contProv1).beforeCreate(MY_NAME, properties); @@ -698,7 +699,7 @@ public class PolicyEngineManagerTest { } @Test - public void testUpdatePolicyControllers() throws Exception { + void testUpdatePolicyControllers() throws Exception { assertEquals(Arrays.asList(controller3, controller4), mgr.updatePolicyControllers(pdpConfig.getControllers())); // controller3 was CREATE @@ -730,7 +731,7 @@ public class PolicyEngineManagerTest { } @Test - public void testUpdatePolicyController() throws Exception { + void testUpdatePolicyController() throws Exception { assertEquals(controller3, mgr.updatePolicyController(config3)); verify(engine).createPolicyController(CONTROLLER3, properties); @@ -825,7 +826,7 @@ public class PolicyEngineManagerTest { } @Test - public void testStart() throws Throwable { + void testStart() throws Throwable { // normal success case testStart(true, () -> { // arrange for first provider, server, source, and sink to throw exceptions @@ -935,7 +936,7 @@ public class PolicyEngineManagerTest { } @Test - public void testStop() throws Throwable { + void testStop() throws Throwable { // normal success case testStop(true, () -> { // arrange for first provider, server, source, and sink to throw exceptions @@ -1043,7 +1044,7 @@ public class PolicyEngineManagerTest { } @Test - public void testShutdown() throws Throwable { + void testShutdown() throws Throwable { // normal success case testShutdown(() -> { // arrange for first provider, source, and sink to throw exceptions @@ -1112,7 +1113,7 @@ public class PolicyEngineManagerTest { } @Test - public void testShutdownThreadRun() throws Throwable { + void testShutdownThreadRun() throws Throwable { // arrange for first server to throw exceptions testShutdownThreadRun(() -> doThrow(new RuntimeException(EXPECTED)).when(server1).shutdown()); @@ -1148,7 +1149,7 @@ public class PolicyEngineManagerTest { } @Test - public void testIsAlive() { + void testIsAlive() { mgr.configure(properties); assertFalse(mgr.isAlive()); @@ -1160,7 +1161,7 @@ public class PolicyEngineManagerTest { } @Test - public void testLock() throws Throwable { + void testLock() throws Throwable { // normal success case testLock(true, () -> { // arrange for first provider to throw exceptions @@ -1237,7 +1238,7 @@ public class PolicyEngineManagerTest { } @Test - public void testUnlock() throws Throwable { + void testUnlock() throws Throwable { // normal success case testUnlock(true, () -> { // arrange for first provider to throw exceptions @@ -1314,7 +1315,7 @@ public class PolicyEngineManagerTest { } @Test - public void testIsLocked() { + void testIsLocked() { mgr.configure(properties); assertFalse(mgr.isLocked()); @@ -1326,31 +1327,31 @@ public class PolicyEngineManagerTest { } @Test - public void testRemovePolicyControllerString() { + void testRemovePolicyControllerString() { mgr.removePolicyController(MY_NAME); verify(controllerFactory).destroy(MY_NAME); } @Test - public void testRemovePolicyControllerPolicyController() { + void testRemovePolicyControllerPolicyController() { mgr.removePolicyController(controller); verify(controllerFactory).destroy(controller); } @Test - public void testGetPolicyControllers() { + void testGetPolicyControllers() { assertEquals(controllers, mgr.getPolicyControllers()); } @Test - public void testGetPolicyControllerIds() { + void testGetPolicyControllerIds() { assertEquals(Arrays.asList(CONTROLLER1, CONTROLLER2), mgr.getPolicyControllerIds()); } @Test - public void testGetProperties() { + void testGetProperties() { properties.setProperty("prop-x", "value-x"); properties.setProperty("prop-y", "value-y"); @@ -1359,35 +1360,35 @@ public class PolicyEngineManagerTest { } @Test - public void testGetSources() { + void testGetSources() { mgr.configure(properties); assertEquals(sources, mgr.getSources()); } @Test - public void testGetSinks() { + void testGetSinks() { mgr.configure(properties); assertEquals(sinks, mgr.getSinks()); } @Test - public void testGetHttpServers() { + void testGetHttpServers() { mgr.configure(properties); assertEquals(servers, mgr.getHttpServers()); } @Test - public void testGetFeatures() { + void testGetFeatures() { assertEquals(Arrays.asList(FEATURE1, FEATURE2), mgr.getFeatures()); } @Test - public void testGetFeatureProviders() { + void testGetFeatureProviders() { assertEquals(providers, mgr.getFeatureProviders()); } @Test - public void testGetFeatureProvider() { + void testGetFeatureProvider() { assertEquals(prov1, mgr.getFeatureProvider(FEATURE1)); assertEquals(prov2, mgr.getFeatureProvider(FEATURE2)); @@ -1402,7 +1403,7 @@ public class PolicyEngineManagerTest { } @Test - public void testTransaction() { + void testTransaction() { mgr.metric(CONTROLLER1, POLICY, new Metric()); assertEquals(0, mgr.getStats().getGroupStat().getPolicyExecutedCount()); assertEquals(0, mgr.getStats().getSubgroupStats().size()); @@ -1434,7 +1435,7 @@ public class PolicyEngineManagerTest { } @Test - public void testOnTopicEvent() { + void testOnTopicEvent() { mgr.onTopicEvent(CommInfrastructure.NOOP, MY_TOPIC, pdpConfigJson); verify(controllerFactory).patch(controller3, drools3); @@ -1448,7 +1449,7 @@ public class PolicyEngineManagerTest { } @Test - public void testDeliverStringObject() throws Exception { + void testDeliverStringObject() throws Exception { mgr.configure(properties); mgr.start(); @@ -1492,7 +1493,7 @@ public class PolicyEngineManagerTest { } @Test - public void testDeliverStringStringObject() { + void testDeliverStringStringObject() { mgr.configure(properties); mgr.start(); @@ -1523,7 +1524,7 @@ public class PolicyEngineManagerTest { } @Test - public void testDeliverCommInfrastructureStringObject() throws Exception { + void testDeliverCommInfrastructureStringObject() throws Exception { mgr.configure(properties); mgr.start(); @@ -1590,7 +1591,7 @@ public class PolicyEngineManagerTest { } @Test - public void testDeliverCommInfrastructureStringString() { + void testDeliverCommInfrastructureStringString() { mgr.configure(properties); // not started yet @@ -1622,7 +1623,7 @@ public class PolicyEngineManagerTest { } @Test - public void testActivate() throws Throwable { + void testActivate() throws Throwable { // normal success case testActivate(() -> { // arrange for first provider and controller to throw exceptions @@ -1679,7 +1680,7 @@ public class PolicyEngineManagerTest { } @Test - public void testDeactivate() throws Throwable { + void testDeactivate() throws Throwable { // normal success case testDeactivate(() -> { // arrange for first provider and controller to throw exceptions @@ -1733,7 +1734,7 @@ public class PolicyEngineManagerTest { } @Test - public void testCreateLock() { + void testCreateLock() { Lock lock = mock(Lock.class); LockCallback callback = mock(LockCallback.class); when(lockmgr.createLock(MY_RESOURCE, MY_OWNER, 10, callback, false)).thenReturn(lock); @@ -1759,7 +1760,7 @@ public class PolicyEngineManagerTest { } @Test - public void testOpen() throws Throwable { + void testOpen() throws Throwable { when(prov1.beforeOpen(mgr)).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterOpen(mgr)).thenThrow(new RuntimeException(EXPECTED)); @@ -1814,7 +1815,7 @@ public class PolicyEngineManagerTest { } @Test - public void testControllerConfig() throws Exception { + void testControllerConfig() throws Exception { mgr.configure(properties); assertTrue(mgr.configure(pdpConfig)); @@ -1845,7 +1846,7 @@ public class PolicyEngineManagerTest { } @Test - public void testToString() { + void testToString() { assertTrue(mgr.toString().startsWith("PolicyEngineManager(")); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java index 2054d91d..a6b8ac3f 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2022 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,9 +22,9 @@ package org.onap.policy.drools.system; import static org.awaitility.Awaitility.await; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.IOException; @@ -32,11 +33,11 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Properties; import java.util.concurrent.TimeUnit; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runners.MethodSorters; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; 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.bus.NoopTopicFactories; @@ -55,8 +56,8 @@ import org.slf4j.LoggerFactory; * PolicyEngine unit tests. */ -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class PolicyEngineTest { +@TestMethodOrder(MethodOrderer.DisplayName.class) +class PolicyEngineTest { /** * Default Telemetry port for JUnits. */ @@ -132,9 +133,9 @@ public class PolicyEngineTest { * * @throws IOException throws IO exception */ - @BeforeClass - public static void startUp() throws IOException { - logger.info("enter"); + @BeforeAll + static void startUp() throws IOException { + logger.info("startUp"); gson = new GsonTestUtils(); @@ -147,14 +148,8 @@ public class PolicyEngineTest { } } - @AfterClass - public static void tearDown() { - logger.info("enter"); - cleanUpWorkingDir(); - } - @Test - public void test100Configure() { + void test100Configure() { var manager = (PolicyEngineManager) PolicyEngineConstants.getManager(); var engineProps = manager.defaultTelemetryConfig(); @@ -177,7 +172,7 @@ public class PolicyEngineTest { } @Test - public void test200Start() { + void test200Start() { logger.info("enter"); PolicyEngineConstants.getManager().start(); @@ -189,7 +184,7 @@ public class PolicyEngineTest { } @Test - public void test300Lock() { + void test300Lock() { logger.info("enter"); PolicyEngineConstants.getManager().lock(); @@ -201,7 +196,7 @@ public class PolicyEngineTest { } @Test - public void test301Unlock() { + void test301Unlock() { logger.info("enter"); PolicyEngineConstants.getManager().unlock(); @@ -213,7 +208,7 @@ public class PolicyEngineTest { } @Test - public void test350TopicDeliver() { + void test350TopicDeliver() { final Properties noopSinkProperties = new Properties(); noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, NOOP_TOPIC); @@ -236,7 +231,7 @@ public class PolicyEngineTest { } @Test - public void test400ControllerAdd() { + void test400ControllerAdd() { logger.info("enter"); final Properties controllerProperties = new Properties(); @@ -251,7 +246,7 @@ public class PolicyEngineTest { } @Test - public void test401ControllerVerify() { + void test401ControllerVerify() { logger.info("enter"); final PolicyController testController = PolicyControllerConstants.getFactory().get(TEST_CONTROLLER_NAME); @@ -266,7 +261,7 @@ public class PolicyEngineTest { } @Test - public void test500Deactivate() { + void test500Deactivate() { logger.info("enter"); PolicyEngineConstants.getManager().deactivate(); @@ -279,7 +274,7 @@ public class PolicyEngineTest { } @Test - public void test501Activate() { + void test501Activate() { logger.info("enter"); PolicyEngineConstants.getManager().activate(); @@ -292,7 +287,7 @@ public class PolicyEngineTest { } @Test - public void test900ControllerRemove() { + void test900ControllerRemove() { logger.info("enter"); PolicyEngineConstants.getManager().removePolicyController(TEST_CONTROLLER_NAME); @@ -300,7 +295,7 @@ public class PolicyEngineTest { } @Test - public void test901Stop() { + void test901Stop() { logger.info("enter"); /* Shutdown managed resources */ diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java index a6aa9d9d..bc81a3cb 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +24,11 @@ package org.onap.policy.drools.system.internal; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; 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.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -39,8 +41,8 @@ import java.util.List; import java.util.Properties; import java.util.function.BiConsumer; import java.util.function.Consumer; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; import org.onap.policy.common.endpoints.event.comm.TopicSink; @@ -53,7 +55,7 @@ import org.onap.policy.drools.persistence.SystemPersistence; import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; import org.onap.policy.drools.system.GsonMgmtTestBuilder; -public class AggregatedPolicyControllerTest { +class AggregatedPolicyControllerTest { private static final String AGG_NAME = "agg-name"; private static final String SINK_TOPIC1 = "sink-a"; @@ -93,7 +95,7 @@ public class AggregatedPolicyControllerTest { /** * Initializes the object to be tested. */ - @Before + @BeforeEach public void setUp() { properties = new Properties(); @@ -144,7 +146,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testFactory() { + void testFactory() { apc = new AggregatedPolicyController(AGG_NAME, properties); assertNotNull(apc.getDroolsFactory()); assertNotNull(apc.getEndpointManager()); @@ -153,32 +155,34 @@ public class AggregatedPolicyControllerTest { } @Test - public void testAggregatedPolicyController_() { + void testAggregatedPolicyController_() { verify(persist).storeController(AGG_NAME, properties); } - @Test(expected = IllegalArgumentException.class) - public void testInitDrools_Ex() { + @Test + void testInitDrools_Ex() { + assertThrows(IllegalArgumentException.class, () -> new AggregatedPolicyControllerImpl(AGG_NAME, properties) { @Override protected DroolsControllerFactory getDroolsFactory() { throw new RuntimeException(EXPECTED); } - }; + }); } - @Test(expected = IllegalArgumentException.class) - public void testInitDrools_Error() { + @Test + void testInitDrools_Error() { + assertThrows(IllegalArgumentException.class, () -> new AggregatedPolicyControllerImpl(AGG_NAME, properties) { @Override protected DroolsControllerFactory getDroolsFactory() { throw new LinkageError(EXPECTED); } - }; + }); } @Test - public void testUpdateDrools_ConfigVariations() { + void testUpdateDrools_ConfigVariations() { // config should return same values as current controller when(config.getArtifactId()).thenReturn(ARTIFACT1.toUpperCase()); @@ -233,7 +237,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testUpdateDrools_LockVariations() { + void testUpdateDrools_LockVariations() { // not locked apc.updateDrools(config); verify(drools, never()).lock(); @@ -248,7 +252,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testUpdateDrools_AliveVariations() { + void testUpdateDrools_AliveVariations() { // not started apc.updateDrools(config); verify(drools, never()).start(); @@ -263,19 +267,19 @@ public class AggregatedPolicyControllerTest { } @Test - public void testSerialize() { + void testSerialize() { GsonTestUtils gson = new GsonMgmtTestBuilder().addDroolsControllerMock().addTopicSinkMock().addTopicSourceMock() .build(); assertThatCode(() -> gson.compareGson(apc, AggregatedPolicyControllerTest.class)).doesNotThrowAnyException(); } @Test - public void testGetName() { + void testGetName() { assertEquals(AGG_NAME, apc.getName()); } @Test - public void testStart() { + void testStart() { // arrange for first provider to throw exceptions when(prov1.beforeStart(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterStart(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -310,7 +314,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testStart_AlreadyStarted() { + void testStart_AlreadyStarted() { apc.start(); // re-start it @@ -329,7 +333,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testStart_Locked() { + void testStart_Locked() { apc.lock(); // start it @@ -347,7 +351,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testStop() { + void testStop() { // arrange for first provider to throw exceptions when(prov1.beforeStop(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterStop(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -387,7 +391,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testStop_AlreadyStopped() { + void testStop_AlreadyStopped() { apc.start(); apc.stop(); @@ -404,7 +408,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testShutdown() { + void testShutdown() { // arrange for first provider to throw exceptions when(prov1.beforeShutdown(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterShutdown(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -444,7 +448,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testHalt() { + void testHalt() { // arrange for first provider to throw exceptions when(prov1.beforeHalt(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterHalt(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -485,7 +489,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testOnTopicEvent() { + void testOnTopicEvent() { // arrange for first provider to throw exceptions when(prov1.beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT)) .thenThrow(new RuntimeException(EXPECTED)); @@ -522,7 +526,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testOnTopicEvent_Locked() { + void testOnTopicEvent_Locked() { // start it apc.start(); @@ -540,7 +544,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testOnTopicEvent_NotStarted() { + void testOnTopicEvent_NotStarted() { // offer it apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); @@ -554,7 +558,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testDeliver_testInitSinks() { + void testDeliver_testInitSinks() { // arrange for first provider to throw exceptions when(prov1.beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)) .thenThrow(new RuntimeException(EXPECTED)); @@ -598,42 +602,43 @@ public class AggregatedPolicyControllerTest { prov -> verify(prov).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true)); } - @Test(expected = IllegalArgumentException.class) - public void testDeliver_NullTopic() { - validateDeliverFailure(null, MY_EVENT); + @Test + void testDeliver_NullTopic() { + assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure(null, MY_EVENT)); } - @Test(expected = IllegalArgumentException.class) - public void testDeliver_EmptyTopic() { - validateDeliverFailure("", MY_EVENT); + @Test + void testDeliver_EmptyTopic() { + assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure("", MY_EVENT)); } - @Test(expected = IllegalArgumentException.class) - public void testDeliver_NullEvent() { - validateDeliverFailure(SINK_TOPIC1, null); + @Test + void testDeliver_NullEvent() { + assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure(SINK_TOPIC1, null)); } - @Test(expected = IllegalStateException.class) - public void testDeliver_NotStarted() { + @Test + void testDeliver_NotStarted() { // do NOT start - apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + assertThrows(IllegalStateException.class, () -> apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)); } - @Test(expected = IllegalStateException.class) - public void testDeliver_Locked() { + @Test + void testDeliver_Locked() { apc.start(); apc.lock(); - apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + assertThrows(IllegalStateException.class, () -> apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)); } - @Test(expected = IllegalArgumentException.class) - public void testDeliver_UnknownTopic() { + @Test + void testDeliver_UnknownTopic() { apc.start(); - apc.deliver(CommInfrastructure.NOOP, "unknown-topic", MY_EVENT); + assertThrows(IllegalArgumentException.class, + () -> apc.deliver(CommInfrastructure.NOOP, "unknown-topic", MY_EVENT)); } @Test - public void testIsAlive() { + void testIsAlive() { assertFalse(apc.isAlive()); apc.start(); @@ -644,7 +649,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testLock() { + void testLock() { // arrange for first provider to throw exceptions when(prov1.beforeLock(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterLock(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -678,7 +683,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testLock_AlreadyLocked() { + void testLock_AlreadyLocked() { apc.start(); apc.lock(); @@ -697,7 +702,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testUnlock() { + void testUnlock() { // arrange for first provider to throw exceptions when(prov1.beforeUnlock(any())).thenThrow(new RuntimeException(EXPECTED)); when(prov1.afterUnlock(any())).thenThrow(new RuntimeException(EXPECTED)); @@ -733,7 +738,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testUnlock_NotLocked() { + void testUnlock_NotLocked() { apc.start(); // now unlock it @@ -750,7 +755,7 @@ public class AggregatedPolicyControllerTest { } @Test - public void testIsLocked() { + void testIsLocked() { assertFalse(apc.isLocked()); apc.lock(); @@ -761,27 +766,27 @@ public class AggregatedPolicyControllerTest { } @Test - public void testGetTopicSources() { + void testGetTopicSources() { assertEquals(sources, apc.getTopicSources()); } @Test - public void testGetTopicSinks() { + void testGetTopicSinks() { assertEquals(sinks, apc.getTopicSinks()); } @Test - public void testGetDrools() { + void testGetDrools() { assertEquals(drools, apc.getDrools()); } @Test - public void testGetProperties() { + void testGetProperties() { assertEquals(properties, apc.getProperties()); } @Test - public void testToString() { + void testToString() { assertTrue(apc.toString().startsWith("AggregatedPolicyController(")); } diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java index 2ba7cde9..23511abd 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/FeatureLockImplTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,12 +24,12 @@ package org.onap.policy.drools.system.internal; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -40,15 +40,18 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serial; import java.util.concurrent.ScheduledExecutorService; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.policy.drools.core.DroolsRunnable; import org.onap.policy.drools.core.PolicySession; import org.onap.policy.drools.core.lock.LockCallback; @@ -56,8 +59,8 @@ import org.onap.policy.drools.core.lock.LockState; import org.onap.policy.drools.system.PolicyEngineConstants; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(MockitoJUnitRunner.class) -public class FeatureLockImplTest { +@ExtendWith(MockitoExtension.class) +class FeatureLockImplTest { private static final String POLICY_ENGINE_EXECUTOR_FIELD = "executorService"; private static final String OWNER_KEY = "my key"; private static final String RESOURCE = "my resource"; @@ -72,11 +75,13 @@ public class FeatureLockImplTest { @Mock private LockCallback callback; + AutoCloseable closeable; + /** * Saves static fields and configures the location of the property files. */ - @BeforeClass - public static void setUpBeforeClass() { + @BeforeAll + static void setUpBeforeClass() { saveExec = (ScheduledExecutorService) ReflectionTestUtils.getField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD); } @@ -84,8 +89,8 @@ public class FeatureLockImplTest { /** * Restores static fields. */ - @AfterClass - public static void tearDownAfterClass() { + @AfterAll + static void tearDownAfterClass() { ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, saveExec); } @@ -93,13 +98,19 @@ public class FeatureLockImplTest { * Initializes the mocks and creates a feature that uses {@link #exsvc} to execute * tasks. */ - @Before - public void setUp() { + @BeforeEach + void setUp() { + closeable = MockitoAnnotations.openMocks(this); ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, exsvc); } + @AfterEach + void closeMocks() throws Exception { + closeable.close(); + } + @Test - public void testNoArgs() { + void testNoArgs() { MyLock lock = new MyLock(); assertNull(lock.getResourceId()); assertNull(lock.getOwnerKey()); @@ -108,7 +119,7 @@ public class FeatureLockImplTest { } @Test - public void testFeatureLockImpl() { + void testFeatureLockImpl() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); assertTrue(lock.isWaiting()); assertEquals(RESOURCE, lock.getResourceId()); @@ -118,7 +129,7 @@ public class FeatureLockImplTest { } @Test - public void testSerializable() throws Exception { + void testSerializable() throws Exception { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock = roundTrip(lock); @@ -131,14 +142,14 @@ public class FeatureLockImplTest { } @Test - public void testGrant() { + void testGrant() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock.grant(); assertTrue(lock.isActive()); assertEquals(1, lock.nupdates); - invokeCallback(1); + invokeCallback(); verify(callback).lockAvailable(any()); verify(callback, never()).lockUnavailable(any()); } @@ -147,7 +158,7 @@ public class FeatureLockImplTest { * Tests grant() when the lock is already unavailable. */ @Test - public void testGrantUnavailable() { + void testGrantUnavailable() { MyLock lock = new MyLock(LockState.UNAVAILABLE, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock.setState(LockState.UNAVAILABLE); lock.grant(); @@ -159,13 +170,13 @@ public class FeatureLockImplTest { } @Test - public void testDeny() { + void testDeny() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock.deny("my reason"); assertTrue(lock.isUnavailable()); - invokeCallback(1); + invokeCallback(); verify(callback, never()).lockAvailable(any()); verify(callback).lockUnavailable(any()); } @@ -174,10 +185,11 @@ public class FeatureLockImplTest { * Tests doNotify() when a session exists. */ @Test - public void testDoNotifySession() { + void testDoNotifySession() { PolicySession session = mock(PolicySession.class); MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback) { + @Serial private static final long serialVersionUID = 1L; @Override @@ -207,20 +219,20 @@ public class FeatureLockImplTest { * Tests doNotify() when there is no session. */ @Test - public void testDoNotifyNoSession() { + void testDoNotifyNoSession() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock.grant(); assertTrue(lock.isActive()); assertEquals(1, lock.nupdates); - invokeCallback(1); + invokeCallback(); verify(callback).lockAvailable(any()); verify(callback, never()).lockUnavailable(any()); } @Test - public void testFreeAllowed() { + void testFreeAllowed() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); assertTrue(lock.freeAllowed()); } @@ -229,7 +241,7 @@ public class FeatureLockImplTest { * Tests freeAllowed() when the lock is unavailable. */ @Test - public void testFreeAllowedUnavailable() { + void testFreeAllowedUnavailable() { MyLock lock = new MyLock(LockState.UNAVAILABLE, RESOURCE, OWNER_KEY, HOLD_SEC, callback); assertFalse(lock.freeAllowed()); assertTrue(lock.isUnavailable()); @@ -241,7 +253,7 @@ public class FeatureLockImplTest { * @throws Exception if an error occurs */ @Test - public void testFreeAllowedSerialized() throws Exception { + void testFreeAllowedSerialized() throws Exception { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock = roundTrip(lock); @@ -254,7 +266,7 @@ public class FeatureLockImplTest { * @throws Exception if an error occurs */ @Test - public void testFreeAllowedNoFeature() throws Exception { + void testFreeAllowedNoFeature() throws Exception { MyLock lock = new MyLockNoFeature(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock = roundTrip(lock); @@ -263,7 +275,7 @@ public class FeatureLockImplTest { } @Test - public void testExtendAllowed() { + void testExtendAllowed() { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); LockCallback scallback = mock(LockCallback.class); @@ -288,7 +300,7 @@ public class FeatureLockImplTest { * Tests extendAllowed() when the lock is unavailable. */ @Test - public void testExtendAllowedUnavailable() { + void testExtendAllowedUnavailable() { MyLock lock = new MyLock(LockState.UNAVAILABLE, RESOURCE, OWNER_KEY, HOLD_SEC, callback); LockCallback scallback = mock(LockCallback.class); @@ -297,7 +309,7 @@ public class FeatureLockImplTest { assertEquals(HOLD_SEC2, lock.getHoldSec()); assertSame(scallback, lock.getCallback()); - invokeCallback(1); + invokeCallback(); verify(scallback, never()).lockAvailable(lock); verify(scallback).lockUnavailable(lock); } @@ -308,7 +320,7 @@ public class FeatureLockImplTest { * @throws Exception if an error occurs */ @Test - public void testExtendAllowedSerialized() throws Exception { + void testExtendAllowedSerialized() throws Exception { MyLock lock = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock = roundTrip(lock); @@ -328,7 +340,7 @@ public class FeatureLockImplTest { * @throws Exception if an error occurs */ @Test - public void testExtendAllowedNoFeature() throws Exception { + void testExtendAllowedNoFeature() throws Exception { MyLock lock = new MyLockNoFeature(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); lock = roundTrip(lock); @@ -339,21 +351,21 @@ public class FeatureLockImplTest { assertEquals(HOLD_SEC2, lock.getHoldSec()); assertSame(scallback, lock.getCallback()); - invokeCallback(1); + invokeCallback(); verify(scallback, never()).lockAvailable(lock); verify(scallback).lockUnavailable(lock); } @Test - public void testGetSession() { + void testGetSession() { MyLockStdSession lock = new MyLockStdSession(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback); // this should invoke the real policy session without throwing an exception - assertThatCode(() -> lock.grant()).doesNotThrowAnyException(); + assertThatCode(lock::grant).doesNotThrowAnyException(); } @Test - public void testToString() { + void testToString() { String text = new MyLock(LockState.WAITING, RESOURCE, OWNER_KEY, HOLD_SEC, callback).toString(); assertNotNull(text); assertThat(text).contains("LockImpl"); @@ -374,21 +386,18 @@ public class FeatureLockImplTest { /** * Invokes the last call-back in the work queue. * - * @param nexpected number of call-backs expected in the work queue */ - private void invokeCallback(int nexpected) { + private void invokeCallback() { ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); - verify(exsvc, times(nexpected)).execute(captor.capture()); - - if (nexpected > 0) { - captor.getAllValues().get(nexpected - 1).run(); - } + verify(exsvc, times(1)).execute(captor.capture()); + captor.getAllValues().get(0).run(); } /** * Lock that inherits the normal getSession() method. */ public static class MyLockStdSession extends FeatureLockImpl { + @Serial private static final long serialVersionUID = 1L; protected int nupdates = 0; @@ -424,6 +433,7 @@ public class FeatureLockImplTest { } public static class MyLock extends MyLockStdSession { + @Serial private static final long serialVersionUID = 1L; public MyLock() { @@ -441,6 +451,7 @@ public class FeatureLockImplTest { } public static class MyLockNoFeature extends MyLock { + @Serial private static final long serialVersionUID = 1L; public MyLockNoFeature() { diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/LockManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/LockManagerTest.java index 3617c445..74e1a9c1 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/LockManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/LockManagerTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +21,10 @@ package org.onap.policy.drools.system.internal; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; @@ -31,10 +33,11 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.Serial; import java.util.concurrent.ScheduledExecutorService; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.policy.drools.core.lock.AlwaysFailLock; @@ -42,7 +45,7 @@ import org.onap.policy.drools.core.lock.Lock; import org.onap.policy.drools.core.lock.LockCallback; import org.onap.policy.drools.core.lock.LockState; -public class LockManagerTest { +class LockManagerTest { private static final String OWNER_KEY = "my key"; private static final String RESOURCE = "my resource"; private static final String RESOURCE2 = "my resource #2"; @@ -56,12 +59,14 @@ public class LockManagerTest { private MyManager mgr; + private AutoCloseable closeable; + /** * Resets fields and creates {@link #mgr}. */ - @Before + @BeforeEach public void setUp() { - MockitoAnnotations.openMocks(this); + closeable = MockitoAnnotations.openMocks(this); doAnswer(args -> { args.getArgument(0, Runnable.class).run(); @@ -71,13 +76,13 @@ public class LockManagerTest { mgr = new MyManager(); } - @After - public void tearDown() { - + @AfterEach + public void tearDown() throws Exception { + closeable.close(); } @Test - public void testIsAlive() { + void testIsAlive() { assertFalse(mgr.isAlive()); assertFalse(mgr.isLocked()); @@ -90,7 +95,7 @@ public class LockManagerTest { } @Test - public void testStart() { + void testStart() { assertTrue(mgr.start()); assertTrue(mgr.isAlive()); @@ -103,7 +108,7 @@ public class LockManagerTest { } @Test - public void testStop() { + void testStop() { assertFalse(mgr.stop()); mgr.start(); @@ -112,7 +117,7 @@ public class LockManagerTest { } @Test - public void testShutdown() { + void testShutdown() { mgr.start(); mgr.shutdown(); assertFalse(mgr.isAlive()); @@ -122,7 +127,7 @@ public class LockManagerTest { } @Test - public void testIsLocked() { + void testIsLocked() { assertFalse(mgr.isLocked()); assertFalse(mgr.isAlive()); @@ -135,7 +140,7 @@ public class LockManagerTest { } @Test - public void testLock() { + void testLock() { assertTrue(mgr.lock()); assertTrue(mgr.isLocked()); @@ -148,7 +153,7 @@ public class LockManagerTest { } @Test - public void testUnlock() { + void testUnlock() { assertFalse(mgr.unlock()); mgr.lock(); @@ -157,7 +162,7 @@ public class LockManagerTest { } @Test - public void testCreateLock() { + void testCreateLock() { Lock lock = mgr.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); assertTrue(lock.isActive()); verify(callback).lockAvailable(lock); @@ -182,12 +187,12 @@ public class LockManagerTest { * Tests createLock() when the feature instance has changed. */ @Test - public void testCreateLockInstanceChanged() { + void testCreateLockInstanceChanged() { mgr = spy(mgr); when(mgr.hasInstanceChanged()).thenReturn(true); Lock lock = mgr.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); - assertTrue(lock instanceof AlwaysFailLock); + assertInstanceOf(AlwaysFailLock.class, lock); assertTrue(lock.isUnavailable()); verify(callback, never()).lockAvailable(lock); @@ -195,7 +200,7 @@ public class LockManagerTest { } @Test - public void testGetResource2lock() { + void testGetResource2lock() { assertNotNull(mgr.getResource2lock()); } @@ -220,6 +225,7 @@ public class LockManagerTest { } private class MyLock extends FeatureLockImpl { + @Serial private static final long serialVersionUID = 1L; public MyLock(LockState waiting, String resourceId, String ownerKey, int holdSec, LockCallback callback) { diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerExceptionTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerExceptionTest.java index 3e4e5762..fdf840b2 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerExceptionTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerExceptionTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,15 +21,15 @@ package org.onap.policy.drools.system.internal; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.test.ExceptionsTester; -public class SimpleLockManagerExceptionTest extends ExceptionsTester { +class SimpleLockManagerExceptionTest extends ExceptionsTester { @Test - public void test() { + void test() { assertEquals(1, test(SimpleLockManagerException.class)); } } diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerTest.java index 4491a73b..3ee5583a 100644 --- a/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerTest.java +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/SimpleLockManagerTest.java @@ -3,7 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2023 Nordix Foundation. + * Modifications Copyright (C) 2023-2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 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.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyLong; @@ -44,6 +44,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.Serial; import java.util.ArrayList; import java.util.List; import java.util.Properties; @@ -53,15 +54,17 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.kie.api.runtime.KieSession; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.onap.policy.common.utils.time.CurrentTime; import org.onap.policy.common.utils.time.TestTime; import org.onap.policy.drools.core.PolicySession; @@ -72,8 +75,8 @@ import org.onap.policy.drools.system.PolicyEngineConstants; import org.onap.policy.drools.system.internal.SimpleLockManager.SimpleLock; import org.springframework.test.util.ReflectionTestUtils; -@RunWith(MockitoJUnitRunner.class) -public class SimpleLockManagerTest { +@ExtendWith(MockitoExtension.class) +class SimpleLockManagerTest { private static final String POLICY_ENGINE_EXECUTOR_FIELD = "executorService"; private static final String TIME_FIELD = "currentTime"; private static final String OWNER_KEY = "my key"; @@ -91,7 +94,6 @@ public class SimpleLockManagerTest { private static ScheduledExecutorService saveExec; private static ScheduledExecutorService realExec; - private PolicySession session; private TestTime testTime; private AtomicInteger nactive; private AtomicInteger nsuccesses; @@ -109,11 +111,13 @@ public class SimpleLockManagerTest { @Mock private LockCallback callback; + AutoCloseable closeable; + /** * Saves static fields and configures the location of the property files. */ - @BeforeClass - public static void setUpBeforeClass() { + @BeforeAll + static void setUpBeforeClass() { saveTime = (CurrentTime) ReflectionTestUtils.getField(SimpleLockManager.class, TIME_FIELD); saveExec = (ScheduledExecutorService) ReflectionTestUtils.getField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD); @@ -124,8 +128,8 @@ public class SimpleLockManagerTest { /** * Restores static fields. */ - @AfterClass - public static void tearDownAfterClass() { + @AfterAll + static void tearDownAfterClass() { ReflectionTestUtils.setField(SimpleLockManager.class, TIME_FIELD, saveTime); ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, saveExec); @@ -136,10 +140,11 @@ public class SimpleLockManagerTest { * Initializes the mocks and creates a feature that uses {@link #exsvc} to execute * tasks. */ - @Before - public void setUp() { + @BeforeEach + void setUp() { + closeable = MockitoAnnotations.openMocks(this); // grant() and deny() calls will come through here and be immediately executed - session = new PolicySession(null, null, kieSess) { + PolicySession session = new PolicySession(null, null, kieSess) { @Override public void insertDrools(Object object) { ((Runnable) object).run(); @@ -160,11 +165,16 @@ public class SimpleLockManagerTest { feature.start(); } + @AfterEach + void closeMocks() throws Exception { + closeable.close(); + } + /** * Tests constructor() when properties are invalid. */ @Test - public void testSimpleLockManagerInvalidProperties() { + void testSimpleLockManagerInvalidProperties() { // use properties containing an invalid value Properties props = new Properties(); props.setProperty(SimpleLockProperties.EXPIRE_CHECK_SEC, "abc"); @@ -173,7 +183,7 @@ public class SimpleLockManagerTest { } @Test - public void testStart() { + void testStart() { assertTrue(feature.isAlive()); verify(exsvc).scheduleWithFixedDelay(any(), anyLong(), anyLong(), any()); @@ -184,7 +194,7 @@ public class SimpleLockManagerTest { } @Test - public void testStop() { + void testStop() { assertTrue(feature.stop()); assertFalse(feature.isAlive()); verify(future).cancel(true); @@ -196,16 +206,16 @@ public class SimpleLockManagerTest { } @Test - public void testShutdown() { + void testShutdown() { feature.shutdown(); verify(future).cancel(true); } @Test - public void testCreateLock() { + void testCreateLock() { // this lock should be granted immediately - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); assertTrue(lock.isActive()); assertEquals(testTime.getMillis() + HOLD_MS, lock.getHoldUntilMs()); @@ -236,7 +246,7 @@ public class SimpleLockManagerTest { * Tests createLock() when the feature is not the latest instance. */ @Test - public void testCreateLockNotLatestInstance() { + void testCreateLockNotLatestInstance() { SimpleLockManager.setLatestInstance(null); Lock lock = feature.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); @@ -246,10 +256,10 @@ public class SimpleLockManagerTest { } @Test - public void testCheckExpired() throws InterruptedException { - final SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); - final SimpleLock lock2 = getLock(RESOURCE2, OWNER_KEY, HOLD_SEC, callback, false); - final SimpleLock lock3 = getLock(RESOURCE3, OWNER_KEY, HOLD_SEC2, callback, false); + void testCheckExpired() throws InterruptedException { + final SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); + final SimpleLock lock2 = getLock(RESOURCE2, HOLD_SEC, callback); + final SimpleLock lock3 = getLock(RESOURCE3, HOLD_SEC2, callback); ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class); verify(exsvc).scheduleWithFixedDelay(captor.capture(), anyLong(), anyLong(), any()); @@ -292,15 +302,15 @@ public class SimpleLockManagerTest { * Tests checkExpired(), where the lock is removed from the map between invoking * expired() and compute(). Should cause "null" to be returned by compute(). * - * @throws InterruptedException if the test is interrupted */ @Test - public void testCheckExpiredLockDeleted() throws InterruptedException { + void testCheckExpiredLockDeleted() { feature = new MyLockingFeature() { @Override protected SimpleLock makeLock(LockState waiting, String resourceId, String ownerKey, int holdSec, LockCallback callback) { return new SimpleLock(waiting, resourceId, ownerKey, holdSec, callback, feature) { + @Serial private static final long serialVersionUID = 1L; @Override @@ -343,7 +353,7 @@ public class SimpleLockManagerTest { * @throws InterruptedException if the test is interrupted */ @Test - public void testCheckExpiredLockReplaced() throws InterruptedException { + void testCheckExpiredLockReplaced() throws InterruptedException { feature = new MyLockingFeature() { private boolean madeLock = false; @@ -357,6 +367,7 @@ public class SimpleLockManagerTest { madeLock = true; return new SimpleLock(waiting, resourceId, ownerKey, holdSec, callback, feature) { + @Serial private static final long serialVersionUID = 1L; @Override @@ -388,7 +399,7 @@ public class SimpleLockManagerTest { } @Test - public void testGetThreadPool() { + void testGetThreadPool() { // use a real feature feature = new SimpleLockManager(null, new Properties()); @@ -403,7 +414,7 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockNoArgs() { + void testSimpleLockNoArgs() { SimpleLock lock = new SimpleLock(); assertNull(lock.getResourceId()); assertNull(lock.getOwnerKey()); @@ -414,8 +425,8 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockSimpleLock() { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockSimpleLock() { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); assertEquals(RESOURCE, lock.getResourceId()); assertEquals(OWNER_KEY, lock.getOwnerKey()); assertSame(callback, lock.getCallback()); @@ -427,8 +438,8 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockSerializable() throws Exception { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockSerializable() throws Exception { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); lock = roundTrip(lock); assertTrue(lock.isActive()); @@ -440,8 +451,8 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockExpired() { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockExpired() { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); lock.grant(); assertFalse(lock.expired(testTime.getMillis())); @@ -450,11 +461,11 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockFree() { - final SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockFree() { + final SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); // lock2 should be denied - SimpleLock lock2 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + SimpleLock lock2 = getLock(RESOURCE, HOLD_SEC, callback); verify(callback, never()).lockAvailable(lock2); verify(callback).lockUnavailable(lock2); @@ -470,7 +481,7 @@ public class SimpleLockManagerTest { assertEquals(LockState.UNAVAILABLE, lock.getState()); // should be able to get the lock now - SimpleLock lock3 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + SimpleLock lock3 = getLock(RESOURCE, HOLD_SEC, callback); assertTrue(lock3.isActive()); verify(callback).lockAvailable(lock3); @@ -483,8 +494,8 @@ public class SimpleLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testSimpleLockFreeSerialized() throws Exception { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockFreeSerialized() throws Exception { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); feature = new MyLockingFeature(); feature.start(); @@ -495,11 +506,11 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockExtend() { - final SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockExtend() { + final SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); // lock2 should be denied - SimpleLock lock2 = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + SimpleLock lock2 = getLock(RESOURCE, HOLD_SEC, callback); verify(callback, never()).lockAvailable(lock2); verify(callback).lockUnavailable(lock2); @@ -529,8 +540,8 @@ public class SimpleLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testSimpleLockExtendSerialized() throws Exception { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockExtendSerialized() throws Exception { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); feature = new MyLockingFeature(); feature.start(); @@ -551,8 +562,8 @@ public class SimpleLockManagerTest { * @throws Exception if an error occurs */ @Test - public void testSimpleLockExtendNoFeature() throws Exception { - SimpleLock lock = getLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false); + void testSimpleLockExtendNoFeature() throws Exception { + SimpleLock lock = getLock(RESOURCE, HOLD_SEC, callback); SimpleLockManager.setLatestInstance(null); @@ -567,7 +578,7 @@ public class SimpleLockManagerTest { } @Test - public void testSimpleLockToString() { + void testSimpleLockToString() { String text = feature.createLock(RESOURCE, OWNER_KEY, HOLD_SEC, callback, false).toString(); assertNotNull(text); assertThat(text).contains("holdUntil").doesNotContain("ownerInfo").doesNotContain("callback"); @@ -580,7 +591,7 @@ public class SimpleLockManagerTest { * the background threads to complete */ @Test - public void testMultiThreaded() throws InterruptedException { + void testMultiThreaded() throws InterruptedException { ReflectionTestUtils.setField(SimpleLockManager.class, TIME_FIELD, testTime); ReflectionTestUtils.setField(PolicyEngineConstants.getManager(), POLICY_ENGINE_EXECUTOR_FIELD, realExec); feature = new SimpleLockManager(null, new Properties()); @@ -607,9 +618,8 @@ public class SimpleLockManagerTest { assertTrue(nsuccesses.get() > 0); } - private SimpleLock getLock(String resource, String ownerKey, int holdSec, LockCallback callback, - boolean waitForLock) { - return (SimpleLock) feature.createLock(resource, ownerKey, holdSec, callback, waitForLock); + private SimpleLock getLock(String resource, int holdSec, LockCallback callback) { + return (SimpleLock) feature.createLock(resource, SimpleLockManagerTest.OWNER_KEY, holdSec, callback, false); } private SimpleLock roundTrip(SimpleLock lock) throws Exception { @@ -646,7 +656,7 @@ public class SimpleLockManagerTest { } /** - * Thread used with the multi-threaded test. It repeatedly attempts to get a lock, + * Thread used with the multithreaded test. It repeatedly attempts to get a lock, * extend it, and then unlock it. */ private class MyThread extends Thread { diff --git a/policy-management/src/test/resources/echo.kmodule b/policy-management/src/test/resources/echo.kmodule index 496f7098..9abadcb5 100644 --- a/policy-management/src/test/resources/echo.kmodule +++ b/policy-management/src/test/resources/echo.kmodule @@ -4,6 +4,7 @@ ONAP ================================================================================ Copyright (C) 2018-2019 AT&T Intellectual Property. All rights reserved. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,7 @@ ============LICENSE_END========================================================= --> - + diff --git a/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestAdd.json b/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestAdd.json index 576315ec..42fd3554 100644 --- a/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestAdd.json +++ b/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestAdd.json @@ -14,7 +14,6 @@ "sniHostCheck": false, "user": null, "alive": true, - "aaf": false, "prometheus": false } ], diff --git a/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestConfig.json b/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestConfig.json index 69a10480..d7838e01 100644 --- a/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestConfig.json +++ b/policy-management/src/test/resources/org/onap/policy/drools/system/PolicyEngineTestConfig.json @@ -11,7 +11,6 @@ "sniHostCheck": false, "user": null, "alive": false, - "aaf": false, "prometheus": false } ], diff --git a/policy-management/src/test/resources/rules.kmodule b/policy-management/src/test/resources/rules.kmodule index 4f3f8745..f7752c82 100644 --- a/policy-management/src/test/resources/rules.kmodule +++ b/policy-management/src/test/resources/rules.kmodule @@ -4,6 +4,7 @@ ONAP ================================================================================ Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + Modifications Copyright (C) 2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -19,7 +20,7 @@ ============LICENSE_END========================================================= --> - + diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java index 8afc1e1e..5e77ee4b 100644 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java +++ b/policy-utils/src/main/java/org/onap/policy/drools/utils/ReflectionUtil.java @@ -3,6 +3,7 @@ * policy-utils * ================================================================================ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +33,7 @@ import org.slf4j.LoggerFactory; @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ReflectionUtil { - protected static final Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); + private static final Logger logger = LoggerFactory.getLogger(ReflectionUtil.class); /** * returns (if exists) a class fetched from a given classloader. @@ -75,11 +76,11 @@ public final class ReflectionUtil { } /** - * Is it a sub class. + * Is it a subclass. * * @param parent superclass * @param presumedSubclass subclass - * @return true if it is a sub class + * @return true if it is a subclass */ public static boolean isSubclass(Class parent, Class presumedSubclass) { return parent.isAssignableFrom(presumedSubclass); diff --git a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java b/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java deleted file mode 100644 index 10788eb8..00000000 --- a/policy-utils/src/main/java/org/onap/policy/drools/utils/logging/LoggerUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * Copyright (C) 2017-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.utils.logging; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -/** - * Loger Utils. - */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public final class LoggerUtil { - - /** - * Logback configuration file system property. - */ - public static final String LOGBACK_CONFIGURATION_FILE_SYSTEM_PROPERTY = "logback.configurationFile"; - - /** - * Logback default configuration file location. - */ - public static final String LOGBACK_CONFIGURATION_FILE_DEFAULT = "config/logback.xml"; - -} diff --git a/policy-utils/src/test/java/org/onap/policy/drools/metrics/MetricTest.java b/policy-utils/src/test/java/org/onap/policy/drools/metrics/MetricTest.java index 5a5965c4..924d1c95 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/metrics/MetricTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/metrics/MetricTest.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +23,10 @@ package org.onap.policy.drools.metrics; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import com.openpojo.reflection.PojoClass; import com.openpojo.reflection.impl.PojoClassFactory; @@ -39,12 +40,12 @@ import java.text.SimpleDateFormat; import java.time.Duration; import java.time.Instant; import java.util.Date; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class MetricTest { +class MetricTest { @Test - public void testPojo() { + void testPojo() { PojoClass metric = PojoClassFactory.getPojoClass(Metric.class); Validator val = ValidatorBuilder .create() @@ -57,7 +58,7 @@ public class MetricTest { } @Test - public void testEndTimeSetter() { + void testEndTimeSetter() { Metric metric = new Metric(); assertNull(metric.getEndTime()); @@ -66,7 +67,7 @@ public class MetricTest { } @Test - public void testStartTimeSetter() { + void testStartTimeSetter() { Metric metric = new Metric(); assertNull(metric.getStartTime()); @@ -75,7 +76,7 @@ public class MetricTest { } @Test - public void testElapsedTimeSetter() { + void testElapsedTimeSetter() { Metric metric = new Metric(); assertNull(metric.getElapsedTime()); @@ -96,7 +97,7 @@ public class MetricTest { } @Test - public void testInvocationIdSetter() { + void testInvocationIdSetter() { Metric metric = new Metric(); assertNull(metric.getInvocationId()); @@ -105,7 +106,7 @@ public class MetricTest { } @Test - public void testServiceNameSetter() { + void testServiceNameSetter() { Metric metric = new Metric(); assertNull(metric.getServiceName()); @@ -114,7 +115,7 @@ public class MetricTest { } @Test - public void testInstanceUuidSetter() { + void testInstanceUuidSetter() { Metric metric = new Metric(); assertNull(metric.getInstanceUuid()); @@ -123,7 +124,7 @@ public class MetricTest { } @Test - public void testRequestIdSetter() { + void testRequestIdSetter() { Metric metric = new Metric(); assertNull(metric.getRequestId()); @@ -132,7 +133,7 @@ public class MetricTest { } @Test - public void testPartnerSetter() { + void testPartnerSetter() { Metric metric = new Metric(); assertNull(metric.getPartner()); @@ -141,7 +142,7 @@ public class MetricTest { } @Test - public void testServerNameSetter() { + void testServerNameSetter() { Metric metric = new Metric(); assertNull(metric.getServerName()); @@ -150,7 +151,7 @@ public class MetricTest { } @Test - public void testServerFqdnSetter() { + void testServerFqdnSetter() { Metric metric = new Metric(); assertNull(metric.getServerFqdn()); @@ -159,7 +160,7 @@ public class MetricTest { } @Test - public void testVirtualServerNameSetter() { + void testVirtualServerNameSetter() { Metric metric = new Metric(); assertNull(metric.getVirtualServerName()); @@ -168,7 +169,7 @@ public class MetricTest { } @Test - public void testEqualsToString() { + void testEqualsToString() { Metric metric1 = new Metric(); Metric metric2 = new Metric(); @@ -185,7 +186,7 @@ public class MetricTest { } @Test - public void testToTimestamp() { + void testToTimestamp() { Instant now = Instant.now(); assertEquals(new SimpleDateFormat(Metric.DATE_FORMAT).format(Date.from(now)), Metric.toTimestamp(now)); } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Metadata.java b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Metadata.java index 0cad4ff0..e81bdd05 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Metadata.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Metadata.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ package org.onap.policy.drools.models.domains.a; import com.google.gson.annotations.SerializedName; +import java.io.Serial; import java.io.Serializable; import lombok.Builder; import lombok.Data; @@ -28,6 +30,7 @@ import lombok.Data; @Data @Builder public class Metadata implements Serializable { + @Serial private static final long serialVersionUID = 476541531265304644L; @SerializedName("policy-id") diff --git a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Nested.java b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Nested.java index eedadeff..1d46d59d 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Nested.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Nested.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ package org.onap.policy.drools.models.domains.a; import com.google.gson.annotations.SerializedName; +import java.io.Serial; import java.io.Serializable; import lombok.Builder; import lombok.Data; @@ -28,6 +30,7 @@ import lombok.Data; @Data @Builder public class Nested implements Serializable { + @Serial private static final long serialVersionUID = -1203143214137354429L; @SerializedName("nested1") diff --git a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Properties.java b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Properties.java index 3ba66ce9..e323e8ac 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Properties.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/models/domains/a/Properties.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +22,7 @@ package org.onap.policy.drools.models.domains.a; import com.google.gson.annotations.SerializedName; +import java.io.Serial; import java.io.Serializable; import lombok.Builder; import lombok.Data; @@ -28,6 +30,7 @@ import lombok.Data; @Data @Builder public class Properties implements Serializable { + @Serial private static final long serialVersionUID = 8476625479607243095L; @SerializedName("nested") diff --git a/policy-utils/src/test/java/org/onap/policy/drools/policies/DomainMakerTest.java b/policy-utils/src/test/java/org/onap/policy/drools/policies/DomainMakerTest.java index 2c883304..5563d5ea 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/policies/DomainMakerTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/policies/DomainMakerTest.java @@ -1,7 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. - * Modifications Copyright (C) 2021 Nordix Foundation. + * Modifications Copyright (C) 2021, 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,17 +22,17 @@ package org.onap.policy.drools.policies; 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.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import com.worldturner.medeia.api.ValidationFailedException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.drools.models.domains.a.DomainAPolicy; @@ -43,17 +43,17 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; -public class DomainMakerTest { +class DomainMakerTest { private DomainMaker domainMaker; - @Before + @BeforeEach public void setUp() throws Exception { domainMaker = new DomainMaker(); } @Test - public void testIsConformantString() throws IOException { + void testIsConformantString() throws IOException { ToscaConceptIdentifier policyTypeId = new ToscaConceptIdentifier("policy.type.A", "1.0.0"); String rawJsonPolicyType = @@ -66,7 +66,7 @@ public class DomainMakerTest { } @Test - public void testIsConformantToscaPolicy() throws IOException, CoderException { + void testIsConformantToscaPolicy() throws IOException, CoderException { ToscaPolicy policy = getToscaPolicy("src/test/resources/policyA.json"); assertTrue(domainMaker.isConformant(policy)); @@ -75,7 +75,7 @@ public class DomainMakerTest { } @Test - public void testIsDomainConformant() { + void testIsDomainConformant() { ToscaConceptIdentifier policyTypeId = new ToscaConceptIdentifier("policy.type.A", "1.0.0"); @@ -95,7 +95,7 @@ public class DomainMakerTest { @Test - public void testConformance() throws IOException, CoderException { + void testConformance() throws IOException, CoderException { ToscaPolicy policy1 = getToscaPolicy("src/test/resources/policyA.json"); assertTrue(domainMaker.conformance(policy1)); @@ -116,7 +116,7 @@ public class DomainMakerTest { } @Test - public void testRegisterValidator() throws IOException, CoderException { + void testRegisterValidator() throws IOException, CoderException { ToscaConceptIdentifier policyTypeId = new ToscaConceptIdentifier("policy.type.external", "9.9.9"); @@ -133,7 +133,7 @@ public class DomainMakerTest { } @Test - public void testConvertToDomainPolicy() throws IOException, CoderException { + void testConvertToDomainPolicy() throws IOException, CoderException { DomainAPolicy domainAPolicy = domainMaker.convertTo(getToscaPolicy("src/test/resources/policyA.json"), DomainAPolicy.class); assertDomainPolicy(domainAPolicy); @@ -143,7 +143,7 @@ public class DomainMakerTest { } @Test - public void testConvertToSchema() { + void testConvertToSchema() { ToscaPolicyType type = new ToscaPolicyType(); assertThatThrownBy(() -> domainMaker .convertToSchema(type)) @@ -151,7 +151,7 @@ public class DomainMakerTest { } @Test - public void testIsRegistered() { + void testIsRegistered() { ToscaConceptIdentifier policyTypeId1 = new ToscaConceptIdentifier("policy.type.A", "1.0.0"); assertTrue(domainMaker.isRegistered(policyTypeId1)); @@ -189,7 +189,7 @@ public class DomainMakerTest { assertEquals("policy.type.A", domainAPolicy.getType()); assertEquals("A", domainAPolicy.getMetadata().getPolicyId()); assertEquals("nested1", domainAPolicy.getProperties().getNested().getNested1()); - assertEquals(true, domainAPolicy.getProperties().getNested().isNested2()); + assertTrue(domainAPolicy.getProperties().getNested().isNested2()); assertEquals(50, domainAPolicy.getProperties().getNested().getNested3()); } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java index c19adea4..f2676e5d 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/PropertyUtilTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,20 +21,22 @@ package org.onap.policy.drools.utils; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Arrays; +import java.util.Objects; import java.util.Properties; import java.util.Set; import java.util.TreeSet; import java.util.UUID; import org.apache.commons.lang3.StringUtils; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.logging.LoggerUtils; import org.onap.policy.common.utils.security.CryptoUtils; import org.slf4j.Logger; @@ -84,7 +87,7 @@ public class PropertyUtilTest { /** * Test Setup -- Create a directory for temporary files. */ - @BeforeClass + @BeforeAll public static void setup() { logger.info("setup: creating a temporary directory"); @@ -96,15 +99,15 @@ public class PropertyUtilTest { /** * Test Cleanup -- Remove temporary files. */ - @AfterClass + @AfterAll public static void teardown() { logger.info("teardown: remove the temporary directory"); // the assumption is that we only have one level of temporary files - for (File file : directory.listFiles()) { - file.delete(); + for (File file : Objects.requireNonNull(directory.listFiles())) { + assertTrue(file.delete()); } - directory.delete(); + assertTrue(directory.delete()); } /** @@ -153,7 +156,7 @@ public class PropertyUtilTest { * Test the basic properties file interface. */ @Test - public void testGetProperties() throws Exception { + void testGetProperties() throws Exception { logger.info("testGetProperties: test the basic properties file interface"); // copy system properties @@ -253,7 +256,7 @@ public class PropertyUtilTest { * This tests the 'PropertyUtil.Listener' interface. */ @Test - public void testListenerInterface() throws Exception { + void testListenerInterface() throws Exception { logger.info("testListenerInterface: test receipt of dynamic updates"); // create initial property file diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java index 8afe4626..c8c08d9d 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReferenceTest.java @@ -3,6 +3,7 @@ * ONAP * ================================================================================ * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,17 +21,17 @@ package org.onap.policy.drools.utils; -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.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class ReferenceTest { +class ReferenceTest { @Test - public void testReference() { + void testReference() { Reference val = new Reference<>(null); assertNull(val.get()); @@ -39,7 +40,7 @@ public class ReferenceTest { } @Test - public void testGet_testSet() { + void testGet_testSet() { Reference val = new Reference<>(null); assertNull(val.get()); @@ -51,7 +52,7 @@ public class ReferenceTest { } @Test - public void testCompareAndSet() { + void testCompareAndSet() { Reference val = new Reference<>(null); Integer valCompare = 100; diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java index b7feaf06..cd1aac43 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/ReflectionUtilTest.java @@ -3,6 +3,7 @@ * policy-utils * ================================================================================ * Copyright (C) 2017-2018, 2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,26 +21,27 @@ package org.onap.policy.drools.utils; -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.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; -import org.junit.Test; +import org.junit.jupiter.api.Test; -public class ReflectionUtilTest { +class ReflectionUtilTest { public class ParentClass { } - public class ChildClass extends ParentClass{ + class ChildClass extends ParentClass{ } @Test - public void testReflection() { + void testReflection() { try { @@ -61,25 +63,27 @@ public class ReflectionUtilTest { } } - @Test(expected = IllegalArgumentException.class) - public void testException1() { - ReflectionUtil.fetchClass(null, "org.onap.policy.drools.utils.ReflectionUtil"); + @Test + void testException1() { + assertThrows(IllegalArgumentException.class, () -> + ReflectionUtil.fetchClass(null, "org.onap.policy.drools.utils.ReflectionUtil")); } - @Test(expected = IllegalArgumentException.class) - public void testException2() { + @Test + void testException2() { Class class1; try { class1 = Class.forName("org.onap.policy.drools.utils.ReflectionUtil"); ClassLoader classLoader = class1.getClassLoader(); - ReflectionUtil.fetchClass(classLoader, null); + assertThrows(IllegalArgumentException.class, () -> + ReflectionUtil.fetchClass(classLoader, null)); } catch (ClassNotFoundException e) { fail(); } } @Test - public void testException3() throws ClassNotFoundException { + void testException3() { assertNull(ReflectionUtil.fetchClass(ClassLoader.getSystemClassLoader(), "foo.bar")); } } diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java index 195a7add..524d46e4 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/LoggerUtilTest.java @@ -3,6 +3,7 @@ * policy-utils * ================================================================================ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,18 +21,18 @@ package org.onap.policy.drools.utils.logging; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.common.utils.logging.LoggerUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class LoggerUtilTest { +class LoggerUtilTest { @Test - public void test() { + void test() { Logger logger = LoggerFactory.getLogger(LoggerUtilTest.class); diff --git a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java index 213c1c6e..2beddcc3 100644 --- a/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java +++ b/policy-utils/src/test/java/org/onap/policy/drools/utils/logging/MdcTransactionTest.java @@ -3,6 +3,7 @@ * policy-utils * ================================================================================ * Copyright (C) 2018-2020 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2024 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,20 +20,20 @@ package org.onap.policy.drools.utils.logging; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import java.time.Duration; import java.time.Instant; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.slf4j.MDC; -public class MdcTransactionTest { +class MdcTransactionTest { @Test - public void testResetSubTransaction() { + void testResetSubTransaction() { MdcTransaction trans = MdcTransaction.newTransaction(null, null).resetSubTransaction(); @@ -88,7 +89,7 @@ public class MdcTransactionTest { private void assertNullKeys(String... nullKeys) { for (String key: nullKeys) { - assertNull(key, MDC.get(key)); + assertNull(MDC.get(key)); } } @@ -126,7 +127,7 @@ public class MdcTransactionTest { } @Test - public void testFlush() { + void testFlush() { MdcTransaction trans = MdcTransaction.newTransaction() .setRequestId(null) @@ -198,12 +199,12 @@ public class MdcTransactionTest { } private void assertKeyEquals(String expected, String transValue, String mdcKey) { - assertEquals("trans." + expected, expected, transValue); - assertEquals("mdc." + expected, expected, MDC.get(mdcKey)); + assertEquals(expected, transValue, "trans." + expected); + assertEquals(expected, MDC.get(mdcKey), "mdc." + expected); } @Test - public void testMetric() { + void testMetric() { MdcTransaction trans = MdcTransaction.newTransaction(null, null).metric(); @@ -211,7 +212,7 @@ public class MdcTransactionTest { } @Test - public void testTransaction() { + void testTransaction() { MdcTransaction trans = MdcTransaction.newTransaction(null, null).transaction(); @@ -219,7 +220,7 @@ public class MdcTransactionTest { } @Test - public void testSubTransaction() { + void testSubTransaction() { MdcTransaction trans = MdcTransaction.newTransaction(null, "partner"); diff --git a/pom.xml b/pom.xml index 5a55e2e0..e2d29197 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ ONAP Policy Engine - Drools PDP ================================================================================ Copyright (C) 2017-2022 AT&T Intellectual Property. All rights reserved. - Modifications Copyright (C) 2020, 2023 Nordix Foundation. + Modifications Copyright (C) 2020, 2023-2024 Nordix Foundation. ================================================================================ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -48,7 +48,7 @@ content/repositories/staging/ - 2.8.0 + 2.9.0 6.0.6.Final 1.4.01 2.1.1-SNAPSHOT @@ -61,7 +61,7 @@ policy-domains policy-management feature-healthcheck - feature-pooling-dmaap + feature-pooling-messages feature-test-transaction feature-distributed-locking feature-lifecycle @@ -90,8 +90,8 @@ test - junit - junit + org.junit.jupiter + junit-jupiter-engine test @@ -99,6 +99,10 @@ mockito-core test + + org.mockito + mockito-junit-jupiter + org.assertj assertj-core -- cgit 1.2.3-korg