2  * ============LICENSE_START=======================================================
 
   4  * ================================================================================
 
   5  * Copyright (C) 2020 AT&T Intellectual Property. 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.policy.controlloop.actorserviceprovider.parameters;
 
  23 import static org.assertj.core.api.Assertions.assertThat;
 
  24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
 
  25 import static org.junit.Assert.assertEquals;
 
  26 import static org.junit.Assert.assertFalse;
 
  27 import static org.junit.Assert.assertNotNull;
 
  28 import static org.junit.Assert.assertNull;
 
  29 import static org.junit.Assert.assertSame;
 
  30 import static org.junit.Assert.assertTrue;
 
  31 import static org.mockito.ArgumentMatchers.any;
 
  32 import static org.mockito.Mockito.doAnswer;
 
  33 import static org.mockito.Mockito.never;
 
  34 import static org.mockito.Mockito.times;
 
  35 import static org.mockito.Mockito.verify;
 
  36 import static org.mockito.Mockito.when;
 
  39 import java.util.TreeMap;
 
  40 import java.util.UUID;
 
  41 import java.util.concurrent.CompletableFuture;
 
  42 import java.util.concurrent.Executor;
 
  43 import java.util.concurrent.ForkJoinPool;
 
  44 import java.util.concurrent.atomic.AtomicInteger;
 
  45 import java.util.function.Consumer;
 
  46 import java.util.function.Function;
 
  47 import org.junit.Before;
 
  48 import org.junit.Test;
 
  49 import org.mockito.Mock;
 
  50 import org.mockito.MockitoAnnotations;
 
  51 import org.onap.policy.common.parameters.BeanValidationResult;
 
  52 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 
  53 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
 
  54 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
 
  55 import org.onap.policy.controlloop.actorserviceprovider.Operator;
 
  56 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
 
  57 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams.ControlLoopOperationParamsBuilder;
 
  58 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
 
  59 import org.onap.policy.controlloop.policy.Target;
 
  61 public class ControlLoopOperationParamsTest {
 
  62     private static final String EXPECTED_EXCEPTION = "expected exception";
 
  63     private static final String ACTOR = "my-actor";
 
  64     private static final String OPERATION = "my-operation";
 
  65     private static final Target TARGET = new Target();
 
  66     private static final String TARGET_ENTITY = "my-target";
 
  67     private static final Integer RETRY = 3;
 
  68     private static final Integer TIMEOUT = 100;
 
  69     private static final UUID REQ_ID = UUID.randomUUID();
 
  75     private ActorService actorService;
 
  78     private Consumer<OperationOutcome> completer;
 
  81     private ControlLoopEventContext context;
 
  84     private VirtualControlLoopEvent event;
 
  87     private Executor executor;
 
  90     private CompletableFuture<OperationOutcome> operation;
 
  93     private Operator operator;
 
  96     private Consumer<OperationOutcome> starter;
 
  98     private Map<String, String> payload;
 
 100     private ControlLoopOperationParams params;
 
 101     private OperationOutcome outcome;
 
 105      * Initializes mocks and sets {@link #params} to a fully-loaded set of parameters.
 
 108     public void setUp() {
 
 109         MockitoAnnotations.initMocks(this);
 
 111         when(actorService.getActor(ACTOR)).thenReturn(actor);
 
 112         when(actor.getOperator(OPERATION)).thenReturn(operator);
 
 113         when(operator.startOperation(any())).thenReturn(operation);
 
 115         when(event.getRequestId()).thenReturn(REQ_ID);
 
 117         when(context.getEvent()).thenReturn(event);
 
 119         payload = new TreeMap<>();
 
 121         params = ControlLoopOperationParams.builder().actorService(actorService).completeCallback(completer)
 
 122                         .context(context).executor(executor).actor(ACTOR).operation(OPERATION).payload(payload)
 
 123                         .retry(RETRY).target(TARGET).targetEntity(TARGET_ENTITY).timeoutSec(TIMEOUT)
 
 124                         .startCallback(starter).build();
 
 126         outcome = params.makeOutcome();
 
 130     public void testStart() {
 
 131         assertSame(operation, params.start());
 
 133         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().start());
 
 137     public void testGetRequestId() {
 
 138         assertSame(REQ_ID, params.getRequestId());
 
 140         // try with null context
 
 141         assertNull(params.toBuilder().context(null).build().getRequestId());
 
 143         // try with null event
 
 144         when(context.getEvent()).thenReturn(null);
 
 145         assertNull(params.getRequestId());
 
 149     public void testMakeOutcome() {
 
 150         assertEquals(ACTOR, outcome.getActor());
 
 151         assertEquals(OPERATION, outcome.getOperation());
 
 152         checkRemainingFields("with actor");
 
 155     protected void checkRemainingFields(String testName) {
 
 156         assertEquals(testName, TARGET_ENTITY, outcome.getTarget());
 
 157         assertNull(testName, outcome.getStart());
 
 158         assertNull(testName, outcome.getEnd());
 
 159         assertNull(testName, outcome.getSubRequestId());
 
 160         assertNotNull(testName, outcome.getResult());
 
 161         assertNull(testName, outcome.getMessage());
 
 165     public void testCallbackStarted() {
 
 166         params.callbackStarted(outcome);
 
 167         verify(starter).accept(outcome);
 
 169         // modify starter to throw an exception
 
 170         AtomicInteger count = new AtomicInteger();
 
 172             count.incrementAndGet();
 
 173             throw new IllegalStateException(EXPECTED_EXCEPTION);
 
 174         }).when(starter).accept(outcome);
 
 176         params.callbackStarted(outcome);
 
 177         verify(starter, times(2)).accept(outcome);
 
 178         assertEquals(1, count.get());
 
 180         // repeat with no start-callback - no additional calls expected
 
 181         params.toBuilder().startCallback(null).build().callbackStarted(outcome);
 
 182         verify(starter, times(2)).accept(outcome);
 
 183         assertEquals(1, count.get());
 
 185         // should not call complete-callback
 
 186         verify(completer, never()).accept(any());
 
 190     public void testCallbackCompleted() {
 
 191         params.callbackCompleted(outcome);
 
 192         verify(completer).accept(outcome);
 
 194         // modify completer to throw an exception
 
 195         AtomicInteger count = new AtomicInteger();
 
 197             count.incrementAndGet();
 
 198             throw new IllegalStateException(EXPECTED_EXCEPTION);
 
 199         }).when(completer).accept(outcome);
 
 201         params.callbackCompleted(outcome);
 
 202         verify(completer, times(2)).accept(outcome);
 
 203         assertEquals(1, count.get());
 
 205         // repeat with no complete-callback - no additional calls expected
 
 206         params.toBuilder().completeCallback(null).build().callbackCompleted(outcome);
 
 207         verify(completer, times(2)).accept(outcome);
 
 208         assertEquals(1, count.get());
 
 210         // should not call start-callback
 
 211         verify(starter, never()).accept(any());
 
 215     public void testValidateFields() {
 
 216         testValidate("actor", "null", bldr -> bldr.actor(null));
 
 217         testValidate("actorService", "null", bldr -> bldr.actorService(null));
 
 218         testValidate("context", "null", bldr -> bldr.context(null));
 
 219         testValidate("executor", "null", bldr -> bldr.executor(null));
 
 220         testValidate("operation", "null", bldr -> bldr.operation(null));
 
 221         testValidate("target", "null", bldr -> bldr.targetEntity(null));
 
 224         assertTrue(params.toBuilder().build().validate().isValid());
 
 227         assertTrue(params.toBuilder().payload(null).retry(null).target(null).timeoutSec(null).startCallback(null)
 
 228                         .completeCallback(null).build().validate().isValid());
 
 230         // test with minimal fields
 
 231         assertTrue(ControlLoopOperationParams.builder().actorService(actorService).context(context).actor(ACTOR)
 
 232                         .operation(OPERATION).targetEntity(TARGET_ENTITY).build().validate().isValid());
 
 235     private void testValidate(String fieldName, String expected,
 
 236                     Function<ControlLoopOperationParamsBuilder, ControlLoopOperationParamsBuilder> makeInvalid) {
 
 238         // original params should be valid
 
 239         BeanValidationResult result = params.validate();
 
 240         assertTrue(fieldName, result.isValid());
 
 242         // make invalid params
 
 243         result = makeInvalid.apply(params.toBuilder()).build().validate();
 
 244         assertFalse(fieldName, result.isValid());
 
 245         assertThat(result.getResult()).contains(fieldName).contains(expected);
 
 249     public void testBuilder_testToBuilder() {
 
 250         assertEquals(params, params.toBuilder().build());
 
 254     public void testGetActor() {
 
 255         assertSame(ACTOR, params.getActor());
 
 259     public void testGetActorService() {
 
 260         assertSame(actorService, params.getActorService());
 
 264     public void testGetContext() {
 
 265         assertSame(context, params.getContext());
 
 269     public void testGetExecutor() {
 
 270         assertSame(executor, params.getExecutor());
 
 272         // should use default when unspecified
 
 273         assertSame(ForkJoinPool.commonPool(), ControlLoopOperationParams.builder().build().getExecutor());
 
 277     public void testGetOperation() {
 
 278         assertSame(OPERATION, params.getOperation());
 
 282     public void testGetPayload() {
 
 283         assertSame(payload, params.getPayload());
 
 285         // should be null when unspecified
 
 286         assertNull(ControlLoopOperationParams.builder().build().getPayload());
 
 290     public void testGetRetry() {
 
 291         assertSame(RETRY, params.getRetry());
 
 293         // should be null when unspecified
 
 294         assertNull(ControlLoopOperationParams.builder().build().getRetry());
 
 298     public void testTarget() {
 
 299         assertSame(TARGET, params.getTarget());
 
 301         // should be null when unspecified
 
 302         assertNull(ControlLoopOperationParams.builder().build().getTarget());
 
 306     public void testGetTimeoutSec() {
 
 307         assertSame(TIMEOUT, params.getTimeoutSec());
 
 309         // should be 300 when unspecified
 
 310         assertEquals(Integer.valueOf(300), ControlLoopOperationParams.builder().build().getTimeoutSec());
 
 312         // null should be ok too
 
 313         assertNull(ControlLoopOperationParams.builder().timeoutSec(null).build().getTimeoutSec());
 
 317     public void testGetStartCallback() {
 
 318         assertSame(starter, params.getStartCallback());
 
 322     public void testGetCompleteCallback() {
 
 323         assertSame(completer, params.getCompleteCallback());
 
 327     public void testGetTargetEntity() {
 
 328         assertEquals(TARGET_ENTITY, params.getTargetEntity());