57f98bd0a732f2b78d102f9b58b1239676a07847
[policy/drools-applications.git] /
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2020 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
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  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.extension.system;
22
23 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
24 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNull;
28 import static org.junit.Assert.assertSame;
29 import static org.junit.Assert.assertTrue;
30 import static org.junit.Assert.fail;
31 import static org.mockito.ArgumentMatchers.any;
32 import static org.mockito.Mockito.mock;
33 import static org.mockito.Mockito.when;
34 import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE;
35
36 import java.util.List;
37 import java.util.Properties;
38 import java.util.function.Function;
39 import org.junit.After;
40 import org.junit.Before;
41 import org.junit.BeforeClass;
42 import org.junit.Test;
43 import org.onap.policy.common.endpoints.event.comm.TopicSink;
44 import org.onap.policy.controlloop.VirtualControlLoopNotification;
45 import org.onap.policy.drools.controller.DroolsController;
46 import org.onap.policy.drools.features.DroolsControllerFeatureApi;
47 import org.onap.policy.drools.features.PolicyControllerFeatureApi;
48 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
49 import org.onap.policy.drools.system.PolicyController;
50 import org.onap.policy.drools.system.PolicyControllerConstants;
51 import org.onap.policy.drools.utils.PropertyUtil;
52
53 public class NonDroolsPolicyControllerTest {
54     //public static boolean loop = true;
55     private static Properties prop;
56
57     private NonDroolsPolicyController controller;
58
59     @BeforeClass
60     public static void setupClass() throws Exception {
61         prop = PropertyUtil.getProperties("src/test/resources/config/tdjam-controller.properties");
62     }
63
64     /**
65      * Resets the stats and creates the controller.
66      */
67     @Before
68     public void setUp() {
69         DroolsControllerFeatureHandler.resetStats();
70
71         controller = buildController("tdjam");
72     }
73
74     /**
75      * Destroys the controller.
76      */
77     @After
78     public void tearDown() {
79         String name = controller.getName();
80         assertSame(controller, PolicyControllerConstants.getFactory().get(name));
81         PolicyControllerConstants.getFactory().destroy(controller);
82         assertThatIllegalArgumentException().isThrownBy(
83             () -> PolicyControllerConstants.getFactory().get(name));
84     }
85
86     @Test
87     public void testState() {
88         assertEquals("nondrools", controller.getName());
89         assertEquals("NonDroolsPolicyController", controller.getGroupId());
90         assertEquals("nondrools", controller.getArtifactId());
91         assertEquals("1.0", controller.getVersion());
92         assertTrue(controller.isBrained());
93
94         assertFalse(controller.isAlive());
95         assertFalse(controller.isLocked());
96
97         // first 'start()'
98         controller.start();
99         assertTrue(controller.isAlive());
100         assertFalse(controller.isLocked());
101
102         // second 'start()'
103         controller.start();
104         assertTrue(controller.isAlive());
105         assertFalse(controller.isLocked());
106
107         // test a few stubbed-off methods
108         assertNull(controller.getContainer());
109         assertThatIllegalStateException().isThrownBy(() -> controller.updateToVersion(null, null, null, null, null));
110
111         controller.lock();
112         assertTrue(controller.isAlive());
113         assertTrue(controller.isLocked());
114
115         controller.stop();
116         assertFalse(controller.isAlive());
117         assertTrue(controller.isLocked());
118
119         controller.unlock();
120         assertFalse(controller.isAlive());
121         assertFalse(controller.isLocked());
122     }
123
124     @Test
125     public void testNames() {
126         assertTrue(controller.getSessionNames().isEmpty());
127         assertTrue(controller.getCanonicalSessionNames().isEmpty());
128         assertTrue(controller.getBaseDomainNames().isEmpty());
129     }
130
131     @Test
132     public void testOffer() {
133         controller.start();
134
135         assertFalse(controller.offer("topic", "event"));
136         assertFalse(controller.offer("event"));
137         assertEquals(0, controller.getRecentSourceEvents().length);
138         assertEquals(0, controller.getRecentSinkEvents().length);
139     }
140
141     @Test
142     public void testFacts() {
143         assertThatIllegalArgumentException().isThrownBy(
144             () -> controller.fetchModelClass("NoSuchClass"));
145         assertTrue(controller.factClassNames(null).isEmpty());
146         assertEquals(0, controller.factCount(null));
147         assertTrue(controller.facts(null, null, false).isEmpty());
148         assertTrue(controller.facts("sessionName", String.class).isEmpty());
149         assertTrue(controller.factQuery(null, null, null, false).isEmpty());
150     }
151
152     @Test
153     public void testDelete() {
154         assertFalse(controller.delete("sessionName", "fact"));
155         assertFalse(controller.delete("fact"));
156         assertFalse(controller.delete("sessionName", String.class));
157         assertFalse(controller.delete(String.class));
158     }
159
160     @Test
161     public void testDeliver() {
162         final TopicSink topicSink = mock(TopicSink.class);
163         when(topicSink.getTopic()).thenReturn("POLICY-CL-MGT");
164         when(topicSink.send(any())).thenReturn(false);
165
166         final VirtualControlLoopNotification msg = new VirtualControlLoopNotification(null);
167
168         controller.lock();
169
170         // invalid sink
171         try {
172             controller.deliver(null, null);
173             fail("Expected IllegalArgumentException did not occur");
174         } catch (IllegalArgumentException ex) {
175             assertTrue(ex.getMessage(),
176                        ex.getMessage().endsWith(" invalid sink"));
177         }
178
179         // invalid event
180         try {
181             controller.deliver(topicSink, null);
182             fail("Expected IllegalArgumentException did not occur");
183         } catch (IllegalArgumentException ex) {
184             assertTrue(ex.getMessage(),
185                        ex.getMessage().endsWith(" invalid event"));
186         }
187
188         // is locked
189         try {
190             controller.deliver(topicSink, "event");
191             fail("Expected IllegalStateException did not occur");
192         } catch (IllegalStateException ex) {
193             assertTrue(ex.getMessage(),
194                        ex.getMessage().endsWith(" is locked"));
195         }
196         controller.unlock();
197
198         // is stopped
199         try {
200             controller.deliver(topicSink, "event");
201             fail("Expected IllegalStateException did not occur");
202         } catch (IllegalStateException ex) {
203             assertTrue(ex.getMessage(),
204                        ex.getMessage().endsWith(" is stopped"));
205         }
206
207         // there should have been 4 'beforeDeliver' calls up to this point
208         assertEquals(4, DroolsControllerFeatureHandler.beforeDeliverFalse);
209
210         Function<String, Boolean> signal = (sig) -> {
211             msg.getAai().put("signal", sig);
212             return controller.deliver(topicSink, msg);
213         };
214
215         controller.start();
216
217         // 'beforeDeliver' intercepts
218         DroolsControllerFeatureHandler.resetStats();
219
220         assertTrue(signal.apply("beforeDeliverTrue"));
221         assertEquals(1, DroolsControllerFeatureHandler.beforeDeliverTrue);
222         assertEquals(0, DroolsControllerFeatureHandler.afterDeliverFalse);
223
224         assertFalse(signal.apply("beforeDeliverException"));
225         assertEquals(1, DroolsControllerFeatureHandler.beforeDeliverException);
226         assertEquals(1, DroolsControllerFeatureHandler.afterDeliverFalse);
227         // it would be nice to check the log message at this point
228
229         // 'afterDeliver' intercepts
230         DroolsControllerFeatureHandler.resetStats();
231
232         assertTrue(signal.apply("afterDeliverTrue"));
233         assertEquals(1, DroolsControllerFeatureHandler.afterDeliverTrue);
234
235         assertFalse(signal.apply("afterDeliverException"));
236         assertEquals(1, DroolsControllerFeatureHandler.afterDeliverException);
237
238         assertFalse(signal.apply("nothing in particular"));
239         assertEquals(1, DroolsControllerFeatureHandler.afterDeliverFalse);
240     }
241
242     private NonDroolsPolicyController buildController(String type) {
243         prop.setProperty(PROPERTY_CONTROLLER_TYPE, type);
244         PolicyController controller =
245             PolicyControllerConstants.getFactory().build("nondrools", prop);
246         assertTrue(controller instanceof NonDroolsPolicyController);
247         return (NonDroolsPolicyController) controller;
248     }
249
250     /* ============================================================ */
251
252     /**
253      * An instance of this class is called by 'IndexedPolicyControllerFactory'.
254      * It does the build operation when the value of the 'controller.type'
255      * property matches the value of TDJAM_CONTROLLER_BUILDER_TAG.
256      */
257     public static class PolicyBuilder implements PolicyControllerFeatureApi {
258         @Override
259         public int getSequenceNumber() {
260             return 1;
261         }
262
263         @Override
264         public PolicyController beforeInstance(String name, Properties properties) {
265             if ("nondrools".equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
266                 return new NonDroolsPolicyController(name, properties);
267             }
268             return null;
269         }
270     }
271
272     /* ============================================================ */
273
274     /**
275      * An instance of this class is called by 'IndexedDroolsControllerFactory'.
276      * It does the build operation when the value of the 'controller.type'
277      * property matches the value of TDJAM_CONTROLLER_BUILDER_TAG.
278      */
279     public static class DroolsBuilder implements DroolsControllerFeatureApi {
280         @Override
281         public int getSequenceNumber() {
282             return 1;
283         }
284
285         @Override
286         public DroolsController beforeInstance(Properties properties,
287                                       String groupId, String artifactId, String version,
288                                       List<TopicCoderFilterConfiguration> decoderConfigurations,
289                                       List<TopicCoderFilterConfiguration> encoderConfigurations) throws LinkageError {
290
291             if ("nondrools".equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
292                 return NonDroolsPolicyController.getBuildInProgress();
293             }
294             return null;
295         }
296     }
297
298     /* ============================================================ */
299
300     public static class DroolsControllerFeatureHandler implements DroolsControllerFeatureApi {
301         static int beforeDeliverFalse = 0;
302         static int beforeDeliverTrue = 0;
303         static int beforeDeliverException = 0;
304         static int afterDeliverFalse = 0;
305         static int afterDeliverTrue = 0;
306         static int afterDeliverException = 0;
307
308         private static void resetStats() {
309             beforeDeliverFalse = 0;
310             beforeDeliverTrue = 0;
311             beforeDeliverException = 0;
312             afterDeliverFalse = 0;
313             afterDeliverTrue = 0;
314             afterDeliverException = 0;
315         }
316
317         @Override
318         public int getSequenceNumber() {
319             return 1;
320         }
321
322         @Override
323         public boolean beforeDeliver(DroolsController controller, TopicSink sink, Object fact) {
324             if (fact instanceof VirtualControlLoopNotification) {
325                 String factString = ((VirtualControlLoopNotification) fact).getAai().get("signal");
326                 if (factString == null) {
327                     // this hook is run during 'FrankfurtTest' as well
328                     return false;
329                 }
330                 if (factString.contains("beforeDeliverTrue")) {
331                     beforeDeliverTrue += 1;
332                     return true;
333                 }
334                 if (factString.contains("beforeDeliverException")) {
335                     beforeDeliverException += 1;
336                     RuntimeException ex = new RuntimeException("beforeDeliver");
337                     ex.printStackTrace();
338                     throw ex;
339                 }
340             }
341             beforeDeliverFalse += 1;
342             return false;
343         }
344
345
346         @Override
347             public boolean afterDeliver(DroolsController controller, TopicSink sink, Object fact,
348                                         String json, boolean success) {
349
350             if (fact instanceof VirtualControlLoopNotification) {
351                 String factString = ((VirtualControlLoopNotification) fact).getAai().get("signal");
352                 if (factString == null) {
353                     // this hook is run during 'FrankfurtTest' as well
354                     return false;
355                 }
356                 if (factString.contains("afterDeliverTrue")) {
357                     afterDeliverTrue += 1;
358                     return true;
359                 }
360                 if (factString.contains("afterDeliverException")) {
361                     afterDeliverException += 1;
362                     throw new RuntimeException("afterDeliver");
363                 }
364             }
365             afterDeliverFalse += 1;
366             return false;
367         }
368     }
369 }