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