Removing deprecated DMAAP library
[policy/drools-pdp.git] / feature-test-transaction / src / test / java / org / onap / policy / drools / testtransaction / TestTransactionAdditionalTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * feature-test-transaction
4  * ================================================================================
5  * Copyright (C) 2017-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
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.testtransaction;
23
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertFalse;
26 import static org.junit.jupiter.api.Assertions.assertNotNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyBoolean;
30 import static org.mockito.ArgumentMatchers.anyString;
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.Arrays;
38 import java.util.Collections;
39 import java.util.EventObject;
40 import java.util.List;
41 import java.util.Map;
42 import java.util.TreeMap;
43 import java.util.concurrent.atomic.AtomicInteger;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46 import org.onap.policy.drools.controller.DroolsController;
47 import org.onap.policy.drools.core.PolicyContainer;
48 import org.onap.policy.drools.system.PolicyController;
49
50 class TestTransactionAdditionalTest {
51
52     private static final int MAX_SLEEP_COUNT = 3;
53     private static final String EXPECTED = "expected exception";
54     private static final String CONTROLLER1 = "controller-a";
55     private static final String CONTROLLER2 = "controller-b";
56     private static final String CONTROLLER3 = "controller-c";
57     private static final String SESSION1 = "session-a";
58     private static final String SESSION2 = "session-b";
59     private static final List<String> sessions = Arrays.asList(SESSION1, SESSION2);
60     private static final List<Object> facts = List.of(0L);
61
62     private Thread theThread;
63     private PolicyController controller;
64     private PolicyController controller2;
65     private PolicyController controller3;
66     private Runnable theAction;
67     private long waitJoinMs;
68     private long doSleepMs;
69     private DroolsController drools;
70     private PolicyContainer container;
71     private Map<String, TtControllerTask> name2task;
72     private TtControllerTask task;
73     private TtControllerTask task2;
74     private TtControllerTask task3;
75     private TestTransTImplTester impl;
76
77     /**
78      * Initialize objects for each test.
79      */
80     @BeforeEach
81     public void setUp() {
82         theThread = mock(Thread.class);
83         controller = mock(PolicyController.class);
84         controller2 = mock(PolicyController.class);
85         controller3 = mock(PolicyController.class);
86         theAction = null;
87         waitJoinMs = -1;
88         doSleepMs = -1;
89         drools = mock(DroolsController.class);
90         container = mock(PolicyContainer.class);
91         task2 = mock(TtControllerTask.class);
92         task3 = mock(TtControllerTask.class);
93         name2task = new TreeMap<>();
94
95         when(drools.getSessionNames()).thenReturn(sessions);
96         when(drools.isBrained()).thenReturn(true);
97         when(drools.factQuery(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(facts);
98         when(drools.getContainer()).thenReturn(container);
99
100         when(controller.getName()).thenReturn(CONTROLLER1);
101         when(controller.getDrools()).thenReturn(drools);
102         when(controller.isAlive()).thenReturn(true);
103
104         when(controller2.getName()).thenReturn(CONTROLLER2);
105         when(controller2.getDrools()).thenReturn(drools);
106         when(controller2.isAlive()).thenReturn(true);
107
108         when(controller3.getName()).thenReturn(CONTROLLER3);
109         when(controller3.getDrools()).thenReturn(drools);
110         when(controller3.isAlive()).thenReturn(true);
111
112         task = new TestTransControllerTaskTester(controller);
113
114         name2task.put(CONTROLLER1, task);
115         name2task.put(CONTROLLER2, task2);
116         name2task.put(CONTROLLER3, task3);
117
118         impl = new TestTransTImplTester();
119     }
120
121     @Test
122     void testTestTransactionImpl() {
123         assertNotNull(TestTransactionConstants.getManager());
124     }
125
126     @Test
127     void testTestTransactionImplRegister_testTestTransactionImplUnregister() {
128         task = mock(TtControllerTask.class);
129         when(task.isAlive()).thenReturn(true);
130         name2task.put(CONTROLLER1, task);
131
132         impl.register(controller);
133         impl.register(controller2);
134
135         // re-register
136         impl.register(controller);
137
138         // re-register when task is not running
139
140         // give controller3 same name as controller1 -> task3 replaces task
141         when(controller3.getName()).thenReturn(CONTROLLER1);
142         name2task.put(CONTROLLER1, task3);
143         when(task.isAlive()).thenReturn(false);
144         impl.register(controller3);
145
146         impl.unregister(controller);
147         verify(task, never()).stop();
148         verify(task2, never()).stop();
149         verify(task3).stop();
150
151         impl.unregister(controller2);
152         verify(task2).stop();
153
154         // unregister again - stop() should not be called again
155         impl.unregister(controller3);
156         verify(task3).stop();
157
158         // unregister original controller - no stop() should be called again
159         impl.unregister(controller);
160         verify(task, never()).stop();
161         verify(task2).stop();
162         verify(task3).stop();
163     }
164
165     @Test
166     void testTestTransactionControllerTaskFactory() throws Exception {
167         task = new TtControllerTask(controller) {
168             @Override
169             protected Thread makeThread(Runnable action) {
170                 return theThread;
171             }
172
173             @Override
174             protected void joinThread(long waitTimeMs) {
175                 // do nothing
176             }
177         };
178
179         task.doSleep(1);
180         assertEquals(Thread.currentThread(), task.getCurrentThread());
181     }
182
183     @Test
184     void testTestTransactionControllerTask() {
185         assertEquals(task, theAction);
186         assertTrue(task.isAlive());
187         assertEquals(controller, task.getController());
188         assertEquals(theThread, task.getThread());
189
190         verify(theThread).start();
191     }
192
193     @Test
194     void testTestTransactionControllerTaskGetController() {
195         assertEquals(controller, task.getController());
196     }
197
198     @Test
199     void testTestTransactionControllerTaskGetThread() {
200         assertEquals(theThread, task.getThread());
201     }
202
203     @Test
204     void testTestTransactionControllerTaskStop() {
205         task.stop();
206         assertFalse(task.isAlive());
207         verify(theThread).interrupt();
208         assertTrue(waitJoinMs > 0);
209
210         // throw interrupt during join()
211         setUp();
212         task = new TestTransControllerTaskTester(controller) {
213             @Override
214             protected void joinThread(long waitTimeMs) throws InterruptedException {
215                 waitJoinMs = waitTimeMs;
216                 throw new InterruptedException(EXPECTED);
217             }
218         };
219         task.stop();
220         assertFalse(task.isAlive());
221         verify(theThread, times(2)).interrupt();
222         assertTrue(waitJoinMs > 0);
223     }
224
225     @Test
226     void testTestTransactionControllerTaskRun() {
227         task.run();
228         assertFalse(task.isAlive());
229         verify(theThread, never()).interrupt();
230         verify(controller, times(MAX_SLEEP_COUNT + 1)).isAlive();
231         assertTrue(doSleepMs > 0);
232
233         // not brained
234         setUp();
235         when(drools.isBrained()).thenReturn(false);
236         task.run();
237         assertFalse(task.isAlive());
238         verify(controller, never()).isAlive();
239         assertEquals(-1, doSleepMs);
240
241         // controller not running
242         setUp();
243         when(controller.isAlive()).thenReturn(false);
244         task.run();
245         assertFalse(task.isAlive());
246         assertEquals(-1, doSleepMs);
247
248         // controller is locked
249         setUp();
250         when(controller.isLocked()).thenReturn(true);
251         task.run();
252         assertFalse(task.isAlive());
253         assertEquals(-1, doSleepMs);
254
255         // un-brain during sleep
256         setUp();
257         task = new TestTransControllerTaskTester(controller) {
258             @Override
259             protected void doSleep(long sleepMs) throws InterruptedException {
260                 when(drools.isBrained()).thenReturn(false);
261                 super.doSleep(sleepMs);
262             }
263         };
264         task.run();
265         assertFalse(task.isAlive());
266         // only hit top of the loop twice
267         verify(controller, times(2)).isAlive();
268         assertTrue(doSleepMs > 0);
269
270         // stop during sleep
271         setUp();
272         task = new TestTransControllerTaskTester(controller) {
273             @Override
274             protected void doSleep(long sleepMs) throws InterruptedException {
275                 task.stop();
276                 super.doSleep(sleepMs);
277             }
278         };
279         task.run();
280         assertFalse(task.isAlive());
281         // only hit top of the loop twice
282         verify(controller, times(2)).isAlive();
283         assertTrue(doSleepMs > 0);
284
285         // isInterrupted() returns true the first time, interrupt next time
286         setUp();
287         AtomicInteger count = new AtomicInteger(1);
288         when(theThread.isInterrupted()).thenAnswer(args -> {
289             if (count.decrementAndGet() >= 0) {
290                 return true;
291             } else {
292                 throw new InterruptedException(EXPECTED);
293             }
294         });
295         task.run();
296         assertFalse(task.isAlive());
297         verify(controller, times(2)).isAlive();
298         // doSleep() should not be called
299         assertEquals(-1, doSleepMs);
300
301         // interrupt during sleep
302         setUp();
303         task = new TestTransControllerTaskTester(controller) {
304             @Override
305             protected void doSleep(long sleepMs) throws InterruptedException {
306                 super.doSleep(sleepMs);
307                 throw new InterruptedException(EXPECTED);
308             }
309         };
310         task.run();
311         assertFalse(task.isAlive());
312         verify(theThread).interrupt();
313         // only hit top of the loop once
314         verify(controller).isAlive();
315         assertTrue(doSleepMs > 0);
316
317         // stop() during factQuery()
318         setUp();
319         when(drools.factQuery(anyString(), anyString(), anyString(), anyBoolean())).thenAnswer(args -> {
320             task.stop();
321             return facts;
322         });
323         task.run();
324         assertFalse(task.isAlive());
325         // only hit top of the loop once
326         verify(controller).isAlive();
327
328         // exception during isBrained() check
329         setUp();
330         when(drools.isBrained()).thenThrow(new IllegalArgumentException(EXPECTED));
331         task.run();
332         assertFalse(task.isAlive());
333
334         // other exception during isBrained() check
335         setUp();
336         when(drools.isBrained()).thenThrow(new RuntimeException(EXPECTED));
337         task.run();
338         assertFalse(task.isAlive());
339     }
340
341     @Test
342     void testTestTransactionControllerTaskInjectTxIntoSessions() {
343         task.run();
344         verify(container, times(MAX_SLEEP_COUNT * sessions.size())).insert(anyString(), any(EventObject.class));
345
346         // null facts
347         setUp();
348         when(drools.factQuery(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(null);
349         task.run();
350         verify(container, never()).insert(anyString(), any());
351
352         // empty fact list
353         setUp();
354         when(drools.factQuery(anyString(), anyString(), anyString(), anyBoolean())).thenReturn(Collections.emptyList());
355         task.run();
356         verify(container, never()).insert(anyString(), any());
357     }
358
359     @Test
360     void testTestTransactionControllerTaskToString() {
361         assertTrue(task.toString().startsWith("TTControllerTask ["));
362     }
363
364     /**
365      * TestTransaction with overridden methods.
366      */
367     private class TestTransTImplTester extends TtImpl {
368
369         @Override
370         protected TtControllerTask makeControllerTask(PolicyController controller) {
371             return name2task.get(controller.getName());
372         }
373     }
374
375     /**
376      * Controller task with overridden methods.
377      */
378     private class TestTransControllerTaskTester extends TtControllerTask {
379         private int sleepCount = MAX_SLEEP_COUNT;
380
381         public TestTransControllerTaskTester(PolicyController controller) {
382             super(controller);
383         }
384
385         @Override
386         protected Thread makeThread(Runnable action) {
387             theAction = action;
388             return theThread;
389         }
390
391         @Override
392         protected void joinThread(long waitTimeMs) throws InterruptedException {
393             waitJoinMs = waitTimeMs;
394         }
395
396         @Override
397         protected void doSleep(long sleepMs) throws InterruptedException {
398             doSleepMs = sleepMs;
399
400             if (--sleepCount <= 0) {
401                 when(controller.isAlive()).thenReturn(false);
402             }
403         }
404
405         @Override
406         protected Thread getCurrentThread() {
407             return thread;
408         }
409     }
410 }