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.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;
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();
79 private ActorService actorService;
82 private Consumer<OperationOutcome> completer;
85 private ControlLoopEventContext context;
88 private VirtualControlLoopEvent event;
91 private Executor executor;
94 private CompletableFuture<OperationOutcome> operFuture;
97 private Operator operator;
100 private Operation operation;
103 private Consumer<OperationOutcome> starter;
105 private Map<String, Object> payload;
107 private ControlLoopOperationParams params;
108 private OperationOutcome outcome;
112 * Initializes mocks and sets {@link #params} to a fully-loaded set of parameters.
115 public void setUp() {
116 MockitoAnnotations.initMocks(this);
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);
123 when(event.getRequestId()).thenReturn(REQ_ID);
125 when(context.getEvent()).thenReturn(event);
127 payload = new TreeMap<>();
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();
134 outcome = params.makeOutcome();
138 public void testStart() {
139 assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().start());
141 assertSame(operFuture, params.start());
145 public void testBuild() {
146 assertThatIllegalArgumentException().isThrownBy(() -> params.toBuilder().context(null).build().build());
148 assertSame(operation, params.build());
152 public void testGetRequestId() {
153 assertSame(REQ_ID, params.getRequestId());
155 // when both request ID and event request ID are set - should use request ID
157 assertSame(REQ_ID2, params.toBuilder().requestId(REQ_ID2).build().getRequestId());
161 * Tests getRequestId() when the request ID is not available in the context.
164 public void testGetRequestIdNotFromContext() {
165 // try with null context
166 assertNull(params.toBuilder().context(null).build().getRequestId());
168 // try with null event
169 when(context.getEvent()).thenReturn(null);
170 assertNull(params.getRequestId());
172 // set request ID directly
173 assertSame(REQ_ID2, params.toBuilder().requestId(REQ_ID2).build().getRequestId());
177 public void testMakeOutcome() {
178 assertEquals(ACTOR, outcome.getActor());
179 assertEquals(OPERATION, outcome.getOperation());
180 checkRemainingFields("with actor");
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());
193 public void testCallbackStarted() {
194 params.callbackStarted(outcome);
195 verify(starter).accept(outcome);
197 // modify starter to throw an exception
198 AtomicInteger count = new AtomicInteger();
200 count.incrementAndGet();
201 throw new IllegalStateException(EXPECTED_EXCEPTION);
202 }).when(starter).accept(outcome);
204 params.callbackStarted(outcome);
205 verify(starter, times(2)).accept(outcome);
206 assertEquals(1, count.get());
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());
213 // should not call complete-callback
214 verify(completer, never()).accept(any());
218 public void testCallbackCompleted() {
219 params.callbackCompleted(outcome);
220 verify(completer).accept(outcome);
222 // modify completer to throw an exception
223 AtomicInteger count = new AtomicInteger();
225 count.incrementAndGet();
226 throw new IllegalStateException(EXPECTED_EXCEPTION);
227 }).when(completer).accept(outcome);
229 params.callbackCompleted(outcome);
230 verify(completer, times(2)).accept(outcome);
231 assertEquals(1, count.get());
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());
238 // should not call start-callback
239 verify(starter, never()).accept(any());
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 testValidate("target", NULL_MSG, bldr -> bldr.targetEntity(null));
250 // note: if context is null, then it will ACTUALLY complain about the request ID
251 testValidate(REQUEST_ID_NAME, NULL_MSG, bldr -> bldr.context(null));
254 assertTrue(params.toBuilder().build().validate().isValid());
257 assertTrue(params.toBuilder().payload(null).retry(null).target(null).timeoutSec(null).startCallback(null)
258 .completeCallback(null).build().validate().isValid());
260 // test with minimal fields
261 assertTrue(ControlLoopOperationParams.builder().actorService(actorService).context(context).actor(ACTOR)
262 .operation(OPERATION).targetEntity(TARGET_ENTITY).build().validate().isValid());
264 // test when event has no request ID
265 when(event.getRequestId()).thenReturn(null);
266 BeanValidationResult result = params.validate();
267 assertFalse(result.isValid());
268 assertThat(result.getResult()).contains("event").contains(REQUEST_ID_NAME).contains(NULL_MSG);
270 // try when context has no event
271 when(context.getEvent()).thenReturn(null);
272 result = params.validate();
273 assertFalse(result.isValid());
274 assertThat(result.getResult()).contains("event").doesNotContain(REQUEST_ID_NAME).contains(NULL_MSG);
276 // has both request ID and context, but no event
277 result = params.toBuilder().requestId(REQ_ID2).build().validate();
278 assertTrue(result.isValid());
280 // has request ID, but not context
281 result = params.toBuilder().requestId(REQ_ID2).context(null).build().validate();
282 assertTrue(result.isValid());
285 private void testValidate(String fieldName, String expected,
286 Function<ControlLoopOperationParamsBuilder, ControlLoopOperationParamsBuilder> makeInvalid) {
288 // original params should be valid
289 BeanValidationResult result = params.validate();
290 assertTrue(fieldName, result.isValid());
292 // make invalid params
293 result = makeInvalid.apply(params.toBuilder()).build().validate();
294 assertFalse(fieldName, result.isValid());
295 assertThat(result.getResult()).contains(fieldName).contains(expected);
299 public void testBuilder_testToBuilder() {
300 assertEquals(params, params.toBuilder().build());
304 public void testGetActor() {
305 assertSame(ACTOR, params.getActor());
309 public void testGetActorService() {
310 assertSame(actorService, params.getActorService());
314 public void testGetContext() {
315 assertSame(context, params.getContext());
319 public void testGetExecutor() {
320 assertSame(executor, params.getExecutor());
322 // should use default when unspecified
323 assertSame(ForkJoinPool.commonPool(), ControlLoopOperationParams.builder().build().getExecutor());
327 public void testGetOperation() {
328 assertSame(OPERATION, params.getOperation());
332 public void testGetPayload() {
333 assertSame(payload, params.getPayload());
335 // should be null when unspecified
336 assertNull(ControlLoopOperationParams.builder().build().getPayload());
341 assertTrue(params.isPreprocessed());
343 // should be false when unspecified
344 assertFalse(ControlLoopOperationParams.builder().build().isPreprocessed());
348 public void testGetRetry() {
349 assertSame(RETRY, params.getRetry());
351 // should be null when unspecified
352 assertNull(ControlLoopOperationParams.builder().build().getRetry());
356 public void testTarget() {
357 assertSame(TARGET, params.getTarget());
359 // should be null when unspecified
360 assertNull(ControlLoopOperationParams.builder().build().getTarget());
364 public void testGetTimeoutSec() {
365 assertSame(TIMEOUT, params.getTimeoutSec());
367 // should be 300 when unspecified
368 assertEquals(Integer.valueOf(300), ControlLoopOperationParams.builder().build().getTimeoutSec());
370 // null should be ok too
371 assertNull(ControlLoopOperationParams.builder().timeoutSec(null).build().getTimeoutSec());
375 public void testGetStartCallback() {
376 assertSame(starter, params.getStartCallback());
380 public void testGetCompleteCallback() {
381 assertSame(completer, params.getCompleteCallback());
385 public void testGetTargetEntity() {
386 assertEquals(TARGET_ENTITY, params.getTargetEntity());