2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
22 package org.onap.policy.drools.pooling;
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;
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;
52 public class PoolingFeatureTest {
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";
60 private static final String TOPIC1 = "topic.one";
61 private static final String TOPIC2 = "topic.two";
63 private static final String EVENT1 = "event.one";
64 private static final String EVENT2 = "event.two";
66 private static final Object OBJECT1 = new Object();
67 private static final Object OBJECT2 = new Object();
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;
83 private PoolingFeature pool;
88 * @throws Exception exception
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<>();
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);
110 pool = new PoolingFeatureImpl();
112 pool.beforeStart(engine);
114 pool.afterCreate(controller1);
115 pool.afterCreate(controller2);
117 mgr1 = managers.get(0).getLeft();
118 mgr2 = managers.get(1).getLeft();
123 assertEquals(2, managers.size());
127 public void testGetHost() {
128 String host = pool.getHost();
131 // create another and ensure it generates another host name
132 pool = new PoolingFeatureImpl();
133 String host2 = pool.getHost();
134 assertNotNull(host2);
136 assertNotEquals(host, host2);
140 public void testGetSequenceNumber() {
141 assertEquals(0, pool.getSequenceNumber());
145 public void testBeforeStartEngine() {
146 pool = new PoolingFeatureImpl();
148 assertFalse(pool.beforeStart(engine));
152 public void testAfterCreate() {
154 pool = new PoolingFeatureImpl();
155 pool.beforeStart(engine);
157 assertFalse(pool.afterCreate(controller1));
158 assertEquals(1, managers.size());
161 assertFalse(pool.afterCreate(controller1));
162 assertEquals(1, managers.size());
165 assertFalse(pool.afterCreate(controller2));
166 assertEquals(2, managers.size());
170 public void testAfterCreate_NotEnabled() {
172 pool = new PoolingFeatureImpl();
173 pool.beforeStart(engine);
175 assertFalse(pool.afterCreate(controllerDisabled));
176 assertTrue(managers.isEmpty());
179 @Test(expected = PoolingFeatureRtException.class)
180 public void testAfterCreate_PropertyEx() {
182 pool = new PoolingFeatureImpl();
183 pool.beforeStart(engine);
185 pool.afterCreate(controllerException);
188 @Test(expected = PoolingFeatureRtException.class)
189 public void testAfterCreate_NoProps() {
190 pool = new PoolingFeatureImpl();
192 // did not perform globalInit, which is an error
194 pool.afterCreate(controller1);
198 public void testAfterCreate_NoFeatProps() {
200 pool = new PoolingFeatureImpl();
201 pool.beforeStart(engine);
203 assertFalse(pool.afterCreate(controllerUnknown));
204 assertTrue(managers.isEmpty());
208 public void testBeforeStart() throws Exception {
209 assertFalse(pool.beforeStart(controller1));
210 verify(mgr1).beforeStart();
212 // ensure it's still in the map by re-invoking
213 assertFalse(pool.beforeStart(controller1));
214 verify(mgr1, times(2)).beforeStart();
216 assertFalse(pool.beforeStart(controllerDisabled));
220 public void testAfterStart() {
221 assertFalse(pool.afterStart(controller1));
222 verify(mgr1).afterStart();
224 // ensure it's still in the map by re-invoking
225 assertFalse(pool.afterStart(controller1));
226 verify(mgr1, times(2)).afterStart();
228 assertFalse(pool.afterStart(controllerDisabled));
232 public void testBeforeStop() {
233 assertFalse(pool.beforeStop(controller1));
234 verify(mgr1).beforeStop();
236 // ensure it's still in the map by re-invoking
237 assertFalse(pool.beforeStop(controller1));
238 verify(mgr1, times(2)).beforeStop();
240 assertFalse(pool.beforeStop(controllerDisabled));
244 public void testAfterStop() {
245 assertFalse(pool.afterStop(controller1));
246 verify(mgr1).afterStop();
248 assertFalse(pool.afterStop(controllerDisabled));
250 // count should be unchanged
251 verify(mgr1).afterStop();
255 public void testAfterHalt() {
256 assertFalse(pool.afterHalt(controller1));
257 assertFalse(pool.afterHalt(controller1));
259 verify(mgr1, never()).afterStop();
261 assertFalse(pool.afterStop(controllerDisabled));
265 public void testAfterShutdown() {
266 assertFalse(pool.afterShutdown(controller1));
267 assertFalse(pool.afterShutdown(controller1));
269 verify(mgr1, never()).afterStop();
271 assertFalse(pool.afterStop(controllerDisabled));
275 public void testBeforeLock() {
276 assertFalse(pool.beforeLock(controller1));
277 verify(mgr1).beforeLock();
279 // ensure it's still in the map by re-invoking
280 assertFalse(pool.beforeLock(controller1));
281 verify(mgr1, times(2)).beforeLock();
283 assertFalse(pool.beforeLock(controllerDisabled));
287 public void testAfterUnlock() {
288 assertFalse(pool.afterUnlock(controller1));
289 verify(mgr1).afterUnlock();
291 // ensure it's still in the map by re-invoking
292 assertFalse(pool.afterUnlock(controller1));
293 verify(mgr1, times(2)).afterUnlock();
295 assertFalse(pool.afterUnlock(controllerDisabled));
299 public void testBeforeOffer() {
300 assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
301 verify(mgr1).beforeOffer(TOPIC1, EVENT1);
303 // ensure that the args were captured
304 pool.beforeInsert(drools1, OBJECT1);
305 verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
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);
312 // ensure that the new args were captured
313 pool.beforeInsert(drools1, OBJECT2);
314 verify(mgr1).beforeInsert(TOPIC2, OBJECT2);
317 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
321 public void testBeforeOffer_NotFound() {
322 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
326 public void testBeforeOffer_MgrTrue() {
328 // manager will return true
329 when(mgr1.beforeOffer(any(), any())).thenReturn(true);
331 assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
332 verify(mgr1).beforeOffer(TOPIC1, EVENT1);
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);
338 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
342 public void testBeforeInsert() {
343 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
344 assertFalse(pool.beforeInsert(drools1, OBJECT1));
345 verify(mgr1).beforeInsert(TOPIC1, OBJECT1);
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);
352 pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
353 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
357 public void testBeforeInsert_NoArgs() {
359 // call beforeInsert without beforeOffer
360 assertFalse(pool.beforeInsert(drools1, OBJECT1));
361 verify(mgr1, never()).beforeInsert(any(), any());
363 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
364 verify(mgr1, never()).beforeInsert(any(), any());
368 public void testBeforeInsert_ArgEx() {
369 // generate exception
370 pool = new PoolingFeatureImpl() {
372 protected PolicyController getController(DroolsController droolsController) {
373 throw new IllegalArgumentException();
377 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
378 assertFalse(pool.beforeInsert(drools1, OBJECT1));
379 verify(mgr1, never()).beforeInsert(any(), any());
383 public void testBeforeInsert_StateEx() {
384 // generate exception
385 pool = new PoolingFeatureImpl() {
387 protected PolicyController getController(DroolsController droolsController) {
388 throw new IllegalStateException();
392 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
393 assertFalse(pool.beforeInsert(drools1, OBJECT1));
394 verify(mgr1, never()).beforeInsert(any(), any());
398 public void testBeforeInsert_NullController() {
400 // return null controller
401 pool = new PoolingFeatureImpl() {
403 protected PolicyController getController(DroolsController droolsController) {
408 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
409 assertFalse(pool.beforeInsert(drools1, OBJECT1));
410 verify(mgr1, never()).beforeInsert(any(), any());
414 public void testBeforeInsert_NotFound() {
416 pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
417 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
421 public void testAfterOffer() {
422 // this will create OfferArgs
423 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
425 // this should clear them
426 assertFalse(pool.afterOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2, true));
428 assertFalse(pool.beforeInsert(drools1, OBJECT1));
429 verify(mgr1, never()).beforeInsert(any(), any());
432 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
436 public void testDoManager() throws Exception {
437 assertFalse(pool.beforeStart(controller1));
438 verify(mgr1).beforeStart();
440 // ensure it's still in the map by re-invoking
441 assertFalse(pool.beforeStart(controller1));
442 verify(mgr1, times(2)).beforeStart();
445 // different controller
446 assertFalse(pool.beforeStart(controller2));
447 verify(mgr2).beforeStart();
449 // ensure it's still in the map by re-invoking
450 assertFalse(pool.beforeStart(controller2));
451 verify(mgr2, times(2)).beforeStart();
454 assertFalse(pool.beforeStart(controllerDisabled));
458 public void testDoManager_NotFound() {
459 assertFalse(pool.beforeStart(controllerDisabled));
462 @Test(expected = RuntimeException.class)
463 public void testDoManager_Ex() throws Exception {
465 // generate exception
466 doThrow(new RuntimeException()).when(mgr1).beforeStart();
468 pool.beforeStart(controller1);
471 private Properties initProperties() {
472 Properties props = new Properties();
474 initProperties(props, "A", 0);
475 initProperties(props, "B", 1);
476 initProperties(props, "Exception", 2);
478 props.setProperty("pooling.controllerDisabled.enabled", "false");
480 props.setProperty("pooling.controllerException.offline.queue.limit", "INVALID NUMBER");
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));
500 * Feature with overrides.
502 private class PoolingFeatureImpl extends PoolingFeature {
505 protected Properties getProperties(String featName) {
506 if (PoolingProperties.FEATURE_NAME.equals(featName)) {
509 throw new IllegalArgumentException("unknown feature name");
514 protected PoolingManagerImpl makeManager(String host, PolicyController controller, PoolingProperties props,
515 CountDownLatch activeLatch) {
517 PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
519 managers.add(Pair.of(mgr, props));
525 protected PolicyController getController(DroolsController droolsController) {
526 if (droolsController == drools1) {
528 } else if (droolsController == drools2) {
530 } else if (droolsController == droolsDisabled) {
531 return controllerDisabled;
533 throw new IllegalArgumentException("unknown drools controller");
538 protected List<TopicSource> initTopicSources(Properties props) {
539 return Collections.emptyList();
543 protected List<TopicSink> initTopicSinks(Properties props) {
544 return Collections.emptyList();