Update policy committers in policy/models
[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-2021 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2024 Nordix Foundation
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.controlloop.actorserviceprovider.parameters;
23
24 import static org.assertj.core.api.Assertions.assertThat;
25 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertFalse;
28 import static org.junit.jupiter.api.Assertions.assertNotNull;
29 import static org.junit.jupiter.api.Assertions.assertNull;
30 import static org.junit.jupiter.api.Assertions.assertSame;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.Mockito.doAnswer;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
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.jupiter.api.BeforeEach;
48 import org.junit.jupiter.api.Test;
49 import org.junit.jupiter.api.TestInstance;
50 import org.junit.jupiter.api.extension.ExtendWith;
51 import org.mockito.Mock;
52 import org.mockito.Mockito;
53 import org.mockito.junit.jupiter.MockitoExtension;
54 import org.onap.policy.common.parameters.BeanValidationResult;
55 import org.onap.policy.controlloop.actorserviceprovider.ActorService;
56 import org.onap.policy.controlloop.actorserviceprovider.Operation;
57 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
58 import org.onap.policy.controlloop.actorserviceprovider.Operator;
59 import org.onap.policy.controlloop.actorserviceprovider.parameters.ControlLoopOperationParams.ControlLoopOperationParamsBuilder;
60 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
61
62 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
63 @ExtendWith(MockitoExtension.class)
64 class ControlLoopOperationParamsTest {
65     private static final String NULL_MSG = "null";
66     private static final String EXPECTED_EXCEPTION = "expected exception";
67     private static final String ACTOR = "my-actor";
68     private static final String OPERATION = "my-operation";
69     private static final Integer RETRY = 3;
70     private static final Integer TIMEOUT = 100;
71     private static final UUID REQ_ID = 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 Executor executor;
84
85     @Mock
86     private CompletableFuture<OperationOutcome> operFuture;
87
88     @Mock
89     private Operator operator;
90
91     @Mock
92     private Operation operation;
93
94     @Mock
95     private Consumer<OperationOutcome> starter;
96
97     private Map<String, Object> payload;
98
99     private ControlLoopOperationParams params;
100     private OperationOutcome outcome;
101
102
103     /**
104      * Initializes mocks and sets {@link #params} to a fully-loaded set of parameters.
105      */
106     @BeforeEach
107      void setUp() {
108         Mockito.lenient().when(actorService.getActor(ACTOR)).thenReturn(actor);
109         Mockito.lenient().when(actor.getOperator(OPERATION)).thenReturn(operator);
110         Mockito.lenient().when(operator.buildOperation(any())).thenReturn(operation);
111         Mockito.lenient().when(operation.start()).thenReturn(operFuture);
112
113         payload = new TreeMap<>();
114
115         params = ControlLoopOperationParams.builder().actorService(actorService).completeCallback(completer)
116                         .requestId(REQ_ID).executor(executor).actor(ACTOR).operation(OPERATION).payload(payload)
117                         .retry(RETRY).timeoutSec(TIMEOUT)
118                         .startCallback(starter).build();
119
120         outcome = params.makeOutcome();
121     }
122
123     @Test
124      void testStart() {
125         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().requestId(null).build().start());
126
127         assertSame(operFuture, params.start());
128     }
129
130     @Test
131      void testBuild() {
132         assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().requestId(null).build().build());
133
134         assertSame(operation, params.build());
135     }
136
137     @Test
138      void testGetRequestId() {
139         assertSame(REQ_ID, params.getRequestId());
140     }
141
142     @Test
143      void testMakeOutcome() {
144         assertEquals(ACTOR, outcome.getActor());
145         assertEquals(OPERATION, outcome.getOperation());
146         assertNull(outcome.getStart());
147         assertNull(outcome.getEnd());
148         assertNull(outcome.getSubRequestId());
149         assertNotNull(outcome.getResult());
150         assertNull(outcome.getMessage());
151     }
152
153     @Test
154      void testCallbackStarted() {
155         params.callbackStarted(outcome);
156         verify(starter).accept(outcome);
157
158         // modify starter to throw an exception
159         AtomicInteger count = new AtomicInteger();
160         doAnswer(args -> {
161             count.incrementAndGet();
162             throw new IllegalStateException(EXPECTED_EXCEPTION);
163         }).when(starter).accept(outcome);
164
165         params.callbackStarted(outcome);
166         verify(starter, times(2)).accept(outcome);
167         assertEquals(1, count.get());
168
169         // repeat with no start-callback - no additional calls expected
170         params.toBuilder().startCallback(null).build().callbackStarted(outcome);
171         verify(starter, times(2)).accept(outcome);
172         assertEquals(1, count.get());
173
174         // should not call complete-callback
175         verify(completer, never()).accept(any());
176     }
177
178     @Test
179      void testCallbackCompleted() {
180         params.callbackCompleted(outcome);
181         verify(completer).accept(outcome);
182
183         // modify completer to throw an exception
184         AtomicInteger count = new AtomicInteger();
185         doAnswer(args -> {
186             count.incrementAndGet();
187             throw new IllegalStateException(EXPECTED_EXCEPTION);
188         }).when(completer).accept(outcome);
189
190         params.callbackCompleted(outcome);
191         verify(completer, times(2)).accept(outcome);
192         assertEquals(1, count.get());
193
194         // repeat with no complete-callback - no additional calls expected
195         params.toBuilder().completeCallback(null).build().callbackCompleted(outcome);
196         verify(completer, times(2)).accept(outcome);
197         assertEquals(1, count.get());
198
199         // should not call start-callback
200         verify(starter, never()).accept(any());
201     }
202
203     @Test
204      void testValidateFields() {
205         testValidate("actor", NULL_MSG, bldr -> bldr.actor(null));
206         testValidate("actorService", NULL_MSG, bldr -> bldr.actorService(null));
207         testValidate("executor", NULL_MSG, bldr -> bldr.executor(null));
208         testValidate("operation", NULL_MSG, bldr -> bldr.operation(null));
209         testValidate("requestId", NULL_MSG, bldr -> bldr.requestId(null));
210
211         // has no target entity
212         BeanValidationResult result = params.toBuilder().build().validate();
213         assertTrue(result.isValid());
214
215         // check edge cases
216         assertTrue(params.toBuilder().build().validate().isValid());
217
218         // these can be null
219         assertTrue(params.toBuilder().payload(null).retry(null).timeoutSec(null).startCallback(null)
220                         .completeCallback(null).build().validate().isValid());
221
222         // test with minimal fields
223         assertTrue(ControlLoopOperationParams.builder().actorService(actorService).requestId(REQ_ID).actor(ACTOR)
224                         .operation(OPERATION).build().validate().isValid());
225     }
226
227     private void testValidate(String fieldName, String expected,
228                     Function<ControlLoopOperationParamsBuilder, ControlLoopOperationParamsBuilder> makeInvalid) {
229
230         // original params should be valid
231         BeanValidationResult result = params.validate();
232         assertTrue(result.isValid(), fieldName);
233
234         // make invalid params
235         result = makeInvalid.apply(params.toBuilder()).build().validate();
236         assertFalse(result.isValid(), fieldName);
237         assertThat(result.getResult()).contains(fieldName).contains(expected);
238     }
239
240     @Test
241      void testBuilder_testToBuilder() {
242         assertEquals(params, params.toBuilder().build());
243     }
244
245     @Test
246      void testGetActor() {
247         assertSame(ACTOR, params.getActor());
248     }
249
250     @Test
251      void testGetActorService() {
252         assertSame(actorService, params.getActorService());
253     }
254
255     @Test
256      void testGetExecutor() {
257         assertSame(executor, params.getExecutor());
258
259         // should use default when unspecified
260         assertSame(ForkJoinPool.commonPool(), ControlLoopOperationParams.builder().build().getExecutor());
261     }
262
263     @Test
264      void testGetOperation() {
265         assertSame(OPERATION, params.getOperation());
266     }
267
268     @Test
269      void testGetPayload() {
270         assertSame(payload, params.getPayload());
271
272         // should be null when unspecified
273         assertNull(ControlLoopOperationParams.builder().build().getPayload());
274     }
275
276     @Test
277      void testGetRetry() {
278         assertSame(RETRY, params.getRetry());
279
280         // should be null when unspecified
281         assertNull(ControlLoopOperationParams.builder().build().getRetry());
282     }
283
284     @Test
285      void testGetTimeoutSec() {
286         assertSame(TIMEOUT, params.getTimeoutSec());
287
288         // should be 300 when unspecified
289         assertEquals(Integer.valueOf(300), ControlLoopOperationParams.builder().build().getTimeoutSec());
290
291         // null should be ok too
292         assertNull(ControlLoopOperationParams.builder().timeoutSec(null).build().getTimeoutSec());
293     }
294
295     @Test
296      void testGetStartCallback() {
297         assertSame(starter, params.getStartCallback());
298     }
299
300     @Test
301      void testGetCompleteCallback() {
302         assertSame(completer, params.getCompleteCallback());
303     }
304 }