Wait for pdp-pap topic in xacml-pdp
[policy/xacml-pdp.git] / main / src / test / java / org / onap / policy / pdpx / main / comm / XacmlPdpHearbeatPublisherTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pdpx.main.comm;
22
23 import static org.assertj.core.api.Assertions.assertThatCode;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertSame;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyBoolean;
28 import static org.mockito.ArgumentMatchers.anyLong;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.times;
31 import static org.mockito.Mockito.verify;
32 import static org.mockito.Mockito.when;
33
34 import java.util.Arrays;
35 import java.util.LinkedList;
36 import java.util.Queue;
37 import java.util.concurrent.ScheduledExecutorService;
38 import java.util.concurrent.ScheduledFuture;
39 import java.util.concurrent.TimeUnit;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 import org.mockito.Mock;
44 import org.mockito.junit.MockitoJUnitRunner;
45 import org.onap.policy.common.endpoints.event.comm.TopicSink;
46 import org.onap.policy.common.endpoints.event.comm.client.BidirectionalTopicClient;
47 import org.onap.policy.common.utils.coder.CoderException;
48 import org.onap.policy.models.pdp.concepts.PdpStatus;
49 import org.onap.policy.pdpx.main.XacmlState;
50
51 @RunWith(MockitoJUnitRunner.class)
52 public class XacmlPdpHearbeatPublisherTest {
53
54     private static final long INTERVAL1 = 1000L;
55     private static final long INTERVAL2 = 2000L;
56     private static final long INTERVAL_INVALID = 0;
57
58     @Mock
59     private TopicSink sink;
60
61     @Mock
62     private BidirectionalTopicClient checker;
63
64     @Mock
65     private XacmlState state;
66
67     @Mock
68     private ScheduledExecutorService executor;
69
70     @Mock
71     private ScheduledFuture<?> timer1;
72
73     @Mock
74     private ScheduledFuture<?> timer2;
75
76     private PdpStatus status;
77
78     private Queue<ScheduledFuture<?>> timers;
79
80     private XacmlPdpHearbeatPublisher publisher;
81
82
83     /**
84      * Initializes objects, including the publisher.
85      */
86     @Before
87     public void setUp() {
88         when(sink.getTopic()).thenReturn("my-topic");
89         when(checker.getSink()).thenReturn(sink);
90         when(checker.isReady()).thenReturn(true);
91         when(state.genHeartbeat()).thenReturn(status);
92
93         status = new PdpStatus();
94         timers = new LinkedList<>(Arrays.asList(timer1, timer2));
95
96         when(executor.scheduleWithFixedDelay(any(), anyLong(), anyLong(), any())).thenAnswer(args -> timers.remove());
97
98         publisher = new MyPublisher(checker, 10, state);
99     }
100
101     @Test
102     public void testRun() {
103         publisher.run();
104
105         verify(state).genHeartbeat();
106         verify(checker).send(any());
107     }
108
109     /**
110      * Tests the run() method when the probe is disabled.
111      */
112     @Test
113     public void testRunNoProbe() throws CoderException {
114         publisher = new MyPublisher(checker, 0, state);
115
116         publisher.run();
117
118         verify(checker, never()).isReady();
119         verify(checker, never()).awaitReady(any(), anyLong());
120
121         verify(state).genHeartbeat();
122         verify(checker).send(any());
123     }
124
125     /**
126      * Tests the run() method when the topic is not ready, and then becomes ready.
127      */
128     @Test
129     public void testRunNotReady() throws CoderException {
130         // not ready yet
131         when(checker.isReady()).thenReturn(false);
132         when(checker.awaitReady(any(), anyLong())).thenReturn(false);
133
134         publisher.run();
135         verify(state, never()).genHeartbeat();
136         verify(checker, never()).send(any());
137
138         // isReady is still false, but awaitReady is now true - should generate heartbeat
139         when(checker.awaitReady(any(), anyLong())).thenReturn(true);
140
141         publisher.run();
142         verify(state).genHeartbeat();
143         verify(checker).send(any());
144
145         // now isReady is true, too - should not rerun awaitReady
146         when(checker.isReady()).thenReturn(true);
147
148         publisher.run();
149         verify(state, times(2)).genHeartbeat();
150         verify(checker, times(2)).send(any());
151         verify(checker, times(2)).awaitReady(any(), anyLong());
152     }
153
154     /**
155      * Tests the run() method when the checker throws an exception.
156      */
157     @Test
158     public void testRunCheckerEx() throws CoderException {
159         // force it to call awaitReady
160         when(checker.isReady()).thenReturn(false);
161
162         when(checker.awaitReady(any(), anyLong()))
163             .thenThrow(new CoderException("expected exception"))
164             .thenReturn(true);
165
166         // exception thrown - should not generate heartbeat
167         publisher.run();
168         verify(state, never()).genHeartbeat();
169         verify(checker, never()).send(any());
170
171         // no exception this time - SHOULD generate heartbeat
172         publisher.run();
173         verify(state).genHeartbeat();
174         verify(checker).send(any());
175     }
176
177     @Test
178     public void testTerminate() {
179         // not yet started
180         publisher.terminate();
181
182         verify(checker).stopWaiting();
183
184
185         // now start it and then try again
186         publisher.start();
187         publisher.terminate();
188
189         // timer2 should still be in the queue
190         assertSame(timer2, timers.peek());
191
192
193         // repeat - nothing more should happen
194         publisher.terminate();
195
196         // timer2 should still be in the queue
197         assertSame(timer2, timers.peek());
198     }
199
200     @Test
201     public void testRestart() {
202         // not started yet - should only update the interval
203         publisher.restart(INTERVAL1);
204
205         assertEquals(INTERVAL1, publisher.getIntervalMs());
206         assertSame(timer1, timers.peek());
207
208         // now start it
209         publisher.start();
210         verify(executor).scheduleWithFixedDelay(publisher, 0, INTERVAL1, TimeUnit.MILLISECONDS);
211
212         // null interval - no changes
213         publisher.restart(null);
214         verify(executor, times(1)).scheduleWithFixedDelay(any(), anyLong(), anyLong(), any());
215         assertSame(timer2, timers.peek());
216
217         // same interval - no changes
218         publisher.restart(INTERVAL1);
219         verify(executor, times(1)).scheduleWithFixedDelay(any(), anyLong(), anyLong(), any());
220         assertSame(timer2, timers.peek());
221
222         // invalid interval - no changes
223         publisher.restart(INTERVAL_INVALID);
224         verify(executor, times(1)).scheduleWithFixedDelay(any(), anyLong(), anyLong(), any());
225         assertSame(timer2, timers.peek());
226
227         // new interval - old timer should be cancelled and new started
228         publisher.restart(INTERVAL2);
229         verify(timer1).cancel(anyBoolean());
230         verify(executor).scheduleWithFixedDelay(publisher, 0, INTERVAL2, TimeUnit.MILLISECONDS);
231     }
232
233     @Test
234     public void testStart() {
235         publisher.start();
236
237         verify(executor).scheduleWithFixedDelay(publisher, 0, XacmlPdpHearbeatPublisher.DEFAULT_HB_INTERVAL_MS,
238                         TimeUnit.MILLISECONDS);
239
240         // repeat - nothing more should happen
241         publisher.start();
242         verify(executor, times(1)).scheduleWithFixedDelay(any(), anyLong(), anyLong(), any());
243         verify(timer1, never()).cancel(anyBoolean());
244     }
245
246     @Test
247     public void testMakeTimerThread() {
248         // create a plain listener to test the "real" makeTimer() method
249         publisher = new XacmlPdpHearbeatPublisher(checker, 1, state);
250
251         assertThatCode(() -> {
252             publisher.start();
253             publisher.restart(100L);
254             publisher.terminate();
255         }).doesNotThrowAnyException();
256     }
257
258     private class MyPublisher extends XacmlPdpHearbeatPublisher {
259
260         public MyPublisher(BidirectionalTopicClient topicChecker, long probeHeartbeatTopicMs, XacmlState state) {
261             super(topicChecker, probeHeartbeatTopicMs, state);
262         }
263
264         @Override
265         protected ScheduledExecutorService makeTimerThread() {
266             return executor;
267         }
268     }
269 }