Clean up and enhancement of Actor re-design
[policy/models.git] / models-interactions / model-actors / actorServiceProvider / src / test / java / org / onap / policy / controlloop / actorserviceprovider / parameters / ControlLoopOperationParamsTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 package org.onap.policy.controlloop.actorserviceprovider.parameters;
22
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;
37
38 import java.util.Map;
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;
60
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();
70
71     @Mock
72     private Actor actor;
73
74     @Mock
75     private ActorService actorService;
76
77     @Mock
78     private Consumer<OperationOutcome> completer;
79
80     @Mock
81     private ControlLoopEventContext context;
82
83     @Mock
84     private VirtualControlLoopEvent event;
85
86     @Mock
87     private Executor executor;
88
89     @Mock
90     private CompletableFuture<OperationOutcome> operation;
91
92     @Mock
93     private Operator operator;
94
95     @Mock
96     private Consumer<OperationOutcome> starter;
97
98     private Map<String, String> payload;
99
100     private ControlLoopOperationParams params;
101     private OperationOutcome outcome;
102
103
104     /**
105      * Initializes mocks and sets {@link #params} to a fully-loaded set of parameters.
106      */
107     @Before
108     public void setUp() {
109         MockitoAnnotations.initMocks(this);
110
111         when(actorService.getActor(ACTOR)).thenReturn(actor);
112         when(actor.getOperator(OPERATION)).thenReturn(operator);
113         when(operator.startOperation(any())).thenReturn(operation);
114
115         when(event.getRequestId()).thenReturn(REQ_ID);
116
117         when(context.getEvent()).thenReturn(event);
118
119         payload = new TreeMap<>();
120
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();
125
126         outcome = params.makeOutcome();
127     }
128
129     @Test
130     public void testStart() {
131         assertSame(operation, params.start());
132
133         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().start());
134     }
135
136     @Test
137     public void testGetRequestId() {
138         assertSame(REQ_ID, params.getRequestId());
139
140         // try with null context
141         assertNull(params.toBuilder().context(null).build().getRequestId());
142
143         // try with null event
144         when(context.getEvent()).thenReturn(null);
145         assertNull(params.getRequestId());
146     }
147
148     @Test
149     public void testMakeOutcome() {
150         assertEquals(ACTOR, outcome.getActor());
151         assertEquals(OPERATION, outcome.getOperation());
152         checkRemainingFields("with actor");
153     }
154
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());
162     }
163
164     @Test
165     public void testCallbackStarted() {
166         params.callbackStarted(outcome);
167         verify(starter).accept(outcome);
168
169         // modify starter to throw an exception
170         AtomicInteger count = new AtomicInteger();
171         doAnswer(args -> {
172             count.incrementAndGet();
173             throw new IllegalStateException(EXPECTED_EXCEPTION);
174         }).when(starter).accept(outcome);
175
176         params.callbackStarted(outcome);
177         verify(starter, times(2)).accept(outcome);
178         assertEquals(1, count.get());
179
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());
184
185         // should not call complete-callback
186         verify(completer, never()).accept(any());
187     }
188
189     @Test
190     public void testCallbackCompleted() {
191         params.callbackCompleted(outcome);
192         verify(completer).accept(outcome);
193
194         // modify completer to throw an exception
195         AtomicInteger count = new AtomicInteger();
196         doAnswer(args -> {
197             count.incrementAndGet();
198             throw new IllegalStateException(EXPECTED_EXCEPTION);
199         }).when(completer).accept(outcome);
200
201         params.callbackCompleted(outcome);
202         verify(completer, times(2)).accept(outcome);
203         assertEquals(1, count.get());
204
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());
209
210         // should not call start-callback
211         verify(starter, never()).accept(any());
212     }
213
214     @Test
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));
222
223         // check edge cases
224         assertTrue(params.toBuilder().build().validate().isValid());
225
226         // these can be null
227         assertTrue(params.toBuilder().payload(null).retry(null).target(null).timeoutSec(null).startCallback(null)
228                         .completeCallback(null).build().validate().isValid());
229
230         // test with minimal fields
231         assertTrue(ControlLoopOperationParams.builder().actorService(actorService).context(context).actor(ACTOR)
232                         .operation(OPERATION).targetEntity(TARGET_ENTITY).build().validate().isValid());
233     }
234
235     private void testValidate(String fieldName, String expected,
236                     Function<ControlLoopOperationParamsBuilder, ControlLoopOperationParamsBuilder> makeInvalid) {
237
238         // original params should be valid
239         BeanValidationResult result = params.validate();
240         assertTrue(fieldName, result.isValid());
241
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);
246     }
247
248     @Test
249     public void testBuilder_testToBuilder() {
250         assertEquals(params, params.toBuilder().build());
251     }
252
253     @Test
254     public void testGetActor() {
255         assertSame(ACTOR, params.getActor());
256     }
257
258     @Test
259     public void testGetActorService() {
260         assertSame(actorService, params.getActorService());
261     }
262
263     @Test
264     public void testGetContext() {
265         assertSame(context, params.getContext());
266     }
267
268     @Test
269     public void testGetExecutor() {
270         assertSame(executor, params.getExecutor());
271
272         // should use default when unspecified
273         assertSame(ForkJoinPool.commonPool(), ControlLoopOperationParams.builder().build().getExecutor());
274     }
275
276     @Test
277     public void testGetOperation() {
278         assertSame(OPERATION, params.getOperation());
279     }
280
281     @Test
282     public void testGetPayload() {
283         assertSame(payload, params.getPayload());
284
285         // should be null when unspecified
286         assertNull(ControlLoopOperationParams.builder().build().getPayload());
287     }
288
289     @Test
290     public void testGetRetry() {
291         assertSame(RETRY, params.getRetry());
292
293         // should be null when unspecified
294         assertNull(ControlLoopOperationParams.builder().build().getRetry());
295     }
296
297     @Test
298     public void testTarget() {
299         assertSame(TARGET, params.getTarget());
300
301         // should be null when unspecified
302         assertNull(ControlLoopOperationParams.builder().build().getTarget());
303     }
304
305     @Test
306     public void testGetTimeoutSec() {
307         assertSame(TIMEOUT, params.getTimeoutSec());
308
309         // should be 300 when unspecified
310         assertEquals(Integer.valueOf(300), ControlLoopOperationParams.builder().build().getTimeoutSec());
311
312         // null should be ok too
313         assertNull(ControlLoopOperationParams.builder().timeoutSec(null).build().getTimeoutSec());
314     }
315
316     @Test
317     public void testGetStartCallback() {
318         assertSame(starter, params.getStartCallback());
319     }
320
321     @Test
322     public void testGetCompleteCallback() {
323         assertSame(completer, params.getCompleteCallback());
324     }
325
326     @Test
327     public void testGetTargetEntity() {
328         assertEquals(TARGET_ENTITY, params.getTargetEntity());
329     }
330 }