From 290aa864c6a7d02a4f310c5d1cf8106e02e9dd47 Mon Sep 17 00:00:00 2001 From: JoeOLeary Date: Wed, 13 Mar 2019 16:47:20 +0000 Subject: Add Dynamic Configuration *Implement Configurable in DataRouter subscriber *Add reconfigure.sh *Update Dockerfile to use reconfigure.sh Issue-ID: DCAEGEN2-1038 Change-Id: I9ce387819afff644c3dc76a94786fa1f95afd985 Signed-off-by: JoeOLeary --- .../pmmapper/config/DynamicConfigurationTest.java | 153 +++++++++++++++++++ .../datarouter/DataRouterSubscriberTest.java | 168 +++++++++++++++++++-- .../valid_bc_response.json | 15 ++ 3 files changed, 322 insertions(+), 14 deletions(-) create mode 100644 src/test/java/org/onap/dcaegen2/services/pmmapper/config/DynamicConfigurationTest.java create mode 100644 src/test/resources/datarouter_subscriber_test/valid_bc_response.json (limited to 'src/test') diff --git a/src/test/java/org/onap/dcaegen2/services/pmmapper/config/DynamicConfigurationTest.java b/src/test/java/org/onap/dcaegen2/services/pmmapper/config/DynamicConfigurationTest.java new file mode 100644 index 0000000..67510da --- /dev/null +++ b/src/test/java/org/onap/dcaegen2/services/pmmapper/config/DynamicConfigurationTest.java @@ -0,0 +1,153 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.dcaegen2.services.pmmapper.config; + + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import io.undertow.server.HttpServerExchange; +import io.undertow.util.StatusCodes; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import org.onap.dcaegen2.services.pmmapper.exceptions.ReconfigurationException; +import org.onap.dcaegen2.services.pmmapper.model.EnvironmentConfig; +import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; +import org.onap.dcaegen2.services.pmmapper.utils.RequestSender; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.RETURNS_DEEP_STUBS; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(PowerMockRunner.class) +@PrepareForTest({DynamicConfiguration.class, EnvironmentConfig.class}) +public class DynamicConfigurationTest { + private static Path VALID_CONFIG_PATH = Paths.get("src/test/resources/valid_mapper_config.json"); + + private static ArrayList configurables; + private DynamicConfiguration objUnderTest; + private static String config; + private MapperConfig originalMapperConfig; + + @Mock + private RequestSender sender; + + @BeforeClass() + public static void setupBeforeClass() throws Exception { + config = new String(Files.readAllBytes(VALID_CONFIG_PATH)); + } + + @Before + public void setup() throws Exception { + configurables = new ArrayList<>(); + PowerMockito.mockStatic(EnvironmentConfig.class); + PowerMockito.when(EnvironmentConfig.getCBSHostName()).thenReturn(""); + PowerMockito.when(EnvironmentConfig.getCBSPort()).thenReturn(1); + PowerMockito.when(EnvironmentConfig.getServiceName()).thenReturn(""); + + when(sender.send(any())).thenReturn(config); + ConfigHandler configHandler = new ConfigHandler(sender); + originalMapperConfig = configHandler.getMapperConfig(); + objUnderTest = new DynamicConfiguration(configurables, originalMapperConfig); + } + + @Test + public void testNoChangeResponse() throws Exception { + ConfigHandler configHandler = new ConfigHandler(sender); + originalMapperConfig = configHandler.getMapperConfig(); + objUnderTest.setConfigHandler(configHandler); + + HttpServerExchange httpServerExchange = mock(HttpServerExchange.class, RETURNS_DEEP_STUBS); + objUnderTest.handleRequest(httpServerExchange); + assertEquals(originalMapperConfig, objUnderTest.getOriginalConfig()); + verify(httpServerExchange, times(1)).setStatusCode(StatusCodes.OK); + } + + @Test + public void testApplyOriginalUponFailure() throws Exception { + ConfigHandler configHandler = new ConfigHandler(sender); + Configurable configurable = mock(Configurable.class); + configurables.add(configurable); + JsonObject modifiedConfig = new JsonParser().parse(config).getAsJsonObject(); + modifiedConfig.addProperty("dmaap_dr_feed_id","3"); + when(sender.send(any())).thenReturn(modifiedConfig.toString()); + MapperConfig modifiedMapperConfig = configHandler.getMapperConfig(); + + objUnderTest.setConfigHandler(configHandler); + + doAnswer(new Answer() { + boolean failFirstReconfigure = true; + @Override + public Object answer(InvocationOnMock invocationOnMock) throws Throwable { + if (failFirstReconfigure) { + failFirstReconfigure = false; + throw new ReconfigurationException(""); + } + return null; + } + }).when(configurable).reconfigure(any()); + + HttpServerExchange httpServerExchange = mock(HttpServerExchange.class, RETURNS_DEEP_STUBS); + objUnderTest.handleRequest(httpServerExchange); + assertEquals(originalMapperConfig, objUnderTest.getOriginalConfig()); + verify(httpServerExchange, times(1)).setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR); + verify(configurable, times(1)).reconfigure(modifiedMapperConfig); + verify(configurable, times(1)).reconfigure(originalMapperConfig); + } + + @Test + public void testSuccessfulReconfiguration() throws Exception { + ConfigHandler configHandler = new ConfigHandler(sender); + Configurable configurable = mock(Configurable.class); + configurables.add(configurable); + JsonObject modifiedConfig = new JsonParser().parse(config).getAsJsonObject(); + modifiedConfig.addProperty("dmaap_dr_feed_id","3"); + + when(sender.send(any())).thenReturn(modifiedConfig.toString()); + MapperConfig modifiedMapperConfig = configHandler.getMapperConfig(); + objUnderTest.setConfigHandler(configHandler); + + HttpServerExchange httpServerExchange = mock(HttpServerExchange.class, RETURNS_DEEP_STUBS); + objUnderTest.handleRequest(httpServerExchange); + assertEquals(modifiedMapperConfig, objUnderTest.getOriginalConfig()); + verify(httpServerExchange, times(1)).setStatusCode(StatusCodes.OK); + verify(configurable, times(1)).reconfigure(modifiedMapperConfig); + + } +} diff --git a/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java b/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java index fdc1bf6..dbb95a7 100644 --- a/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java +++ b/src/test/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriberTest.java @@ -43,10 +43,15 @@ import io.undertow.server.HttpServerExchange; import io.undertow.util.HeaderMap; import io.undertow.util.StatusCodes; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import org.junit.Before; import org.junit.Test; @@ -55,28 +60,38 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.onap.dcaegen2.services.pmmapper.config.ConfigHandler; +import org.onap.dcaegen2.services.pmmapper.exceptions.ReconfigurationException; import org.onap.dcaegen2.services.pmmapper.exceptions.TooManyTriesException; +import org.onap.dcaegen2.services.pmmapper.model.EnvironmentConfig; import org.onap.dcaegen2.services.pmmapper.model.Event; import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; import org.onap.dcaegen2.services.pmmapper.utils.HttpServerExchangeAdapter; +import org.onap.dcaegen2.services.pmmapper.utils.RequestSender; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import utils.LoggingUtils; @RunWith(PowerMockRunner.class) -@PrepareForTest(DataRouterSubscriber.class) +@PrepareForTest({DataRouterSubscriber.class, EnvironmentConfig.class}) public class DataRouterSubscriberTest { + private Path VALID_BC_RESPONSE_PATH = Paths.get("src/test/resources/datarouter_subscriber_test/valid_bc_response.json"); + private Path VALID_METADATA_PATH = Paths.get("src/test/resources/valid_metadata.json"); + private Path INVALID_METADATA_PATH = Paths.get("src/test/resources/invalid_metadata.json"); + private Path VALID_CONFIG_PATH = Paths.get("src/test/resources/valid_mapper_config.json"); @Mock private EventReceiver eventReceiver; + @Mock + private MapperConfig config; private DataRouterSubscriber objUnderTest; @Before public void setUp() { - objUnderTest = new DataRouterSubscriber(eventReceiver); + objUnderTest = new DataRouterSubscriber(eventReceiver, config); } @Test @@ -84,34 +99,37 @@ public class DataRouterSubscriberTest { PowerMockito.mockStatic(Thread.class); URL subEndpoint = mock(URL.class); - MapperConfig config = mock(MapperConfig.class); when(config.getBusControllerSubscriptionUrl()).thenReturn(subEndpoint); HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); when(subEndpoint.openConnection()).thenReturn(huc); when(huc.getResponseCode()).thenReturn(300); - Assertions.assertThrows(TooManyTriesException.class, () -> objUnderTest.start(config)); + Assertions.assertThrows(TooManyTriesException.class, () -> objUnderTest.start()); } @Test public void testStartImmediateSuccess() throws IOException, TooManyTriesException, InterruptedException { URL subEndpoint = mock(URL.class); - MapperConfig config = mock(MapperConfig.class); when(config.getBusControllerSubscriptionUrl()).thenReturn(subEndpoint); HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + String bcResponse = new String(Files.readAllBytes(VALID_BC_RESPONSE_PATH)); + InputStream responseStream = new ByteArrayInputStream(bcResponse.getBytes(StandardCharsets.UTF_8)); + when(huc.getInputStream()).thenReturn(responseStream); when(subEndpoint.openConnection()).thenReturn(huc); when(huc.getResponseCode()).thenReturn(200); - objUnderTest.start(config); + objUnderTest.start(); verify(huc, times(1)).getResponseCode(); } @Test public void testStartDelayedSuccess() throws IOException, TooManyTriesException, InterruptedException { PowerMockito.mockStatic(Thread.class); - + HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + String bcResponse = new String(Files.readAllBytes(VALID_BC_RESPONSE_PATH)); + InputStream responseStream = new ByteArrayInputStream(bcResponse.getBytes(StandardCharsets.UTF_8)); + when(huc.getInputStream()).thenReturn(responseStream); URL subEndpoint = mock(URL.class); - MapperConfig config = mock(MapperConfig.class); when(config.getBusControllerSubscriptionUrl()).thenReturn(subEndpoint); - HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + when(subEndpoint.openConnection()).thenReturn(huc); doAnswer(new Answer() { boolean forceRetry = true; @@ -125,7 +143,7 @@ public class DataRouterSubscriberTest { return 200; } }).when(huc).getResponseCode(); - objUnderTest.start(config); + objUnderTest.start(); verify(huc, times(2)).getResponseCode(); } @@ -134,12 +152,11 @@ public class DataRouterSubscriberTest { PowerMockito.mockStatic(Thread.class); URL subEndpoint = mock(URL.class); - MapperConfig config = mock(MapperConfig.class); when(config.getBusControllerSubscriptionUrl()).thenReturn(subEndpoint); HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); when(subEndpoint.openConnection()).thenReturn(huc); doThrow(new IOException()).when(huc).getResponseCode(); - Assertions.assertThrows(TooManyTriesException.class, () -> objUnderTest.start(config)); + Assertions.assertThrows(TooManyTriesException.class, () -> objUnderTest.start()); } @Test @@ -170,11 +187,30 @@ public class DataRouterSubscriberTest { verify(eventReceiver, times(0)).receive(any()); } + @Test + public void testStartPositiveResponseCodeInvalidResponseBody() throws Exception{ + PowerMockito.mockStatic(EnvironmentConfig.class); + PowerMockito.mockStatic(Thread.class); + PowerMockito.when(EnvironmentConfig.getCBSHostName()).thenReturn(""); + PowerMockito.when(EnvironmentConfig.getCBSPort()).thenReturn(1); + PowerMockito.when(EnvironmentConfig.getServiceName()).thenReturn(""); + + URL mockURL = mock(URL.class); + when(config.getBusControllerSubscriptionUrl()).thenReturn(mockURL); + HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + String bcResponse = "not a valid response"; + InputStream responseStream = new ByteArrayInputStream(bcResponse.getBytes(StandardCharsets.UTF_8)); + when(huc.getInputStream()).thenReturn(responseStream); + when(mockURL.openConnection()).thenReturn(huc); + when(huc.getResponseCode()).thenReturn(200); + Assertions.assertThrows(TooManyTriesException.class, () -> objUnderTest.start()); + } + @Test public void testRequestInboundInvalidMetadata() throws Exception { HttpServerExchange httpServerExchange = mock(HttpServerExchange.class, RETURNS_DEEP_STUBS); JsonObject metadata = new JsonParser().parse(new String(Files - .readAllBytes(Paths.get("src/test/resources/invalid_metadata.json")))).getAsJsonObject(); + .readAllBytes(INVALID_METADATA_PATH))).getAsJsonObject(); when(httpServerExchange.getRequestHeaders().get(any(String.class)).get(anyInt())) .thenReturn(metadata.toString()); when(httpServerExchange.setStatusCode(anyInt())).thenReturn(httpServerExchange); @@ -218,7 +254,7 @@ public class DataRouterSubscriberTest { when(httpServerExchange.getRequestReceiver()).thenReturn(receiver); String testString = "MESSAGE BODY"; JsonObject metadata = new JsonParser().parse( - new String(Files.readAllBytes(Paths.get("src/test/resources/valid_metadata.json")))).getAsJsonObject(); + new String(Files.readAllBytes(VALID_METADATA_PATH))).getAsJsonObject(); when(httpServerExchange.getRequestHeaders().get(DataRouterSubscriber.METADATA_HEADER).get(anyInt())) .thenReturn(metadata.toString()); when(httpServerExchange.getRequestHeaders().get(DataRouterSubscriber.PUB_ID_HEADER).getFirst()).thenReturn(""); @@ -244,4 +280,108 @@ public class DataRouterSubscriberTest { logAppender.stop(); } + @Test + public void testConfigThrowsMalformedURLException() throws MalformedURLException { + when(config.getBusControllerSubscriptionUrl()).thenThrow(MalformedURLException.class); + Assertions.assertThrows(IllegalStateException.class, () -> objUnderTest.start()); + } + @Test + public void testReconfigurationSameConfig() throws Exception { + PowerMockito.mockStatic(EnvironmentConfig.class); + PowerMockito.when(EnvironmentConfig.getCBSHostName()).thenReturn(""); + PowerMockito.when(EnvironmentConfig.getCBSPort()).thenReturn(1); + PowerMockito.when(EnvironmentConfig.getServiceName()).thenReturn(""); + + RequestSender sender = mock(RequestSender.class); + String mapperConfig = new String(Files.readAllBytes(VALID_CONFIG_PATH)); + when(sender.send(any())).thenReturn(mapperConfig); + MapperConfig originalMapperConfig = new ConfigHandler(sender).getMapperConfig(); + + DataRouterSubscriber objUnderTest = new DataRouterSubscriber(eventReceiver, originalMapperConfig); + objUnderTest.reconfigure(originalMapperConfig); + assertEquals(originalMapperConfig, objUnderTest.getConfig()); + } + + @Test + public void testReconfigurationModifiedFeedId() throws Exception { + PowerMockito.mockStatic(EnvironmentConfig.class); + PowerMockito.when(EnvironmentConfig.getCBSHostName()).thenReturn(""); + PowerMockito.when(EnvironmentConfig.getCBSPort()).thenReturn(1); + PowerMockito.when(EnvironmentConfig.getServiceName()).thenReturn(""); + + URL mockURL = mock(URL.class); + when(config.getBusControllerSubscriptionUrl()).thenReturn(mockURL); + HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + String bcResponse = new String(Files.readAllBytes(VALID_BC_RESPONSE_PATH)); + InputStream responseStream = new ByteArrayInputStream(bcResponse.getBytes(StandardCharsets.UTF_8)); + when(huc.getInputStream()).thenReturn(responseStream); + when(mockURL.openConnection()).thenReturn(huc); + when(huc.getResponseCode()).thenReturn(200); + + PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL); + + RequestSender sender = mock(RequestSender.class); + String mapperConfig = new String(Files.readAllBytes(VALID_CONFIG_PATH)); + when(sender.send(any())).thenReturn(mapperConfig); + MapperConfig originalMapperConfig = new ConfigHandler(sender).getMapperConfig(); + JsonObject modifiedMapperConfigObj = new JsonParser().parse(mapperConfig).getAsJsonObject(); + modifiedMapperConfigObj.addProperty("dmaap_dr_feed_id", "3"); + when(sender.send(any())).thenReturn(modifiedMapperConfigObj.toString()); + MapperConfig modifiedMapperConfig = new ConfigHandler(sender).getMapperConfig(); + + DataRouterSubscriber objUnderTest = new DataRouterSubscriber(eventReceiver, originalMapperConfig); + objUnderTest.reconfigure(modifiedMapperConfig); + assertEquals(modifiedMapperConfig, objUnderTest.getConfig()); + } + + @Test + public void testReconfigurationModifiedUsername() throws Exception { + PowerMockito.mockStatic(EnvironmentConfig.class); + PowerMockito.when(EnvironmentConfig.getCBSHostName()).thenReturn(""); + PowerMockito.when(EnvironmentConfig.getCBSPort()).thenReturn(1); + PowerMockito.when(EnvironmentConfig.getServiceName()).thenReturn(""); + + URL mockURL = mock(URL.class); + when(config.getBusControllerSubscriptionUrl()).thenReturn(mockURL); + HttpURLConnection huc = mock(HttpURLConnection.class, RETURNS_DEEP_STUBS); + String bcResponse = new String(Files.readAllBytes(VALID_BC_RESPONSE_PATH)); + InputStream responseStream = new ByteArrayInputStream(bcResponse.getBytes(StandardCharsets.UTF_8)); + when(huc.getInputStream()).thenReturn(responseStream); + when(mockURL.openConnection()).thenReturn(huc); + when(huc.getResponseCode()).thenReturn(200); + + PowerMockito.whenNew(URL.class).withAnyArguments().thenReturn(mockURL); + + RequestSender sender = mock(RequestSender.class); + String mapperConfig = new String(Files.readAllBytes(VALID_CONFIG_PATH)); + when(sender.send(any())).thenReturn(mapperConfig); + MapperConfig originalMapperConfig = new ConfigHandler(sender).getMapperConfig(); + JsonObject modifiedMapperConfigObj = new JsonParser().parse(mapperConfig).getAsJsonObject(); + modifiedMapperConfigObj.get("streams_subscribes") + .getAsJsonObject().get("dmaap_subscriber") + .getAsJsonObject().get("dmaap_info") + .getAsJsonObject() + .addProperty("username", "bob"); + when(sender.send(any())).thenReturn(modifiedMapperConfigObj.toString()); + MapperConfig modifiedMapperConfig = new ConfigHandler(sender).getMapperConfig(); + + DataRouterSubscriber objUnderTest = new DataRouterSubscriber(eventReceiver, originalMapperConfig); + objUnderTest.reconfigure(modifiedMapperConfig); + assertEquals(modifiedMapperConfig, objUnderTest.getConfig()); + } + + @Test + public void testReconfigurationMalformedURL() throws Exception { + when(config.getBusControllerSubscriptionUrl()).thenThrow(MalformedURLException.class); + Assertions.assertThrows(IllegalStateException.class, () -> objUnderTest.reconfigure(config)); + } + @Test + public void testReconfigurationException() throws Exception { + PowerMockito.mockStatic(Thread.class); + URL url = mock(URL.class); + when(url.toString()).thenReturn("http://valid:8080/"); + when(url.openConnection()).thenThrow(IOException.class); + when(config.getBusControllerSubscriptionUrl()).thenReturn(url); + Assertions.assertThrows(ReconfigurationException.class, () -> objUnderTest.reconfigure(config)); + } } diff --git a/src/test/resources/datarouter_subscriber_test/valid_bc_response.json b/src/test/resources/datarouter_subscriber_test/valid_bc_response.json new file mode 100644 index 0000000..201b786 --- /dev/null +++ b/src/test/resources/datarouter_subscriber_test/valid_bc_response.json @@ -0,0 +1,15 @@ +{ + "type": "dr_Sub", + "lastMod": "2019-03-11T14:29:39.659", + "status": "VALID", + "dcaeLocationName": "location", + "deliveryURL": "delivery_url", + "feedId": "2", + "logURL": "https://dmaap-dr-prov/sublog/2", + "owner": "DGL", + "subId": "1", + "suspended": false, + "use100": false, + "username": "username", + "userpwd": "password" +} \ No newline at end of file -- cgit 1.2.3-korg