ab0bf303f422b9a219a92f31d73d7b0cf4ecd4df
[policy/apex-pdp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2016-2018 Ericsson. All rights reserved.
4  *  Modifications Copyright (C) 2019-2020 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.apex.examples.adaptive;
23
24 import static org.awaitility.Awaitility.await;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertNotNull;
27 import static org.junit.Assert.assertTrue;
28
29 import java.io.IOException;
30 import java.util.Random;
31 import java.util.concurrent.TimeUnit;
32
33 import org.junit.After;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.onap.policy.apex.context.impl.schema.java.JavaSchemaHelperParameters;
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.SchemaParameters;
40 import org.onap.policy.apex.core.engine.EngineParameters;
41 import org.onap.policy.apex.core.engine.engine.ApexEngine;
42 import org.onap.policy.apex.core.engine.engine.impl.ApexEngineFactory;
43 import org.onap.policy.apex.core.engine.event.EnEvent;
44 import org.onap.policy.apex.examples.adaptive.model.AdaptiveDomainModelFactory;
45 import org.onap.policy.apex.model.basicmodel.concepts.ApexException;
46 import org.onap.policy.apex.model.basicmodel.concepts.AxArtifactKey;
47 import org.onap.policy.apex.model.basicmodel.concepts.AxValidationResult;
48 import org.onap.policy.apex.model.enginemodel.concepts.AxEngineState;
49 import org.onap.policy.apex.model.policymodel.concepts.AxPolicyModel;
50 import org.onap.policy.apex.plugins.executor.java.JavaExecutorParameters;
51 import org.onap.policy.apex.plugins.executor.mvel.MvelExecutorParameters;
52 import org.onap.policy.common.parameters.ParameterService;
53 import org.slf4j.ext.XLogger;
54 import org.slf4j.ext.XLoggerFactory;
55
56 // TODO: Auto-generated Javadoc
57 /**
58  * Test Auto learning in TSL.
59  *
60  * @author John Keeney (John.Keeney@ericsson.com)
61  */
62 public class AutoLearnTslUseCaseTest {
63     private static final XLogger LOGGER = XLoggerFactory.getXLogger(AutoLearnTslUseCaseTest.class);
64
65     private static final int MAXITERATIONS = 1000;
66     private static final Random rand = new Random(System.currentTimeMillis());
67
68     private SchemaParameters schemaParameters;
69     private ContextParameters contextParameters;
70     private EngineParameters engineParameters;
71
72     /**
73      * Before test.
74      */
75     @Before
76     public void beforeTest() {
77         schemaParameters = new SchemaParameters();
78         
79         schemaParameters.setName(ContextParameterConstants.SCHEMA_GROUP_NAME);
80         schemaParameters.getSchemaHelperParameterMap().put("JAVA", new JavaSchemaHelperParameters());
81
82         ParameterService.register(schemaParameters);
83         
84         contextParameters = new ContextParameters();
85
86         contextParameters.setName(ContextParameterConstants.MAIN_GROUP_NAME);
87         contextParameters.getDistributorParameters().setName(ContextParameterConstants.DISTRIBUTOR_GROUP_NAME);
88         contextParameters.getLockManagerParameters().setName(ContextParameterConstants.LOCKING_GROUP_NAME);
89         contextParameters.getPersistorParameters().setName(ContextParameterConstants.PERSISTENCE_GROUP_NAME);
90
91         ParameterService.register(contextParameters);
92         ParameterService.register(contextParameters.getDistributorParameters());
93         ParameterService.register(contextParameters.getLockManagerParameters());
94         ParameterService.register(contextParameters.getPersistorParameters());
95         
96         engineParameters = new EngineParameters();
97         engineParameters.getExecutorParameterMap().put("MVEL", new MvelExecutorParameters());
98         engineParameters.getExecutorParameterMap().put("JAVA", new JavaExecutorParameters());
99         ParameterService.register(engineParameters);
100     }
101
102     /**
103      * After test.
104      */
105     @After
106     public void afterTest() {
107         ParameterService.deregister(engineParameters);
108         
109         ParameterService.deregister(contextParameters.getDistributorParameters());
110         ParameterService.deregister(contextParameters.getLockManagerParameters());
111         ParameterService.deregister(contextParameters.getPersistorParameters());
112         ParameterService.deregister(contextParameters);
113
114         ParameterService.deregister(schemaParameters);
115     }
116
117     /**
118      * Test auto learn tsl.
119      *
120      * @throws ApexException the apex exception
121      * @throws InterruptedException the interrupted exception
122      * @throws IOException Signals that an I/O exception has occurred.
123      */
124     @Test
125     // once through the long running test below
126     public void testAutoLearnTsl() throws ApexException, InterruptedException, IOException {
127         final AxPolicyModel apexPolicyModel = new AdaptiveDomainModelFactory().getAutoLearnPolicyModel();
128         assertNotNull(apexPolicyModel);
129
130         final AxValidationResult validationResult = new AxValidationResult();
131         apexPolicyModel.validate(validationResult);
132         assertTrue(validationResult.isValid());
133
134         final AxArtifactKey key = new AxArtifactKey("AADMApexEngine", "0.0.1");
135
136         final ApexEngine apexEngine1 = new ApexEngineFactory().createApexEngine(key);
137
138         final TestApexActionListener listener1 = new TestApexActionListener("TestListener1");
139         apexEngine1.addEventListener("listener", listener1);
140         apexEngine1.updateModel(apexPolicyModel, false);
141         apexEngine1.start();
142         final EnEvent triggerEvent = apexEngine1.createEvent(new AxArtifactKey("AutoLearnTriggerEvent", "0.0.1"));
143         final double rval = rand.nextGaussian();
144         triggerEvent.put("MonitoredValue", rval);
145         triggerEvent.put("LastMonitoredValue", 0D);
146         LOGGER.info("Triggering policy in Engine 1 with " + triggerEvent);
147         apexEngine1.handleEvent(triggerEvent);
148         final EnEvent result = listener1.getResult();
149         LOGGER.info("Receiving action event {} ", result);
150         assertEquals("ExecutionIDs are different", triggerEvent.getExecutionId(), result.getExecutionId());
151         triggerEvent.clear();
152         result.clear();
153         await().atLeast(10, TimeUnit.MILLISECONDS).until(() -> triggerEvent.isEmpty() && result.isEmpty());
154         apexEngine1.stop();
155     }
156
157     /**
158      * This policy passes, and receives a Double event context filed called "EVCDouble"<br>
159      * The policy tries to keep the value at 50, with a Min -100, Max 100 (These should probably be set using
160      * TaskParameters!)<br>
161      * The policy has 7 Decide Tasks that manipulate the value of this field in unknown ways.<br>
162      * The Decide TSL learns the effect of each task, and then selects the appropriate task to get the value back to
163      * 50<br>
164      * After the value settles close to 50 for a while, the test Rests the value to to random number and then
165      * continues<br>
166      * To plot the results grep stdout debug results for the string "*******", paste into excel and delete non-relevant
167      * columns<br>
168      *
169      * @throws ApexException the apex exception
170      * @throws InterruptedException the interrupted exception
171      * @throws IOException Signals that an I/O exception has occurred.
172      */
173     // @Test
174     public void testAutoLearnTslMain() throws ApexException, InterruptedException, IOException {
175
176         final double dwant = 50.0;
177         final double toleranceTileJump = 3.0;
178
179         final AxPolicyModel apexPolicyModel = new AdaptiveDomainModelFactory().getAutoLearnPolicyModel();
180         assertNotNull(apexPolicyModel);
181
182         final AxValidationResult validationResult = new AxValidationResult();
183         apexPolicyModel.validate(validationResult);
184         assertTrue(validationResult.isValid());
185
186         final AxArtifactKey key = new AxArtifactKey("AADMApexEngine", "0.0.1");
187         final EngineParameters parameters = new EngineParameters();
188         parameters.getExecutorParameterMap().put("MVEL", new MvelExecutorParameters());
189         parameters.getExecutorParameterMap().put("JAVA", new JavaExecutorParameters());
190
191         final ApexEngine apexEngine1 = new ApexEngineFactory().createApexEngine(key);
192
193         final TestApexActionListener listener1 = new TestApexActionListener("TestListener1");
194         apexEngine1.addEventListener("listener1", listener1);
195         apexEngine1.updateModel(apexPolicyModel, false);
196         apexEngine1.start();
197
198         final EnEvent triggerEvent = apexEngine1.createEvent(new AxArtifactKey("AutoLearnTriggerEvent", "0.0.1"));
199         assertNotNull(triggerEvent);
200         final double dmin = -100;
201         final double dmax = 100;
202
203         double rval = (((rand.nextGaussian() + 1) / 2) * (dmax - dmin)) + dmin;
204         triggerEvent.put("MonitoredValue", rval);
205         triggerEvent.put("LastMonitoredValue", 0);
206
207         double avval = 0;
208         double distance;
209         double avcount = 0;
210
211         for (int iteration = 0; iteration < MAXITERATIONS; iteration++) {
212             // Trigger the policy in engine 1
213             LOGGER.info("Triggering policy in Engine 1 with " + triggerEvent);
214             apexEngine1.handleEvent(triggerEvent);
215             final EnEvent result = listener1.getResult();
216             LOGGER.info("Receiving action event {} ", result);
217             triggerEvent.clear();
218
219             double val = (Double) result.get("MonitoredValue");
220             final double prevval = (Double) result.get("LastMonitoredValue");
221
222             triggerEvent.put("MonitoredValue", prevval);
223             triggerEvent.put("LastMonitoredValue", val);
224
225             avcount = Math.min((avcount + 1), 20); // maintain average of only the last 20 values
226             avval = ((avval * (avcount - 1)) + val) / (avcount);
227
228             distance = Math.abs(dwant - avval);
229             if (distance < toleranceTileJump) {
230                 rval = (((rand.nextGaussian() + 1) / 2) * (dmax - dmin)) + dmin;
231                 val = rval;
232                 triggerEvent.put("MonitoredValue", val);
233                 LOGGER.info("Iteration " + iteration + ": Average " + avval + " has become closer (" + distance
234                         + ") than " + toleranceTileJump + " to " + dwant + " so reseting val:\t\t\t\t\t\t\t\t" + val);
235                 avval = 0;
236                 avcount = 0;
237             }
238             LOGGER.info("Iteration " + iteration + ": \tpreval\t" + prevval + "\tval\t" + val + "\tavval\t" + avval);
239
240             result.clear();
241             await().atLeast(10, TimeUnit.MILLISECONDS).until(() -> !result.isEmpty());
242         }
243
244         apexEngine1.stop();
245         await().atMost(1000, TimeUnit.MILLISECONDS).until(() -> apexEngine1.getState().equals(AxEngineState.STOPPED));
246     }
247
248     /**
249      * The main method.
250      *
251      * @param args the arguments
252      * @throws ApexException the apex exception
253      * @throws InterruptedException the interrupted exception
254      * @throws IOException Signals that an I/O exception has occurred.
255      */
256     public static void main(final String[] args) throws ApexException, InterruptedException, IOException {
257         new AutoLearnTslUseCaseTest().testAutoLearnTslMain();
258     }
259 }