Drools support for kafka topics
[policy/drools-pdp.git] / feature-pooling-dmaap / src / test / java / org / onap / policy / drools / pooling / PoolingFeatureTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2020 Nordix Foundation
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.drools.pooling;
23
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotEquals;
27 import static org.junit.Assert.assertNotNull;
28 import static org.junit.Assert.assertTrue;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.Mockito.doThrow;
31 import static org.mockito.Mockito.mock;
32 import static org.mockito.Mockito.never;
33 import static org.mockito.Mockito.times;
34 import static org.mockito.Mockito.verify;
35 import static org.mockito.Mockito.when;
36
37 import java.util.Collections;
38 import java.util.LinkedList;
39 import java.util.List;
40 import java.util.Properties;
41 import java.util.concurrent.CountDownLatch;
42 import org.apache.commons.lang3.tuple.Pair;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
46 import org.onap.policy.common.endpoints.event.comm.TopicSink;
47 import org.onap.policy.common.endpoints.event.comm.TopicSource;
48 import org.onap.policy.drools.controller.DroolsController;
49 import org.onap.policy.drools.system.PolicyController;
50 import org.onap.policy.drools.system.PolicyEngine;
51
52 public class PoolingFeatureTest {
53
54     private static final String CONTROLLER1 = "controllerA";
55     private static final String CONTROLLER2 = "controllerB";
56     private static final String CONTROLLER_DISABLED = "controllerDisabled";
57     private static final String CONTROLLER_EX = "controllerException";
58     private static final String CONTROLLER_UNKNOWN = "controllerUnknown";
59
60     private static final String TOPIC1 = "topic.one";
61     private static final String TOPIC2 = "topic.two";
62
63     private static final String EVENT1 = "event.one";
64     private static final String EVENT2 = "event.two";
65
66     private static final Object OBJECT1 = new Object();
67     private static final Object OBJECT2 = new Object();
68
69     private Properties props;
70     private PolicyEngine engine;
71     private PolicyController controller1;
72     private PolicyController controller2;
73     private PolicyController controllerDisabled;
74     private PolicyController controllerException;
75     private PolicyController controllerUnknown;
76     private DroolsController drools1;
77     private DroolsController drools2;
78     private DroolsController droolsDisabled;
79     private List<Pair<PoolingManagerImpl, PoolingProperties>> managers;
80     private PoolingManagerImpl mgr1;
81     private PoolingManagerImpl mgr2;
82
83     private PoolingFeature pool;
84
85     /**
86      * Setup.
87      *
88      * @throws Exception exception
89      */
90     @Before
91     public void setUp() throws Exception {
92         props = initProperties();
93         engine = mock(PolicyEngine.class);
94         controller1 = mock(PolicyController.class);
95         controller2 = mock(PolicyController.class);
96         controllerDisabled = mock(PolicyController.class);
97         controllerException = mock(PolicyController.class);
98         controllerUnknown = mock(PolicyController.class);
99         drools1 = mock(DroolsController.class);
100         drools2 = mock(DroolsController.class);
101         droolsDisabled = mock(DroolsController.class);
102         managers = new LinkedList<>();
103
104         when(controller1.getName()).thenReturn(CONTROLLER1);
105         when(controller2.getName()).thenReturn(CONTROLLER2);
106         when(controllerDisabled.getName()).thenReturn(CONTROLLER_DISABLED);
107         when(controllerException.getName()).thenReturn(CONTROLLER_EX);
108         when(controllerUnknown.getName()).thenReturn(CONTROLLER_UNKNOWN);
109
110         pool = new PoolingFeatureImpl();
111
112         pool.beforeStart(engine);
113
114         pool.afterCreate(controller1);
115         pool.afterCreate(controller2);
116
117         mgr1 = managers.get(0).getLeft();
118         mgr2 = managers.get(1).getLeft();
119     }
120
121     @Test
122     public void test() {
123         assertEquals(2, managers.size());
124     }
125
126     @Test
127     public void testGetHost() {
128         String host = pool.getHost();
129         assertNotNull(host);
130
131         // create another and ensure it generates another host name
132         pool = new PoolingFeatureImpl();
133         String host2 = pool.getHost();
134         assertNotNull(host2);
135
136         assertNotEquals(host, host2);
137     }
138
139     @Test
140     public void testGetSequenceNumber() {
141         assertEquals(0, pool.getSequenceNumber());
142     }
143
144     @Test
145     public void testBeforeStartEngine() {
146         pool = new PoolingFeatureImpl();
147
148         assertFalse(pool.beforeStart(engine));
149     }
150
151     @Test
152     public void testAfterCreate() {
153         managers.clear();
154         pool = new PoolingFeatureImpl();
155         pool.beforeStart(engine);
156
157         assertFalse(pool.afterCreate(controller1));
158         assertEquals(1, managers.size());
159
160         // duplicate
161         assertFalse(pool.afterCreate(controller1));
162         assertEquals(1, managers.size());
163
164         // second controller
165         assertFalse(pool.afterCreate(controller2));
166         assertEquals(2, managers.size());
167     }
168
169     @Test
170     public void testAfterCreate_NotEnabled() {
171         managers.clear();
172         pool = new PoolingFeatureImpl();
173         pool.beforeStart(engine);
174
175         assertFalse(pool.afterCreate(controllerDisabled));
176         assertTrue(managers.isEmpty());
177     }
178
179     @Test(expected = PoolingFeatureRtException.class)
180     public void testAfterCreate_PropertyEx() {
181         managers.clear();
182         pool = new PoolingFeatureImpl();
183         pool.beforeStart(engine);
184
185         pool.afterCreate(controllerException);
186     }
187
188     @Test(expected = PoolingFeatureRtException.class)
189     public void testAfterCreate_NoProps() {
190         pool = new PoolingFeatureImpl();
191
192         // did not perform globalInit, which is an error
193
194         pool.afterCreate(controller1);
195     }
196
197     @Test
198     public void testAfterCreate_NoFeatProps() {
199         managers.clear();
200         pool = new PoolingFeatureImpl();
201         pool.beforeStart(engine);
202
203         assertFalse(pool.afterCreate(controllerUnknown));
204         assertTrue(managers.isEmpty());
205     }
206
207     @Test
208     public void testBeforeStart() throws Exception {
209         assertFalse(pool.beforeStart(controller1));
210         verify(mgr1).beforeStart();
211
212         // ensure it's still in the map by re-invoking
213         assertFalse(pool.beforeStart(controller1));
214         verify(mgr1, times(2)).beforeStart();
215
216         assertFalse(pool.beforeStart(controllerDisabled));
217     }
218
219     @Test
220     public void testAfterStart() {
221         assertFalse(pool.afterStart(controller1));
222         verify(mgr1).afterStart();
223
224         // ensure it's still in the map by re-invoking
225         assertFalse(pool.afterStart(controller1));
226         verify(mgr1, times(2)).afterStart();
227
228         assertFalse(pool.afterStart(controllerDisabled));
229     }
230
231     @Test
232     public void testBeforeStop() {
233         assertFalse(pool.beforeStop(controller1));
234         verify(mgr1).beforeStop();
235
236         // ensure it's still in the map by re-invoking
237         assertFalse(pool.beforeStop(controller1));
238         verify(mgr1, times(2)).beforeStop();
239
240         assertFalse(pool.beforeStop(controllerDisabled));
241     }
242
243     @Test
244     public void testAfterStop() {
245         assertFalse(pool.afterStop(controller1));
246         verify(mgr1).afterStop();
247
248         assertFalse(pool.afterStop(controllerDisabled));
249
250         // count should be unchanged
251         verify(mgr1).afterStop();
252     }
253
254     @Test
255     public void testAfterHalt() {
256         assertFalse(pool.afterHalt(controller1));
257         assertFalse(pool.afterHalt(controller1));
258
259         verify(mgr1, never()).afterStop();
260
261         assertFalse(pool.afterStop(controllerDisabled));
262     }
263
264     @Test
265     public void testAfterShutdown() {
266         assertFalse(pool.afterShutdown(controller1));
267         assertFalse(pool.afterShutdown(controller1));
268
269         verify(mgr1, never()).afterStop();
270
271         assertFalse(pool.afterStop(controllerDisabled));
272     }
273
274     @Test
275     public void testBeforeLock() {
276         assertFalse(pool.beforeLock(controller1));
277         verify(mgr1).beforeLock();
278
279         // ensure it's still in the map by re-invoking
280         assertFalse(pool.beforeLock(controller1));
281         verify(mgr1, times(2)).beforeLock();
282
283         assertFalse(pool.beforeLock(controllerDisabled));
284     }
285
286     @Test
287     public void testAfterUnlock() {
288         assertFalse(pool.afterUnlock(controller1));
289         verify(mgr1).afterUnlock();
290
291         // ensure it's still in the map by re-invoking
292         assertFalse(pool.afterUnlock(controller1));
293         verify(mgr1, times(2)).afterUnlock();
294
295         assertFalse(pool.afterUnlock(controllerDisabled));
296     }
297
298     @Test
299     public void testBeforeOffer() {
300         assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
301         verify(mgr1).beforeOffer(TOPIC1, EVENT1);
302
303         // ensure that the args were captured
304         pool.beforeInsert(drools1, OBJECT1);
305         verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
306
307
308         // ensure it's still in the map by re-invoking
309         assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
310         verify(mgr1).beforeOffer(TOPIC2, EVENT2);
311
312         // ensure that the new args were captured
313         pool.beforeInsert(drools1, OBJECT2);
314         verify(mgr1).beforeInsert(TOPIC2, OBJECT2);
315
316
317         assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
318     }
319
320     @Test
321     public void testBeforeOffer_NotFound() {
322         assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
323     }
324
325     @Test
326     public void testBeforeOffer_MgrTrue() {
327
328         // manager will return true
329         when(mgr1.beforeOffer(any(), any())).thenReturn(true);
330
331         assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
332         verify(mgr1).beforeOffer(TOPIC1, EVENT1);
333
334         // ensure it's still in the map by re-invoking
335         assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
336         verify(mgr1).beforeOffer(TOPIC2, EVENT2);
337
338         assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
339     }
340
341     @Test
342     public void testBeforeInsert() {
343         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
344         assertFalse(pool.beforeInsert(drools1, OBJECT1));
345         verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
346
347         // ensure it's still in the map by re-invoking
348         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2);
349         assertFalse(pool.beforeInsert(drools1, OBJECT2));
350         verify(mgr1).beforeInsert(TOPIC2, OBJECT2);
351
352         pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
353         assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
354     }
355
356     @Test
357     public void testBeforeInsert_NoArgs() {
358
359         // call beforeInsert without beforeOffer
360         assertFalse(pool.beforeInsert(drools1, OBJECT1));
361         verify(mgr1, never()).beforeInsert(any(), any());
362
363         assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
364         verify(mgr1, never()).beforeInsert(any(), any());
365     }
366
367     @Test
368     public void testBeforeInsert_ArgEx() {
369         // generate exception
370         pool = new PoolingFeatureImpl() {
371             @Override
372             protected PolicyController getController(DroolsController droolsController) {
373                 throw new IllegalArgumentException();
374             }
375         };
376
377         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
378         assertFalse(pool.beforeInsert(drools1, OBJECT1));
379         verify(mgr1, never()).beforeInsert(any(), any());
380     }
381
382     @Test
383     public void testBeforeInsert_StateEx() {
384         // generate exception
385         pool = new PoolingFeatureImpl() {
386             @Override
387             protected PolicyController getController(DroolsController droolsController) {
388                 throw new IllegalStateException();
389             }
390         };
391
392         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
393         assertFalse(pool.beforeInsert(drools1, OBJECT1));
394         verify(mgr1, never()).beforeInsert(any(), any());
395     }
396
397     @Test
398     public void testBeforeInsert_NullController() {
399
400         // return null controller
401         pool = new PoolingFeatureImpl() {
402             @Override
403             protected PolicyController getController(DroolsController droolsController) {
404                 return null;
405             }
406         };
407
408         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
409         assertFalse(pool.beforeInsert(drools1, OBJECT1));
410         verify(mgr1, never()).beforeInsert(any(), any());
411     }
412
413     @Test
414     public void testBeforeInsert_NotFound() {
415
416         pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
417         assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
418     }
419
420     @Test
421     public void testAfterOffer() {
422         // this will create OfferArgs
423         pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
424
425         // this should clear them
426         assertFalse(pool.afterOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2, true));
427
428         assertFalse(pool.beforeInsert(drools1, OBJECT1));
429         verify(mgr1, never()).beforeInsert(any(), any());
430
431
432         assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
433     }
434
435     @Test
436     public void testDoManager() throws Exception {
437         assertFalse(pool.beforeStart(controller1));
438         verify(mgr1).beforeStart();
439
440         // ensure it's still in the map by re-invoking
441         assertFalse(pool.beforeStart(controller1));
442         verify(mgr1, times(2)).beforeStart();
443
444
445         // different controller
446         assertFalse(pool.beforeStart(controller2));
447         verify(mgr2).beforeStart();
448
449         // ensure it's still in the map by re-invoking
450         assertFalse(pool.beforeStart(controller2));
451         verify(mgr2, times(2)).beforeStart();
452
453
454         assertFalse(pool.beforeStart(controllerDisabled));
455     }
456
457     @Test
458     public void testDoManager_NotFound() {
459         assertFalse(pool.beforeStart(controllerDisabled));
460     }
461
462     @Test(expected = RuntimeException.class)
463     public void testDoManager_Ex() throws Exception {
464
465         // generate exception
466         doThrow(new RuntimeException()).when(mgr1).beforeStart();
467
468         pool.beforeStart(controller1);
469     }
470
471     private Properties initProperties() {
472         Properties props = new Properties();
473
474         initProperties(props, "A", 0);
475         initProperties(props, "B", 1);
476         initProperties(props, "Exception", 2);
477
478         props.setProperty("pooling.controllerDisabled.enabled", "false");
479
480         props.setProperty("pooling.controllerException.offline.queue.limit", "INVALID NUMBER");
481
482         return props;
483     }
484
485     private void initProperties(Properties props, String suffix, int offset) {
486         props.setProperty("pooling.controller" + suffix + ".topic", "topic." + suffix);
487         props.setProperty("pooling.controller" + suffix + ".enabled", "true");
488         props.setProperty("pooling.controller" + suffix + ".offline.queue.limit", String.valueOf(5 + offset));
489         props.setProperty("pooling.controller" + suffix + ".offline.queue.age.milliseconds",
490                         String.valueOf(100 + offset));
491         props.setProperty("pooling.controller" + suffix + ".start.heartbeat.milliseconds", String.valueOf(10 + offset));
492         props.setProperty("pooling.controller" + suffix + ".reactivate.milliseconds", String.valueOf(20 + offset));
493         props.setProperty("pooling.controller" + suffix + ".identification.milliseconds", String.valueOf(30 + offset));
494         props.setProperty("pooling.controller" + suffix + ".active.heartbeat.milliseconds",
495                         String.valueOf(40 + offset));
496         props.setProperty("pooling.controller" + suffix + ".inter.heartbeat.milliseconds", String.valueOf(50 + offset));
497     }
498
499     /**
500      * Feature with overrides.
501      */
502     private class PoolingFeatureImpl extends PoolingFeature {
503
504         @Override
505         protected Properties getProperties(String featName) {
506             if (PoolingProperties.FEATURE_NAME.equals(featName)) {
507                 return props;
508             } else {
509                 throw new IllegalArgumentException("unknown feature name");
510             }
511         }
512
513         @Override
514         protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
515                         CountDownLatch activeLatch) {
516
517             PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
518
519             managers.add(Pair.of(mgr, props));
520
521             return mgr;
522         }
523
524         @Override
525         protected PolicyController getController(DroolsController droolsController) {
526             if (droolsController == drools1) {
527                 return controller1;
528             } else if (droolsController == drools2) {
529                 return controller2;
530             } else if (droolsController == droolsDisabled) {
531                 return controllerDisabled;
532             } else {
533                 throw new IllegalArgumentException("unknown drools controller");
534             }
535         }
536
537         @Override
538         protected List<TopicSource> initTopicSources(Properties props) {
539             return Collections.emptyList();
540         }
541
542         @Override
543         protected List<TopicSink> initTopicSinks(Properties props) {
544             return Collections.emptyList();
545         }
546     }
547 }