91434d7ea52f6e8eb6ae9bf84f932533924d7ff7
[policy/drools-applications.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.eventmanager;
22
23 import static org.assertj.core.api.Assertions.assertThat;
24 import static org.assertj.core.api.Assertions.assertThatCode;
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.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.mockito.Mockito.verify;
31
32 import java.io.IOException;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.UUID;
36 import java.util.concurrent.CompletableFuture;
37 import java.util.concurrent.ExecutorService;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.mockito.ArgumentCaptor;
41 import org.mockito.Mock;
42 import org.mockito.MockitoAnnotations;
43 import org.onap.policy.common.utils.coder.Coder;
44 import org.onap.policy.common.utils.coder.CoderException;
45 import org.onap.policy.common.utils.coder.StandardYamlCoder;
46 import org.onap.policy.common.utils.io.Serializer;
47 import org.onap.policy.common.utils.resources.ResourceUtils;
48 import org.onap.policy.controlloop.ControlLoopException;
49 import org.onap.policy.controlloop.actorserviceprovider.OperationOutcome;
50 import org.onap.policy.controlloop.drl.legacy.ControlLoopParams;
51 import org.onap.policy.controlloop.policy.PolicyResult;
52 import org.onap.policy.controlloop.policy.Target;
53 import org.onap.policy.controlloop.policy.TargetType;
54 import org.onap.policy.drools.core.lock.LockCallback;
55 import org.onap.policy.drools.core.lock.LockImpl;
56 import org.onap.policy.drools.core.lock.LockState;
57 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
58 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
59
60 public class ControlLoopEventManagerTest {
61     private static final UUID REQ_ID = UUID.randomUUID();
62     private static final String CL_NAME = "my-closed-loop-name";
63     private static final String POLICY_NAME = "my-policy-name";
64     private static final String POLICY_SCOPE = "my-scope";
65     private static final String POLICY_VERSION = "1.2.3";
66     private static final String LOCK1 = "my-lock-A";
67     private static final String LOCK2 = "my-lock-B";
68     private static final Coder yamlCoder = new StandardYamlCoder();
69     private static final String MY_KEY = "def";
70
71     @Mock
72     private ExecutorService executor;
73
74     private long preCreateTimeMs;
75     private List<LockImpl> locks;
76     private Target target;
77     private ToscaPolicy tosca;
78     private ControlLoopParams params;
79     private ControlLoopEventManager mgr;
80
81     /**
82      * Sets up.
83      */
84     @Before
85     public void setUp() throws ControlLoopException, CoderException {
86         MockitoAnnotations.initMocks(this);
87
88         target = new Target();
89         target.setType(TargetType.VNF);
90
91         params = new ControlLoopParams();
92         params.setClosedLoopControlName(CL_NAME);
93         params.setPolicyName(POLICY_NAME);
94         params.setPolicyScope(POLICY_SCOPE);
95         params.setPolicyVersion(POLICY_VERSION);
96
97         loadPolicy("eventManager/event-mgr-simple.yaml");
98
99         locks = new ArrayList<>();
100
101         preCreateTimeMs = System.currentTimeMillis();
102
103         MyManager.executor = executor;
104         MyManager.locks = locks;
105
106         mgr = new MyManager(params, REQ_ID);
107     }
108
109     @Test
110     public void testConstructor() {
111         assertEquals(POLICY_NAME, mgr.getPolicyName());
112
113         assertTrue(mgr.isActive());
114         assertEquals(CL_NAME, mgr.getClosedLoopControlName());
115         assertSame(REQ_ID, mgr.getRequestId());
116         assertEquals(POLICY_NAME, mgr.getPolicyName());
117         assertEquals(POLICY_VERSION, mgr.getPolicyVersion());
118         assertNotNull(mgr.getProcessor());
119         assertThat(mgr.getEndTimeMs()).isGreaterThanOrEqualTo(preCreateTimeMs);
120     }
121
122     @Test
123     public void testGetCreateCount() throws ControlLoopException {
124         long original = ControlLoopEventManager.getCreateCount();
125
126         new MyManager(params, REQ_ID);
127         assertEquals(original + 1, ControlLoopEventManager.getCreateCount());
128
129         new MyManager(params, REQ_ID);
130         assertEquals(original + 2, ControlLoopEventManager.getCreateCount());
131     }
132
133     @Test
134     public void testIsActive() throws Exception {
135         mgr = new ControlLoopEventManager(params, REQ_ID);
136         assertTrue(mgr.isActive());
137
138         ControlLoopEventManager mgr2 = Serializer.roundTrip(mgr);
139         assertFalse(mgr2.isActive());
140     }
141
142     @Test
143     public void testDestroy() throws IOException {
144         mgr.requestLock(LOCK1);
145         mgr.requestLock(LOCK2);
146         mgr.requestLock(LOCK1);
147
148         // ensure destroy() doesn't throw an exception if the object is deserialized
149         ControlLoopEventManager mgr2 = Serializer.roundTrip(mgr);
150         assertThatCode(() -> mgr2.destroy()).doesNotThrowAnyException();
151
152         // locks should not have been freed
153         for (LockImpl lock : locks) {
154             assertFalse(lock.isUnavailable());
155         }
156
157         mgr.destroy();
158
159         runExecutor();
160
161         for (LockImpl lock : locks) {
162             assertTrue(lock.isUnavailable());
163         }
164     }
165
166     @Test
167     public void testDetmControlLoopTimeoutMs() throws Exception {
168         long timeMs = 1200 * 1000L;
169         long end = mgr.getEndTimeMs();
170         assertThat(end).isGreaterThanOrEqualTo(preCreateTimeMs + timeMs);
171         assertThat(end).isLessThan(preCreateTimeMs + timeMs + 5000);
172     }
173
174     @Test
175     public void testRequestLock() {
176         final CompletableFuture<OperationOutcome> future1 = mgr.requestLock(LOCK1);
177         assertTrue(mgr.getOutcomes().isEmpty());
178
179         final CompletableFuture<OperationOutcome> future2 = mgr.requestLock(LOCK2);
180         assertTrue(mgr.getOutcomes().isEmpty());
181
182         assertSame(future1, mgr.requestLock(LOCK1));
183         assertTrue(mgr.getOutcomes().isEmpty());
184
185         assertEquals(2, locks.size());
186
187         assertTrue(future1.isDone());
188         assertTrue(future2.isDone());
189
190         // indicate that the first lock failed
191         locks.get(0).notifyUnavailable();
192
193         verifyLock(PolicyResult.FAILURE);
194         assertTrue(mgr.getOutcomes().isEmpty());
195     }
196
197     private void verifyLock(PolicyResult result) {
198         OperationOutcome outcome = mgr.getOutcomes().poll();
199         assertNotNull(outcome);
200         assertEquals(ActorConstants.LOCK_ACTOR, outcome.getActor());
201         assertEquals(ActorConstants.LOCK_OPERATION, outcome.getOperation());
202         assertNotNull(outcome.getEnd());
203         assertTrue(outcome.isFinalOutcome());
204         assertEquals(result, outcome.getResult());
205     }
206
207     @Test
208     public void testOnStart() {
209         OperationOutcome outcome1 = new OperationOutcome();
210         OperationOutcome outcome2 = new OperationOutcome();
211
212         mgr.onStart(outcome1);
213         mgr.onStart(outcome2);
214
215         assertSame(outcome1, mgr.getOutcomes().poll());
216         assertSame(outcome2, mgr.getOutcomes().poll());
217         assertTrue(mgr.getOutcomes().isEmpty());
218     }
219
220     @Test
221     public void testOnComplete() {
222         OperationOutcome outcome1 = new OperationOutcome();
223         OperationOutcome outcome2 = new OperationOutcome();
224
225         mgr.onComplete(outcome1);
226         mgr.onComplete(outcome2);
227
228         assertSame(outcome1, mgr.getOutcomes().poll());
229         assertSame(outcome2, mgr.getOutcomes().poll());
230         assertTrue(mgr.getOutcomes().isEmpty());
231     }
232
233     @Test
234     public void testContains_testGetProperty_testSetProperty_testRemoveProperty() {
235         mgr.setProperty("abc", "a string");
236         mgr.setProperty(MY_KEY, 100);
237
238         assertTrue(mgr.contains(MY_KEY));
239         assertFalse(mgr.contains("ghi"));
240
241         String strValue = mgr.getProperty("abc");
242         assertEquals("a string", strValue);
243
244         int intValue = mgr.getProperty(MY_KEY);
245         assertEquals(100, intValue);
246
247         mgr.removeProperty(MY_KEY);
248         assertFalse(mgr.contains(MY_KEY));
249     }
250
251     @Test
252     public void testToString() {
253         assertNotNull(mgr.toString());
254     }
255
256     private void loadPolicy(String fileName) throws CoderException {
257         ToscaServiceTemplate template =
258                         yamlCoder.decode(ResourceUtils.getResourceAsString(fileName), ToscaServiceTemplate.class);
259         tosca = template.getToscaTopologyTemplate().getPolicies().get(0).values().iterator().next();
260
261         params.setToscaPolicy(tosca);
262     }
263
264     private void runExecutor() {
265         ArgumentCaptor<Runnable> runCaptor = ArgumentCaptor.forClass(Runnable.class);
266         verify(executor).execute(runCaptor.capture());
267
268         runCaptor.getValue().run();
269     }
270
271
272     private static class MyManager extends ControlLoopEventManager {
273         private static final long serialVersionUID = 1L;
274
275         private static ExecutorService executor;
276         private static List<LockImpl> locks;
277
278         public MyManager(ControlLoopParams params, UUID requestId)
279                         throws ControlLoopException {
280             super(params, requestId);
281         }
282
283         @Override
284         protected ExecutorService getBlockingExecutor() {
285             return executor;
286         }
287
288         @Override
289         protected void makeLock(String targetEntity, String requestId, int holdSec, LockCallback callback) {
290             LockImpl lock = new LockImpl(LockState.ACTIVE, targetEntity, requestId, holdSec, callback);
291             locks.add(lock);
292             callback.lockAvailable(lock);
293         }
294     }
295 }