2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2021 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2024 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.system.internal;
24 import static org.assertj.core.api.Assertions.assertThatCode;
25 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
26 import static org.assertj.core.api.Assertions.assertThatThrownBy;
27 import static org.junit.jupiter.api.Assertions.assertEquals;
28 import static org.junit.jupiter.api.Assertions.assertFalse;
29 import static org.junit.jupiter.api.Assertions.assertNotNull;
30 import static org.junit.jupiter.api.Assertions.assertThrows;
31 import static org.junit.jupiter.api.Assertions.assertTrue;
32 import static org.mockito.ArgumentMatchers.any;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.times;
36 import static org.mockito.Mockito.verify;
37 import static org.mockito.Mockito.when;
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.Properties;
42 import java.util.function.BiConsumer;
43 import java.util.function.Consumer;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
47 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
48 import org.onap.policy.common.endpoints.event.comm.TopicSink;
49 import org.onap.policy.common.endpoints.event.comm.TopicSource;
50 import org.onap.policy.common.utils.gson.GsonTestUtils;
51 import org.onap.policy.drools.controller.DroolsController;
52 import org.onap.policy.drools.controller.DroolsControllerFactory;
53 import org.onap.policy.drools.features.PolicyControllerFeatureApi;
54 import org.onap.policy.drools.persistence.SystemPersistence;
55 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
56 import org.onap.policy.drools.system.GsonMgmtTestBuilder;
58 class AggregatedPolicyControllerTest {
60 private static final String AGG_NAME = "agg-name";
61 private static final String SINK_TOPIC1 = "sink-a";
62 private static final String SINK_TOPIC2 = "sink-b";
63 private static final String SOURCE_TOPIC1 = "source-a";
64 private static final String SOURCE_TOPIC2 = "source-b";
66 private static final String EXPECTED = "expected exception";
68 private static final String MY_EVENT = "my-event";
70 private static final String ARTIFACT1 = "artifact-a";
71 private static final String GROUP1 = "group-a";
72 private static final String VERSION1 = "version-a";
74 private static final String ARTIFACT2 = "artifact-b";
75 private static final String GROUP2 = "group-b";
76 private static final String VERSION2 = "version-b";
78 private Properties properties;
79 private TopicEndpoint endpointMgr;
80 private List<TopicSource> sources;
81 private TopicSource source1;
82 private TopicSource source2;
83 private List<TopicSink> sinks;
84 private TopicSink sink1;
85 private TopicSink sink2;
86 private SystemPersistence persist;
87 private DroolsControllerFactory droolsFactory;
88 private DroolsController drools;
89 private DroolsConfiguration config;
90 private List<PolicyControllerFeatureApi> providers;
91 private PolicyControllerFeatureApi prov1;
92 private PolicyControllerFeatureApi prov2;
93 private AggregatedPolicyController apc;
96 * Initializes the object to be tested.
100 properties = new Properties();
102 source1 = mock(TopicSource.class);
103 source2 = mock(TopicSource.class);
104 when(source1.getTopic()).thenReturn(SOURCE_TOPIC1);
105 when(source2.getTopic()).thenReturn(SOURCE_TOPIC2);
107 sink1 = mock(TopicSink.class);
108 sink2 = mock(TopicSink.class);
109 when(sink1.getTopic()).thenReturn(SINK_TOPIC1);
110 when(sink2.getTopic()).thenReturn(SINK_TOPIC2);
112 sources = Arrays.asList(source1, source2);
113 sinks = Arrays.asList(sink1, sink2);
115 endpointMgr = mock(TopicEndpoint.class);
116 when(endpointMgr.addTopicSources(any(Properties.class))).thenReturn(sources);
117 when(endpointMgr.addTopicSinks(any(Properties.class))).thenReturn(sinks);
119 persist = mock(SystemPersistence.class);
121 drools = mock(DroolsController.class);
122 when(drools.start()).thenReturn(true);
123 when(drools.stop()).thenReturn(true);
124 when(drools.offer(any(), any())).thenReturn(true);
125 when(drools.deliver(any(), any())).thenReturn(true);
126 when(drools.lock()).thenReturn(true);
127 when(drools.unlock()).thenReturn(true);
128 when(drools.getArtifactId()).thenReturn(ARTIFACT1);
129 when(drools.getGroupId()).thenReturn(GROUP1);
130 when(drools.getVersion()).thenReturn(VERSION1);
132 config = mock(DroolsConfiguration.class);
133 when(config.getArtifactId()).thenReturn(ARTIFACT2);
134 when(config.getGroupId()).thenReturn(GROUP2);
135 when(config.getVersion()).thenReturn(VERSION2);
137 droolsFactory = mock(DroolsControllerFactory.class);
138 when(droolsFactory.build(any(), any(), any())).thenReturn(drools);
140 prov1 = mock(PolicyControllerFeatureApi.class);
141 prov2 = mock(PolicyControllerFeatureApi.class);
143 providers = Arrays.asList(prov1, prov2);
145 apc = new AggregatedPolicyControllerImpl(AGG_NAME, properties);
150 apc = new AggregatedPolicyController(AGG_NAME, properties);
151 assertNotNull(apc.getDroolsFactory());
152 assertNotNull(apc.getEndpointManager());
153 assertNotNull(apc.getProviders());
154 assertNotNull(apc.getPersistenceManager());
158 void testAggregatedPolicyController_() {
159 verify(persist).storeController(AGG_NAME, properties);
163 void testInitDrools_Ex() {
164 assertThrows(IllegalArgumentException.class, () ->
165 new AggregatedPolicyControllerImpl(AGG_NAME, properties) {
167 protected DroolsControllerFactory getDroolsFactory() {
168 throw new RuntimeException(EXPECTED);
174 void testInitDrools_Error() {
175 assertThrows(IllegalArgumentException.class, () ->
176 new AggregatedPolicyControllerImpl(AGG_NAME, properties) {
178 protected DroolsControllerFactory getDroolsFactory() {
179 throw new LinkageError(EXPECTED);
185 void testUpdateDrools_ConfigVariations() {
187 // config should return same values as current controller
188 when(config.getArtifactId()).thenReturn(ARTIFACT1.toUpperCase());
189 when(config.getGroupId()).thenReturn(GROUP1.toUpperCase());
190 when(config.getVersion()).thenReturn(VERSION1.toUpperCase());
192 assertTrue(apc.updateDrools(config));
194 // number of times store should have been called
197 // invoked once during construction, but shouldn't be invoked during update
198 verify(persist, times(++count)).storeController(any(), any());
201 // different artifact
202 when(config.getArtifactId()).thenReturn(ARTIFACT2);
204 assertTrue(apc.updateDrools(config));
206 // should be invoked during update
207 verify(persist, times(++count)).storeController(any(), any());
211 when(config.getArtifactId()).thenReturn(ARTIFACT1);
212 when(config.getGroupId()).thenReturn(GROUP2);
214 assertTrue(apc.updateDrools(config));
216 // should be invoked during update
217 verify(persist, times(++count)).storeController(any(), any());
221 when(config.getGroupId()).thenReturn(GROUP1);
222 when(config.getVersion()).thenReturn(VERSION2);
224 assertTrue(apc.updateDrools(config));
226 // should be invoked during update
227 verify(persist, times(++count)).storeController(any(), any());
233 when(drools.lock()).thenThrow(new IllegalArgumentException(EXPECTED));
234 when(drools.unlock()).thenThrow(new IllegalArgumentException(EXPECTED));
236 assertFalse(apc.updateDrools(config));
240 void testUpdateDrools_LockVariations() {
242 apc.updateDrools(config);
243 verify(drools, never()).lock();
244 verify(drools).unlock();
249 apc.updateDrools(config);
250 verify(drools, times(2)).lock();
251 verify(drools, never()).unlock();
255 void testUpdateDrools_AliveVariations() {
257 apc.updateDrools(config);
258 verify(drools, never()).start();
259 verify(drools).stop();
264 apc.updateDrools(config);
265 verify(drools, times(2)).start();
266 verify(drools, never()).stop();
270 void testSerialize() {
271 GsonTestUtils gson = new GsonMgmtTestBuilder().addDroolsControllerMock().addTopicSinkMock().addTopicSourceMock()
273 assertThatCode(() -> gson.compareGson(apc, AggregatedPolicyControllerTest.class)).doesNotThrowAnyException();
278 assertEquals(AGG_NAME, apc.getName());
283 // arrange for first provider to throw exceptions
284 when(prov1.beforeStart(any())).thenThrow(new RuntimeException(EXPECTED));
285 when(prov1.afterStart(any())).thenThrow(new RuntimeException(EXPECTED));
287 // arrange for first sink to throw exception
288 when(sink1.start()).thenThrow(new RuntimeException(EXPECTED));
291 assertTrue(apc.start());
293 assertTrue(apc.isAlive());
295 verify(prov1).beforeStart(apc);
296 verify(prov2).beforeStart(apc);
298 verify(source1).register(apc);
299 verify(source2).register(apc);
301 verify(sink1).start();
302 verify(sink2).start();
304 verify(prov1).afterStart(apc);
305 verify(prov2).afterStart(apc);
308 (prov, flag) -> when(prov.beforeStart(apc)).thenReturn(flag),
309 (prov, flag) -> when(prov.afterStart(apc)).thenReturn(flag),
311 prov -> verify(prov).beforeStart(apc),
312 () -> verify(source1).register(apc),
313 prov -> verify(prov).afterStart(apc));
317 void testStart_AlreadyStarted() {
321 assertTrue(apc.start());
323 assertTrue(apc.isAlive());
325 // these should now have been called twice
326 verify(prov1, times(2)).beforeStart(apc);
327 verify(prov2, times(2)).beforeStart(apc);
329 // these should still only have been called once
330 verify(source1).register(apc);
331 verify(sink1).start();
332 verify(prov1).afterStart(apc);
336 void testStart_Locked() {
340 assertThatIllegalStateException().isThrownBy(() -> apc.start());
342 assertFalse(apc.isAlive());
344 // should call beforeStart(), but stop after that
345 verify(prov1).beforeStart(apc);
346 verify(prov2).beforeStart(apc);
348 verify(source1, never()).register(apc);
349 verify(sink1, never()).start();
350 verify(prov1, never()).afterStart(apc);
355 // arrange for first provider to throw exceptions
356 when(prov1.beforeStop(any())).thenThrow(new RuntimeException(EXPECTED));
357 when(prov1.afterStop(any())).thenThrow(new RuntimeException(EXPECTED));
363 assertTrue(apc.stop());
365 assertFalse(apc.isAlive());
367 verify(prov1).beforeStop(apc);
368 verify(prov2).beforeStop(apc);
370 verify(source1).unregister(apc);
371 verify(source2).unregister(apc);
373 verify(prov1).afterStop(apc);
374 verify(prov2).afterStop(apc);
376 // ensure no shutdown operations were called
377 verify(prov1, never()).beforeShutdown(apc);
378 verify(droolsFactory, never()).shutdown(drools);
379 verify(prov2, never()).afterShutdown(apc);
382 (prov, flag) -> when(prov.beforeStop(apc)).thenReturn(flag),
383 (prov, flag) -> when(prov.afterStop(apc)).thenReturn(flag),
388 prov -> verify(prov).beforeStop(apc),
389 () -> verify(source1).unregister(apc),
390 prov -> verify(prov).afterStop(apc));
394 void testStop_AlreadyStopped() {
399 assertTrue(apc.stop());
402 verify(prov1, times(2)).beforeStop(apc);
403 verify(prov2, times(2)).beforeStop(apc);
405 // should NOT be called again
406 verify(source1).unregister(apc);
407 verify(prov1).afterStop(apc);
411 void testShutdown() {
412 // arrange for first provider to throw exceptions
413 when(prov1.beforeShutdown(any())).thenThrow(new RuntimeException(EXPECTED));
414 when(prov1.afterShutdown(any())).thenThrow(new RuntimeException(EXPECTED));
422 verify(prov1).beforeShutdown(apc);
423 verify(prov2).beforeShutdown(apc);
425 assertFalse(apc.isAlive());
427 verify(prov1).afterStop(apc);
428 verify(prov2).afterStop(apc);
430 verify(droolsFactory).shutdown(drools);
432 verify(prov1).afterShutdown(apc);
433 verify(prov2).afterShutdown(apc);
435 // ensure no halt operation was called
436 verify(prov1, never()).beforeHalt(apc);
439 (prov, flag) -> when(prov.beforeShutdown(apc)).thenReturn(flag),
440 (prov, flag) -> when(prov.afterShutdown(apc)).thenReturn(flag),
445 prov -> verify(prov).beforeShutdown(apc),
446 () -> verify(source1).unregister(apc),
447 prov -> verify(prov).afterShutdown(apc));
452 // arrange for first provider to throw exceptions
453 when(prov1.beforeHalt(any())).thenThrow(new RuntimeException(EXPECTED));
454 when(prov1.afterHalt(any())).thenThrow(new RuntimeException(EXPECTED));
462 verify(prov1).beforeHalt(apc);
463 verify(prov2).beforeHalt(apc);
465 assertFalse(apc.isAlive());
467 verify(prov1).beforeStop(apc);
468 verify(prov2).beforeStop(apc);
470 verify(droolsFactory).destroy(drools);
471 verify(persist).deleteController(AGG_NAME);
473 verify(prov1).afterHalt(apc);
474 verify(prov2).afterHalt(apc);
476 // ensure no shutdown operation was called
477 verify(prov1, never()).beforeShutdown(apc);
480 (prov, flag) -> when(prov.beforeHalt(apc)).thenReturn(flag),
481 (prov, flag) -> when(prov.afterHalt(apc)).thenReturn(flag),
486 prov -> verify(prov).beforeHalt(apc),
487 () -> verify(source1).unregister(apc),
488 prov -> verify(prov).afterHalt(apc));
492 void testOnTopicEvent() {
493 // arrange for first provider to throw exceptions
494 when(prov1.beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT))
495 .thenThrow(new RuntimeException(EXPECTED));
496 when(prov1.afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true))
497 .thenThrow(new RuntimeException(EXPECTED));
503 apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
505 verify(prov1).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
506 verify(prov2).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
508 verify(drools).offer(SOURCE_TOPIC1, MY_EVENT);
510 verify(prov1).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true);
511 verify(prov2).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true);
514 (prov, flag) -> when(prov.beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT))
516 (prov, flag) -> when(
517 prov.afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true))
521 apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
523 prov -> verify(prov).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT),
524 () -> verify(drools).offer(SOURCE_TOPIC1, MY_EVENT),
525 prov -> verify(prov).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true));
529 void testOnTopicEvent_Locked() {
536 apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
538 verify(prov1, never()).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
539 verify(prov2, never()).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
541 // never gets this far
542 verify(drools, never()).offer(SOURCE_TOPIC1, MY_EVENT);
543 verify(prov1, never()).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true);
547 void testOnTopicEvent_NotStarted() {
550 apc.onTopicEvent(CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
552 verify(prov1, never()).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
553 verify(prov2, never()).beforeOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT);
555 // never gets this far
556 verify(drools, never()).offer(SOURCE_TOPIC1, MY_EVENT);
557 verify(prov1, never()).afterOffer(apc, CommInfrastructure.NOOP, SOURCE_TOPIC1, MY_EVENT, true);
561 void testDeliver_testInitSinks() {
562 // arrange for first provider to throw exceptions
563 when(prov1.beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT))
564 .thenThrow(new RuntimeException(EXPECTED));
565 when(prov1.afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true))
566 .thenThrow(new RuntimeException(EXPECTED));
572 assertTrue(apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT));
574 verify(prov1).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT);
575 verify(prov2).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT);
577 verify(drools).deliver(sink1, MY_EVENT);
578 verify(drools, never()).deliver(sink2, MY_EVENT);
580 verify(prov1).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true);
581 verify(prov2).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true);
583 // offer to the other topic
584 assertTrue(apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC2, MY_EVENT));
586 // now both topics should show one message delivered
587 verify(drools).deliver(sink1, MY_EVENT);
588 verify(drools).deliver(sink2, MY_EVENT);
591 (prov, flag) -> when(prov.beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT))
593 (prov, flag) -> when(
594 prov.afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true))
598 apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT);
600 prov -> verify(prov).beforeDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT),
601 () -> verify(drools).deliver(sink1, MY_EVENT),
602 prov -> verify(prov).afterDeliver(apc, CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT, true));
606 void testDeliver_NullTopic() {
607 assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure(null, MY_EVENT));
611 void testDeliver_EmptyTopic() {
612 assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure("", MY_EVENT));
616 void testDeliver_NullEvent() {
617 assertThrows(IllegalArgumentException.class, () -> validateDeliverFailure(SINK_TOPIC1, null));
621 void testDeliver_NotStarted() {
623 assertThrows(IllegalStateException.class, () -> apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT));
627 void testDeliver_Locked() {
630 assertThrows(IllegalStateException.class, () -> apc.deliver(CommInfrastructure.NOOP, SINK_TOPIC1, MY_EVENT));
634 void testDeliver_UnknownTopic() {
636 assertThrows(IllegalArgumentException.class,
637 () -> apc.deliver(CommInfrastructure.NOOP, "unknown-topic", MY_EVENT));
642 assertFalse(apc.isAlive());
645 assertTrue(apc.isAlive());
648 assertFalse(apc.isAlive());
653 // arrange for first provider to throw exceptions
654 when(prov1.beforeLock(any())).thenThrow(new RuntimeException(EXPECTED));
655 when(prov1.afterLock(any())).thenThrow(new RuntimeException(EXPECTED));
661 assertTrue(apc.lock());
663 verify(prov1).beforeLock(apc);
664 verify(prov2).beforeLock(apc);
666 assertTrue(apc.isLocked());
668 verify(drools).lock();
670 verify(prov1).afterLock(apc);
671 verify(prov2).afterLock(apc);
674 (prov, flag) -> when(prov.beforeLock(apc)).thenReturn(flag),
675 (prov, flag) -> when(prov.afterLock(apc)).thenReturn(flag),
680 prov -> verify(prov).beforeLock(apc),
681 () -> verify(drools).lock(),
682 prov -> verify(prov).afterLock(apc));
686 void testLock_AlreadyLocked() {
691 assertTrue(apc.lock());
693 // these should be invoked a second time
694 verify(prov1, times(2)).beforeLock(apc);
695 verify(prov2, times(2)).beforeLock(apc);
697 assertTrue(apc.isLocked());
699 // these shouldn't be invoked a second time
700 verify(drools).lock();
701 verify(prov1).afterLock(apc);
706 // arrange for first provider to throw exceptions
707 when(prov1.beforeUnlock(any())).thenThrow(new RuntimeException(EXPECTED));
708 when(prov1.afterUnlock(any())).thenThrow(new RuntimeException(EXPECTED));
715 assertTrue(apc.unlock());
717 verify(prov1).beforeUnlock(apc);
718 verify(prov2).beforeUnlock(apc);
720 assertFalse(apc.isLocked());
722 verify(drools).unlock();
724 verify(prov1).afterUnlock(apc);
725 verify(prov2).afterUnlock(apc);
728 (prov, flag) -> when(prov.beforeUnlock(apc)).thenReturn(flag),
729 (prov, flag) -> when(prov.afterUnlock(apc)).thenReturn(flag),
735 prov -> verify(prov).beforeUnlock(apc),
736 () -> verify(drools).unlock(),
737 prov -> verify(prov).afterUnlock(apc));
741 void testUnlock_NotLocked() {
745 assertTrue(apc.unlock());
747 verify(prov1).beforeUnlock(apc);
748 verify(prov2).beforeUnlock(apc);
750 assertFalse(apc.isLocked());
752 // these shouldn't be invoked
753 verify(drools, never()).unlock();
754 verify(prov1, never()).afterLock(apc);
758 void testIsLocked() {
759 assertFalse(apc.isLocked());
762 assertTrue(apc.isLocked());
765 assertFalse(apc.isLocked());
769 void testGetTopicSources() {
770 assertEquals(sources, apc.getTopicSources());
774 void testGetTopicSinks() {
775 assertEquals(sinks, apc.getTopicSinks());
779 void testGetDrools() {
780 assertEquals(drools, apc.getDrools());
784 void testGetProperties() {
785 assertEquals(properties, apc.getProperties());
789 void testToString() {
790 assertTrue(apc.toString().startsWith("AggregatedPolicyController("));
793 private void validateDeliverFailure(String topic, String event) {
795 apc.deliver(CommInfrastructure.NOOP, topic, event);
799 * Performs an operation that has a beforeXxx method and an afterXxx method. Tries
800 * combinations where beforeXxx and afterXxx return {@code true} and {@code false}.
802 * @param setBefore function to set the return value of a provider's beforeXxx method
803 * @param setAfter function to set the return value of a provider's afterXxx method
804 * @param action invokes the operation
805 * @param verifyBefore verifies that a provider's beforeXxx method was invoked
806 * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
807 * and the afterXxx loop was invoked
808 * @param verifyAfter verifies that a provider's afterXxx method was invoked
810 private void checkBeforeAfter(BiConsumer<PolicyControllerFeatureApi, Boolean> setBefore,
811 BiConsumer<PolicyControllerFeatureApi, Boolean> setAfter, Runnable action,
812 Consumer<PolicyControllerFeatureApi> verifyBefore, Runnable verifyMiddle,
813 Consumer<PolicyControllerFeatureApi> verifyAfter) {
815 checkBeforeAfter_FalseFalse(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter);
816 checkBeforeAfter_FalseTrue(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter);
817 checkBeforeAfter_TrueFalse(setBefore, setAfter, action, verifyBefore, verifyMiddle, verifyAfter);
819 // don't need to test true-true, as it's behavior is a subset of true-false
823 * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the
824 * case where both the beforeXxx and afterXxx methods return {@code false}.
826 * @param setBefore function to set the return value of a provider's beforeXxx method
827 * @param setAfter function to set the return value of a provider's afterXxx method
828 * @param action invokes the operation
829 * @param verifyBefore verifies that a provider's beforeXxx method was invoked
830 * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
831 * and the afterXxx loop was invoked
832 * @param verifyAfter verifies that a provider's afterXxx method was invoked
834 private void checkBeforeAfter_FalseFalse(BiConsumer<PolicyControllerFeatureApi, Boolean> setBefore,
835 BiConsumer<PolicyControllerFeatureApi, Boolean> setAfter, Runnable action,
836 Consumer<PolicyControllerFeatureApi> verifyBefore, Runnable verifyMiddle,
837 Consumer<PolicyControllerFeatureApi> verifyAfter) {
841 // configure for the test
842 setBefore.accept(prov1, false);
843 setBefore.accept(prov2, false);
845 setAfter.accept(prov1, false);
846 setAfter.accept(prov2, false);
851 // verify that various methods were invoked
852 verifyBefore.accept(prov1);
853 verifyBefore.accept(prov2);
857 verifyAfter.accept(prov1);
858 verifyAfter.accept(prov2);
862 * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the
863 * case where the first provider's afterXxx returns {@code true}, while the others
864 * return {@code false}.
866 * @param setBefore function to set the return value of a provider's beforeXxx method
867 * @param setAfter function to set the return value of a provider's afterXxx method
868 * @param action invokes the operation
869 * @param verifyBefore verifies that a provider's beforeXxx method was invoked
870 * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
871 * and the afterXxx loop was invoked
872 * @param verifyAfter verifies that a provider's afterXxx method was invoked
874 private void checkBeforeAfter_FalseTrue(BiConsumer<PolicyControllerFeatureApi, Boolean> setBefore,
875 BiConsumer<PolicyControllerFeatureApi, Boolean> setAfter, Runnable action,
876 Consumer<PolicyControllerFeatureApi> verifyBefore, Runnable verifyMiddle,
877 Consumer<PolicyControllerFeatureApi> verifyAfter) {
881 // configure for the test
882 setBefore.accept(prov1, false);
883 setBefore.accept(prov2, false);
885 setAfter.accept(prov1, true);
886 setAfter.accept(prov2, false);
891 // verify that various methods were invoked
892 verifyBefore.accept(prov1);
893 verifyBefore.accept(prov2);
897 verifyAfter.accept(prov1);
898 assertThatThrownBy(() -> verifyAfter.accept(prov2)).isInstanceOf(AssertionError.class);
902 * Performs an operation that has a beforeXxx method and an afterXxx method. Tries the
903 * case where the first provider's beforeXxx returns {@code true}, while the others
904 * return {@code false}.
906 * @param setBefore function to set the return value of a provider's beforeXxx method
907 * @param setAfter function to set the return value of a provider's afterXxx method
908 * @param action invokes the operation
909 * @param verifyBefore verifies that a provider's beforeXxx method was invoked
910 * @param verifyMiddle verifies that the action occurring between the beforeXxx loop
911 * and the afterXxx loop was invoked
912 * @param verifyAfter verifies that a provider's afterXxx method was invoked
914 private void checkBeforeAfter_TrueFalse(BiConsumer<PolicyControllerFeatureApi, Boolean> setBefore,
915 BiConsumer<PolicyControllerFeatureApi, Boolean> setAfter, Runnable action,
916 Consumer<PolicyControllerFeatureApi> verifyBefore, Runnable verifyMiddle,
917 Consumer<PolicyControllerFeatureApi> verifyAfter) {
921 // configure for the test
922 setBefore.accept(prov1, true);
923 setBefore.accept(prov2, false);
925 setAfter.accept(prov1, false);
926 setAfter.accept(prov2, false);
931 // verify that various methods were invoked
932 verifyBefore.accept(prov1);
934 // remaining methods should not have been invoked
935 assertThatThrownBy(() -> verifyBefore.accept(prov2)).isInstanceOf(AssertionError.class);
937 assertThatThrownBy(verifyMiddle::run).isInstanceOf(AssertionError.class);
939 assertThatThrownBy(() -> verifyAfter.accept(prov1)).isInstanceOf(AssertionError.class);
940 assertThatThrownBy(() -> verifyAfter.accept(prov2)).isInstanceOf(AssertionError.class);
944 * Controller with overrides.
946 private class AggregatedPolicyControllerImpl extends AggregatedPolicyController {
948 public AggregatedPolicyControllerImpl(String name, Properties properties) {
949 super(name, properties);
953 protected SystemPersistence getPersistenceManager() {
958 protected TopicEndpoint getEndpointManager() {
963 protected DroolsControllerFactory getDroolsFactory() {
964 return droolsFactory;
968 protected List<PolicyControllerFeatureApi> getProviders() {