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