From b020843d050ece966c4652d00ff7dead897be917 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Tue, 26 Feb 2019 14:09:35 -0500 Subject: Add code to publish to PDP Added code to take an arbitrary object and send it to PDPs using a topic sink. Does not include the code or properties needed to configure the topic. Fixed method name - test case does not cover what the method name implied. Fixed some comments. Add test to verify that the PdpClient works with a real TopicSink. Moved coder classes to policy/common. Change-Id: I4dec746b07d384c5d9d1449ca91fa39a4f680260 Issue-ID: POLICY-1444 Signed-off-by: Jim Hahn --- main/pom.xml | 16 +++ .../org/onap/policy/pap/main/comm/PdpClient.java | 101 +++++++++++++++ .../policy/pap/main/comm/PdpClientException.java | 49 +++++++ .../pap/main/comm/PdpClientExceptionTest.java | 34 +++++ .../onap/policy/pap/main/comm/PdpClientTest.java | 141 +++++++++++++++++++++ pom.xml | 2 +- 6 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 main/src/main/java/org/onap/policy/pap/main/comm/PdpClient.java create mode 100644 main/src/main/java/org/onap/policy/pap/main/comm/PdpClientException.java create mode 100644 main/src/test/java/org/onap/policy/pap/main/comm/PdpClientExceptionTest.java create mode 100644 main/src/test/java/org/onap/policy/pap/main/comm/PdpClientTest.java diff --git a/main/pom.xml b/main/pom.xml index 19c54dbb..1a1f537c 100644 --- a/main/pom.xml +++ b/main/pom.xml @@ -68,6 +68,22 @@ 1.18.4 provided + + org.onap.policy.common + utils-test + ${policy.common.version} + test + + + org.powermock + powermock-api-mockito + test + + + org.assertj + assertj-core + test + diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpClient.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpClient.java new file mode 100644 index 00000000..7919912a --- /dev/null +++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpClient.java @@ -0,0 +1,101 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pap.main.comm; + +import java.util.List; +import lombok.Getter; +import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; +import org.onap.policy.common.endpoints.event.comm.TopicSink; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Client for communication with PDPs. + */ +public class PdpClient { + private static final Logger logger = LoggerFactory.getLogger(PdpClient.class); + + /** + * Coder used to encode messages being sent to PDPs. + */ + private static final Coder CODER = new StandardCoder(); + + /** + * Topic to which messages are published. + */ + @Getter + private final String topic; + + /** + * Where messages are published. + */ + private final TopicSink sink; + + /** + * Constructs the object. + * + * @param topic topic to which messages should be published + * @throws PdpClientException if the topic does not exist + */ + public PdpClient(String topic) throws PdpClientException { + this.topic = topic; + + List lst = getTopicSinks(topic); + if (lst.isEmpty()) { + throw new PdpClientException("no sinks for topic: " + topic); + } + + this.sink = lst.get(0); + } + + /** + * Sends a message to the PDPs via the topic, after encoding the message as json. + * + * @param message message to be encoded and sent + * @return {@code true} if the message was successfully sent/enqueued, {@code false} + * otherwise + */ + public boolean send(Object message) { + try { + String json = CODER.encode(message); + return sink.send(json); + + } catch (RuntimeException | CoderException e) { + logger.warn("send to {} failed because of {}", topic, e.getMessage(), e); + return false; + } + } + + // the remaining methods are wrappers that can be overridden by junit tests + + /** + * Gets the sinks for a given topic. + * + * @param topic the topic of interest + * @return the sinks for the topic + */ + protected List getTopicSinks(String topic) { + return TopicEndpoint.manager.getTopicSinks(topic); + } +} diff --git a/main/src/main/java/org/onap/policy/pap/main/comm/PdpClientException.java b/main/src/main/java/org/onap/policy/pap/main/comm/PdpClientException.java new file mode 100644 index 00000000..547812f2 --- /dev/null +++ b/main/src/main/java/org/onap/policy/pap/main/comm/PdpClientException.java @@ -0,0 +1,49 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pap.main.comm; + +/** + * Exception thrown by PDP client classes. + */ +public class PdpClientException extends Exception { + private static final long serialVersionUID = 1L; + + public PdpClientException() { + super(); + } + + public PdpClientException(String message) { + super(message); + } + + public PdpClientException(Throwable cause) { + super(cause); + } + + public PdpClientException(String message, Throwable cause) { + super(message, cause); + } + + public PdpClientException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + +} diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientExceptionTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientExceptionTest.java new file mode 100644 index 00000000..dcaba782 --- /dev/null +++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientExceptionTest.java @@ -0,0 +1,34 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pap.main.comm; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.onap.policy.common.utils.test.ExceptionsTester; + +public class PdpClientExceptionTest { + + @Test + public void test() { + assertEquals(5, new ExceptionsTester().test(PdpClientException.class)); + } +} diff --git a/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientTest.java b/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientTest.java new file mode 100644 index 00000000..22823bfb --- /dev/null +++ b/main/src/test/java/org/onap/policy/pap/main/comm/PdpClientTest.java @@ -0,0 +1,141 @@ +/* + * ============LICENSE_START======================================================= + * ONAP PAP + * ================================================================================ + * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.pap.main.comm; + +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.assertSame; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.Before; +import org.junit.Test; +import org.mockito.internal.util.reflection.Whitebox; +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.TopicListener; +import org.onap.policy.common.endpoints.event.comm.TopicSink; + +public class PdpClientTest { + private static final String SINK_FIELD_NAME = "sink"; + private static final String TOPIC = "my-topic"; + + private PdpClient client; + private TopicSink sink; + private List sinks; + + /** + * Creates mocks and an initial client object. + * + * @throws Exception if an error occurs + */ + @Before + public void setUp() throws Exception { + sink = mock(TopicSink.class); + when(sink.send(anyString())).thenReturn(true); + + sinks = Arrays.asList(sink, null); + + client = new PdpClient2(TOPIC); + } + + /** + * Uses a real NO-OP topic sink. + */ + @Test + public void testGetTopicSinks() throws Exception { + // clear all topics and then configure one topic + TopicEndpoint.manager.shutdown(); + + Properties props = new Properties(); + props.setProperty("noop.sink.topics", TOPIC); + TopicEndpoint.manager.addTopicSinks(props); + + sink = TopicEndpoint.manager.getNoopTopicSink(TOPIC); + assertNotNull(sink); + + AtomicReference evref = new AtomicReference<>(null); + + sink.register(new TopicListener() { + @Override + public void onTopicEvent(CommInfrastructure infra, String topic, String event) { + evref.set(event); + } + }); + + sink.start(); + + client = new PdpClient(TOPIC); + client.send(100); + + assertEquals("100", evref.get()); + } + + @Test + public void testPdpClient_testGetTopic() { + assertEquals(TOPIC, client.getTopic()); + assertSame(sink, Whitebox.getInternalState(client, SINK_FIELD_NAME)); + + // unknown topic -> should throw exception + sinks = new LinkedList<>(); + assertThatThrownBy(() -> new PdpClient2(TOPIC)).isInstanceOf(PdpClientException.class) + .hasMessage("no sinks for topic: my-topic"); + } + + @Test + public void testSend() throws Exception { + client.send(Arrays.asList("abc", "def")); + verify(sink).send("['abc','def']".replace('\'', '"')); + + // sink send fails + when(sink.send(anyString())).thenReturn(false); + assertFalse(client.send("ghi")); + + // sink send throws an exception + RuntimeException ex = new RuntimeException("expected exception"); + when(sink.send(anyString())).thenThrow(ex); + assertFalse(client.send("jkl")); + } + + /** + * PdpClient with some overrides. + */ + private class PdpClient2 extends PdpClient { + + public PdpClient2(String topic) throws PdpClientException { + super(topic); + } + + @Override + protected List getTopicSinks(String topic) { + return sinks; + } + } +} diff --git a/pom.xml b/pom.xml index a1d33786..91f9f856 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ org.onap.policy.parent integration - 2.0.0 + 2.1.0-SNAPSHOT -- cgit 1.2.3-korg