2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2019 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
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.
18 * ============LICENSE_END=========================================================
21 package org.onap.policy.template.demo;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
28 import java.io.IOException;
29 import java.io.UnsupportedEncodingException;
30 import java.net.URLEncoder;
31 import java.time.Instant;
32 import java.util.HashMap;
33 import java.util.LinkedList;
34 import java.util.List;
35 import java.util.Properties;
36 import java.util.UUID;
37 import org.junit.AfterClass;
38 import org.junit.BeforeClass;
39 import org.junit.Ignore;
40 import org.junit.Test;
41 import org.kie.api.runtime.KieSession;
42 import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager;
43 import org.onap.policy.common.endpoints.event.comm.TopicSink;
44 import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance;
45 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
46 import org.onap.policy.controlloop.ControlLoopEventStatus;
47 import org.onap.policy.controlloop.VirtualControlLoopEvent;
48 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
49 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
50 import org.onap.policy.drools.protocol.coders.EventProtocolCoderConstants;
51 import org.onap.policy.drools.protocol.coders.EventProtocolParams;
52 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
53 import org.onap.policy.drools.system.PolicyControllerConstants;
54 import org.onap.policy.drools.system.PolicyEngineConstants;
55 import org.onap.policy.drools.utils.logging.LoggerUtil;
56 import org.onap.policy.template.demo.SupportUtil.Pair;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
61 * Verifies that event objects are cleaned up when rules are updated. This loads
62 * <b>two</b> copies of the rule set into a single policy to ensure that the two copies
63 * interact appropriately with each other's event objects.
65 public class ControlLoopEventCleanupTest {
66 private static final Logger logger = LoggerFactory.getLogger(ControlLoopEventCleanupTest.class);
69 * Number of objects per control loop, including the Params object.
71 private static int CL_OBJECTS = 7;
73 private static final String YAML = "src/test/resources/yaml/policy_ControlLoop_EventCleanup-test.yaml";
76 * YAML to be used when the first rule set is updated.
78 private static final String YAML2 = "src/test/resources/yaml/policy_ControlLoop_EventCleanup-test2.yaml";
80 private static final String POLICY_VERSION = "v2.0";
82 private static final String POLICY_NAME = "CL_CleanupTest";
84 private static final String POLICY_SCOPE = "type=operational";
86 private static final String CONTROL_LOOP_NAME = "ControlLoop-Event-Cleanup-Test";
88 private static final String DROOLS_TEMPLATE = "../archetype-cl-amsterdam/src/main/resources/archetype-resources/"
89 + "src/main/resources/__closedLoopControlName__.drl";
91 // values specific to the second copy of the rules
93 private static final String YAML_B = "src/test/resources/yaml/policy_ControlLoop_EventCleanup-test-B.yaml";
94 private static final String POLICY_NAME_B = "CL_CleanupTest_B";
95 private static final String CONTROL_LOOP_NAME_B = "ControlLoop-Event-Cleanup-Test-B";
97 private static final String GUARD_DISABLED = "guard.disabled";
99 private static String saveGuardFlag;
101 private static KieSession kieSession;
102 private static SupportUtil.RuleSpec[] specifications;
105 * Setup the simulator.
108 public static void setUpSimulator() {
109 LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO");
111 saveGuardFlag = PolicyEngineConstants.getManager().getEnvironmentProperty(GUARD_DISABLED);
112 PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_DISABLED, "true");
114 SupportUtil.setAaiProps();
116 PolicyEngineConstants.getManager().configure(new Properties());
117 assertTrue(PolicyEngineConstants.getManager().start());
118 Properties noopSinkProperties = new Properties();
119 noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-CL,POLICY-CL-MGT");
120 noopSinkProperties.put("noop.sink.topics.APPC-CL.events", "org.onap.policy.appc.Response");
121 noopSinkProperties.put("noop.sink.topics.APPC-CL.events.custom.gson",
122 "org.onap.policy.appc.util.Serialization,gsonPretty");
123 noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events",
124 "org.onap.policy.controlloop.VirtualControlLoopNotification");
125 noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson",
126 "org.onap.policy.controlloop.util.Serialization,gsonPretty");
127 final List<TopicSink> noopTopics = TopicEndpointManager.getManager().addTopicSinks(noopSinkProperties);
129 EventProtocolCoderConstants.getManager().addEncoder(EventProtocolParams.builder()
130 .groupId("junit.groupId")
131 .artifactId("junit.artifactId")
132 .topic("POLICY-CL-MGT")
133 .eventClass("org.onap.policy.controlloop.VirtualControlLoopNotification")
134 .protocolFilter(new JsonProtocolFilter())
135 .modelClassLoaderHash(1111));
136 EventProtocolCoderConstants.getManager().addEncoder(EventProtocolParams.builder()
137 .groupId("junit.groupId")
138 .artifactId("junit.artifactId")
140 .eventClass("org.onap.policy.appc.Request")
141 .protocolFilter(new JsonProtocolFilter())
142 .modelClassLoaderHash(1111));
145 SupportUtil.buildAaiSim();
147 } catch (Exception e) {
148 logger.error("Could not create simulator", e);
149 fail("Could not create simulator");
152 for (TopicSink sink : noopTopics) {
153 assertTrue(sink.start());
157 specifications = new SupportUtil.RuleSpec[2];
159 specifications[0] = new SupportUtil.RuleSpec(DROOLS_TEMPLATE, CONTROL_LOOP_NAME, POLICY_SCOPE, POLICY_NAME,
160 POLICY_VERSION, loadYaml(YAML));
162 specifications[1] = new SupportUtil.RuleSpec(DROOLS_TEMPLATE, CONTROL_LOOP_NAME_B, POLICY_SCOPE,
163 POLICY_NAME_B, POLICY_VERSION, loadYaml(YAML_B));
165 kieSession = SupportUtil.buildContainer(POLICY_VERSION, specifications);
167 } catch (IOException e) {
168 logger.error("Could not create kieSession", e);
169 fail("Could not create kieSession");
177 public static void tearDown() {
178 kieSession.dispose();
180 PolicyEngineConstants.getManager().stop();
181 HttpServletServerFactoryInstance.getServerFactory().destroy();
182 PolicyControllerConstants.getFactory().shutdown();
183 TopicEndpointManager.getManager().shutdown();
185 if (saveGuardFlag == null) {
186 PolicyEngineConstants.getManager().getEnvironment().remove(GUARD_DISABLED);
189 PolicyEngineConstants.getManager().getEnvironment().setProperty(GUARD_DISABLED, saveGuardFlag);
195 public void test() throws IOException {
198 * Let rules create Params objects.
200 kieSession.fireAllRules();
202 injectEvent(CONTROL_LOOP_NAME);
203 injectEvent(CONTROL_LOOP_NAME_B);
205 kieSession.fireAllRules();
206 List<Object> facts = getSessionObjects();
208 // should have events for both control loops
209 assertEquals(2 * CL_OBJECTS, facts.size());
210 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME));
211 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME_B));
213 logger.info("UPDATING VERSION TO v3.0");
214 updatePolicy(YAML2, "v3.0");
217 * Let rules update Params objects. The Params for the first set of rules should
218 * now be deleted and replaced with a new one, while the Params for the second set
219 * should be unchanged.
221 kieSession.fireAllRules();
222 facts = getSessionObjects();
224 // should only have event for second control loop + 1 Params for first control loop
225 assertEquals(CL_OBJECTS + 1, facts.size());
226 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME_B));
228 // add event for first control loop again
229 injectEvent(CONTROL_LOOP_NAME);
230 kieSession.fireAllRules();
232 logger.info("UPDATING VERSION TO v4.0");
233 updatePolicy(YAML, "v4.0");
236 * Let rules update Params objects. The Params for the first set of rules should
237 * now be deleted and replaced with a new one, while the Params for the second set
238 * should be unchanged.
240 kieSession.fireAllRules();
241 facts = getSessionObjects();
243 // should only have event for second control loop + 1 Params for first control loop
244 assertEquals(CL_OBJECTS + 1, facts.size());
245 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME_B));
247 // add event for first control loop again
248 injectEvent(CONTROL_LOOP_NAME);
249 kieSession.fireAllRules();
251 logger.info("UPDATING VERSION TO v4.0 (i.e., unchanged)");
252 updatePolicy(YAML, "v4.0");
255 * Let rules update Params objects. As the version (and YAML) are unchanged for
256 * either rule set, both Params objects should be unchanged.
258 kieSession.fireAllRules();
259 facts = getSessionObjects();
261 // should have events for both control loops
262 assertEquals(2 * CL_OBJECTS, facts.size());
263 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME));
264 assertTrue(hasEvent(facts, CONTROL_LOOP_NAME_B));
267 * Now we'll delete the first rule set. That won't actually have any immediate
268 * effect, so then we'll update the second rule set, which should trigger a
271 SupportUtil.RuleSpec[] specs = new SupportUtil.RuleSpec[1];
272 specs[0] = specifications[1];
274 logger.info("UPDATING VERSION TO v5.0 - DELETED RULE SET");
275 SupportUtil.updateContainer("v5.0", specs);
277 specs[0] = new SupportUtil.RuleSpec(DROOLS_TEMPLATE, CONTROL_LOOP_NAME_B, POLICY_SCOPE, POLICY_NAME_B,
278 POLICY_VERSION, loadYaml(YAML));
280 logger.info("UPDATING VERSION TO v6.0 - UPDATED SECOND RULE SET");
281 SupportUtil.updateContainer("v6.0", specs);
283 kieSession.fireAllRules();
284 facts = getSessionObjects();
286 // only 1 Params should remain, for second rule set, but events should be gone
287 assertEquals(1, facts.size());
288 assertTrue(facts.stream().anyMatch(obj -> obj.toString().startsWith("Params( ")));
292 * Updates the policy, changing the YAML associated with the first rule set.
294 * @param yamlFile name of the YAML file
295 * @param policyVersion policy version
296 * @throws IOException if an error occurs
298 private static void updatePolicy(String yamlFile, String policyVersion) throws IOException {
300 specifications[0] = new SupportUtil.RuleSpec(DROOLS_TEMPLATE, CONTROL_LOOP_NAME, POLICY_SCOPE, POLICY_NAME,
301 policyVersion, loadYaml(yamlFile));
304 * Update the policy within the container.
306 SupportUtil.updateContainer(policyVersion, specifications);
310 * Loads a YAML file and URL-encodes it.
312 * @param yamlFile name of the YAML file
313 * @return the contents of the specified file, URL-encoded
314 * @throws UnsupportedEncodingException if an error occurs
316 private static String loadYaml(String yamlFile) throws UnsupportedEncodingException {
317 Pair<ControlLoopPolicy, String> pair = SupportUtil.loadYaml(yamlFile);
319 assertNotNull(pair.first);
320 assertNotNull(pair.first.getControlLoop());
321 assertNotNull(pair.first.getControlLoop().getControlLoopName());
322 assertTrue(pair.first.getControlLoop().getControlLoopName().length() > 0);
324 return URLEncoder.encode(pair.second, "UTF-8");
328 * Gets the session objects.
330 * @return the session objects
332 private static List<Object> getSessionObjects() {
333 // sort the objects so we know the order
334 LinkedList<Object> lst = new LinkedList<>(kieSession.getObjects());
335 lst.sort((left, right) -> left.toString().compareTo(right.toString()));
337 lst.forEach(obj -> logger.info("obj={}", obj));
343 * Injects an ONSET event into the rule engine.
345 * @param controlLoopName the control loop name
347 private void injectEvent(String controlLoopName) {
348 VirtualControlLoopEvent event = new VirtualControlLoopEvent();
350 event.setClosedLoopControlName(controlLoopName);
352 UUID reqid = UUID.randomUUID();
353 event.setRequestId(reqid);
355 event.setTarget("generic-vnf.vnf-id");
356 event.setClosedLoopAlarmStart(Instant.now());
357 event.setAai(new HashMap<>());
358 event.getAai().put("generic-vnf.vnf-id", "vnf-" + reqid.toString());
359 event.getAai().put(ControlLoopEventManager.GENERIC_VNF_IS_CLOSED_LOOP_DISABLED, "false");
360 event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
362 kieSession.insert(event);
366 * Determines if the facts contain an event for the given control loop.
368 * @param facts session facts to be checked
369 * @param controlLoopName name of the control loop of interest
370 * @return {@code true} if the facts contain an event for the given control loop,
371 * {@code false} otherwise
373 private boolean hasEvent(List<Object> facts, String controlLoopName) {
374 return (facts.stream().anyMatch(obj -> obj instanceof VirtualControlLoopEvent
375 && controlLoopName.equals(((VirtualControlLoopEvent) obj).getClosedLoopControlName())));