b421c1ce25393465de581d137913eee5a585ed18
[policy/models.git] /
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.pipeline;
22
23 import static org.assertj.core.api.Assertions.assertThatThrownBy;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotSame;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.ArgumentMatchers.anyBoolean;
31 import static org.mockito.Mockito.never;
32 import static org.mockito.Mockito.verify;
33
34 import java.util.concurrent.CompletableFuture;
35 import java.util.concurrent.Future;
36 import java.util.concurrent.atomic.AtomicReference;
37 import java.util.function.BiConsumer;
38 import java.util.function.Function;
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.mockito.Mock;
42 import org.mockito.MockitoAnnotations;
43
44 public class PipelineControllerFutureTest {
45     private static final IllegalStateException EXPECTED_EXCEPTION = new IllegalStateException("expected exception");
46     private static final String TEXT = "some text";
47
48     @Mock
49     private Runnable runnable1;
50
51     @Mock
52     private Runnable runnable2;
53
54     @Mock
55     private Future<String> future1;
56
57     @Mock
58     private Future<String> future2;
59
60     @Mock
61     private CompletableFuture<String> compFuture;
62
63
64     private PipelineControllerFuture<String> controller;
65
66
67     /**
68      * Initializes fields, including {@link #controller}. Adds all runners and futures to
69      * the controller.
70      */
71     @Before
72     public void setUp() {
73         MockitoAnnotations.initMocks(this);
74
75         controller = new PipelineControllerFuture<>();
76
77         controller.add(runnable1);
78         controller.add(future1);
79         controller.add(runnable2);
80         controller.add(future2);
81     }
82
83     @Test
84     public void testCancel_testAddFutureOfFBoolean_testAddRunnable__testIsRunning() {
85         assertTrue(controller.isRunning());
86
87         assertTrue(controller.cancel(false));
88
89         assertTrue(controller.isCancelled());
90         assertFalse(controller.isRunning());
91
92         verify(runnable1).run();
93         verify(runnable2).run();
94         verify(future1).cancel(anyBoolean());
95         verify(future2).cancel(anyBoolean());
96
97         // re-invoke; nothing should change
98         assertTrue(controller.cancel(true));
99
100         assertTrue(controller.isCancelled());
101         assertFalse(controller.isRunning());
102
103         verify(runnable1).run();
104         verify(runnable2).run();
105         verify(future1).cancel(anyBoolean());
106         verify(future2).cancel(anyBoolean());
107     }
108
109     @Test
110     public void testDelayedComplete() throws Exception {
111         controller.add(runnable1);
112
113         BiConsumer<String, Throwable> stopper = controller.delayedComplete();
114
115         // shouldn't have run yet
116         assertTrue(controller.isRunning());
117         verify(runnable1, never()).run();
118
119         stopper.accept(TEXT, null);
120
121         assertTrue(controller.isDone());
122         assertEquals(TEXT, controller.get());
123
124         assertFalse(controller.isRunning());
125         verify(runnable1).run();
126
127         // re-invoke; nothing should change
128         stopper.accept(TEXT, EXPECTED_EXCEPTION);
129         assertFalse(controller.isCompletedExceptionally());
130
131         assertFalse(controller.isRunning());
132         verify(runnable1).run();
133     }
134
135     /**
136      * Tests delayedComplete() when an exception is generated.
137      */
138     @Test
139     public void testDelayedCompleteWithException() throws Exception {
140         controller.add(runnable1);
141
142         BiConsumer<String, Throwable> stopper = controller.delayedComplete();
143
144         // shouldn't have run yet
145         assertTrue(controller.isRunning());
146         verify(runnable1, never()).run();
147
148         stopper.accept(TEXT, EXPECTED_EXCEPTION);
149
150         assertTrue(controller.isDone());
151         assertThatThrownBy(() -> controller.get()).hasCause(EXPECTED_EXCEPTION);
152
153         assertFalse(controller.isRunning());
154         verify(runnable1).run();
155
156         // re-invoke; nothing should change
157         stopper.accept(TEXT, null);
158         assertTrue(controller.isCompletedExceptionally());
159
160         assertFalse(controller.isRunning());
161         verify(runnable1).run();
162     }
163
164     @Test
165     public void testDelayedRemoveFutureOfF() throws Exception {
166         BiConsumer<String, Throwable> remover = controller.delayedRemove(future1);
167
168         remover.accept(TEXT, EXPECTED_EXCEPTION);
169
170         // should not have completed the controller
171         assertFalse(controller.isDone());
172
173         verify(future1, never()).cancel(anyBoolean());
174
175         controller.delayedComplete().accept(TEXT, EXPECTED_EXCEPTION);
176
177         verify(future1, never()).cancel(anyBoolean());
178         verify(future2).cancel(anyBoolean());
179     }
180
181     @Test
182     public void testDelayedRemoveRunnable() throws Exception {
183         BiConsumer<String, Throwable> remover = controller.delayedRemove(runnable1);
184
185         remover.accept(TEXT, EXPECTED_EXCEPTION);
186
187         // should not have completed the controller
188         assertFalse(controller.isDone());
189
190         verify(runnable1, never()).run();
191
192         controller.delayedComplete().accept(TEXT, EXPECTED_EXCEPTION);
193
194         verify(runnable1, never()).run();
195         verify(runnable2).run();
196     }
197
198     @Test
199     public void testRemoveFutureOfF_testRemoveRunnable() {
200         controller.remove(runnable2);
201         controller.remove(future1);
202
203         controller.cancel(true);
204
205         verify(runnable1).run();
206         verify(runnable2, never()).run();
207         verify(future1, never()).cancel(anyBoolean());
208         verify(future2).cancel(anyBoolean());
209     }
210
211     @Test
212     public void testAddFunction() {
213         AtomicReference<String> value = new AtomicReference<>();
214
215         Function<String, CompletableFuture<String>> func = controller.add(input -> {
216             value.set(input);
217             return compFuture;
218         });
219
220         assertSame(compFuture, func.apply(TEXT));
221         assertEquals(TEXT, value.get());
222
223         verify(compFuture, never()).cancel(anyBoolean());
224
225         // should not have completed the controller
226         assertFalse(controller.isDone());
227
228         // cancel - should propagate
229         controller.cancel(false);
230
231         verify(compFuture).cancel(anyBoolean());
232     }
233
234     /**
235      * Tests add(Function) when the controller is not running.
236      */
237     @Test
238     public void testAddFunctionNotRunning() {
239         AtomicReference<String> value = new AtomicReference<>();
240
241         Function<String, CompletableFuture<String>> func = controller.add(input -> {
242             value.set(input);
243             return compFuture;
244         });
245
246         controller.cancel(false);
247
248         CompletableFuture<String> fut = func.apply(TEXT);
249         assertNotSame(compFuture, fut);
250         assertFalse(fut.isDone());
251
252         assertNull(value.get());
253     }
254 }