2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2018, 2020 AT&T Intellectual Property. All rights reserved.
6 * Modifications Copyright (C) 2020, 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.pooling.state;
24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 import static org.junit.jupiter.api.Assertions.assertNotNull;
26 import static org.junit.jupiter.api.Assertions.assertNull;
27 import static org.junit.jupiter.api.Assertions.assertTrue;
28 import static org.mockito.ArgumentMatchers.any;
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;
35 import org.apache.commons.lang3.tuple.Pair;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38 import org.onap.policy.drools.pooling.message.BucketAssignments;
39 import org.onap.policy.drools.pooling.message.Identification;
40 import org.onap.policy.drools.pooling.message.Leader;
41 import org.onap.policy.drools.pooling.message.Offline;
43 class QueryStateTest extends SupportBasicStateTester {
45 private QueryState state;
52 public void setUp() throws Exception {
55 state = new QueryState(mgr);
60 assertNull(state.goQuery());
67 Pair<Long, StateTimerTask> timer = onceTasks.remove();
69 assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
70 assertNotNull(timer.getRight());
74 void testProcessIdentification_SameSource() {
75 String[] arr = {HOST2, PREV_HOST, MY_HOST};
76 BucketAssignments asgn = new BucketAssignments(arr);
78 assertNull(state.process(new Identification(MY_HOST, asgn)));
80 // info should be unchanged
81 assertEquals(MY_HOST, state.getLeader());
82 verify(mgr, never()).startDistributing(asgn);
86 void testProcessIdentification_DiffSource() {
87 String[] arr = {HOST2, PREV_HOST, MY_HOST};
88 BucketAssignments asgn = new BucketAssignments(arr);
90 assertNull(state.process(new Identification(HOST2, asgn)));
92 // leader should be unchanged
93 assertEquals(MY_HOST, state.getLeader());
95 // should have picked up the assignments
96 verify(mgr).startDistributing(asgn);
100 void testProcessLeader_Invalid() {
101 Leader msg = new Leader(PREV_HOST, null);
103 // should stay in the same state, and not start distributing
104 assertNull(state.process(msg));
105 verify(mgr, never()).startDistributing(any());
106 verify(mgr, never()).goActive();
107 verify(mgr, never()).goInactive();
109 // info should be unchanged
110 assertEquals(MY_HOST, state.getLeader());
111 assertEquals(ASGN3, state.getAssignments());
115 void testProcessLeader_SameLeader() {
116 String[] arr = {HOST2, PREV_HOST, MY_HOST};
117 BucketAssignments asgn = new BucketAssignments(arr);
119 // identify a leader that's better than my host
120 assertNull(state.process(new Identification(PREV_HOST, asgn)));
122 // now send a Leader message for that leader
123 Leader msg = new Leader(PREV_HOST, asgn);
125 State next = mock(State.class);
126 when(mgr.goActive()).thenReturn(next);
128 // should go Active and start distributing
129 assertEquals(next, state.process(msg));
130 verify(mgr, never()).goInactive();
132 // Ident msg + Leader msg = times(2)
133 verify(mgr, times(2)).startDistributing(asgn);
137 void testProcessLeader_BetterLeaderWithAssignment() {
138 String[] arr = {HOST2, PREV_HOST, MY_HOST};
139 BucketAssignments asgn = new BucketAssignments(arr);
140 Leader msg = new Leader(PREV_HOST, asgn);
142 State next = mock(State.class);
143 when(mgr.goActive()).thenReturn(next);
145 // should go Active and start distributing
146 assertEquals(next, state.process(msg));
147 verify(mgr).startDistributing(asgn);
148 verify(mgr, never()).goInactive();
152 void testProcessLeader_BetterLeaderWithoutAssignment() {
153 String[] arr = {HOST2, PREV_HOST, HOST1};
154 BucketAssignments asgn = new BucketAssignments(arr);
155 Leader msg = new Leader(PREV_HOST, asgn);
157 State next = mock(State.class);
158 when(mgr.goInactive()).thenReturn(next);
160 // should go Inactive, but start distributing
161 assertEquals(next, state.process(msg));
162 verify(mgr).startDistributing(asgn);
163 verify(mgr, never()).goActive();
167 void testProcessLeader_NotABetterLeader() {
168 // no assignments yet
169 mgr.startDistributing(null);
170 state = new QueryState(mgr);
172 BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
173 Leader msg = new Leader(HOST1, asgn);
175 State next = mock(State.class);
176 when(mgr.goInactive()).thenReturn(next);
178 // should stay in the same state
179 assertNull(state.process(msg));
180 verify(mgr, never()).goActive();
181 verify(mgr, never()).goInactive();
183 // should have started distributing
184 verify(mgr).startDistributing(asgn);
186 // this host should still be the leader
187 assertEquals(MY_HOST, state.getLeader());
190 assertEquals(asgn, state.getAssignments());
194 void testProcessOffline_NullHost() {
195 assertNull(state.process(new Offline()));
196 assertEquals(MY_HOST, state.getLeader());
200 void testProcessOffline_SameHost() {
201 assertNull(state.process(new Offline(MY_HOST)));
202 assertEquals(MY_HOST, state.getLeader());
206 void testProcessOffline_DiffHost() {
207 BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, HOST1});
208 mgr.startDistributing(asgn);
209 state = new QueryState(mgr);
211 // tell it that the hosts are alive
212 state.process(new Identification(PREV_HOST, asgn));
213 state.process(new Identification(HOST1, asgn));
216 assertNull(state.process(new Offline(HOST1)));
218 // #1 should still be the leader
219 assertEquals(PREV_HOST, state.getLeader());
222 assertNull(state.process(new Offline(PREV_HOST)));
224 // this should still be the leader now
225 assertEquals(MY_HOST, state.getLeader());
229 void testQueryState() {
231 * Prove the state is attached to the manager by invoking getHost(), which
232 * delegates to the manager.
234 assertEquals(MY_HOST, state.getHost());
238 void testAwaitIdentification_MissingSelfIdent() {
241 Pair<Long, StateTimerTask> timer = onceTasks.remove();
243 assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
244 assertNotNull(timer.getRight());
246 // should published an Offline message and go inactive
248 State next = mock(State.class);
249 when(mgr.goStart()).thenReturn(next);
251 assertEquals(next, timer.getRight().fire());
253 // should continue distributing
254 verify(mgr, never()).startDistributing(null);
256 Offline msg = captureAdminMessage(Offline.class);
257 assertEquals(MY_HOST, msg.getSource());
261 void testAwaitIdentification_Leader() {
263 state.process(new Identification(MY_HOST, null));
265 Pair<Long, StateTimerTask> timer = onceTasks.remove();
267 assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
268 assertNotNull(timer.getRight());
270 State next = mock(State.class);
271 when(mgr.goActive()).thenReturn(next);
273 assertEquals(next, timer.getRight().fire());
275 // should have published a Leader message
276 Leader msg = captureAdminMessage(Leader.class);
277 assertEquals(MY_HOST, msg.getSource());
278 assertTrue(msg.getAssignments().hasAssignment(MY_HOST));
282 void testAwaitIdentification_HasAssignment() {
283 // not the leader, but has an assignment
284 BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
285 mgr.startDistributing(asgn);
286 state = new QueryState(mgr);
289 state.process(new Identification(MY_HOST, null));
291 // tell it the leader is still active
292 state.process(new Identification(PREV_HOST, asgn));
294 Pair<Long, StateTimerTask> timer = onceTasks.remove();
296 assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
297 assertNotNull(timer.getRight());
299 // set up active state, as that's what it should return
300 State next = mock(State.class);
301 when(mgr.goActive()).thenReturn(next);
303 assertEquals(next, timer.getRight().fire());
305 // should NOT have published a Leader message
306 assertTrue(admin.isEmpty());
308 // should have gone active with the current assignments
309 verify(mgr).goActive();
313 void testAwaitIdentification_NoAssignment() {
314 // not the leader and no assignment
315 BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
316 mgr.startDistributing(asgn);
317 state = new QueryState(mgr);
320 state.process(new Identification(MY_HOST, null));
322 // tell it the leader is still active
323 state.process(new Identification(PREV_HOST, asgn));
325 Pair<Long, StateTimerTask> timer = onceTasks.remove();
327 assertEquals(STD_IDENTIFICATION_MS, timer.getLeft().longValue());
328 assertNotNull(timer.getRight());
330 // set up inactive state, as that's what it should return
331 State next = mock(State.class);
332 when(mgr.goInactive()).thenReturn(next);
334 assertEquals(next, timer.getRight().fire());
336 // should NOT have published a Leader message
337 assertTrue(admin.isEmpty());
341 void testRecordInfo_NullSource() {
342 state.setAssignments(ASGN3);
343 state.setLeader(MY_HOST);
345 BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
346 state.process(new Identification(null, asgn));
349 assertEquals(MY_HOST, state.getLeader());
351 // assignments still updated
352 assertEquals(asgn, state.getAssignments());
356 void testRecordInfo_SourcePreceedsMyHost() {
357 state.setAssignments(ASGN3);
358 state.setLeader(MY_HOST);
360 BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
361 state.process(new Identification(PREV_HOST, asgn));
364 assertEquals(PREV_HOST, state.getLeader());
366 // assignments still updated
367 assertEquals(asgn, state.getAssignments());
371 void testRecordInfo_SourceFollowsMyHost() {
372 mgr.startDistributing(null);
373 state.setLeader(MY_HOST);
375 BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
376 state.process(new Identification(HOST1, asgn));
379 assertEquals(MY_HOST, state.getLeader());
381 // assignments still updated
382 assertEquals(asgn, state.getAssignments());
386 void testRecordInfo_NewIsNull() {
387 state.setAssignments(ASGN3);
388 state.process(new Identification(HOST1, null));
390 assertEquals(ASGN3, state.getAssignments());
394 void testRecordInfo_NewIsEmpty() {
395 state.setAssignments(ASGN3);
396 state.process(new Identification(PREV_HOST, new BucketAssignments()));
398 assertEquals(ASGN3, state.getAssignments());
402 void testRecordInfo_OldIsNull() {
403 mgr.startDistributing(null);
405 BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
406 state.process(new Identification(HOST1, asgn));
408 assertEquals(asgn, state.getAssignments());
412 void testRecordInfo_OldIsEmpty() {
413 state.setAssignments(new BucketAssignments());
415 BucketAssignments asgn = new BucketAssignments(new String[] {HOST1, HOST2});
416 state.process(new Identification(HOST1, asgn));
418 assertEquals(asgn, state.getAssignments());
422 void testRecordInfo_NewLeaderPreceedsOld() {
423 state.setAssignments(ASGN3);
424 state.setLeader(MY_HOST);
426 BucketAssignments asgn = new BucketAssignments(new String[] {PREV_HOST, MY_HOST, HOST2});
427 state.process(new Identification(HOST3, asgn));
429 assertEquals(asgn, state.getAssignments());
433 void testRecordInfo_NewLeaderSucceedsOld() {
434 state.setAssignments(ASGN3);
435 state.setLeader(MY_HOST);
437 BucketAssignments asgn = new BucketAssignments(new String[] {HOST2, HOST3});
438 state.process(new Identification(HOST3, asgn));
440 // should be unchanged
441 assertEquals(ASGN3, state.getAssignments());