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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 * SPDX-License-Identifier: Apache-2.0
20 * ============LICENSE_END=========================================================
23 package org.onap.policy.apex.service.engine.runtime.impl;
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;
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;
66 * Test the engine worker class.
68 class EngineWorkerTest {
69 private final ApplicationThreadFactory atFactory = new ApplicationThreadFactory("apex-engine-service", 512);
71 private static String simpleModelString;
72 private static String differentModelString;
73 private static AxPolicyModel simpleModel;
76 * Read the models into strings.
78 * @throws IOException on model reading errors
79 * @throws ApexModelException on model reading exceptions
82 static void readSimpleModel() throws IOException, ApexModelException {
83 simpleModelString = TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModel.json");
85 differentModelString =
86 TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModelDifferent.json");
88 final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<>(AxPolicyModel.class);
89 simpleModel = modelReader.read(new ByteArrayInputStream(simpleModelString.getBytes()));
93 * Initialize default parameters.
96 static void initializeDefaultParameters() {
97 ParameterService.clear();
98 final SchemaParameters schemaParameters = new SchemaParameters();
99 schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
100 ParameterService.register(schemaParameters);
102 final ContextParameters contextParameters = new ContextParameters();
103 contextParameters.setName(ContextParameterConstants.MAIN_GROUP_NAME);
104 ParameterService.register(contextParameters);
106 final DistributorParameters distributorParameters = new DistributorParameters();
107 distributorParameters.setName(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
108 ParameterService.register(distributorParameters);
110 final LockManagerParameters lockManagerParameters = new LockManagerParameters();
111 lockManagerParameters.setName(ContextParameterConstants.LOCKING_GROUP_NAME);
112 ParameterService.register(lockManagerParameters);
114 final PersistorParameters persistorParameters = new PersistorParameters();
115 persistorParameters.setName(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
116 ParameterService.register(persistorParameters);
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);
128 private static @NotNull ExecutorParameters getExecutorParameters(String lang) {
129 ExecutorParameters jsExecutorParameters = new ExecutorParameters();
130 jsExecutorParameters.setName(lang);
132 .setTaskSelectionExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTse");
133 jsExecutorParameters.setTaskExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTe");
135 .setStateFinalizerExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummySfe");
136 return jsExecutorParameters;
140 * Teardown default parameters.
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);
153 void clearDownTest() {
154 ModelService.clear();
158 void testEngineWorker() {
160 BlockingQueue<ApexEvent> eventQueue = new LinkedBlockingQueue<>();
162 EngineWorker worker = new EngineWorker(new AxArtifactKey("Worker", "0.0.1"), eventQueue, atFactory);
164 assertThatThrownBy(() -> worker.registerActionListener(null, null))
165 .hasMessageContaining("addEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
167 worker.registerActionListener("DummyListener", null);
169 assertThatThrownBy(() -> worker.registerActionListener(null, new DummyApexEventListener()))
170 .hasMessageContaining("addEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
172 worker.registerActionListener("DummyListener", new DummyApexEventListener());
174 assertThatThrownBy(() -> worker.deregisterActionListener(null))
175 .hasMessageContaining("removeEventListener()<-Worker:0.0.1,STOPPED, listenerName is null");
177 worker.deregisterActionListener("DummyListener");
179 assertThatThrownBy(worker::getEngineServiceEventInterface)
180 .hasMessageContaining("getEngineServiceEventInterface() call is not allowed on an Apex Engine Worker");
182 assertThatThrownBy(() -> worker.startPeriodicEvents(100000))
183 .hasMessageContaining("startPeriodicEvents() call is not allowed on an Apex Engine Worker");
185 assertThatThrownBy(worker::stopPeriodicEvents)
186 .hasMessageContaining("stopPeriodicEvents() call is not allowed on an Apex Engine Worker");
188 assertEquals("Worker:0.0.1", worker.getEngineKeys().iterator().next().getId());
190 assertNull(worker.getApexModelKey());
192 assertEngineWorkerStartStop(worker);
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");
197 assertDoesNotThrow(() -> worker.clear(worker.getEngineKeys().iterator().next()));
198 assertDoesNotThrow(() -> worker.clear());
200 assertUpdateEngineModel(worker);
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<>();
209 EngineWorker worker = new EngineWorker(new AxArtifactKey("Worker", "0.0.1"), eventQueue, atFactory);
210 assertEquals("Worker:0.0.1", worker.getKey().getId());
212 assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), simpleModelString, false));
214 eventQueue.add(new ApexEvent("SomeEvent", "0.0.1", "the.event.namespace", "EventSource", "EventTarget", ""));
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\"");
221 assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), differentModelString, true));
223 assertDoesNotThrow(() -> worker.updateModel(worker.getKey(), simpleModelString, true));
225 String runtimeInfo = worker.getRuntimeInfo(worker.getEngineKeys().iterator().next());
226 assertEquals("{\"TimeStamp\":", runtimeInfo.replaceAll("\\s+", "").substring(0, 13));
228 assertEquals(AxEngineState.STOPPED, worker.getState());
231 assertEquals(AxEngineState.READY, worker.getState());
233 String status = worker.getStatus(worker.getEngineKeys().iterator().next());
234 assertNotNull(status);
235 assertEquals("{\"timestamp\":", status.replaceAll("\\s+", "").substring(0, 13));
237 assertTrue(worker.isStarted());
238 assertTrue(worker.isStarted(worker.getEngineKeys().iterator().next()));
239 assertFalse(worker.isStopped());
240 assertFalse(worker.isStopped(worker.getEngineKeys().iterator().next()));
242 assertWorkerStartStopWithModel(worker);
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");
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");
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");
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");
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");
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));
268 assertEquals(AxEngineState.STOPPED, worker.getState());
270 assertEquals("{\"TimeStamp\":", runtimeInfo.replaceAll("\\s+", "").substring(0, 13));
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()));
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");
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");
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");
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");
296 assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
298 assertDoesNotThrow(() -> worker.stop());
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");
305 assertThatThrownBy(worker::startAll)
306 .hasMessageContaining("apex engine for engine key Worker:0.0.1 is already running with state READY");
308 assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
309 assertDoesNotThrow(() -> worker.start(worker.getEngineKeys().iterator().next()));
310 assertDoesNotThrow(() -> worker.stop());
311 assertDoesNotThrow(worker::startAll);
316 assertThatThrownBy(() -> worker.clear(worker.getEngineKeys().iterator().next()))
317 .hasMessageContaining("clear()<-Worker:0.0.1,READY, cannot clear engine, engine is not stopped");
319 assertDoesNotThrow(() -> worker.stop(worker.getEngineKeys().iterator().next()));
320 assertDoesNotThrow(() -> worker.clear(worker.getEngineKeys().iterator().next()));
321 assertDoesNotThrow(() -> worker.clear());
323 assertNotNull(worker.getApexModelKey());
325 final ApexPolicyStatisticsManager policyCounter = ApexPolicyStatisticsManager.getInstanceFromRegistry();
326 assertNotNull(policyCounter);
327 assertEquals(policyCounter.getPolicyExecutedCount(),
328 policyCounter.getPolicyExecutedFailCount() + policyCounter.getPolicyExecutedSuccessCount());