2  * ========================LICENSE_START=================================
 
   4  * ======================================================================
 
   5  * Copyright (C) 2020 Nordix Foundation. All rights reserved.
 
   6  * ======================================================================
 
   7  * Licensed under the Apache License, Version 2.0 (the "License");
 
   8  * you may not use this file except in compliance with the License.
 
   9  * You may obtain a copy of the License at
 
  11  *      http://www.apache.org/licenses/LICENSE-2.0
 
  13  * Unless required by applicable law or agreed to in writing, software
 
  14  * distributed under the License is distributed on an "AS IS" BASIS,
 
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  16  * See the License for the specific language governing permissions and
 
  17  * limitations under the License.
 
  18  * ========================LICENSE_END===================================
 
  21 package org.onap.ccsdk.oran.a1policymanagementservice.tasks;
 
  23 import static org.assertj.core.api.Assertions.assertThat;
 
  24 import static org.awaitility.Awaitility.await;
 
  25 import static org.mockito.ArgumentMatchers.any;
 
  26 import static org.mockito.Mockito.doReturn;
 
  27 import static org.mockito.Mockito.spy;
 
  28 import static org.mockito.Mockito.times;
 
  29 import static org.mockito.Mockito.verify;
 
  30 import static org.mockito.Mockito.verifyNoInteractions;
 
  31 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
  32 import static org.mockito.Mockito.when;
 
  34 import java.time.Duration;
 
  35 import java.time.Instant;
 
  36 import java.util.Arrays;
 
  37 import java.util.Collections;
 
  39 import org.junit.jupiter.api.BeforeEach;
 
  40 import org.junit.jupiter.api.Test;
 
  41 import org.junit.jupiter.api.extension.ExtendWith;
 
  42 import org.mockito.Mock;
 
  43 import org.mockito.junit.jupiter.MockitoExtension;
 
  44 import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1Client;
 
  45 import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory;
 
  46 import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory;
 
  47 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
 
  48 import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ImmutableRicConfig;
 
  49 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies;
 
  50 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy;
 
  51 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType;
 
  52 import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes;
 
  53 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric;
 
  54 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric.RicState;
 
  55 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics;
 
  56 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Service;
 
  57 import org.onap.ccsdk.oran.a1policymanagementservice.repository.Services;
 
  59 import reactor.core.publisher.Flux;
 
  60 import reactor.core.publisher.Mono;
 
  62 @ExtendWith(MockitoExtension.class)
 
  63 class RicSynchronizationTaskTest {
 
  64     private static final String POLICY_TYPE_1_NAME = "type1";
 
  65     private static final PolicyType POLICY_TYPE_1 = PolicyType.builder() //
 
  66             .id(POLICY_TYPE_1_NAME) //
 
  70     private static final String RIC_1_NAME = "ric1";
 
  72     private static Ric ric1;
 
  74     private static Policy createPolicy(String policyId, boolean isTransient) {
 
  75         return Policy.builder() //
 
  78                 .ownerServiceId("service") //
 
  80                 .type(POLICY_TYPE_1) //
 
  81                 .lastModified(Instant.now()) //
 
  82                 .isTransient(isTransient) //
 
  83                 .statusNotificationUri("statusNotificationUri") //
 
  87     private static Policy policy1;
 
  88     private static final String SERVICE_1_NAME = "service1";
 
  89     private static final String SERVICE_1_CALLBACK_URL = "callbackUrl";
 
  90     private static Service service1;
 
  93     private A1Client a1ClientMock;
 
  96     private A1ClientFactory a1ClientFactoryMock;
 
  98     private PolicyTypes policyTypes;
 
  99     private Policies policies;
 
 100     private Services services;
 
 103     private final ApplicationConfig appConfig = new ApplicationConfig();
 
 107         ric1 = new Ric(ImmutableRicConfig.builder() //
 
 108                 .ricId(RIC_1_NAME) //
 
 109                 .baseUrl("baseUrl1") //
 
 110                 .managedElementIds(Collections.emptyList()) //
 
 111                 .controllerName("controllerName") //
 
 113         policy1 = createPolicy("policyId1", false);
 
 114         policyTypes = new PolicyTypes(appConfig);
 
 115         policies = new Policies(appConfig);
 
 116         services = new Services(appConfig);
 
 119         service1 = new Service(SERVICE_1_NAME, Duration.ofSeconds(1), SERVICE_1_CALLBACK_URL);
 
 122     private RicSynchronizationTask createTask() {
 
 123         ApplicationConfig config = new ApplicationConfig();
 
 124         AsyncRestClientFactory restClientFactory = new AsyncRestClientFactory(config.getWebClientConfig());
 
 125         return new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services, restClientFactory,
 
 130     void ricAlreadySynchronizing_thenNoSynchronization() {
 
 131         ric1.setState(RicState.SYNCHRONIZING);
 
 132         ric1.addSupportedPolicyType(POLICY_TYPE_1);
 
 134         policyTypes.put(POLICY_TYPE_1);
 
 135         policies.put(policy1);
 
 137         RicSynchronizationTask synchronizerUnderTest = createTask();
 
 139         synchronizerUnderTest.run(ric1);
 
 141         verifyNoInteractions(a1ClientMock);
 
 143         assertThat(policyTypes.size()).isEqualTo(1);
 
 144         assertThat(policies.size()).isEqualTo(1);
 
 145         assertThat(ric1.getState()).isEqualTo(RicState.SYNCHRONIZING);
 
 146         assertThat(ric1.getSupportedPolicyTypeNames()).hasSize(1);
 
 150     void ricIdlePolicyTypeInRepo_thenSynchronizationWithReuseOfTypeFromRepoAndCorrectServiceNotified() {
 
 152         ric1.setState(RicState.AVAILABLE);
 
 154         policyTypes.put(POLICY_TYPE_1);
 
 156         services.put(service1);
 
 157         Service serviceWithoutCallbackUrlShouldNotBeNotified = new Service("service2", Duration.ofSeconds(1), "");
 
 158         services.put(serviceWithoutCallbackUrlShouldNotBeNotified);
 
 160         setUpCreationOfA1Client();
 
 161         simulateRicWithOnePolicyType();
 
 163         RicSynchronizationTask synchronizerUnderTest = spy(createTask());
 
 165         ric1.setState(RicState.UNAVAILABLE);
 
 166         synchronizerUnderTest.run(ric1);
 
 167         await().untilAsserted(() -> RicState.AVAILABLE.equals(ric1.getState()));
 
 169         verify(a1ClientMock, times(1)).getPolicyTypeIdentities();
 
 170         verifyNoMoreInteractions(a1ClientMock);
 
 172         verify(synchronizerUnderTest).run(ric1);
 
 174         assertThat(policyTypes.size()).isEqualTo(1);
 
 175         assertThat(policies.size()).isZero();
 
 176         assertThat(ric1.getState()).isEqualTo(RicState.AVAILABLE);
 
 180     void ricIdlePolicyTypeNotInRepo_thenSynchronizationWithTypeFromRic() throws Exception {
 
 181         ric1.setState(RicState.AVAILABLE);
 
 184         setUpCreationOfA1Client();
 
 185         simulateRicWithOnePolicyType();
 
 186         String typeSchema = "schema";
 
 187         when(a1ClientMock.getPolicyTypeSchema(POLICY_TYPE_1_NAME)).thenReturn(Mono.just(typeSchema));
 
 189         RicSynchronizationTask synchronizerUnderTest = createTask();
 
 191         ric1.setState(RicState.UNAVAILABLE);
 
 192         synchronizerUnderTest.run(ric1);
 
 193         await().untilAsserted(() -> RicState.AVAILABLE.equals(ric1.getState()));
 
 195         verify(a1ClientMock).getPolicyTypeIdentities();
 
 196         verifyNoMoreInteractions(a1ClientMock);
 
 198         assertThat(policyTypes.size()).isEqualTo(1);
 
 199         assertThat(policyTypes.getType(POLICY_TYPE_1_NAME).getSchema()).isEqualTo(typeSchema);
 
 200         assertThat(policies.size()).isZero();
 
 201         assertThat(ric1.getState()).isEqualTo(RicState.AVAILABLE);
 
 205     void ricIdleAndHavePolicies_thenSynchronizationWithRecreationOfPolicies() {
 
 206         ric1.setState(RicState.AVAILABLE);
 
 209         Policy transientPolicy = createPolicy("transientPolicyId", true);
 
 211         policies.put(transientPolicy);
 
 212         policies.put(policy1);
 
 214         setUpCreationOfA1Client();
 
 215         simulateRicWithNoPolicyTypes();
 
 217         when(a1ClientMock.deleteAllPolicies()).thenReturn(Flux.just("OK"));
 
 218         when(a1ClientMock.putPolicy(any(Policy.class))).thenReturn(Mono.just("OK"));
 
 220         RicSynchronizationTask synchronizerUnderTest = createTask();
 
 222         ric1.setState(RicState.UNAVAILABLE);
 
 223         synchronizerUnderTest.run(ric1);
 
 224         await().untilAsserted(() -> RicState.AVAILABLE.equals(ric1.getState()));
 
 226         verify(a1ClientMock).deleteAllPolicies();
 
 227         verify(a1ClientMock).putPolicy(policy1);
 
 228         verifyNoMoreInteractions(a1ClientMock);
 
 230         assertThat(policyTypes.size()).isZero();
 
 231         assertThat(policies.size()).isEqualTo(1); // The transient policy shall be deleted
 
 232         assertThat(ric1.getState()).isEqualTo(RicState.AVAILABLE);
 
 236     void ricIdleAndErrorDeletingPoliciesFirstTime_thenSynchronizationWithDeletionOfPolicies() {
 
 237         ric1.setState(RicState.AVAILABLE);
 
 240         policies.put(policy1);
 
 242         setUpCreationOfA1Client();
 
 243         simulateRicWithNoPolicyTypes();
 
 245         when(a1ClientMock.deleteAllPolicies()) //
 
 246                 .thenReturn(Flux.error(new Exception("Exception"))) //
 
 247                 .thenReturn(Flux.just("OK"));
 
 249         RicSynchronizationTask synchronizerUnderTest = createTask();
 
 251         ric1.setState(RicState.UNAVAILABLE);
 
 252         synchronizerUnderTest.run(ric1);
 
 253         await().untilAsserted(() -> RicState.AVAILABLE.equals(ric1.getState()));
 
 255         verify(a1ClientMock, times(2)).deleteAllPolicies();
 
 256         verifyNoMoreInteractions(a1ClientMock);
 
 258         assertThat(policyTypes.size()).isZero();
 
 259         assertThat(policies.size()).isZero();
 
 260         assertThat(ric1.getState()).isEqualTo(RicState.AVAILABLE);
 
 264     void ricIdleAndErrorDeletingPoliciesAllTheTime_thenSynchronizationWithFailedRecovery() {
 
 265         setUpCreationOfA1Client();
 
 266         simulateRicWithNoPolicyTypes();
 
 268         policies.put(policy1);
 
 270         String originalErrorMessage = "Exception";
 
 271         when(a1ClientMock.deleteAllPolicies()).thenReturn(Flux.error(new Exception(originalErrorMessage)));
 
 273         RicSynchronizationTask synchronizerUnderTest = createTask();
 
 275         ric1.setState(RicState.AVAILABLE);
 
 276         synchronizerUnderTest.run(ric1);
 
 277         await().untilAsserted(() -> RicState.UNAVAILABLE.equals(ric1.getState()));
 
 279         verify(a1ClientMock, times(2)).deleteAllPolicies();
 
 280         verifyNoMoreInteractions(a1ClientMock);
 
 282         assertThat(policyTypes.size()).isZero();
 
 283         assertThat(policies.size()).isZero();
 
 284         assertThat(ric1.getState()).isEqualTo(RicState.UNAVAILABLE);
 
 287     private void setUpCreationOfA1Client() {
 
 288         when(a1ClientFactoryMock.createA1Client(any(Ric.class))).thenReturn(Mono.just(a1ClientMock));
 
 289         doReturn(Flux.empty()).when(a1ClientMock).deleteAllPolicies();
 
 292     private void simulateRicWithOnePolicyType() {
 
 293         when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.just(Arrays.asList(POLICY_TYPE_1_NAME)));
 
 296     private void simulateRicWithNoPolicyTypes() {
 
 297         when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.just(Collections.emptyList()));