2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018 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.drools.pooling;
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.mockito.ArgumentMatchers.any;
28 import static org.mockito.Mockito.doThrow;
29 import static org.mockito.Mockito.mock;
30 import static org.mockito.Mockito.never;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Properties;
37 import org.junit.AfterClass;
38 import org.junit.Before;
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.onap.policy.drools.controller.DroolsController;
42 import org.onap.policy.drools.event.comm.Topic.CommInfrastructure;
43 import org.onap.policy.drools.pooling.PoolingFeature.Factory;
44 import org.onap.policy.drools.system.PolicyController;
45 import org.onap.policy.drools.system.PolicyEngine;
46 import org.onap.policy.drools.utils.Pair;
48 public class PoolingFeatureTest {
50 private static final String CONTROLLER1 = "controllerA";
51 private static final String CONTROLLER2 = "controllerB";
52 private static final String CONTROLLER_DISABLED = "controllerDisabled";
53 private static final String CONTROLLER_EX = "controllerException";
54 private static final String CONTROLLER_UNKNOWN = "controllerUnknown";
56 private static final String TOPIC1 = "topic.one";
57 private static final String TOPIC2 = "topic.two";
59 private static final String EVENT1 = "event.one";
60 private static final String EVENT2 = "event.two";
62 private static final Object OBJECT1 = new Object();
63 private static final Object OBJECT2 = new Object();
66 * Saved from PoolingFeature and restored on exit from this test class.
68 private static Factory saveFactory;
70 private Properties props;
71 private PolicyEngine engine;
72 private PolicyController controller1;
73 private PolicyController controller2;
74 private PolicyController controllerDisabled;
75 private PolicyController controllerException;
76 private PolicyController controllerUnknown;
77 private DroolsController drools1;
78 private DroolsController drools2;
79 private DroolsController droolsDisabled;
80 private List<Pair<PoolingManagerImpl, PoolingProperties>> managers;
81 private PoolingManagerImpl mgr1;
82 private PoolingManagerImpl mgr2;
83 private Factory factory;
85 private PoolingFeature pool;
89 public static void setUpBeforeClass() {
90 saveFactory = PoolingFeature.getFactory();
94 public static void tearDownAfterClass() {
95 PoolingFeature.setFactory(saveFactory);
99 public void setUp() throws Exception {
100 props = initProperties();
101 engine = mock(PolicyEngine.class);
102 factory = mock(Factory.class);
103 controller1 = mock(PolicyController.class);
104 controller2 = mock(PolicyController.class);
105 controllerDisabled = mock(PolicyController.class);
106 controllerException = mock(PolicyController.class);
107 controllerUnknown = mock(PolicyController.class);
108 drools1 = mock(DroolsController.class);
109 drools2 = mock(DroolsController.class);
110 droolsDisabled = mock(DroolsController.class);
111 managers = new LinkedList<>();
113 PoolingFeature.setFactory(factory);
115 when(controller1.getName()).thenReturn(CONTROLLER1);
116 when(controller2.getName()).thenReturn(CONTROLLER2);
117 when(controllerDisabled.getName()).thenReturn(CONTROLLER_DISABLED);
118 when(controllerException.getName()).thenReturn(CONTROLLER_EX);
119 when(controllerUnknown.getName()).thenReturn(CONTROLLER_UNKNOWN);
121 when(factory.getProperties(PoolingProperties.FEATURE_NAME)).thenReturn(props);
122 when(factory.getController(drools1)).thenReturn(controller1);
123 when(factory.getController(drools2)).thenReturn(controller2);
124 when(factory.getController(droolsDisabled)).thenReturn(controllerDisabled);
126 when(factory.makeManager(any(), any(), any())).thenAnswer(args -> {
127 PoolingProperties props = args.getArgument(2);
129 PoolingManagerImpl mgr = mock(PoolingManagerImpl.class);
131 managers.add(new Pair<>(mgr, props));
136 pool = new PoolingFeature();
138 pool.beforeStart(engine);
140 pool.afterCreate(controller1);
141 pool.afterCreate(controller2);
143 mgr1 = managers.get(0).first();
144 mgr2 = managers.get(1).first();
149 assertEquals(2, managers.size());
153 public void testGetHost() {
154 String host = pool.getHost();
157 // create another and ensure it generates another host name
158 pool = new PoolingFeature();
159 String host2 = pool.getHost();
160 assertNotNull(host2);
162 assertTrue(!host.equals(host2));
166 public void testGetSequenceNumber() {
167 assertEquals(0, pool.getSequenceNumber());
171 public void testBeforeStartEngine() {
172 pool = new PoolingFeature();
174 assertFalse(pool.beforeStart(engine));
178 public void testAfterCreate() {
180 pool = new PoolingFeature();
181 pool.beforeStart(engine);
183 assertFalse(pool.afterCreate(controller1));
184 assertEquals(1, managers.size());
187 assertFalse(pool.afterCreate(controller1));
188 assertEquals(1, managers.size());
191 assertFalse(pool.afterCreate(controller2));
192 assertEquals(2, managers.size());
196 public void testAfterCreate_NotEnabled() {
198 pool = new PoolingFeature();
199 pool.beforeStart(engine);
201 assertFalse(pool.afterCreate(controllerDisabled));
202 assertTrue(managers.isEmpty());
205 @Test(expected = PoolingFeatureRtException.class)
206 public void testAfterCreate_PropertyEx() {
208 pool = new PoolingFeature();
209 pool.beforeStart(engine);
211 pool.afterCreate(controllerException);
214 @Test(expected = PoolingFeatureRtException.class)
215 public void testAfterCreate_NoProps() {
216 pool = new PoolingFeature();
218 // did not perform globalInit, which is an error
220 pool.afterCreate(controller1);
224 public void testAfterCreate_NoFeatProps() {
226 pool = new PoolingFeature();
227 pool.beforeStart(engine);
229 assertFalse(pool.afterCreate(controllerUnknown));
230 assertTrue(managers.isEmpty());
234 public void testBeforeStart() throws Exception {
235 assertFalse(pool.beforeStart(controller1));
236 verify(mgr1).beforeStart();
238 // ensure it's still in the map by re-invoking
239 assertFalse(pool.beforeStart(controller1));
240 verify(mgr1, times(2)).beforeStart();
242 assertFalse(pool.beforeStart(controllerDisabled));
246 public void testAfterStart() {
247 assertFalse(pool.afterStart(controller1));
248 verify(mgr1).afterStart();
250 // ensure it's still in the map by re-invoking
251 assertFalse(pool.afterStart(controller1));
252 verify(mgr1, times(2)).afterStart();
254 assertFalse(pool.afterStart(controllerDisabled));
258 public void testBeforeStop() {
259 assertFalse(pool.beforeStop(controller1));
260 verify(mgr1).beforeStop();
262 // ensure it's still in the map by re-invoking
263 assertFalse(pool.beforeStop(controller1));
264 verify(mgr1, times(2)).beforeStop();
266 assertFalse(pool.beforeStop(controllerDisabled));
270 public void testAfterStop() {
271 assertFalse(pool.afterStop(controller1));
272 verify(mgr1).afterStop();
274 // ensure it has been removed from the map by re-invoking
275 assertFalse(pool.afterStop(controller1));
277 // count should be unchanged
278 verify(mgr1).afterStop();
280 assertFalse(pool.afterStop(controllerDisabled));
284 public void testBeforeLock() {
285 assertFalse(pool.beforeLock(controller1));
286 verify(mgr1).beforeLock();
288 // ensure it's still in the map by re-invoking
289 assertFalse(pool.beforeLock(controller1));
290 verify(mgr1, times(2)).beforeLock();
292 assertFalse(pool.beforeLock(controllerDisabled));
296 public void testAfterUnlock() {
297 assertFalse(pool.afterUnlock(controller1));
298 verify(mgr1).afterUnlock();
300 // ensure it's still in the map by re-invoking
301 assertFalse(pool.afterUnlock(controller1));
302 verify(mgr1, times(2)).afterUnlock();
304 assertFalse(pool.afterUnlock(controllerDisabled));
308 public void testBeforeOffer() {
309 assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
310 verify(mgr1).beforeOffer(CommInfrastructure.UEB, TOPIC1, EVENT1);
312 // ensure that the args were captured
313 pool.beforeInsert(drools1, OBJECT1);
314 verify(mgr1).beforeInsert(CommInfrastructure.UEB, TOPIC1, EVENT1, OBJECT1);
317 // ensure it's still in the map by re-invoking
318 assertFalse(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
319 verify(mgr1).beforeOffer(CommInfrastructure.UEB, TOPIC2, EVENT2);
321 // ensure that the new args were captured
322 pool.beforeInsert(drools1, OBJECT2);
323 verify(mgr1).beforeInsert(CommInfrastructure.UEB, TOPIC2, EVENT2, OBJECT2);
326 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
330 public void testBeforeOffer_NotFound() {
331 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
335 public void testBeforeOffer_MgrTrue() {
337 // manager will return true
338 when(mgr1.beforeOffer(any(), any(), any())).thenReturn(true);
340 assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1));
341 verify(mgr1).beforeOffer(CommInfrastructure.UEB, TOPIC1, EVENT1);
343 // ensure it's still in the map by re-invoking
344 assertTrue(pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2));
345 verify(mgr1).beforeOffer(CommInfrastructure.UEB, TOPIC2, EVENT2);
347 assertFalse(pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC1, EVENT1));
351 public void testBeforeInsert() {
352 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
353 assertFalse(pool.beforeInsert(drools1, OBJECT1));
354 verify(mgr1).beforeInsert(CommInfrastructure.UEB, TOPIC1, EVENT1, OBJECT1);
356 // ensure it's still in the map by re-invoking
357 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2);
358 assertFalse(pool.beforeInsert(drools1, OBJECT2));
359 verify(mgr1).beforeInsert(CommInfrastructure.UEB, TOPIC2, EVENT2, OBJECT2);
361 pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
362 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
366 public void testBeforeInsert_NoArgs() {
368 // call beforeInsert without beforeOffer
369 assertFalse(pool.beforeInsert(drools1, OBJECT1));
370 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
372 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
373 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
377 public void testBeforeInsert_ArgEx() {
379 // generate exception
380 doThrow(new IllegalArgumentException()).when(factory).getController(any());
382 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
383 assertFalse(pool.beforeInsert(drools1, OBJECT1));
384 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
388 public void testBeforeInsert_StateEx() {
390 // generate exception
391 doThrow(new IllegalStateException()).when(factory).getController(any());
393 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
394 assertFalse(pool.beforeInsert(drools1, OBJECT1));
395 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
399 public void testBeforeInsert_NullController() {
401 // return null controller
402 when(factory.getController(any())).thenReturn(null);
404 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
405 assertFalse(pool.beforeInsert(drools1, OBJECT1));
406 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
410 public void testBeforeInsert_NotFound() {
412 pool.beforeOffer(controllerDisabled, CommInfrastructure.UEB, TOPIC2, EVENT2);
413 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
417 public void testAfterOffer() {
418 // this will create OfferArgs
419 pool.beforeOffer(controller1, CommInfrastructure.UEB, TOPIC1, EVENT1);
421 // this should clear them
422 assertFalse(pool.afterOffer(controller1, CommInfrastructure.UEB, TOPIC2, EVENT2, true));
424 assertFalse(pool.beforeInsert(drools1, OBJECT1));
425 verify(mgr1, never()).beforeInsert(any(), any(), any(), any());
428 assertFalse(pool.beforeInsert(droolsDisabled, OBJECT1));
432 public void testDoManager() throws Exception {
433 assertFalse(pool.beforeStart(controller1));
434 verify(mgr1).beforeStart();
436 // ensure it's still in the map by re-invoking
437 assertFalse(pool.beforeStart(controller1));
438 verify(mgr1, times(2)).beforeStart();
441 // different controller
442 assertFalse(pool.beforeStart(controller2));
443 verify(mgr2).beforeStart();
445 // ensure it's still in the map by re-invoking
446 assertFalse(pool.beforeStart(controller2));
447 verify(mgr2, times(2)).beforeStart();
450 assertFalse(pool.beforeStart(controllerDisabled));
454 public void testDoManager_NotFound() {
455 assertFalse(pool.beforeStart(controllerDisabled));
458 @Test(expected = PoolingFeatureRtException.class)
459 public void testDoManager_Ex() throws Exception {
461 // generate exception
462 doThrow(new PoolingFeatureException()).when(mgr1).beforeStart();
464 pool.beforeStart(controller1);
468 public void testDoDeleteManager() {
469 assertFalse(pool.afterStop(controller1));
470 verify(mgr1).afterStop();
472 // ensure it has been removed from the map by re-invoking
473 assertFalse(pool.afterStop(controller1));
475 // count should be unchanged
476 verify(mgr1).afterStop();
479 // different controller
480 assertFalse(pool.afterStop(controller2));
481 verify(mgr2).afterStop();
483 // ensure it has been removed from the map by re-invoking
484 assertFalse(pool.afterStop(controller2));
486 // count should be unchanged
487 verify(mgr2).afterStop();
490 assertFalse(pool.afterStop(controllerDisabled));
494 public void testDoDeleteManager_NotFound() {
495 assertFalse(pool.afterStop(controllerDisabled));
498 @Test(expected = PoolingFeatureRtException.class)
499 public void testDoDeleteManager_Ex() {
501 // generate exception
502 doThrow(new PoolingFeatureRtException()).when(mgr1).afterStop();
504 pool.afterStop(controller1);
507 private Properties initProperties() {
508 Properties props = new Properties();
510 initProperties(props, "A", 0);
511 initProperties(props, "B", 1);
512 initProperties(props, "Exception", 2);
514 props.setProperty("pooling.controllerDisabled.enabled", "false");
516 props.setProperty("pooling.controllerException.offline.queue.limit", "INVALID NUMBER");
521 private void initProperties(Properties props, String suffix, int offset) {
522 props.setProperty("pooling.controller" + suffix + ".topic", "topic." + suffix);
523 props.setProperty("pooling.controller" + suffix + ".enabled", "true");
524 props.setProperty("pooling.controller" + suffix + ".offline.queue.limit", String.valueOf(5 + offset));
525 props.setProperty("pooling.controller" + suffix + ".offline.queue.age.milliseconds",
526 String.valueOf(100 + offset));
527 props.setProperty("pooling.controller" + suffix + ".start.heartbeat.milliseconds", String.valueOf(10 + offset));
528 props.setProperty("pooling.controller" + suffix + ".reactivate.milliseconds", String.valueOf(20 + offset));
529 props.setProperty("pooling.controller" + suffix + ".identification.milliseconds", String.valueOf(30 + offset));
530 props.setProperty("pooling.controller" + suffix + ".active.heartbeat.milliseconds",
531 String.valueOf(40 + offset));
532 props.setProperty("pooling.controller" + suffix + ".inter.heartbeat.milliseconds", String.valueOf(50 + offset));