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