3fe96a64fa8a3fc06e670b26ab14cf25390dea5c
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2020-2021 Nordix Foundation.
5  *  Modifications Copyright (C) 2020 Bell Canada. 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.Assert.assertEquals;
27 import static org.junit.Assert.assertFalse;
28 import static org.junit.Assert.assertNull;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.fail;
31
32 import java.io.ByteArrayInputStream;
33 import java.io.IOException;
34 import org.junit.AfterClass;
35 import org.junit.BeforeClass;
36 import org.junit.Test;
37 import org.onap.policy.apex.context.parameters.ContextParameterConstants;
38 import org.onap.policy.apex.context.parameters.ContextParameters;
39 import org.onap.policy.apex.context.parameters.DistributorParameters;
40 import org.onap.policy.apex.context.parameters.LockManagerParameters;
41 import org.onap.policy.apex.context.parameters.PersistorParameters;
42 import org.onap.policy.apex.context.parameters.SchemaParameters;
43 import org.onap.policy.apex.core.engine.EngineParameterConstants;
44 import org.onap.policy.apex.core.engine.EngineParameters;
45 import org.onap.policy.apex.core.engine.ExecutorParameters;
46 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
48 import org.onap.policy.apex.model.basicmodel.handling.ApexModelException;
49 import org.onap.policy.apex.model.basicmodel.handling.ApexModelReader;
50 import org.onap.policy.apex.model.basicmodel.service.ModelService;
51 import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
52 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
53 import org.onap.policy.apex.service.engine.event.ApexEvent;
54 import org.onap.policy.apex.service.parameters.engineservice.EngineServiceParameters;
55 import org.onap.policy.common.parameters.ParameterService;
56 import org.onap.policy.common.utils.resources.TextFileUtils;
57
58 /**
59  * Test the engine service implementation.
60  */
61 public class EngineServiceImplTest {
62
63     private static String simpleModelString;
64     private static String differentModelString;
65     private static AxPolicyModel simpleModel;
66
67     /**
68      * Read the models into strings.
69      *
70      * @throws IOException on model reading errors
71      * @throws ApexModelException on model reading exceptions
72      */
73     @BeforeClass
74     public static void readSimpleModel() throws IOException, ApexModelException {
75         simpleModelString = TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModel.json");
76
77         differentModelString =
78             TextFileUtils.getTextFileAsString("src/test/resources/policymodels/SmallModelDifferent.json");
79
80         final ApexModelReader<AxPolicyModel> modelReader = new ApexModelReader<>(AxPolicyModel.class);
81         simpleModel = modelReader.read(new ByteArrayInputStream(simpleModelString.getBytes()));
82     }
83
84     /**
85      * Initialize default parameters.
86      */
87     @BeforeClass
88     public static void initializeDefaultParameters() {
89         ParameterService.clear();
90         final SchemaParameters schemaParameters = new SchemaParameters();
91         schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
92         ParameterService.register(schemaParameters);
93
94         final ContextParameters contextParameters = new ContextParameters();
95         contextParameters.setName(ContextParameterConstants.MAIN_GROUP_NAME);
96         ParameterService.register(contextParameters);
97
98         final DistributorParameters distributorParameters = new DistributorParameters();
99         distributorParameters.setName(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
100         ParameterService.register(distributorParameters);
101
102         final LockManagerParameters lockManagerParameters = new LockManagerParameters();
103         lockManagerParameters.setName(ContextParameterConstants.LOCKING_GROUP_NAME);
104         ParameterService.register(lockManagerParameters);
105
106         final PersistorParameters persistorParameters = new PersistorParameters();
107         persistorParameters.setName(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
108         ParameterService.register(persistorParameters);
109
110         final EngineParameters engineParameters = new EngineParameters();
111         engineParameters.setName(EngineParameterConstants.MAIN_GROUP_NAME);
112         ExecutorParameters jsExecutorParameters = new ExecutorParameters();
113         jsExecutorParameters.setName("JAVASCRIPT");
114         jsExecutorParameters
115             .setTaskSelectionExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTse");
116         jsExecutorParameters.setTaskExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTe");
117         jsExecutorParameters
118             .setStateFinalizerExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummySfe");
119         engineParameters.getExecutorParameterMap().put("JAVASCRIPT", jsExecutorParameters);
120         ExecutorParameters mvvelExecutorParameters = new ExecutorParameters();
121         mvvelExecutorParameters.setName("MVEL");
122         mvvelExecutorParameters
123             .setTaskSelectionExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTse");
124         mvvelExecutorParameters.setTaskExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummyTe");
125         mvvelExecutorParameters
126             .setStateFinalizerExecutorPluginClass("org.onap.policy.apex.service.engine.runtime.impl.DummySfe");
127         engineParameters.getExecutorParameterMap().put("MVEL", jsExecutorParameters);
128         ParameterService.register(engineParameters);
129     }
130
131     /**
132      * Teardown default parameters.
133      */
134     @AfterClass
135     public static void teardownDefaultParameters() {
136         ParameterService.deregister(ContextParameterConstants.SCHEMA_GROUP_NAME);
137         ParameterService.deregister(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
138         ParameterService.deregister(ContextParameterConstants.LOCKING_GROUP_NAME);
139         ParameterService.deregister(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
140         ParameterService.deregister(ContextParameterConstants.MAIN_GROUP_NAME);
141         ParameterService.deregister(EngineParameterConstants.MAIN_GROUP_NAME);
142         ModelService.clear();
143     }
144
145     private EngineServiceParameters makeConfig() {
146         EngineServiceParameters config = new EngineServiceParameters();
147         config.setInstanceCount(0);
148         config.setId(123);
149         config.setEngineKey(new AxArtifactKey("Engine", "0.0.1"));
150         config.setInstanceCount(1);
151         config.setPolicyModel("policyModelContent");
152         return config;
153     }
154
155     @Test
156     public void testEngineServiceImplSanity() throws ApexException {
157         assertThatThrownBy(() -> EngineServiceImpl.create(null)).isInstanceOf(ApexException.class)
158             .hasMessage("engine service configuration parameters are null");
159
160         EngineServiceParameters invalidConfig = new EngineServiceParameters();
161         invalidConfig.setInstanceCount(0);
162         assertThatThrownBy(() -> EngineServiceImpl.create(invalidConfig)).isInstanceOf(ApexException.class)
163             .hasMessageContaining("Invalid engine service configuration parameters");
164
165         EngineServiceParameters config = makeConfig();
166         EngineServiceImpl esImpl = EngineServiceImpl.create(config);
167         assertEquals("Engine:0.0.1", esImpl.getKey().getId());
168
169         esImpl.registerActionListener(null, null);
170         esImpl.registerActionListener("DummyListener", null);
171         esImpl.registerActionListener(null, new DummyApexEventListener());
172
173         esImpl.registerActionListener("DummyListener", new DummyApexEventListener());
174         assertThatThrownBy(() -> esImpl.deregisterActionListener(null))
175             .hasMessage("removeEventListener()<-Engine-0:0.0.1,STOPPED, listenerName is null");
176
177         esImpl.deregisterActionListener("DummyListener");
178
179         assertEquals(esImpl, esImpl.getEngineServiceEventInterface());
180         assertEquals(1, esImpl.getEngineKeys().size());
181
182         assertNull(esImpl.getApexModelKey());
183
184         assertThatThrownBy(() -> esImpl.getRuntimeInfo(null)).isInstanceOf(ApexException.class)
185             .hasMessage("engine key must be specified and may not be null");
186
187         assertThatThrownBy(() -> esImpl.getRuntimeInfo(new AxArtifactKey("DummyKey", "0.0.1")))
188             .isInstanceOf(ApexException.class).hasMessage("engine with key DummyKey:0.0.1 not found in engine service");
189
190         String runtimeInfo = esImpl.getRuntimeInfo(esImpl.getEngineKeys().iterator().next());
191         assertEquals("{\n  \"TimeStamp\":", runtimeInfo.substring(0, 16));
192
193         assertEquals(AxEngineState.STOPPED, esImpl.getState());
194
195         assertThatThrownBy(() -> esImpl.getStatus(null)).isInstanceOf(ApexException.class)
196             .hasMessage("engine key must be specified and may not be null");
197         assertThatThrownBy(() -> esImpl.getStatus(new AxArtifactKey("DummyKey", "0.0.1")))
198             .isInstanceOf(ApexException.class).hasMessage("engine with key DummyKey:0.0.1 not found in engine service");
199
200         String status = esImpl.getStatus(esImpl.getEngineKeys().iterator().next());
201         assertTrue(status.contains("\n   \"apexEngineModel\" :"));
202
203         assertFalse(esImpl.isStarted());
204         assertFalse(esImpl.isStarted(null));
205         assertFalse(esImpl.isStarted(new AxArtifactKey("DummyKey", "0.0.1")));
206         assertFalse(esImpl.isStarted(esImpl.getEngineKeys().iterator().next()));
207         assertTrue(esImpl.isStopped());
208         assertTrue(esImpl.isStopped(null));
209         assertTrue(esImpl.isStopped(new AxArtifactKey("DummyKey", "0.0.1")));
210         assertTrue(esImpl.isStopped(esImpl.getEngineKeys().iterator().next()));
211     }
212
213     @Test
214     public void testEngineServiceExceptions() throws ApexException {
215         EngineServiceParameters config = makeConfig();
216         EngineServiceImpl esImpl = EngineServiceImpl.create(config);
217         assertThatThrownBy(() -> esImpl.start(null)).isInstanceOf(ApexException.class)
218             .hasMessage("engine key must be specified and may not be null");
219
220         assertThatThrownBy(() -> esImpl.start(new AxArtifactKey("DummyKey", "0.0.1"))).isInstanceOf(ApexException.class)
221             .hasMessage("engine with key DummyKey:0.0.1 not found in engine service");
222
223         assertThatThrownBy(() -> esImpl.start(esImpl.getEngineKeys().iterator().next()))
224             .isInstanceOf(ApexException.class).hasMessage("start()<-Engine-0:0.0.1,STOPPED,  cannot start engine, "
225                 + "engine has not been initialized, its model is not loaded");
226
227         assertThatThrownBy(() -> esImpl.startAll()).isInstanceOf(ApexException.class)
228             .hasMessage("start()<-Engine-0:0.0.1,STOPPED,  cannot start engine, "
229                 + "engine has not been initialized, its model is not loaded");
230
231         assertThatThrownBy(() -> esImpl.stop(null)).isInstanceOf(ApexException.class)
232             .hasMessage("engine key must be specified and may not be null");
233
234         assertThatThrownBy(() -> esImpl.stop(new AxArtifactKey("DummyKey", "0.0.1"))).isInstanceOf(ApexException.class)
235             .hasMessage("engine with key DummyKey:0.0.1 not found in engine service");
236
237         esImpl.stop(esImpl.getEngineKeys().iterator().next());
238
239         esImpl.stop();
240         esImpl.sendEvent(null);
241         esImpl.sendEvent(new ApexEvent("SomeEvent", "0.0.1", "the.event.namespace", "EventSource", "EventTarget"));
242
243         esImpl.startPeriodicEvents(100000);
244
245         assertThatThrownBy(() -> esImpl.startPeriodicEvents(100000)).isInstanceOf(ApexException.class)
246             .hasMessage("Peiodic event geneation already running on engine Engine:0.0.1, ApexPeriodicEventGenerator "
247                 + "[period=100000, firstEventTime=0, lastEventTime=0, eventCount=0]");
248
249         esImpl.stopPeriodicEvents();
250
251         assertThatThrownBy(() -> esImpl.stopPeriodicEvents()).isInstanceOf(ApexException.class)
252             .hasMessage("Peiodic event geneation not running on engine Engine:0.0.1");
253
254         assertThatThrownBy(() -> esImpl.clear(null)).isInstanceOf(ApexException.class)
255             .hasMessage("engine key must be specified and may not be null");
256
257         assertThatThrownBy(() -> esImpl.clear(new AxArtifactKey("DummyKey", "0.0.1"))).isInstanceOf(ApexException.class)
258             .hasMessage("engine with key DummyKey:0.0.1 not found in engine service");
259         esImpl.clear(esImpl.getEngineKeys().iterator().next());
260         esImpl.clear();
261
262         assertThatThrownBy(() -> esImpl.updateModel(null, (String) null, true)).isInstanceOf(ApexException.class)
263             .hasMessage("engine key must be specified and may not be null");
264
265         assertThatThrownBy(() -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), (String) null, true))
266             .isInstanceOf(ApexException.class)
267             .hasMessage("model for updating engine service with key DummyKey:0.0.1 is empty");
268
269         assertThatThrownBy(() -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), "", true))
270             .isInstanceOf(ApexException.class)
271             .hasMessage("model for updating engine service with key DummyKey:0.0.1 is empty");
272
273         assertThatThrownBy(
274             () -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), "I am not an Apex model", true))
275                 .isInstanceOf(ApexException.class)
276                 .hasMessage("failed to unmarshal the apex model on engine service DummyKey:0.0.1");
277
278         assertThatThrownBy(() -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), simpleModelString, true))
279             .isInstanceOf(ApexException.class)
280             .hasMessage("engine service key DummyKey:0.0.1 does not match the keyEngine:0.0.1 of this engine service");
281
282         assertThatThrownBy(() -> esImpl.updateModel(null, simpleModelString, true)).isInstanceOf(ApexException.class)
283             .hasMessage("engine key must be specified and may not be null");
284
285         assertThatThrownBy(() -> esImpl.updateModel(null, (AxPolicyModel) null, true)).isInstanceOf(ApexException.class)
286             .hasMessage("engine key must be specified and may not be null");
287
288         assertThatThrownBy(() -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), (AxPolicyModel) null, true))
289             .isInstanceOf(ApexException.class)
290             .hasMessage("model for updating on engine service with key DummyKey:0.0.1 is null");
291
292         assertThatThrownBy(() -> esImpl.updateModel(new AxArtifactKey("DummyKey", "0.0.1"), simpleModel, true))
293             .isInstanceOf(ApexException.class)
294             .hasMessage("engine service key DummyKey:0.0.1 does not match the keyEngine:0.0.1 of this engine service");
295     }
296
297     @Test
298     public void testApexImplModelWIthModel() throws ApexException {
299         EngineServiceParameters config = makeConfig();
300         EngineServiceImpl esImpl = EngineServiceImpl.create(config);
301         assertEquals("Engine:0.0.1", esImpl.getKey().getId());
302
303         try {
304             esImpl.updateModel(config.getEngineKey(), simpleModelString, false);
305         } catch (ApexException apEx) {
306             fail("test should not throw an exception");
307         }
308
309         try {
310             esImpl.updateModel(config.getEngineKey(), differentModelString, false);
311             fail("test should throw an exception");
312         } catch (ApexException apEx) {
313             assertEquals("apex model update failed, supplied model with key \"SmallModelDifferent:0.0.1\" is not a "
314                     + "compatible model update " + "from the existing engine model with key \"SmallModel:0.0.1\"",
315                     apEx.getMessage());
316         }
317
318         try {
319             esImpl.updateModel(config.getEngineKey(), differentModelString, true);
320         } catch (ApexException apEx) {
321             fail("test should not throw an exception");
322         }
323
324         try {
325             esImpl.updateModel(config.getEngineKey(), simpleModelString, true);
326         } catch (ApexException apEx) {
327             fail("test should not throw an exception");
328         }
329
330         String runtimeInfo = esImpl.getRuntimeInfo(esImpl.getEngineKeys().iterator().next());
331         assertEquals("{\n  \"TimeStamp\":", runtimeInfo.substring(0, 16));
332
333         assertEquals(AxEngineState.EXECUTING, esImpl.getState());
334
335         String status = esImpl.getStatus(esImpl.getEngineKeys().iterator().next());
336         assertTrue(status.contains("\n   \"apexEngineModel\" :"));
337         assertTrue(esImpl.isStarted());
338         assertTrue(esImpl.isStarted(esImpl.getEngineKeys().iterator().next()));
339         assertFalse(esImpl.isStopped());
340         assertFalse(esImpl.isStopped(esImpl.getEngineKeys().iterator().next()));
341
342         try {
343             esImpl.start(esImpl.getEngineKeys().iterator().next());
344             fail("test should throw an exception");
345         } catch (ApexException apEx) {
346             assertEquals("apex engine for engine key Engine-0:0.0.1 is already running with state READY",
347                     apEx.getMessage());
348         }
349
350         try {
351             esImpl.startAll();
352             fail("test should throw an exception");
353         } catch (ApexException apEx) {
354             assertEquals("apex engine for engine key Engine-0:0.0.1 is already running with state READY",
355                     apEx.getMessage());
356         }
357
358         try {
359             esImpl.stop(esImpl.getEngineKeys().iterator().next());
360         } catch (ApexException apEx) {
361             fail("test should not throw an exception");
362         }
363
364         try {
365             esImpl.start(esImpl.getEngineKeys().iterator().next());
366         } catch (ApexException apEx) {
367             fail("test should not throw an exception");
368         }
369
370         try {
371             esImpl.stop();
372         } catch (ApexException apEx) {
373             fail("test should not throw an exception");
374         }
375
376         try {
377             esImpl.startAll();
378         } catch (ApexException apEx) {
379             fail("test should not throw an exception");
380         }
381
382         try {
383             esImpl.sendEvent(new ApexEvent("SomeEvent", "0.0.1", "the.event.namespace", "EventSource", "EventTarget"));
384         } catch (ApexException apEx) {
385             fail("test should not throw an exception");
386         }
387
388         esImpl.startPeriodicEvents(100000);
389         esImpl.stop();
390         esImpl.startAll();
391         esImpl.stopPeriodicEvents();
392
393         esImpl.startPeriodicEvents(100000);
394         try {
395             esImpl.startPeriodicEvents(100000);
396             fail("test should throw an exception");
397         } catch (ApexException apEx) {
398             assertEquals("Peiodic event geneation already running on engine Engine:0.0.1, ApexPeriodicEventGenerator "
399                     + "[period=100000, firstEventTime=0, lastEventTime=0, eventCount=0]", apEx.getMessage());
400         }
401
402         esImpl.stopPeriodicEvents();
403         try {
404             esImpl.stopPeriodicEvents();
405             fail("test should throw an exception");
406         } catch (ApexException apEx) {
407             assertEquals("Peiodic event geneation not running on engine Engine:0.0.1", apEx.getMessage());
408         }
409
410         try {
411             esImpl.clear(esImpl.getEngineKeys().iterator().next());
412         } catch (ApexException apEx) {
413             fail("test should not throw an exception");
414         }
415
416         try {
417             esImpl.clear();
418         } catch (ApexException apEx) {
419             fail("test should not throw an exception");
420         }
421     }
422 }