0716e0ad3174a1d0f224b3f07e21fc340fdfb798
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2020, 2022-2024 Nordix Foundation.
5  *  Modifications Copyright (C) 2021-2022 Bell Canada 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  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.apex.service.engine.runtime.impl;
24
25 import static org.assertj.core.api.Assertions.assertThatThrownBy;
26 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertFalse;
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertNull;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.util.concurrent.BlockingQueue;
36 import java.util.concurrent.LinkedBlockingQueue;
37 import org.jetbrains.annotations.NotNull;
38 import org.junit.jupiter.api.AfterAll;
39 import org.junit.jupiter.api.AfterEach;
40 import org.junit.jupiter.api.BeforeAll;
41 import org.junit.jupiter.api.Test;
42 import org.onap.policy.apex.context.parameters.ContextParameterConstants;
43 import org.onap.policy.apex.context.parameters.ContextParameters;
44 import org.onap.policy.apex.context.parameters.DistributorParameters;
45 import org.onap.policy.apex.context.parameters.LockManagerParameters;
46 import org.onap.policy.apex.context.parameters.PersistorParameters;
47 import org.onap.policy.apex.context.parameters.SchemaParameters;
48 import org.onap.policy.apex.core.engine.EngineParameterConstants;
49 import org.onap.policy.apex.core.engine.EngineParameters;
50 import org.onap.policy.apex.core.engine.ExecutorParameters;
51 import org.onap.policy.apex.core.infrastructure.threading.ApplicationThreadFactory;
52 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
53 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
54 import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
55 import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
56 import org.onap.policy.apex.model.basicmodel.service.ModelService;
57 import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
58 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
59 import org.onap.policy.apex.service.engine.event.ApexEvent;
60 import org.onap.policy.apex.service.engine.main.ApexPolicyStatisticsManager;
61 import org.onap.policy.common.parameters.ParameterService;
62 import org.onap.policy.common.utils.resources.TextFileUtils;
63 import org.onap.policy.common.utils.services.Registry;
64
65 /**
66  * Test the engine worker class.
67  */
68 class EngineWorkerTest {
69     private final ApplicationThreadFactory atFactory = new ApplicationThreadFactory("apex-engine-service", 512);
70
71     private static String simpleModelString;
72     private static String differentModelString;
73     private static AxPolicyModel simpleModel;
74
75     /**
76      * Read the models into strings.
77      *
78      * @throws IOException        on model reading errors
79      * @throws ApexModelException on model reading exceptions
80      */
81     @BeforeAll
82     static void readSimpleModel() throws IOException, ApexModelException {
83         simpleModelString = TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModel.json");
84
85         differentModelString =
86             TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModelDifferent.json");
87
88         final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<>(AxPolicyModel.class);
89         simpleModel = modelReader.read(new ByteArrayInputStream(simpleModelString.getBytes()));
90     }
91
92     /**
93      * Initialize default parameters.
94      */
95     @BeforeAll
96     static void initializeDefaultParameters() {
97         ParameterService.clear();
98         final SchemaParameters schemaParameters = new SchemaParameters();
99         schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
100         ParameterService.register(schemaParameters);
101
102         final ContextParameters contextParameters = new ContextParameters();
103         contextParameters.setName(ContextParameterConstants.MAIN_GROUP_NAME);
104         ParameterService.register(contextParameters);
105
106         final DistributorParameters distributorParameters = new DistributorParameters();
107         distributorParameters.setName(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
108         ParameterService.register(distributorParameters);
109
110         final LockManagerParameters lockManagerParameters = new LockManagerParameters();
111         lockManagerParameters.setName(ContextParameterConstants.LOCKING_GROUP_NAME);
112         ParameterService.register(lockManagerParameters);
113
114         final PersistorParameters persistorParameters = new PersistorParameters();
115         persistorParameters.setName(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
116         ParameterService.register(persistorParameters);
117
118         final EngineParameters engineParameters = new EngineParameters();
119         engineParameters.setName(EngineParameterConstants.MAIN_GROUP_NAME);
120         ExecutorParameters jsExecutorParameters = getExecutorParameters("JAVASCRIPT");
121         engineParameters.getExecutorParameterMap().put("JAVASCRIPT", jsExecutorParameters);
122         getExecutorParameters("MVEL");
123         engineParameters.getExecutorParameterMap().put("MVEL", jsExecutorParameters);
124         ParameterService.register(engineParameters);
125
126     }
127
128     private static @NotNull ExecutorParameters getExecutorParameters(String lang) {
129         ExecutorParameters jsExecutorParameters = new ExecutorParameters();
130         jsExecutorParameters.setName(lang);
131         jsExecutorParameters
132             .setTaskSelectionExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTse");
133         jsExecutorParameters.setTaskExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTe");
134         jsExecutorParameters
135             .setStateFinalizerExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummySfe");
136         return jsExecutorParameters;
137     }
138
139     /**
140      * Teardown default parameters.
141      */
142     @AfterAll
143     static void teardownDefaultParameters() {
144         ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
145         ParameterService.deregister(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
146         ParameterService.deregister(ContextParameterConstants.LOCKING_GROUP_NAME);
147         ParameterService.deregister(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
148         ParameterService.deregister(ContextParameterConstants.MAIN_GROUP_NAME);
149         ParameterService.deregister(EngineParameterConstants.MAIN_GROUP_NAME);
150     }
151
152     @AfterEach
153     void clearDownTest() {
154         ModelService.clear();
155     }
156
157     @Test
158     void testEngineWorker() {
159
160         BlockingQueue<ApexEvent> eventQueue = new LinkedBlockingQueue<>();
161
162         EngineWorker worker = new EngineWorker(new AxArtifactKey("Worker", "0.0.1"), eventQueue, atFactory);
163
164         assertThatThrownBy(() -> worker.registerActionListener(null, null))
165             .hasMessageContaining("addEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
166
167         worker.registerActionListener("DummyListener", null);
168
169         assertThatThrownBy(() -> worker.registerActionListener(null, new DummyApexEventListener()))
170             .hasMessageContaining("addEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
171
172         worker.registerActionListener("DummyListener", new DummyApexEventListener());
173
174         assertThatThrownBy(() -> worker.deregisterActionListener(null))
175             .hasMessageContaining("removeEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
176
177         worker.deregisterActionListener("DummyListener");
178
179         assertThatThrownBy(worker::getEngineServiceEventInterface)
180             .hasMessageContaining("getEngineServiceEventInterface() call is not allowed on an Apex Engine Worker");
181
182         assertThatThrownBy(() -> worker.startPeriodicEvents(100000))
183             .hasMessageContaining("startPeriodicEvents() call is not allowed on an Apex Engine Worker");
184
185         assertThatThrownBy(worker::stopPeriodicEvents)
186             .hasMessageContaining("stopPeriodicEvents() call is not allowed on an Apex Engine Worker");
187
188         assertEquals("Worker:0.0.1", worker.getEngineKeys().iterator().next().getId());
189
190         assertNull(worker.getApexModelKey());
191
192         assertEngineWorkerStartStop(worker);
193
194         assertThatThrownBy(() -> worker.clear(new AxArtifactKey("DummyKey", "0.0.1")))
195             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
196
197         assertDoesNotThrow(() -> worker.clear(worker.getEngineKeys().iterator().next()));
198         assertDoesNotThrow(() -> worker.clear());
199
200         assertUpdateEngineModel(worker);
201     }
202
203     @Test
204     void testApexImplModelWIthModel() throws ApexException {
205         Registry.newRegistry();
206         Registry.register(ApexPolicyStatisticsManager.REG_APEX_PDP_POLICY_COUNTER, new ApexPolicyStatisticsManager());
207         BlockingQueue<ApexEvent> eventQueue = new LinkedBlockingQueue<>();
208
209         EngineWorker worker = new EngineWorker(new AxArtifactKey("Worker", "0.0.1"), eventQueue, atFactory);
210         assertEquals("Worker:0.0.1", worker.getKey().getId());
211
212         assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), simpleModelString, false));
213
214         eventQueue.add(new ApexEvent("SomeEvent", "0.0.1", "the.event.namespace", "EventSource", "EventTarget", ""));
215
216         assertThatThrownBy(() -> worker.updateModel(worker.getKey(), differentModelString, false))
217             .hasMessageContaining("apex model update failed, supplied model with key "
218                 + "\"SmallModelDifferent:0.0.1\" is not a compatible model update "
219                 + "from the existing engine model with key \"SmallModel:0.0.1\"");
220
221         assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), differentModelString, true));
222
223         assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), simpleModelString, true));
224
225         String runtimeInfo = worker.getRuntimeInfo(worker.getEngineKeys().iterator().next());
226         assertEquals("{\"TimeStamp\":", runtimeInfo.replaceAll("\\s+", "").substring(0, 13));
227
228         assertEquals(AxEngineState.STOPPED, worker.getState());
229         worker.startAll();
230
231         assertEquals(AxEngineState.READY, worker.getState());
232
233         String status = worker.getStatus(worker.getEngineKeys().iterator().next());
234         assertNotNull(status);
235         assertEquals("{\"timestamp\":", status.replaceAll("\\s+", "").substring(0, 13));
236
237         assertTrue(worker.isStarted());
238         assertTrue(worker.isStarted(worker.getEngineKeys().iterator().next()));
239         assertFalse(worker.isStopped());
240         assertFalse(worker.isStopped(worker.getEngineKeys().iterator().next()));
241
242         assertWorkerStartStopWithModel(worker);
243     }
244
245     private static void assertUpdateEngineModel(EngineWorker worker) {
246         assertThatThrownBy(() -> worker.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), "", true))
247             .hasMessageContaining("failed to unmarshal the apex model on engine DummyKey:0.0.1");
248
249         assertThatThrownBy(
250             () -> worker.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), "I am not an Apex model", true))
251             .hasMessageContaining("failed to unmarshal the apex model on engine DummyKey:0.0.1");
252
253         assertThatThrownBy(() -> worker.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), simpleModelString, true))
254             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
255
256         assertThatThrownBy(
257             () -> worker.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), (AxPolicyModel) null, true))
258             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
259
260         assertThatThrownBy(() -> worker.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), simpleModel, true))
261             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
262     }
263
264     private static void assertEngineWorkerStartStop(EngineWorker worker) {
265         String runtimeInfo = worker.getRuntimeInfo(worker.getEngineKeys().iterator().next());
266         assertEquals("{\"TimeStamp\":", runtimeInfo.replaceAll("\\s+", "").substring(0, 13));
267
268         assertEquals(AxEngineState.STOPPED, worker.getState());
269
270         assertEquals("{\"TimeStamp\":", runtimeInfo.replaceAll("\\s+", "").substring(0, 13));
271
272         assertFalse(worker.isStarted());
273         assertFalse(worker.isStarted(null));
274         assertFalse(worker.isStarted(new AxArtifactKey("DummyKey", "0.0.1")));
275         assertFalse(worker.isStarted(worker.getEngineKeys().iterator().next()));
276         assertTrue(worker.isStopped());
277         assertTrue(worker.isStopped(null));
278         assertTrue(worker.isStopped(new AxArtifactKey("DummyKey", "0.0.1")));
279         assertTrue(worker.isStopped(worker.getEngineKeys().iterator().next()));
280
281         assertThatThrownBy(() -> worker.start(new AxArtifactKey("DummyKey", "0.0.1")))
282             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
283
284         assertThatThrownBy(() -> worker.start(worker.getEngineKeys().iterator().next()))
285             .hasMessageContaining(
286                 "start()<-Worker:0.0.1,STOPPED,  cannot start engine, engine has not been initialized, "
287                     + "its model is not loaded");
288
289         assertThatThrownBy(worker::startAll).hasMessageContaining(
290             "start()<-Worker:0.0.1,STOPPED,  cannot start engine, engine has not been initialized, its "
291                 + "model is not loaded");
292
293         assertThatThrownBy(() -> worker.stop(new AxArtifactKey("DummyKey", "0.0.1")))
294             .hasMessageContaining("engine key DummyKey:0.0.1 does not match the keyWorker:0.0.1 of this engine");
295
296         assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
297
298         assertDoesNotThrow(() -> worker.stop());
299     }
300
301     private static void assertWorkerStartStopWithModel(EngineWorker worker) throws ApexException {
302         assertThatThrownBy(() -> worker.start(worker.getEngineKeys().iterator().next()))
303             .hasMessageContaining("apex engine for engine key Worker:0.0.1 is already running with state READY");
304
305         assertThatThrownBy(worker::startAll)
306             .hasMessageContaining("apex engine for engine key Worker:0.0.1 is already running with state READY");
307
308         assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
309         assertDoesNotThrow(() -> worker.start(worker.getEngineKeys().iterator().next()));
310         assertDoesNotThrow(() -> worker.stop());
311         assertDoesNotThrow(worker::startAll);
312
313         worker.stop();
314         worker.startAll();
315
316         assertThatThrownBy(() -> worker.clear(worker.getEngineKeys().iterator().next()))
317             .hasMessageContaining("clear()<-Worker:0.0.1,READY, cannot clear engine, engine is not stopped");
318
319         assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
320         assertDoesNotThrow(() -> worker.clear(worker.getEngineKeys().iterator().next()));
321         assertDoesNotThrow(() -> worker.clear());
322
323         assertNotNull(worker.getApexModelKey());
324
325         final ApexPolicyStatisticsManager policyCounter = ApexPolicyStatisticsManager.getInstanceFromRegistry();
326         assertNotNull(policyCounter);
327         assertEquals(policyCounter.getPolicyExecutedCount(),
328             policyCounter.getPolicyExecutedFailCount() + policyCounter.getPolicyExecutedSuccessCount());
329     }
330 }