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