2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018-2020 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;
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
26 import static org.junit.jupiter.api.Assertions.assertEquals;
27 import static org.junit.jupiter.api.Assertions.assertNotNull;
28 import static org.junit.jupiter.api.Assertions.assertSame;
29 import static org.mockito.ArgumentMatchers.any;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.never;
32 import static org.mockito.Mockito.times;
33 import static org.mockito.Mockito.verify;
34 import static org.mockito.Mockito.when;
35 import static org.onap.policy.drools.properties.DroolsPropertyConstants.PROPERTY_CONTROLLER_TYPE;
37 import java.util.Arrays;
38 import java.util.Collections;
39 import java.util.Comparator;
40 import java.util.List;
41 import java.util.Properties;
42 import org.junit.jupiter.api.BeforeEach;
43 import org.junit.jupiter.api.Test;
44 import org.onap.policy.common.utils.gson.GsonTestUtils;
45 import org.onap.policy.drools.controller.DroolsController;
46 import org.onap.policy.drools.controller.internal.NullDroolsController;
47 import org.onap.policy.drools.features.DroolsControllerFeatureApi;
48 import org.onap.policy.drools.features.PolicyControllerFeatureApi;
49 import org.onap.policy.drools.protocol.coders.TopicCoderFilterConfiguration;
50 import org.onap.policy.drools.protocol.configuration.DroolsConfiguration;
51 import org.onap.policy.drools.system.internal.AggregatedPolicyController;
53 class PolicyControllerFactoryTest {
54 private static final String POLICY_CONTROLLER_BUILDER_TAG = "PolicyControllerFactoryTest";
56 private static final String MY_NAME = "my-name-a";
57 private static final String MY_NAME2 = "my-name-b";
59 private static final String ARTIFACT1 = "artifact-a";
60 private static final String GROUP1 = "group-a";
61 private static final String VERSION1 = "version-a";
63 private static final String ARTIFACT2 = "artifact-b";
64 private static final String GROUP2 = "group-b";
65 private static final String VERSION2 = "version-b";
67 private static final String FEATURE1 = "feature-a";
68 private static final String FEATURE2 = "feature-b";
70 private PolicyController controller;
71 private PolicyController controller2;
72 private Properties properties;
73 private DroolsController drools;
74 private DroolsController drools2;
75 private DroolsConfiguration config;
76 private PolicyControllerFeatureApi feature1;
77 private PolicyControllerFeatureApi feature2;
78 private List<PolicyControllerFeatureApi> providers;
79 private IndexedPolicyControllerFactory ipc;
82 * Initializes the object to be tested.
86 controller = mock(PolicyController.class);
87 controller2 = mock(PolicyController.class);
88 properties = new Properties();
89 drools = mock(DroolsController.class);
90 drools2 = mock(DroolsController.class);
91 config = mock(DroolsConfiguration.class);
92 feature1 = mock(PolicyControllerFeatureApi.class);
93 feature2 = mock(PolicyControllerFeatureApi.class);
94 providers = Arrays.asList(feature1, feature2);
96 when(feature1.getName()).thenReturn(FEATURE1);
97 when(feature2.getName()).thenReturn(FEATURE2);
99 when(drools.getArtifactId()).thenReturn(ARTIFACT1);
100 when(drools.getGroupId()).thenReturn(GROUP1);
101 when(drools.getVersion()).thenReturn(VERSION1);
103 when(drools2.getArtifactId()).thenReturn(ARTIFACT2);
104 when(drools2.getGroupId()).thenReturn(GROUP2);
105 when(drools2.getVersion()).thenReturn(VERSION2);
107 when(controller.getName()).thenReturn(MY_NAME);
108 when(controller.getDrools()).thenReturn(drools);
109 when(controller.updateDrools(any())).thenReturn(true);
111 when(controller2.getName()).thenReturn(MY_NAME2);
112 when(controller2.getDrools()).thenReturn(drools2);
113 when(controller2.updateDrools(any())).thenReturn(true);
115 ipc = new IndexedPolicyControllerFactoryImpl();
120 // use a REAL object instead of an Impl
121 ipc = new IndexedPolicyControllerFactory();
122 assertNotNull(ipc.getProviders());
127 assertEquals(controller, ipc.build(MY_NAME, properties));
129 // re-build - should not create another one
130 assertEquals(controller, ipc.build(MY_NAME, properties));
134 when(drools.isBrained()).thenReturn(true);
135 ipc.build(MY_NAME, properties);
139 void testSerialize() {
140 assertEquals(controller, ipc.build(MY_NAME, properties));
142 new GsonTestUtils().compareGson(ipc, PolicyControllerFactoryTest.class);
146 void testPatchStringDroolsConfiguration() {
147 // unknown controller
148 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(MY_NAME, config));
151 * Build controller to be used by remaining tests.
153 ipc.build(MY_NAME, properties);
156 String nullName = null;
157 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(nullName, config));
160 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch("", config));
163 ipc.patch(MY_NAME, config);
164 verify(controller).updateDrools(config);
166 // create a factory whose get() method returns null
167 ipc = new IndexedPolicyControllerFactory() {
169 public PolicyController get(String name) {
173 ipc.build(MY_NAME, properties);
174 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(MY_NAME, config));
178 void testPatchPolicyControllerDroolsConfiguration() {
179 ipc.patch(controller, config);
180 verify(controller).updateDrools(config);
183 PolicyController nullCtlr = null;
184 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(nullCtlr, config));
187 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(controller, null));
190 when(drools.isBrained()).thenReturn(true);
191 ipc.patch(controller, config);
194 when(controller.updateDrools(config)).thenReturn(false);
195 assertThatIllegalArgumentException().isThrownBy(() -> ipc.patch(controller, config));
199 void testShutdownString() {
201 String nullName = null;
202 assertThatIllegalArgumentException().isThrownBy(() -> ipc.shutdown(nullName));
205 assertThatIllegalArgumentException().isThrownBy(() -> ipc.shutdown(""));
207 // unknown controller
208 ipc.shutdown(MY_NAME);
209 verify(controller, never()).shutdown();
212 ipc.build(MY_NAME, properties);
213 ipc.shutdown(MY_NAME);
214 verify(controller).shutdown();
218 void testShutdownPolicyController() {
219 ipc.build(MY_NAME, properties);
221 ipc.shutdown(controller);
223 verify(controller).shutdown();
225 // should no longer be managed
226 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
230 void testShutdown() {
231 ipc.build(MY_NAME, properties);
232 ipc.build(MY_NAME2, properties);
236 verify(controller).shutdown();
237 verify(controller2).shutdown();
239 // should no longer be managed
240 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
241 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME2));
245 void testUnmanage() {
246 ipc.build(MY_NAME, properties);
247 ipc.build(MY_NAME2, properties);
249 ipc.shutdown(MY_NAME);
251 verify(controller).shutdown();
252 verify(controller2, never()).shutdown();
254 // should no longer be managed
255 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
257 // should still be managed
258 assertEquals(controller2, ipc.get(MY_NAME2));
261 PolicyController nullCtlr = null;
262 assertThatIllegalArgumentException().isThrownBy(() -> ipc.shutdown(nullCtlr));
264 // unknown controller
265 ipc.shutdown(controller);
266 verify(controller, times(2)).shutdown();
270 void testDestroyString() {
272 String nullName = null;
273 assertThatIllegalArgumentException().isThrownBy(() -> ipc.destroy(nullName));
276 assertThatIllegalArgumentException().isThrownBy(() -> ipc.destroy(""));
278 // unknown controller
279 ipc.destroy(MY_NAME);
280 verify(controller, never()).halt();
283 ipc.build(MY_NAME, properties);
284 ipc.destroy(MY_NAME);
285 verify(controller).halt();
289 void testDestroyPolicyController() {
290 ipc.build(MY_NAME, properties);
292 ipc.destroy(controller);
294 verify(controller).halt();
296 // should no longer be managed
297 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
302 ipc.build(MY_NAME, properties);
303 ipc.build(MY_NAME2, properties);
307 verify(controller).halt();
308 verify(controller2).halt();
310 // should no longer be managed
311 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
312 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME2));
316 void testGetString() {
318 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(MY_NAME));
320 ipc.build(MY_NAME, properties);
321 ipc.build(MY_NAME2, properties);
323 assertEquals(controller, ipc.get(MY_NAME));
324 assertEquals(controller2, ipc.get(MY_NAME2));
327 String nullName = null;
328 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(nullName));
331 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(""));
335 void testGetStringString_testToKey() {
336 // unknown controller
337 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(GROUP1, ARTIFACT1));
339 when(drools.isBrained()).thenReturn(true);
340 when(drools2.isBrained()).thenReturn(true);
342 ipc.build(MY_NAME, properties);
343 ipc.build(MY_NAME2, properties);
345 assertEquals(controller, ipc.get(GROUP1, ARTIFACT1));
346 assertEquals(controller2, ipc.get(GROUP2, ARTIFACT2));
349 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(null, ARTIFACT1));
352 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get("", ARTIFACT1));
355 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(GROUP1, null));
358 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(GROUP1, ""));
362 void testGetDroolsController() {
363 // unknown controller
364 assertThatIllegalStateException().isThrownBy(() -> ipc.get(drools));
366 when(drools.isBrained()).thenReturn(true);
367 when(drools2.isBrained()).thenReturn(true);
369 ipc.build(MY_NAME, properties);
370 ipc.build(MY_NAME2, properties);
372 assertEquals(controller, ipc.get(drools));
373 assertEquals(controller2, ipc.get(drools2));
376 DroolsController nullDrools = null;
377 assertThatIllegalArgumentException().isThrownBy(() -> ipc.get(nullDrools));
381 void testInventory() {
382 ipc.build(MY_NAME, properties);
383 ipc.build(MY_NAME2, properties);
385 List<PolicyController> lst = ipc.inventory();
386 lst.sort(Comparator.comparing(PolicyController::getName));
387 assertEquals(Arrays.asList(controller, controller2), lst);
391 void testGetFeatures() {
392 assertEquals(Arrays.asList(FEATURE1, FEATURE2), ipc.getFeatures());
396 void testGetFeatureProviders() {
397 assertEquals(providers, ipc.getFeatureProviders());
401 void testGetFeatureProvider() {
403 assertThatIllegalArgumentException().isThrownBy(() -> ipc.getFeatureProvider(null));
406 assertThatIllegalArgumentException().isThrownBy(() -> ipc.getFeatureProvider(""));
409 assertThatIllegalArgumentException().isThrownBy(() -> ipc.getFeatureProvider("unknown-feature"));
411 assertEquals(feature1, ipc.getFeatureProvider(FEATURE1));
412 assertEquals(feature2, ipc.getFeatureProvider(FEATURE2));
416 void testControllerType() {
417 PolicyControllerFactory factory = new IndexedPolicyControllerFactory();
418 Properties props = new Properties();
420 // this should build an 'AggregatedPolicyController'
421 final String name1 = "ctrl1";
422 PolicyController ctrl1 = factory.build(name1, props);
424 // this should build a 'TestPolicyController'
425 final String name2 = "ctrl2";
426 props.setProperty(PROPERTY_CONTROLLER_TYPE, POLICY_CONTROLLER_BUILDER_TAG);
427 PolicyController ctrl2 = factory.build(name2, props);
429 // verify controller types
430 assertSame(AggregatedPolicyController.class, ctrl1.getClass());
431 assertSame(TestPolicyController.class, ctrl2.getClass());
432 assertSame(NullDroolsController.class, ctrl2.getDrools().getClass());
434 // verify controller lookups
435 assertSame(ctrl1, factory.get(name1));
436 assertSame(ctrl2, factory.get(name2));
440 * Factory with overrides.
442 private class IndexedPolicyControllerFactoryImpl extends IndexedPolicyControllerFactory {
445 protected PolicyController newPolicyController(String name, Properties properties) {
446 if (MY_NAME.equals(name)) {
449 } else if (MY_NAME2.equals(name)) {
453 throw new IllegalArgumentException("unknown controller name: " + name);
459 protected List<PolicyControllerFeatureApi> getProviders() {
465 * This class provides an alternate PolicyController implementation,
466 * for the purpose of easy identification within a junit test.
468 public static class TestPolicyController extends AggregatedPolicyController {
469 public TestPolicyController(String name, Properties properties) {
470 super(name, properties);
475 * An instance of this class is created by 'IndexedPolicyControllerFactory',
476 * using features. It does the build operation when the value of the
477 * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG.
479 public static class PolicyBuilder implements PolicyControllerFeatureApi {
481 public int getSequenceNumber() {
486 public PolicyController beforeInstance(String name, Properties properties) {
487 if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
488 return new TestPolicyController(name, properties);
495 * An instance of this class is created by 'IndexedDroolsControllerFactory',
496 * using features. It does the build operation when the value of the
497 * 'controller.type' property matches the value of POLICY_CONTROLLER_BUILDER_TAG.
499 public static class DroolsBuilder implements DroolsControllerFeatureApi {
501 public int getSequenceNumber() {
506 public DroolsController beforeInstance(Properties properties,
507 String groupId, String artifactId, String version,
508 List<TopicCoderFilterConfiguration> decoderConfigurations,
509 List<TopicCoderFilterConfiguration> encoderConfigurations) {
511 if (POLICY_CONTROLLER_BUILDER_TAG.equals(properties.getProperty(PROPERTY_CONTROLLER_TYPE))) {
512 return new NullDroolsController();