X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=policy-agent%2Fsrc%2Ftest%2Fjava%2Forg%2Foransc%2Fpolicyagent%2Ftasks%2FRefreshConfigTaskTest.java;h=673ed68a723c0c2193ef4a7734fcae9c5f3a2b81;hb=6a39814272307d0207222c9229b0d765ac062bf0;hp=90b384743fb3d93e6cac1bd75eb2de9f9c413c33;hpb=80ebd8eb750de60424ffb3895fbc7b2032bd1a50;p=nonrtric.git diff --git a/policy-agent/src/test/java/org/oransc/policyagent/tasks/RefreshConfigTaskTest.java b/policy-agent/src/test/java/org/oransc/policyagent/tasks/RefreshConfigTaskTest.java index 90b38474..673ed68a 100644 --- a/policy-agent/src/test/java/org/oransc/policyagent/tasks/RefreshConfigTaskTest.java +++ b/policy-agent/src/test/java/org/oransc/policyagent/tasks/RefreshConfigTaskTest.java @@ -20,13 +20,17 @@ package org.oransc.policyagent.tasks; +import static ch.qos.logback.classic.Level.ERROR; +import static ch.qos.logback.classic.Level.WARN; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.awaitility.Awaitility.await; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; @@ -44,11 +48,13 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.time.Duration; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; import java.util.Properties; import java.util.Vector; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -57,11 +63,22 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties; import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties; +import org.oransc.policyagent.clients.A1ClientFactory; import org.oransc.policyagent.configuration.ApplicationConfig; +import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate.Type; import org.oransc.policyagent.configuration.ApplicationConfigParser; +import org.oransc.policyagent.configuration.ApplicationConfigParser.ConfigParserResult; +import org.oransc.policyagent.configuration.ImmutableConfigParserResult; import org.oransc.policyagent.configuration.ImmutableRicConfig; import org.oransc.policyagent.configuration.RicConfig; -import org.oransc.policyagent.exceptions.ServiceException; +import org.oransc.policyagent.repository.ImmutablePolicy; +import org.oransc.policyagent.repository.ImmutablePolicyType; +import org.oransc.policyagent.repository.Policies; +import org.oransc.policyagent.repository.Policy; +import org.oransc.policyagent.repository.PolicyTypes; +import org.oransc.policyagent.repository.Ric; +import org.oransc.policyagent.repository.Rics; +import org.oransc.policyagent.repository.Services; import org.oransc.policyagent.utils.LoggingUtils; import reactor.core.publisher.Flux; @@ -69,7 +86,10 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @ExtendWith(MockitoExtension.class) -public class RefreshConfigTaskTest { +class RefreshConfigTaskTest { + + private static final boolean CONFIG_FILE_EXISTS = true; + private static final boolean CONFIG_FILE_DOES_NOT_EXIST = false; private RefreshConfigTask refreshTaskUnderTest; @@ -79,10 +99,12 @@ public class RefreshConfigTaskTest { @Mock CbsClient cbsClient; - public static final ImmutableRicConfig CORRECT_RIC_CONIFG = ImmutableRicConfig.builder() // - .name("ric1") // + private static final String RIC_1_NAME = "ric1"; + private static final ImmutableRicConfig CORRECT_RIC_CONIFG = ImmutableRicConfig.builder() // + .name(RIC_1_NAME) // .baseUrl("http://localhost:8080/") // .managedElementIds(new Vector(Arrays.asList("kista_1", "kista_2"))) // + .controllerName("") // .build(); private static EnvProperties properties() { @@ -94,17 +116,78 @@ public class RefreshConfigTaskTest { .build(); } + private RefreshConfigTask createTestObject(boolean configFileExists) { + return createTestObject(configFileExists, new Rics(), new Policies(), true); + } + + private RefreshConfigTask createTestObject(boolean configFileExists, Rics rics, Policies policies, + boolean stubConfigFileExists) { + RefreshConfigTask obj = spy(new RefreshConfigTask(appConfig, rics, policies, new Services(), new PolicyTypes(), + new A1ClientFactory(appConfig))); + if (stubConfigFileExists) { + doReturn(configFileExists).when(obj).fileExists(any()); + } + return obj; + } + + @Test + void startWithStubbedRefresh_thenTerminationLogged() { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false); + doReturn(Flux.empty()).when(refreshTaskUnderTest).createRefreshTask(); + + final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR); + + refreshTaskUnderTest.start(); + + assertThat(logAppender.list.get(0).getFormattedMessage()).isEqualTo("Configuration refresh terminated"); + } + + @Test + void startWithStubbedRefreshReturnError_thenErrorAndTerminationLogged() { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false); + String errorMessage = "Error"; + doReturn(Flux.error(new Exception(errorMessage))).when(refreshTaskUnderTest).createRefreshTask(); + + final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR); + + refreshTaskUnderTest.start(); + + ILoggingEvent event = logAppender.list.get(0); + assertThat(event.getFormattedMessage()) + .isEqualTo("Configuration refresh terminated due to exception java.lang.Exception: " + errorMessage); + } + @Test - public void whenTheConfigurationFits() throws IOException, ServiceException { - refreshTaskUnderTest = spy(new RefreshConfigTask(appConfig)); + void stop_thenTaskIsDisposed() throws Exception { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false); + refreshTaskUnderTest.systemEnvironment = new Properties(); + + refreshTaskUnderTest.start(); + refreshTaskUnderTest.stop(); + + assertThat(refreshTaskUnderTest.getRefreshTask().isDisposed()).as("Refresh task is disposed").isTrue(); + } + + @Test + void whenTheConfigurationFits_thenConfiguredRicsArePutInRepository() throws Exception { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_EXISTS); refreshTaskUnderTest.systemEnvironment = new Properties(); // When doReturn(getCorrectJson()).when(refreshTaskUnderTest).createInputStream(any()); doReturn("fileName").when(appConfig).getLocalConfigurationFilePath(); - refreshTaskUnderTest.start(); + + StepVerifier // + .create(refreshTaskUnderTest.createRefreshTask()) // + .expectSubscription() // + .expectNext(Type.ADDED) // + .expectNext(Type.ADDED) // + .thenCancel() // + .verify(); // Then - verify(refreshTaskUnderTest, times(1)).loadConfigurationFromFile(); + verify(refreshTaskUnderTest).loadConfigurationFromFile(); + + verify(refreshTaskUnderTest, times(2)).runRicSynchronization(any(Ric.class)); Iterable ricConfigs = appConfig.getRicConfigs(); RicConfig ricConfig = ricConfigs.iterator().next(); @@ -113,82 +196,180 @@ public class RefreshConfigTaskTest { } @Test - public void whenFileIsExistsButJsonIsIncorrect() throws IOException, ServiceException { - refreshTaskUnderTest = spy(new RefreshConfigTask(appConfig)); + void whenFileExistsButJsonIsIncorrect_thenNoRicsArePutInRepositoryAndErrorIsLogged() throws Exception { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_EXISTS); refreshTaskUnderTest.systemEnvironment = new Properties(); // When doReturn(getIncorrectJson()).when(refreshTaskUnderTest).createInputStream(any()); doReturn("fileName").when(appConfig).getLocalConfigurationFilePath(); - refreshTaskUnderTest.loadConfigurationFromFile(); + + final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR); + + StepVerifier // + .create(refreshTaskUnderTest.createRefreshTask()) // + .expectSubscription() // + .expectNoEvent(Duration.ofMillis(100)) // + .thenCancel() // + .verify(); // Then - verify(refreshTaskUnderTest, times(1)).loadConfigurationFromFile(); - Assertions.assertEquals(0, appConfig.getRicConfigs().size()); + verify(refreshTaskUnderTest).loadConfigurationFromFile(); + assertThat(appConfig.getRicConfigs()).isEmpty(); + + await().until(() -> logAppender.list.size() > 0); + assertThat(logAppender.list.get(0).getFormattedMessage()) + .startsWith("Local configuration file not loaded: fileName, "); } @Test - public void whenPeriodicConfigRefreshNoEnvironmentVariables() { - refreshTaskUnderTest = spy(new RefreshConfigTask(appConfig)); + void whenPeriodicConfigRefreshNoConsul_thenErrorIsLogged() { + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST); refreshTaskUnderTest.systemEnvironment = new Properties(); - final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class); - Flux task = refreshTaskUnderTest.createRefreshTask(); + EnvProperties props = properties(); + doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any()); - StepVerifier.create(task).expectSubscription().verifyComplete(); + doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props); + when(cbsClient.get(any())).thenReturn(Mono.error(new IOException())); + + final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, WARN); - assertTrue(logAppender.list.toString().contains("$CONSUL_HOST environment has not been defined")); + StepVerifier // + .create(refreshTaskUnderTest.createRefreshTask()) // + .expectSubscription() // + .expectNoEvent(Duration.ofMillis(1000)) // + .thenCancel() // + .verify(); + + await().until(() -> logAppender.list.size() > 0); + assertThat(logAppender.list.get(0).getFormattedMessage()) + .isEqualTo("Could not refresh application configuration. java.io.IOException"); } @Test - public void whenPeriodicConfigRefreshNoConsul() { - refreshTaskUnderTest = spy(new RefreshConfigTask(appConfig)); + void whenPeriodicConfigRefreshSuccess_thenNewConfigIsCreatedAndRepositoryUpdated() throws Exception { + Rics rics = new Rics(); + Policies policies = new Policies(); + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, rics, policies, false); refreshTaskUnderTest.systemEnvironment = new Properties(); + RicConfig changedRicConfig = getRicConfig(RIC_1_NAME); + rics.put(new Ric(changedRicConfig)); + RicConfig removedRicConfig = getRicConfig("removed"); + Ric removedRic = new Ric(removedRicConfig); + rics.put(removedRic); + appConfig.setConfiguration(configParserResult(changedRicConfig, removedRicConfig)); + + Policy policy = getPolicy(removedRic); + policies.put(policy); + EnvProperties props = properties(); doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any()); - doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props); - Flux err = Flux.error(new IOException()); - doReturn(err).when(cbsClient).updates(any(), any(), any()); - final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class); - Flux task = refreshTaskUnderTest.createRefreshTask(); + JsonObject configAsJson = getJsonRootObject(true); + String newBaseUrl = "newBaseUrl"; + modifyTheRicConfiguration(configAsJson, newBaseUrl); + when(cbsClient.get(any())).thenReturn(Mono.just(configAsJson)); + doNothing().when(refreshTaskUnderTest).runRicSynchronization(any(Ric.class)); StepVerifier // - .create(task) // + .create(refreshTaskUnderTest.createRefreshTask()) // .expectSubscription() // - .verifyComplete(); - - assertTrue( - logAppender.list.toString().contains("Could not refresh application configuration java.io.IOException")); + .expectNext(Type.CHANGED) // + .expectNext(Type.ADDED) // + .expectNext(Type.REMOVED) // + .thenCancel() // + .verify(); + + assertThat(appConfig.getRicConfigs()).hasSize(2); + assertThat(appConfig.getRic(RIC_1_NAME).baseUrl()).isEqualTo(newBaseUrl); + String ric2Name = "ric2"; + assertThat(appConfig.getRic(ric2Name)).isNotNull(); + + assertThat(rics.size()).isEqualTo(2); + assertThat(rics.get(RIC_1_NAME).getConfig().baseUrl()).isEqualTo(newBaseUrl); + assertThat(rics.get(ric2Name)).isNotNull(); + + assertThat(policies.size()).isZero(); } @Test - public void whenPeriodicConfigRefreshSuccess() throws JsonIOException, JsonSyntaxException, IOException { - refreshTaskUnderTest = spy(new RefreshConfigTask(appConfig)); + void whenPeriodicConfigRefreshInvalidJson_thenErrorIsLogged() throws Exception { + Rics rics = new Rics(); + Policies policies = new Policies(); + refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, rics, policies, false); refreshTaskUnderTest.systemEnvironment = new Properties(); + appConfig.setConfiguration(configParserResult()); + EnvProperties props = properties(); doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any()); doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props); - Flux json = Flux.just(getJsonRootObject()); - doReturn(json).when(cbsClient).updates(any(), any(), any()); + JsonObject configAsJson = getJsonRootObject(false); + when(cbsClient.get(any())).thenReturn(Mono.just(configAsJson)); - Flux task = refreshTaskUnderTest.createRefreshTask(); + final ListAppender logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR); StepVerifier // - .create(task) // + .create(refreshTaskUnderTest.createRefreshTask()) // .expectSubscription() // - .expectNext(appConfig) // - .verifyComplete(); + .expectNoEvent(Duration.ofMillis(1000)) // + .thenCancel() // + .verify(); + + await().until(() -> logAppender.list.size() > 0); + assertThat(logAppender.list.get(0).getFormattedMessage()) + .startsWith("Could not parse configuration org.oransc.policyagent.exceptions.ServiceException: "); + } + + private RicConfig getRicConfig(String name) { + RicConfig ricConfig = ImmutableRicConfig.builder() // + .name(name) // + .baseUrl("url") // + .managedElementIds(Collections.emptyList()) // + .controllerName("controllerName") // + .build(); + return ricConfig; + } + + private Policy getPolicy(Ric ric) { + ImmutablePolicyType type = ImmutablePolicyType.builder() // + .name("type") // + .schema("{}") // + .build(); + Policy policy = ImmutablePolicy.builder() // + .id("id") // + .type(type) // + .lastModified("lastModified") // + .ric(ric) // + .json("{}") // + .ownerServiceName("ownerServiceName") // + .isTransient(false) // + .build(); + return policy; + } + + ConfigParserResult configParserResult(RicConfig... rics) { + return ImmutableConfigParserResult.builder() // + .ricConfigs(Arrays.asList(rics)) // + .dmaapConsumerTopicUrl("") // + .dmaapProducerTopicUrl("") // + .controllerConfigs(new HashMap<>()) // + .build(); + } - Assertions.assertNotNull(appConfig.getRicConfigs()); + private void modifyTheRicConfiguration(JsonObject configAsJson, String newBaseUrl) { + ((JsonObject) configAsJson.getAsJsonObject("config") // + .getAsJsonArray("ric").get(0)) // + .addProperty("baseUrl", newBaseUrl); } - private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException { - JsonObject rootObject = JsonParser.parseReader(new InputStreamReader(getCorrectJson())).getAsJsonObject(); + private JsonObject getJsonRootObject(boolean valid) throws JsonIOException, JsonSyntaxException, IOException { + JsonObject rootObject = JsonParser + .parseReader(new InputStreamReader(valid ? getCorrectJson() : getIncorrectJson())).getAsJsonObject(); return rootObject; } @@ -199,9 +380,7 @@ public class RefreshConfigTaskTest { } private static InputStream getIncorrectJson() { - String string = "{" + // - " \"config\": {" + // - " \"ric\": {"; // + String string = "{}"; // return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8))); } }