From 08dc9c33a66b1bdf7c35696576fcb44e7e072eb6 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Tue, 2 Oct 2018 16:46:57 -0400 Subject: Add coverage for policy-management Added coverage for PolicyControllerFactory and AggregatedPolicyController. Fixed some typos in comments. Reformatted some code. Change-Id: I33aea8e1e7dde29bd51218d0ecad7b34047b33e5 Issue-ID: POLICY-1148 Signed-off-by: Jim Hahn --- .../drools/system/PolicyControllerFactoryTest.java | 421 +++++++++ .../policy/drools/system/PolicyEngineTest.java | 295 +++++++ .../internal/AggregatedPolicyControllerTest.java | 948 +++++++++++++++++++++ .../drools/system/test/PolicyEngineTest.java | 295 ------- 4 files changed, 1664 insertions(+), 295 deletions(-) create mode 100644 policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java create mode 100644 policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java delete mode 100644 policy-management/src/test/java/org/onap/policy/drools/system/test/PolicyEngineTest.java (limited to 'policy-management/src/test/java/org/onap') 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 new file mode 100644 index 00000000..f5c71064 --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyControllerFactoryTest.java @@ -0,0 +1,421 @@ +/* + * ============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.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.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 static org.onap.policy.common.utils.test.PolicyAssert.assertThrows; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Properties; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; + +public class PolicyControllerFactoryTest { + + private static final String MY_NAME = "my-name-a"; + private static final String MY_NAME2 = "my-name-b"; + + private static final String ARTIFACT1 = "artifact-a"; + private static final String GROUP1 = "group-a"; + private static final String VERSION1 = "version-a"; + + private static final String ARTIFACT2 = "artifact-b"; + private static final String GROUP2 = "group-b"; + private static final String VERSION2 = "version-b"; + + private static final String FEATURE1 = "feature-a"; + private static final String FEATURE2 = "feature-b"; + + private PolicyController controller; + private PolicyController controller2; + private Properties properties; + private DroolsController drools; + private DroolsController drools2; + private DroolsConfiguration config; + private PolicyControllerFeatureAPI feature1; + private PolicyControllerFeatureAPI feature2; + private List providers; + private IndexedPolicyControllerFactory ipc; + + /** + * Initializes the object to be tested. + */ + @Before + public void setUp() { + controller = mock(PolicyController.class); + controller2 = mock(PolicyController.class); + properties = new Properties(); + drools = mock(DroolsController.class); + drools2 = mock(DroolsController.class); + config = mock(DroolsConfiguration.class); + feature1 = mock(PolicyControllerFeatureAPI.class); + feature2 = mock(PolicyControllerFeatureAPI.class); + providers = Arrays.asList(feature1, feature2); + + when(feature1.getName()).thenReturn(FEATURE1); + when(feature2.getName()).thenReturn(FEATURE2); + + when(drools.getArtifactId()).thenReturn(ARTIFACT1); + when(drools.getGroupId()).thenReturn(GROUP1); + when(drools.getVersion()).thenReturn(VERSION1); + + when(drools2.getArtifactId()).thenReturn(ARTIFACT2); + when(drools2.getGroupId()).thenReturn(GROUP2); + when(drools2.getVersion()).thenReturn(VERSION2); + + when(controller.getName()).thenReturn(MY_NAME); + when(controller.getDrools()).thenReturn(drools); + when(controller.updateDrools(any())).thenReturn(true); + + when(controller2.getName()).thenReturn(MY_NAME2); + when(controller2.getDrools()).thenReturn(drools2); + when(controller2.updateDrools(any())).thenReturn(true); + + ipc = new IndexedPolicyControllerFactoryImpl(); + } + + @Test + public void testFactory() { + // use a REAL object instead of an Impl + ipc = new IndexedPolicyControllerFactory(); + assertNotNull(ipc.getProviders()); + } + + @Test + public void testBuild() { + assertEquals(controller, ipc.build(MY_NAME, properties)); + + // re-build - should not create another one + assertEquals(controller, ipc.build(MY_NAME, properties)); + + // brained + setUp(); + when(drools.isBrained()).thenReturn(true); + ipc.build(MY_NAME, properties); + } + + @Test + public void testPatchStringDroolsConfiguration() { + // unknown controller + assertThrows(IllegalArgumentException.class, () -> ipc.patch(MY_NAME, config)); + + /* + * Build controller to be used by remaining tests. + */ + ipc.build(MY_NAME, properties); + + // null name + String nullName = null; + assertThrows(IllegalArgumentException.class, () -> ipc.patch(nullName, config)); + + // empty name + assertThrows(IllegalArgumentException.class, () -> ipc.patch("", config)); + + // success + ipc.patch(MY_NAME, config); + verify(controller).updateDrools(config); + + // create a factory whose get() method returns null + ipc = new IndexedPolicyControllerFactory() { + @Override + public PolicyController get(String name) { + return null; + } + }; + ipc.build(MY_NAME, properties); + assertThrows(IllegalArgumentException.class, () -> ipc.patch(MY_NAME, config)); + } + + @Test + public void testPatchPolicyControllerDroolsConfiguration() { + ipc.patch(controller, config); + verify(controller).updateDrools(config); + + // null controller + PolicyController nullCtlr = null; + assertThrows(IllegalArgumentException.class, () -> ipc.patch(nullCtlr, config)); + + // null config + assertThrows(IllegalArgumentException.class, () -> ipc.patch(controller, null)); + + // brained + when(drools.isBrained()).thenReturn(true); + ipc.patch(controller, config); + + // update failed + when(controller.updateDrools(config)).thenReturn(false); + assertThrows(IllegalArgumentException.class, () -> ipc.patch(controller, config)); + } + + @Test + public void testShutdownString() { + // null name + String nullName = null; + assertThrows(IllegalArgumentException.class, () -> ipc.shutdown(nullName)); + + // empty name + assertThrows(IllegalArgumentException.class, () -> ipc.shutdown("")); + + // unknown controller + ipc.shutdown(MY_NAME); + verify(controller, never()).shutdown(); + + // valid controller + ipc.build(MY_NAME, properties); + ipc.shutdown(MY_NAME); + verify(controller).shutdown(); + } + + @Test + public void testShutdownPolicyController() { + ipc.build(MY_NAME, properties); + + ipc.shutdown(controller); + + verify(controller).shutdown(); + + // should no longer be managed + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + } + + @Test + public void testShutdown() { + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + ipc.shutdown(); + + verify(controller).shutdown(); + verify(controller2).shutdown(); + + // should no longer be managed + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME2)); + } + + @Test + public void testUnmanage() { + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + ipc.shutdown(MY_NAME); + + verify(controller).shutdown(); + verify(controller2, never()).shutdown(); + + // should no longer be managed + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + + // should still be managed + assertEquals(controller2, ipc.get(MY_NAME2)); + + // null controller + PolicyController nullCtlr = null; + assertThrows(IllegalArgumentException.class, () -> ipc.shutdown(nullCtlr)); + + // unknown controller + ipc.shutdown(controller); + verify(controller, times(2)).shutdown(); + } + + @Test + public void testDestroyString() { + // null name + String nullName = null; + assertThrows(IllegalArgumentException.class, () -> ipc.destroy(nullName)); + + // empty name + assertThrows(IllegalArgumentException.class, () -> ipc.destroy("")); + + // unknown controller + ipc.destroy(MY_NAME); + verify(controller, never()).halt(); + + // valid controller + ipc.build(MY_NAME, properties); + ipc.destroy(MY_NAME); + verify(controller).halt(); + } + + @Test + public void testDestroyPolicyController() { + ipc.build(MY_NAME, properties); + + ipc.destroy(controller); + + verify(controller).halt(); + + // should no longer be managed + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + } + + @Test + public void testDestroy() { + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + ipc.destroy(); + + verify(controller).halt(); + verify(controller2).halt(); + + // should no longer be managed + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME2)); + } + + @Test + public void testGetString() { + // unknown name + assertThrows(IllegalArgumentException.class, () -> ipc.get(MY_NAME)); + + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + assertEquals(controller, ipc.get(MY_NAME)); + assertEquals(controller2, ipc.get(MY_NAME2)); + + // null name + String nullName = null; + assertThrows(IllegalArgumentException.class, () -> ipc.get(nullName)); + + // empty name + assertThrows(IllegalArgumentException.class, () -> ipc.get("")); + } + + @Test + public void testGetStringString_testToKey() { + // unknown controller + assertThrows(IllegalArgumentException.class, () -> ipc.get(GROUP1, ARTIFACT1)); + + when(drools.isBrained()).thenReturn(true); + when(drools2.isBrained()).thenReturn(true); + + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + assertEquals(controller, ipc.get(GROUP1, ARTIFACT1)); + assertEquals(controller2, ipc.get(GROUP2, ARTIFACT2)); + + // null group + assertThrows(IllegalArgumentException.class, () -> ipc.get(null, ARTIFACT1)); + + // empty group + assertThrows(IllegalArgumentException.class, () -> ipc.get("", ARTIFACT1)); + + // null artifact + assertThrows(IllegalArgumentException.class, () -> ipc.get(GROUP1, null)); + + // empty artifact + assertThrows(IllegalArgumentException.class, () -> ipc.get(GROUP1, "")); + } + + @Test + public void testGetDroolsController() { + // unknown controller + assertThrows(IllegalStateException.class, () -> ipc.get(drools)); + + when(drools.isBrained()).thenReturn(true); + when(drools2.isBrained()).thenReturn(true); + + ipc.build(MY_NAME, properties); + ipc.build(MY_NAME2, properties); + + assertEquals(controller, ipc.get(drools)); + assertEquals(controller2, ipc.get(drools2)); + + // null controller + DroolsController nullDrools = null; + assertThrows(IllegalArgumentException.class, () -> ipc.get(nullDrools)); + } + + @Test + public 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())); + assertEquals(Arrays.asList(controller, controller2), lst); + } + + @Test + public void testGetFeatures() { + assertEquals(Arrays.asList(FEATURE1, FEATURE2), ipc.getFeatures()); + } + + @Test + public void testGetFeatureProviders() { + assertEquals(providers, ipc.getFeatureProviders()); + } + + @Test + public void testGetFeatureProvider() { + // null name + assertThrows(IllegalArgumentException.class, () -> ipc.getFeatureProvider(null)); + + // empty name + assertThrows(IllegalArgumentException.class, () -> ipc.getFeatureProvider("")); + + // unknown name + assertThrows(IllegalArgumentException.class, () -> ipc.getFeatureProvider("unknown-feature")); + + assertEquals(feature1, ipc.getFeatureProvider(FEATURE1)); + assertEquals(feature2, ipc.getFeatureProvider(FEATURE2)); + } + + /** + * Factory with overrides. + */ + private class IndexedPolicyControllerFactoryImpl extends IndexedPolicyControllerFactory { + + @Override + protected PolicyController newPolicyController(String name, Properties properties) { + if (MY_NAME.equals(name)) { + return controller; + + } else if (MY_NAME2.equals(name)) { + return controller2; + + } else { + throw new IllegalArgumentException("unknown controller name: " + name); + + } + } + + @Override + protected List getProviders() { + return providers; + } + } +} 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 new file mode 100644 index 00000000..cd93d94c --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/system/PolicyEngineTest.java @@ -0,0 +1,295 @@ +/*- + * ============LICENSE_START======================================================= + * policy-management + * ================================================================================ + * Copyright (C) 2017-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.system; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +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.onap.policy.common.endpoints.event.comm.TopicEndpoint; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSink; +import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.properties.DroolsProperties; +import org.onap.policy.drools.protocol.coders.EventProtocolCoder; +import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.system.PolicyEngine; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * PolicyEngine unit tests. + */ + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class PolicyEngineTest { + /** + * Default Telemetry port for JUnits. + */ + public static final int DEFAULT_TELEMETRY_PORT = 9698; + + /** + * Test JUnit Controller Name. + */ + public static final String TEST_CONTROLLER_NAME = "foo"; + + /** + * Controller Configuration File. + */ + public static final String TEST_CONTROLLER_FILE = TEST_CONTROLLER_NAME + "-controller.properties"; + + /** + * Controller Configuration Backup File. + */ + public static final String TEST_CONTROLLER_FILE_BAK = TEST_CONTROLLER_FILE + ".bak"; + + /** + * Coder Group. + */ + private static final String ENCODER_GROUP = "foo"; + + /** + * Coder Artifact. + */ + private static final String ENCODER_ARTIFACT = "bar"; + + /** + * Coder Version. + */ + private static final String ENCODER_VERSION = null; + + /** + * noop topic. + */ + private static final String NOOP_TOPIC = "JUNIT"; + + /** + * logger. + */ + private static Logger logger = LoggerFactory.getLogger(PolicyEngineTest.class); + + /** + * clean up working directory. + */ + protected static void cleanUpWorkingDir() { + final Path testControllerPath = + Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE); + try { + Files.deleteIfExists(testControllerPath); + } catch (final Exception e) { + logger.info("Problem cleaning {}", testControllerPath, e); + } + + final Path testControllerBakPath = + Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK); + try { + Files.deleteIfExists(testControllerBakPath); + } catch (final Exception e) { + logger.info("Problem cleaning {}", testControllerBakPath, e); + } + } + + /** + * Start up. + * + * @throws IOException throws IO exception + */ + @BeforeClass + public static void startUp() throws IOException { + logger.info("enter"); + + cleanUpWorkingDir(); + + /* ensure presence of config directory */ + final Path configDir = Paths.get(SystemPersistence.DEFAULT_CONFIGURATION_DIR); + if (Files.notExists(configDir)) { + Files.createDirectories(configDir); + } + } + + @AfterClass + public static void tearDown() throws IOException { + logger.info("enter"); + cleanUpWorkingDir(); + } + + @Test + public void test100Configure() { + logger.info("enter"); + + final Properties engineProps = PolicyEngine.manager.defaultTelemetryConfig(); + + /* override default port */ + engineProps.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." + + PolicyEngine.TELEMETRY_SERVER_DEFAULT_NAME + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, + "" + DEFAULT_TELEMETRY_PORT); + + assertFalse(PolicyEngine.manager.isAlive()); + PolicyEngine.manager.configure(engineProps); + assertFalse(PolicyEngine.manager.isAlive()); + + logger.info("policy-engine {} has configuration {}", PolicyEngine.manager, engineProps); + } + + @Test + public void test200Start() { + logger.info("enter"); + + PolicyEngine.manager.start(); + + assertTrue(PolicyEngine.manager.isAlive()); + assertFalse(PolicyEngine.manager.isLocked()); + assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); + assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); + } + + @Test + public void test300Lock() { + logger.info("enter"); + + PolicyEngine.manager.lock(); + + assertTrue(PolicyEngine.manager.isAlive()); + assertTrue(PolicyEngine.manager.isLocked()); + assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); + assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); + } + + @Test + public void test301Unlock() { + logger.info("enter"); + + PolicyEngine.manager.unlock(); + + assertTrue(PolicyEngine.manager.isAlive()); + assertFalse(PolicyEngine.manager.isLocked()); + assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); + assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); + } + + @Test + public void test350TopicDeliver() { + final Properties noopSinkProperties = new Properties(); + noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, NOOP_TOPIC); + + TopicEndpoint.manager.addTopicSinks(noopSinkProperties).get(0).start(); + + EventProtocolCoder.manager.addEncoder(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC, + DroolsConfiguration.class.getCanonicalName(), new JsonProtocolFilter(), null, null, + DroolsConfiguration.class.getName().hashCode()); + + assertTrue(PolicyEngine.manager.deliver(NOOP_TOPIC, + new DroolsConfiguration(ENCODER_GROUP, ENCODER_ARTIFACT, ENCODER_VERSION))); + + final TopicSink sink = NoopTopicSink.factory.get(NOOP_TOPIC); + assertTrue(sink.getRecentEvents()[0].contains(ENCODER_GROUP)); + assertTrue(sink.getRecentEvents()[0].contains(ENCODER_ARTIFACT)); + + EventProtocolCoder.manager.removeEncoders(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC); + } + + @Test + public void test400ControllerAdd() throws Exception { + logger.info("enter"); + + final Properties controllerProperties = new Properties(); + controllerProperties.put(DroolsProperties.PROPERTY_CONTROLLER_NAME, TEST_CONTROLLER_NAME); + PolicyEngine.manager.createPolicyController(TEST_CONTROLLER_NAME, controllerProperties); + + assertTrue(PolicyController.factory.inventory().size() == 1); + } + + @Test + public void test401ControllerVerify() { + logger.info("enter"); + + final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); + + assertFalse(testController.isAlive()); + assertFalse(testController.isLocked()); + + testController.start(); + + assertTrue(testController.isAlive()); + assertFalse(testController.isLocked()); + } + + @Test + public void test500Deactivate() throws Exception { + logger.info("enter"); + + PolicyEngine.manager.deactivate(); + + final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); + assertFalse(testController.isAlive()); + assertTrue(testController.isLocked()); + assertTrue(PolicyEngine.manager.isLocked()); + assertTrue(PolicyEngine.manager.isAlive()); + } + + @Test + public void test501Activate() throws Exception { + logger.info("enter"); + + PolicyEngine.manager.activate(); + + final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); + assertTrue(testController.isAlive()); + assertFalse(testController.isLocked()); + assertFalse(PolicyEngine.manager.isLocked()); + assertTrue(PolicyEngine.manager.isAlive()); + } + + @Test + public void test900ControllerRemove() throws Exception { + logger.info("enter"); + + PolicyEngine.manager.removePolicyController(TEST_CONTROLLER_NAME); + assertTrue(PolicyController.factory.inventory().isEmpty()); + } + + @Test + public void test901Stop() throws InterruptedException { + logger.info("enter"); + + /* Shutdown managed resources */ + PolicyController.factory.shutdown(); + TopicEndpoint.manager.shutdown(); + PolicyEngine.manager.stop(); + + Thread.sleep(10000L); + assertFalse(PolicyEngine.manager.isAlive()); + } + +} 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 new file mode 100644 index 00000000..4f26419f --- /dev/null +++ b/policy-management/src/test/java/org/onap/policy/drools/system/internal/AggregatedPolicyControllerTest.java @@ -0,0 +1,948 @@ +/* + * ============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.system.internal; + +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.mockito.Matchers.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 static org.onap.policy.common.utils.test.PolicyAssert.assertThrows; + +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.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; +import org.onap.policy.common.endpoints.event.comm.TopicSource; +import org.onap.policy.drools.controller.DroolsController; +import org.onap.policy.drools.controller.DroolsControllerFactory; +import org.onap.policy.drools.features.PolicyControllerFeatureAPI; +import org.onap.policy.drools.persistence.SystemPersistence; +import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; +import org.onap.policy.drools.system.internal.AggregatedPolicyController.Factory; +import org.powermock.reflect.Whitebox; + +public class AggregatedPolicyControllerTest { + + /** + * Name of the "factory" field within the {@link AggregatedPolicyController} class. + */ + private static final String FACTORY_FIELD = "factory"; + + private static final String AGG_NAME = "agg-name"; + private static final String SINK_TOPIC1 = "sink-a"; + private static final String SINK_TOPIC2 = "sink-b"; + private static final String SOURCE_TOPIC1 = "source-a"; + private static final String SOURCE_TOPIC2 = "source-b"; + + private static final String EXPECTED = "expected exception"; + + private static final String MY_EVENT = "my-event"; + + private static final String ARTIFACT1 = "artifact-a"; + private static final String GROUP1 = "group-a"; + private static final String VERSION1 = "version-a"; + + private static final String ARTIFACT2 = "artifact-b"; + private static final String GROUP2 = "group-b"; + private static final String VERSION2 = "version-b"; + + private static Factory savedFactory; + + private Properties properties; + private Factory factory; + private TopicEndpoint endpointMgr; + private List sources; + private TopicSource source1; + private TopicSource source2; + private List sinks; + private TopicSink sink1; + private TopicSink sink2; + private SystemPersistence persist; + private DroolsControllerFactory droolsFactory; + private DroolsController drools; + private DroolsConfiguration config; + private List providers; + private PolicyControllerFeatureAPI prov1; + private PolicyControllerFeatureAPI prov2; + private AggregatedPolicyController apc; + + @BeforeClass + public static void setUpBeforeClass() { + savedFactory = Whitebox.getInternalState(AggregatedPolicyController.class, FACTORY_FIELD); + } + + @AfterClass + public static void tearDownAfterClass() { + Whitebox.setInternalState(AggregatedPolicyController.class, FACTORY_FIELD, savedFactory); + } + + /** + * Initializes the object to be tested. + */ + @Before + public void setUp() { + properties = new Properties(); + + source1 = mock(TopicSource.class); + source2 = mock(TopicSource.class); + when(source1.getTopic()).thenReturn(SOURCE_TOPIC1); + when(source2.getTopic()).thenReturn(SOURCE_TOPIC2); + + sink1 = mock(TopicSink.class); + sink2 = mock(TopicSink.class); + when(sink1.getTopic()).thenReturn(SINK_TOPIC1); + when(sink2.getTopic()).thenReturn(SINK_TOPIC2); + + sources = Arrays.asList(source1, source2); + sinks = Arrays.asList(sink1, sink2); + + endpointMgr = mock(TopicEndpoint.class); + when(endpointMgr.addTopicSources(any())).thenReturn(sources); + when(endpointMgr.addTopicSinks(any())).thenReturn(sinks); + + persist = mock(SystemPersistence.class); + + drools = mock(DroolsController.class); + when(drools.start()).thenReturn(true); + when(drools.stop()).thenReturn(true); + when(drools.offer(any(), any())).thenReturn(true); + when(drools.deliver(any(), any())).thenReturn(true); + when(drools.lock()).thenReturn(true); + when(drools.unlock()).thenReturn(true); + when(drools.getArtifactId()).thenReturn(ARTIFACT1); + when(drools.getGroupId()).thenReturn(GROUP1); + when(drools.getVersion()).thenReturn(VERSION1); + + config = mock(DroolsConfiguration.class); + when(config.getArtifactId()).thenReturn(ARTIFACT2); + when(config.getGroupId()).thenReturn(GROUP2); + when(config.getVersion()).thenReturn(VERSION2); + + droolsFactory = mock(DroolsControllerFactory.class); + when(droolsFactory.build(any(), any(), any())).thenReturn(drools); + + prov1 = mock(PolicyControllerFeatureAPI.class); + prov2 = mock(PolicyControllerFeatureAPI.class); + + providers = Arrays.asList(prov1, prov2); + + factory = mock(Factory.class); + Whitebox.setInternalState(AggregatedPolicyController.class, FACTORY_FIELD, factory); + + when(factory.getEndpointManager()).thenReturn(endpointMgr); + when(factory.getPersistenceManager()).thenReturn(persist); + when(factory.getDroolsFactory()).thenReturn(droolsFactory); + when(factory.getFeatureProviders()).thenReturn(providers); + + apc = new AggregatedPolicyController(AGG_NAME, properties); + } + + @Test + public void testFactory() { + assertNotNull(savedFactory); + + Factory factory = new Factory(); + assertNotNull(factory.getDroolsFactory()); + assertNotNull(factory.getEndpointManager()); + assertNotNull(factory.getFeatureProviders()); + assertNotNull(factory.getPersistenceManager()); + } + + @Test + public void testAggregatedPolicyController_() { + verify(persist).storeController(AGG_NAME, properties); + } + + @Test(expected = IllegalArgumentException.class) + public void testInitDrools_Ex() { + when(factory.getDroolsFactory()).thenThrow(new RuntimeException(EXPECTED)); + new AggregatedPolicyController(AGG_NAME, properties); + } + + @Test(expected = IllegalArgumentException.class) + public void testInitDrools_Error() { + when(factory.getDroolsFactory()).thenThrow(new LinkageError(EXPECTED)); + new AggregatedPolicyController(AGG_NAME, properties); + } + + @Test + public void testUpdateDrools_ConfigVariations() { + + // config should return same values as current controller + when(config.getArtifactId()).thenReturn(ARTIFACT1.toUpperCase()); + when(config.getGroupId()).thenReturn(GROUP1.toUpperCase()); + when(config.getVersion()).thenReturn(VERSION1.toUpperCase()); + + assertTrue(apc.updateDrools(config)); + + // number of times store should have been called + int count = 0; + + // invoked once during construction, but shouldn't be invoked during update + verify(persist, times(++count)).storeController(any(), any()); + + + // different artifact + when(config.getArtifactId()).thenReturn(ARTIFACT2); + + assertTrue(apc.updateDrools(config)); + + // should be invoked during update + verify(persist, times(++count)).storeController(any(), any()); + + + // different group + when(config.getArtifactId()).thenReturn(ARTIFACT1); + when(config.getGroupId()).thenReturn(GROUP2); + + assertTrue(apc.updateDrools(config)); + + // should be invoked during update + verify(persist, times(++count)).storeController(any(), any()); + + + // different version + when(config.getGroupId()).thenReturn(GROUP1); + when(config.getVersion()).thenReturn(VERSION2); + + assertTrue(apc.updateDrools(config)); + + // should be invoked during update + verify(persist, times(++count)).storeController(any(), any()); + + + /* + * Exception case. + */ + when(drools.lock()).thenThrow(new IllegalArgumentException(EXPECTED)); + when(drools.unlock()).thenThrow(new IllegalArgumentException(EXPECTED)); + + assertFalse(apc.updateDrools(config)); + } + + @Test + public void testUpdateDrools_LockVariations() { + // not locked + apc.updateDrools(config); + verify(drools, never()).lock(); + verify(drools).unlock(); + + // locked + setUp(); + apc.lock(); + apc.updateDrools(config); + verify(drools, times(2)).lock(); + verify(drools, never()).unlock(); + } + + @Test + public void testUpdateDrools_AliveVariations() { + // not started + apc.updateDrools(config); + verify(drools, never()).start(); + verify(drools).stop(); + + // started + setUp(); + apc.start(); + apc.updateDrools(config); + verify(drools, times(2)).start(); + verify(drools, never()).stop(); + } + + @Test + public void testGetName() { + assertEquals(AGG_NAME, apc.getName()); + } + + @Test + public 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)); + + // arrange for first sink to throw exception + when(sink1.start()).thenThrow(new RuntimeException(EXPECTED)); + + // start it + assertTrue(apc.start()); + + assertTrue(apc.isAlive()); + + verify(prov1).beforeStart(apc); + verify(prov2).beforeStart(apc); + + verify(source1).register(apc); + verify(source2).register(apc); + + verify(sink1).start(); + verify(sink2).start(); + + verify(prov1).afterStart(apc); + verify(prov2).afterStart(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeStart(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterStart(apc)).thenReturn(flag), + () -> apc.start(), + prov -> verify(prov).beforeStart(apc), + () -> verify(source1).register(apc), + prov -> verify(prov).afterStart(apc)); + } + + @Test + public void testStart_AlreadyStarted() { + apc.start(); + + // re-start it + assertTrue(apc.start()); + + assertTrue(apc.isAlive()); + + // these should now have been called twice + verify(prov1, times(2)).beforeStart(apc); + verify(prov2, times(2)).beforeStart(apc); + + // these should still only have been called once + verify(source1).register(apc); + verify(sink1).start(); + verify(prov1).afterStart(apc); + } + + @Test + public void testStart_Locked() { + apc.lock(); + + // start it + assertThrows(IllegalStateException.class, () -> apc.start()); + + assertFalse(apc.isAlive()); + + // should call beforeStart(), but stop after that + verify(prov1).beforeStart(apc); + verify(prov2).beforeStart(apc); + + verify(source1, never()).register(apc); + verify(sink1, never()).start(); + verify(prov1, never()).afterStart(apc); + } + + @Test + public 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)); + + // start it + apc.start(); + + // now stop it + assertTrue(apc.stop()); + + assertFalse(apc.isAlive()); + + verify(prov1).beforeStop(apc); + verify(prov2).beforeStop(apc); + + verify(source1).unregister(apc); + verify(source2).unregister(apc); + + verify(prov1).afterStop(apc); + verify(prov2).afterStop(apc); + + // ensure no shutdown operations were called + verify(prov1, never()).beforeShutdown(apc); + verify(droolsFactory, never()).shutdown(drools); + verify(prov2, never()).afterShutdown(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeStop(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterStop(apc)).thenReturn(flag), + () -> { + apc.start(); + apc.stop(); + }, + prov -> verify(prov).beforeStop(apc), + () -> verify(source1).unregister(apc), + prov -> verify(prov).afterStop(apc)); + } + + @Test + public void testStop_AlreadyStopped() { + apc.start(); + apc.stop(); + + // now re-stop it + assertTrue(apc.stop()); + + // called again + verify(prov1, times(2)).beforeStop(apc); + verify(prov2, times(2)).beforeStop(apc); + + // should NOT be called again + verify(source1).unregister(apc); + verify(prov1).afterStop(apc); + } + + @Test + public 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)); + + // start it + apc.start(); + + // now shut it down + apc.shutdown(); + + verify(prov1).beforeShutdown(apc); + verify(prov2).beforeShutdown(apc); + + assertFalse(apc.isAlive()); + + verify(prov1).afterStop(apc); + verify(prov2).afterStop(apc); + + verify(droolsFactory).shutdown(drools); + + verify(prov1).afterShutdown(apc); + verify(prov2).afterShutdown(apc); + + // ensure no halt operation was called + verify(prov1, never()).beforeHalt(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeShutdown(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterShutdown(apc)).thenReturn(flag), + () -> { + apc.start(); + apc.shutdown(); + }, + prov -> verify(prov).beforeShutdown(apc), + () -> verify(source1).unregister(apc), + prov -> verify(prov).afterShutdown(apc)); + } + + @Test + public 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)); + + // start it + apc.start(); + + // now halt it + apc.halt(); + + verify(prov1).beforeHalt(apc); + verify(prov2).beforeHalt(apc); + + assertFalse(apc.isAlive()); + + verify(prov1).beforeStop(apc); + verify(prov2).beforeStop(apc); + + verify(droolsFactory).destroy(drools); + verify(persist).deleteController(AGG_NAME); + + verify(prov1).afterHalt(apc); + verify(prov2).afterHalt(apc); + + // ensure no shutdown operation was called + verify(prov1, never()).beforeShutdown(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeHalt(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterHalt(apc)).thenReturn(flag), + () -> { + apc.start(); + apc.halt(); + }, + prov -> verify(prov).beforeHalt(apc), + () -> verify(source1).unregister(apc), + prov -> verify(prov).afterHalt(apc)); + } + + @Test + public void testOnTopicEvent() { + // arrange for first provider to throw exceptions + when(prov1.beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT)) + .thenThrow(new RuntimeException(EXPECTED)); + when(prov1.afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true)) + .thenThrow(new RuntimeException(EXPECTED)); + + // start it + apc.start(); + + // now offer it + apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + verify(prov1).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + verify(prov2).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + verify(drools).offer(SOURCE_TOPIC1, MY_EVENT); + + verify(prov1).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true); + verify(prov2).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT)) + .thenReturn(flag), + (prov, flag) -> when( + prov.afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true)) + .thenReturn(flag), + () -> { + apc.start(); + apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + }, + prov -> verify(prov).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT), + () -> verify(drools).offer(SOURCE_TOPIC1, MY_EVENT), + prov -> verify(prov).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true)); + } + + @Test + public void testOnTopicEvent_Locked() { + // start it + apc.start(); + + apc.lock(); + + // now offer it + apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + verify(prov1).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + verify(prov2).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + // never gets this far + verify(drools, never()).offer(SOURCE_TOPIC1, MY_EVENT); + verify(prov1, never()).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true); + } + + @Test + public void testOnTopicEvent_NotStarted() { + + // offer it + apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + verify(prov1).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + verify(prov2).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT); + + // never gets this far + verify(drools, never()).offer(SOURCE_TOPIC1, MY_EVENT); + verify(prov1, never()).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true); + } + + @Test + public void testDeliver_testInitSinks() { + // arrange for first provider to throw exceptions + when(prov1.beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)) + .thenThrow(new RuntimeException(EXPECTED)); + when(prov1.afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true)) + .thenThrow(new RuntimeException(EXPECTED)); + + // start it + apc.start(); + + // now offer it + assertTrue(apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)); + + verify(prov1).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + verify(prov2).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + + verify(drools).deliver(sink1, MY_EVENT); + verify(drools, never()).deliver(sink2, MY_EVENT); + + verify(prov1).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true); + verify(prov2).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true); + + // offer to the other topic + assertTrue(apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC2, MY_EVENT)); + + // now both topics should show one message delivered + verify(drools).deliver(sink1, MY_EVENT); + verify(drools).deliver(sink2, MY_EVENT); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT)) + .thenReturn(flag), + (prov, flag) -> when( + prov.afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true)) + .thenReturn(flag), + () -> { + apc.start(); + apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + }, + prov -> verify(prov).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT), + () -> verify(drools).deliver(sink1, MY_EVENT), + prov -> verify(prov).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true)); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeliver_NullTopic() { + apc.start(); + apc.deliver(CommInfrastructure.NOOP, null, MY_EVENT); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeliver_EmptyTopic() { + apc.start(); + apc.deliver(CommInfrastructure.NOOP, "", MY_EVENT); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeliver_NullEvent() { + apc.start(); + apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, null); + } + + @Test(expected = IllegalStateException.class) + public void testDeliver_NotStarted() { + // do NOT start + apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + } + + @Test(expected = IllegalStateException.class) + public void testDeliver_Locked() { + apc.start(); + apc.lock(); + apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT); + } + + @Test(expected = IllegalArgumentException.class) + public void testDeliver_UnknownTopic() { + apc.start(); + apc.deliver(CommInfrastructure.NOOP, "unknown-topic", MY_EVENT); + } + + @Test + public void testIsAlive() { + assertFalse(apc.isAlive()); + + apc.start(); + assertTrue(apc.isAlive()); + + apc.stop(); + assertFalse(apc.isAlive()); + } + + @Test + public 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)); + + // start it + apc.start(); + + // now lock it + assertTrue(apc.lock()); + + verify(prov1).beforeLock(apc); + verify(prov2).beforeLock(apc); + + assertTrue(apc.isLocked()); + + verify(drools).lock(); + + verify(prov1).afterLock(apc); + verify(prov2).afterLock(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeLock(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterLock(apc)).thenReturn(flag), + () -> { + apc.start(); + apc.lock(); + }, + prov -> verify(prov).beforeLock(apc), + () -> verify(drools).lock(), + prov -> verify(prov).afterLock(apc)); + } + + @Test + public void testLock_AlreadyLocked() { + apc.start(); + apc.lock(); + + // now re-lock it + assertTrue(apc.lock()); + + // these should be invoked a second time + verify(prov1, times(2)).beforeLock(apc); + verify(prov2, times(2)).beforeLock(apc); + + assertTrue(apc.isLocked()); + + // these shouldn't be invoked a second time + verify(drools).lock(); + verify(prov1).afterLock(apc); + } + + @Test + public 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)); + + // start it + apc.start(); + apc.lock(); + + // now unlock it + assertTrue(apc.unlock()); + + verify(prov1).beforeUnlock(apc); + verify(prov2).beforeUnlock(apc); + + assertFalse(apc.isLocked()); + + verify(drools).unlock(); + + verify(prov1).afterUnlock(apc); + verify(prov2).afterUnlock(apc); + + checkBeforeAfter( + (prov, flag) -> when(prov.beforeUnlock(apc)).thenReturn(flag), + (prov, flag) -> when(prov.afterUnlock(apc)).thenReturn(flag), + () -> { + apc.start(); + apc.lock(); + apc.unlock(); + }, + prov -> verify(prov).beforeUnlock(apc), + () -> verify(drools).unlock(), + prov -> verify(prov).afterUnlock(apc)); + } + + @Test + public void testUnlock_NotLocked() { + apc.start(); + + // now unlock it + assertTrue(apc.unlock()); + + verify(prov1).beforeUnlock(apc); + verify(prov2).beforeUnlock(apc); + + assertFalse(apc.isLocked()); + + // these shouldn't be invoked + verify(drools, never()).unlock(); + verify(prov1, never()).afterLock(apc); + } + + @Test + public void testIsLocked() { + assertFalse(apc.isLocked()); + + apc.lock(); + assertTrue(apc.isLocked()); + + apc.unlock(); + assertFalse(apc.isLocked()); + } + + @Test + public void testGetTopicSources() { + assertEquals(sources, apc.getTopicSources()); + } + + @Test + public void testGetTopicSinks() { + assertEquals(sinks, apc.getTopicSinks()); + } + + @Test + public void testGetDrools() { + assertEquals(drools, apc.getDrools()); + } + + @Test + public void testGetProperties() { + assertEquals(properties, apc.getProperties()); + } + + @Test + public void testToString() { + assertTrue(apc.toString().startsWith("AggregatedPolicyController [")); + } + + /** + * Performs an operation that has a beforeXxx method and an afterXxx method. Tries + * combinations where beforeXxx and afterXxx return {@code true} and {@code false}. + * + * @param setBefore function to set the return value of a provider's beforeXxx method + * @param setAfter function to set the return value of a provider's afterXxx method + * @param action invokes the operation + * @param verifyBefore verifies that a provider's beforeXxx method was invoked + * @param verifyMiddle verifies that the action occurring between the beforeXxx loop + * and the afterXxx loop was invoked + * @param verifyAfter verifies that a provider's afterXxx method was invoked + */ + private void checkBeforeAfter(BiConsumer setBefore, + BiConsumer setAfter, Runnable action, + Consumer verifyBefore, Runnable verifyMiddle, + Consumer verifyAfter) { + + checkBeforeAfter_FalseFalse(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter); + checkBeforeAfter_FalseTrue(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter); + checkBeforeAfter_TrueFalse(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter); + + // don't need to test true-true, as it's behavior is a subset of true-false + } + + /** + * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the + * case where both the beforeXxx and afterXxx methods return {@code false}. + * + * @param setBefore function to set the return value of a provider's beforeXxx method + * @param setAfter function to set the return value of a provider's afterXxx method + * @param action invokes the operation + * @param verifyBefore verifies that a provider's beforeXxx method was invoked + * @param verifyMiddle verifies that the action occurring between the beforeXxx loop + * and the afterXxx loop was invoked + * @param verifyAfter verifies that a provider's afterXxx method was invoked + */ + private void checkBeforeAfter_FalseFalse(BiConsumer setBefore, + BiConsumer setAfter, Runnable action, + Consumer verifyBefore, Runnable verifyMiddle, + Consumer verifyAfter) { + + setUp(); + + // configure for the test + setBefore.accept(prov1, false); + setBefore.accept(prov2, false); + + setAfter.accept(prov1, false); + setAfter.accept(prov2, false); + + // run the action + action.run(); + + // verify that various methods were invoked + verifyBefore.accept(prov1); + verifyBefore.accept(prov2); + + verifyMiddle.run(); + + verifyAfter.accept(prov1); + verifyAfter.accept(prov2); + } + + /** + * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the + * case where the first provider's afterXxx returns {@code true}, while the others + * return {@code false}. + * + * @param setBefore function to set the return value of a provider's beforeXxx method + * @param setAfter function to set the return value of a provider's afterXxx method + * @param action invokes the operation + * @param verifyBefore verifies that a provider's beforeXxx method was invoked + * @param verifyMiddle verifies that the action occurring between the beforeXxx loop + * and the afterXxx loop was invoked + * @param verifyAfter verifies that a provider's afterXxx method was invoked + */ + private void checkBeforeAfter_FalseTrue(BiConsumer setBefore, + BiConsumer setAfter, Runnable action, + Consumer verifyBefore, Runnable verifyMiddle, + Consumer verifyAfter) { + + setUp(); + + // configure for the test + setBefore.accept(prov1, false); + setBefore.accept(prov2, false); + + setAfter.accept(prov1, true); + setAfter.accept(prov2, false); + + // run the action + action.run(); + + // verify that various methods were invoked + verifyBefore.accept(prov1); + verifyBefore.accept(prov2); + + verifyMiddle.run(); + + verifyAfter.accept(prov1); + assertThrows(AssertionError.class, () -> verifyAfter.accept(prov2)); + } + + /** + * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the + * case where the first provider's beforeXxx returns {@code true}, while the others + * return {@code false}. + * + * @param setBefore function to set the return value of a provider's beforeXxx method + * @param setAfter function to set the return value of a provider's afterXxx method + * @param action invokes the operation + * @param verifyBefore verifies that a provider's beforeXxx method was invoked + * @param verifyMiddle verifies that the action occurring between the beforeXxx loop + * and the afterXxx loop was invoked + * @param verifyAfter verifies that a provider's afterXxx method was invoked + */ + private void checkBeforeAfter_TrueFalse(BiConsumer setBefore, + BiConsumer setAfter, Runnable action, + Consumer verifyBefore, Runnable verifyMiddle, + Consumer verifyAfter) { + + setUp(); + + // configure for the test + setBefore.accept(prov1, true); + setBefore.accept(prov2, false); + + setAfter.accept(prov1, false); + setAfter.accept(prov2, false); + + // run the action + action.run(); + + // verify that various methods were invoked + verifyBefore.accept(prov1); + + // remaining methods should not have been invoked + assertThrows(AssertionError.class, () -> verifyBefore.accept(prov2)); + + assertThrows(AssertionError.class, () -> verifyMiddle.run()); + + assertThrows(AssertionError.class, () -> verifyAfter.accept(prov1)); + assertThrows(AssertionError.class, () -> verifyAfter.accept(prov2)); + } +} diff --git a/policy-management/src/test/java/org/onap/policy/drools/system/test/PolicyEngineTest.java b/policy-management/src/test/java/org/onap/policy/drools/system/test/PolicyEngineTest.java deleted file mode 100644 index 7b02d755..00000000 --- a/policy-management/src/test/java/org/onap/policy/drools/system/test/PolicyEngineTest.java +++ /dev/null @@ -1,295 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * policy-management - * ================================================================================ - * Copyright (C) 2017-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.system.test; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -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.onap.policy.common.endpoints.event.comm.TopicEndpoint; -import org.onap.policy.common.endpoints.event.comm.TopicSink; -import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicSink; -import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; -import org.onap.policy.drools.persistence.SystemPersistence; -import org.onap.policy.drools.properties.DroolsProperties; -import org.onap.policy.drools.protocol.coders.EventProtocolCoder; -import org.onap.policy.drools.protocol.coders.JsonProtocolFilter; -import org.onap.policy.drools.protocol.configuration.DroolsConfiguration; -import org.onap.policy.drools.system.PolicyController; -import org.onap.policy.drools.system.PolicyEngine; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * PolicyEngine unit tests. - */ - -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class PolicyEngineTest { - /** - * Default Telemetry port for JUnits. - */ - public static final int DEFAULT_TELEMETRY_PORT = 9698; - - /** - * Test JUnit Controller Name. - */ - public static final String TEST_CONTROLLER_NAME = "foo"; - - /** - * Controller Configuration File. - */ - public static final String TEST_CONTROLLER_FILE = TEST_CONTROLLER_NAME + "-controller.properties"; - - /** - * Controller Configuration Backup File. - */ - public static final String TEST_CONTROLLER_FILE_BAK = TEST_CONTROLLER_FILE + ".bak"; - - /** - * Coder Group. - */ - private static final String ENCODER_GROUP = "foo"; - - /** - * Coder Artifact. - */ - private static final String ENCODER_ARTIFACT = "bar"; - - /** - * Coder Version. - */ - private static final String ENCODER_VERSION = null; - - /** - * noop topic. - */ - private static final String NOOP_TOPIC = "JUNIT"; - - /** - * logger. - */ - private static Logger logger = LoggerFactory.getLogger(PolicyEngineTest.class); - - /** - * clean up working directory. - */ - protected static void cleanUpWorkingDir() { - final Path testControllerPath = - Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE); - try { - Files.deleteIfExists(testControllerPath); - } catch (final Exception e) { - logger.info("Problem cleaning {}", testControllerPath, e); - } - - final Path testControllerBakPath = - Paths.get(SystemPersistence.manager.getConfigurationPath().toString(), TEST_CONTROLLER_FILE_BAK); - try { - Files.deleteIfExists(testControllerBakPath); - } catch (final Exception e) { - logger.info("Problem cleaning {}", testControllerBakPath, e); - } - } - - /** - * Start up. - * - * @throws IOException throws IO exception - */ - @BeforeClass - public static void startUp() throws IOException { - logger.info("enter"); - - cleanUpWorkingDir(); - - /* ensure presence of config directory */ - final Path configDir = Paths.get(SystemPersistence.DEFAULT_CONFIGURATION_DIR); - if (Files.notExists(configDir)) { - Files.createDirectories(configDir); - } - } - - @AfterClass - public static void tearDown() throws IOException { - logger.info("enter"); - cleanUpWorkingDir(); - } - - @Test - public void test100Configure() { - logger.info("enter"); - - final Properties engineProps = PolicyEngine.manager.defaultTelemetryConfig(); - - /* override default port */ - engineProps.put(PolicyEndPointProperties.PROPERTY_HTTP_SERVER_SERVICES + "." - + PolicyEngine.TELEMETRY_SERVER_DEFAULT_NAME + PolicyEndPointProperties.PROPERTY_HTTP_PORT_SUFFIX, - "" + DEFAULT_TELEMETRY_PORT); - - assertFalse(PolicyEngine.manager.isAlive()); - PolicyEngine.manager.configure(engineProps); - assertFalse(PolicyEngine.manager.isAlive()); - - logger.info("policy-engine {} has configuration {}", PolicyEngine.manager, engineProps); - } - - @Test - public void test200Start() { - logger.info("enter"); - - PolicyEngine.manager.start(); - - assertTrue(PolicyEngine.manager.isAlive()); - assertFalse(PolicyEngine.manager.isLocked()); - assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); - assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); - } - - @Test - public void test300Lock() { - logger.info("enter"); - - PolicyEngine.manager.lock(); - - assertTrue(PolicyEngine.manager.isAlive()); - assertTrue(PolicyEngine.manager.isLocked()); - assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); - assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); - } - - @Test - public void test301Unlock() { - logger.info("enter"); - - PolicyEngine.manager.unlock(); - - assertTrue(PolicyEngine.manager.isAlive()); - assertFalse(PolicyEngine.manager.isLocked()); - assertFalse(PolicyEngine.manager.getHttpServers().isEmpty()); - assertTrue(PolicyEngine.manager.getHttpServers().get(0).isAlive()); - } - - @Test - public void test350TopicDeliver() { - final Properties noopSinkProperties = new Properties(); - noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, NOOP_TOPIC); - - TopicEndpoint.manager.addTopicSinks(noopSinkProperties).get(0).start(); - - EventProtocolCoder.manager.addEncoder(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC, - DroolsConfiguration.class.getCanonicalName(), new JsonProtocolFilter(), null, null, - DroolsConfiguration.class.getName().hashCode()); - - assertTrue(PolicyEngine.manager.deliver(NOOP_TOPIC, - new DroolsConfiguration(ENCODER_GROUP, ENCODER_ARTIFACT, ENCODER_VERSION))); - - final TopicSink sink = NoopTopicSink.factory.get(NOOP_TOPIC); - assertTrue(sink.getRecentEvents()[0].contains(ENCODER_GROUP)); - assertTrue(sink.getRecentEvents()[0].contains(ENCODER_ARTIFACT)); - - EventProtocolCoder.manager.removeEncoders(ENCODER_GROUP, ENCODER_ARTIFACT, NOOP_TOPIC); - } - - @Test - public void test400ControllerAdd() throws Exception { - logger.info("enter"); - - final Properties controllerProperties = new Properties(); - controllerProperties.put(DroolsProperties.PROPERTY_CONTROLLER_NAME, TEST_CONTROLLER_NAME); - PolicyEngine.manager.createPolicyController(TEST_CONTROLLER_NAME, controllerProperties); - - assertTrue(PolicyController.factory.inventory().size() == 1); - } - - @Test - public void test401ControllerVerify() { - logger.info("enter"); - - final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); - - assertFalse(testController.isAlive()); - assertFalse(testController.isLocked()); - - testController.start(); - - assertTrue(testController.isAlive()); - assertFalse(testController.isLocked()); - } - - @Test - public void test500Deactivate() throws Exception { - logger.info("enter"); - - PolicyEngine.manager.deactivate(); - - final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); - assertFalse(testController.isAlive()); - assertTrue(testController.isLocked()); - assertTrue(PolicyEngine.manager.isLocked()); - assertTrue(PolicyEngine.manager.isAlive()); - } - - @Test - public void test501Activate() throws Exception { - logger.info("enter"); - - PolicyEngine.manager.activate(); - - final PolicyController testController = PolicyController.factory.get(TEST_CONTROLLER_NAME); - assertTrue(testController.isAlive()); - assertFalse(testController.isLocked()); - assertFalse(PolicyEngine.manager.isLocked()); - assertTrue(PolicyEngine.manager.isAlive()); - } - - @Test - public void test900ControllerRemove() throws Exception { - logger.info("enter"); - - PolicyEngine.manager.removePolicyController(TEST_CONTROLLER_NAME); - assertTrue(PolicyController.factory.inventory().isEmpty()); - } - - @Test - public void test901Stop() throws InterruptedException { - logger.info("enter"); - - /* Shutdown managed resources */ - PolicyController.factory.shutdown(); - TopicEndpoint.manager.shutdown(); - PolicyEngine.manager.stop(); - - Thread.sleep(10000L); - assertFalse(PolicyEngine.manager.isAlive()); - } - -} -- cgit 1.2.3-korg