caa840891df862b21b1b3175f1b27f344cb7d401
[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.Operation;
55 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
56 import org.onap.policy.controlloop.actorserviceprovider.Operator;
57 import org.onap.policy.controlloop.actorserviceprovider.controlloop.ControlLoopEventContext;
58 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams.ControlLoopOperationParamsBuilder;
59 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
60
61 public class ControlLoopOperationParamsTest {
62     private static final String NULL_MSG = "null";
63     private static final String REQUEST_ID_NAME = "requestId";
64     private static final String EXPECTED_EXCEPTION = "expected exception";
65     private static final String ACTOR = "my-actor";
66     private static final String OPERATION = "my-operation";
67     private static final String TARGET_ENTITY = "my-target";
68     private static final Integer RETRY = 3;
69     private static final Integer TIMEOUT = 100;
70     private static final UUID REQ_ID = UUID.randomUUID();
71     private static final UUID REQ_ID2 = UUID.randomUUID();
72
73     @Mock
74     private Actor actor;
75
76     @Mock
77     private ActorService actorService;
78
79     @Mock
80     private Consumer<OperationOutcome> completer;
81
82     @Mock
83     private ControlLoopEventContext context;
84
85     @Mock
86     private VirtualControlLoopEvent event;
87
88     @Mock
89     private Executor executor;
90
91     @Mock
92     private CompletableFuture<OperationOutcome> operFuture;
93
94     @Mock
95     private Operator operator;
96
97     @Mock
98     private Operation operation;
99
100     @Mock
101     private Consumer<OperationOutcome> starter;
102
103     private Map<String, Object> payload;
104
105     private ControlLoopOperationParams params;
106     private OperationOutcome outcome;
107
108
109     /**
110      * Initializes mocks and sets {@link #params} to a fully-loaded set of parameters.
111      */
112     @Before
113     public void setUp() {
114         MockitoAnnotations.initMocks(this);
115
116         when(actorService.getActor(ACTOR)).thenReturn(actor);
117         when(actor.getOperator(OPERATION)).thenReturn(operator);
118         when(operator.buildOperation(any())).thenReturn(operation);
119         when(operation.start()).thenReturn(operFuture);
120
121         when(event.getRequestId()).thenReturn(REQ_ID);
122
123         when(context.getEvent()).thenReturn(event);
124
125         payload = new TreeMap<>();
126
127         params = ControlLoopOperationParams.builder().actorService(actorService).completeCallback(completer)
128                         .context(context).executor(executor).actor(ACTOR).operation(OPERATION).payload(payload)
129                         .retry(RETRY).targetEntity(TARGET_ENTITY).timeoutSec(TIMEOUT)
130                         .startCallback(starter).preprocessed(true).build();
131
132         outcome = params.makeOutcome(TARGET_ENTITY);
133     }
134
135     @Test
136     public void testStart() {
137         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().start());
138
139         assertSame(operFuture, params.start());
140     }
141
142     @Test
143     public void testBuild() {
144         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().build());
145
146         assertSame(operation, params.build());
147     }
148
149     @Test
150     public void testGetRequestId() {
151         assertSame(REQ_ID, params.getRequestId());
152
153         // when both request ID and event request ID are set - should use request ID
154         // parameter
155         assertSame(REQ_ID2, params.toBuilder().requestId(REQ_ID2).build().getRequestId());
156     }
157
158     /**
159      * Tests getRequestId() when the request ID is not available in the context.
160      */
161     @Test
162     public void testGetRequestIdNotFromContext() {
163         // try with null context
164         assertNull(params.toBuilder().context(null).build().getRequestId());
165
166         // try with null event
167         when(context.getEvent()).thenReturn(null);
168         assertNull(params.getRequestId());
169
170         // set request ID directly
171         assertSame(REQ_ID2, params.toBuilder().requestId(REQ_ID2).build().getRequestId());
172     }
173
174     @Test
175     public void testMakeOutcome() {
176         assertEquals(ACTOR, outcome.getActor());
177         assertEquals(OPERATION, outcome.getOperation());
178         checkRemainingFields("with actor");
179     }
180
181     protected void checkRemainingFields(String testName) {
182         assertEquals(testName, TARGET_ENTITY, outcome.getTarget());
183         assertNull(testName, outcome.getStart());
184         assertNull(testName, outcome.getEnd());
185         assertNull(testName, outcome.getSubRequestId());
186         assertNotNull(testName, outcome.getResult());
187         assertNull(testName, outcome.getMessage());
188     }
189
190     @Test
191     public void testCallbackStarted() {
192         params.callbackStarted(outcome);
193         verify(starter).accept(outcome);
194
195         // modify starter to throw an exception
196         AtomicInteger count = new AtomicInteger();
197         doAnswer(args -> {
198             count.incrementAndGet();
199             throw new IllegalStateException(EXPECTED_EXCEPTION);
200         }).when(starter).accept(outcome);
201
202         params.callbackStarted(outcome);
203         verify(starter, times(2)).accept(outcome);
204         assertEquals(1, count.get());
205
206         // repeat with no start-callback - no additional calls expected
207         params.toBuilder().startCallback(null).build().callbackStarted(outcome);
208         verify(starter, times(2)).accept(outcome);
209         assertEquals(1, count.get());
210
211         // should not call complete-callback
212         verify(completer, never()).accept(any());
213     }
214
215     @Test
216     public void testCallbackCompleted() {
217         params.callbackCompleted(outcome);
218         verify(completer).accept(outcome);
219
220         // modify completer to throw an exception
221         AtomicInteger count = new AtomicInteger();
222         doAnswer(args -> {
223             count.incrementAndGet();
224             throw new IllegalStateException(EXPECTED_EXCEPTION);
225         }).when(completer).accept(outcome);
226
227         params.callbackCompleted(outcome);
228         verify(completer, times(2)).accept(outcome);
229         assertEquals(1, count.get());
230
231         // repeat with no complete-callback - no additional calls expected
232         params.toBuilder().completeCallback(null).build().callbackCompleted(outcome);
233         verify(completer, times(2)).accept(outcome);
234         assertEquals(1, count.get());
235
236         // should not call start-callback
237         verify(starter, never()).accept(any());
238     }
239
240     @Test
241     public void testValidateFields() {
242         testValidate("actor", NULL_MSG, bldr -> bldr.actor(null));
243         testValidate("actorService", NULL_MSG, bldr -> bldr.actorService(null));
244         testValidate("executor", NULL_MSG, bldr -> bldr.executor(null));
245         testValidate("operation", NULL_MSG, bldr -> bldr.operation(null));
246
247         // has no target entity
248         BeanValidationResult result = params.toBuilder().targetEntity(null).build().validate();
249         assertTrue(result.isValid());
250
251         // note: if context is null, then it will ACTUALLY complain about the request ID
252         testValidate(REQUEST_ID_NAME, NULL_MSG, bldr -> bldr.context(null));
253
254         // check edge cases
255         assertTrue(params.toBuilder().build().validate().isValid());
256
257         // these can be null
258         assertTrue(params.toBuilder().payload(null).retry(null).timeoutSec(null).startCallback(null)
259                         .completeCallback(null).build().validate().isValid());
260
261         // test with minimal fields
262         assertTrue(ControlLoopOperationParams.builder().actorService(actorService).context(context).actor(ACTOR)
263                         .operation(OPERATION).targetEntity(TARGET_ENTITY).build().validate().isValid());
264
265         // test when event has no request ID
266         when(event.getRequestId()).thenReturn(null);
267         result = params.validate();
268         assertFalse(result.isValid());
269         assertThat(result.getResult()).contains("event").contains(REQUEST_ID_NAME).contains(NULL_MSG);
270
271         // try when context has no event
272         when(context.getEvent()).thenReturn(null);
273         result = params.validate();
274         assertFalse(result.isValid());
275         assertThat(result.getResult()).contains("event").doesNotContain(REQUEST_ID_NAME).contains(NULL_MSG);
276
277         // has both request ID and context, but no event
278         result = params.toBuilder().requestId(REQ_ID2).build().validate();
279         assertTrue(result.isValid());
280
281         // has request ID, but not context
282         result = params.toBuilder().requestId(REQ_ID2).context(null).build().validate();
283         assertTrue(result.isValid());
284     }
285
286     private void testValidate(String fieldName, String expected,
287                     Function<ControlLoopOperationParamsBuilder, ControlLoopOperationParamsBuilder> makeInvalid) {
288
289         // original params should be valid
290         BeanValidationResult result = params.validate();
291         assertTrue(fieldName, result.isValid());
292
293         // make invalid params
294         result = makeInvalid.apply(params.toBuilder()).build().validate();
295         assertFalse(fieldName, result.isValid());
296         assertThat(result.getResult()).contains(fieldName).contains(expected);
297     }
298
299     @Test
300     public void testBuilder_testToBuilder() {
301         assertEquals(params, params.toBuilder().build());
302     }
303
304     @Test
305     public void testGetActor() {
306         assertSame(ACTOR, params.getActor());
307     }
308
309     @Test
310     public void testGetActorService() {
311         assertSame(actorService, params.getActorService());
312     }
313
314     @Test
315     public void testGetContext() {
316         assertSame(context, params.getContext());
317     }
318
319     @Test
320     public void testGetExecutor() {
321         assertSame(executor, params.getExecutor());
322
323         // should use default when unspecified
324         assertSame(ForkJoinPool.commonPool(), ControlLoopOperationParams.builder().build().getExecutor());
325     }
326
327     @Test
328     public void testGetOperation() {
329         assertSame(OPERATION, params.getOperation());
330     }
331
332     @Test
333     public void testGetPayload() {
334         assertSame(payload, params.getPayload());
335
336         // should be null when unspecified
337         assertNull(ControlLoopOperationParams.builder().build().getPayload());
338     }
339
340     @Test
341     public void test() {
342         assertTrue(params.isPreprocessed());
343
344         // should be false when unspecified
345         assertFalse(ControlLoopOperationParams.builder().build().isPreprocessed());
346     }
347
348     @Test
349     public void testGetRetry() {
350         assertSame(RETRY, params.getRetry());
351
352         // should be null when unspecified
353         assertNull(ControlLoopOperationParams.builder().build().getRetry());
354     }
355
356     @Test
357     public void testGetTimeoutSec() {
358         assertSame(TIMEOUT, params.getTimeoutSec());
359
360         // should be 300 when unspecified
361         assertEquals(Integer.valueOf(300), ControlLoopOperationParams.builder().build().getTimeoutSec());
362
363         // null should be ok too
364         assertNull(ControlLoopOperationParams.builder().timeoutSec(null).build().getTimeoutSec());
365     }
366
367     @Test
368     public void testGetStartCallback() {
369         assertSame(starter, params.getStartCallback());
370     }
371
372     @Test
373     public void testGetCompleteCallback() {
374         assertSame(completer, params.getCompleteCallback());
375     }
376
377     @Test
378     public void testGetTargetEntity() {
379         assertEquals(TARGET_ENTITY, params.getTargetEntity());
380     }
381 }