2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2020-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.controlloop.actorserviceprovider.topic;
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.doThrow;
27 import static org.mockito.Mockito.never;
28 import static org.mockito.Mockito.times;
29 import static org.mockito.Mockito.verify;
31 import java.util.Arrays;
33 import java.util.function.BiConsumer;
34 import org.junit.jupiter.api.BeforeAll;
35 import org.junit.jupiter.api.BeforeEach;
36 import org.junit.jupiter.api.Test;
37 import org.junit.jupiter.api.TestInstance;
38 import org.junit.jupiter.api.extension.ExtendWith;
39 import org.mockito.Mock;
40 import org.mockito.junit.jupiter.MockitoExtension;
41 import org.onap.policy.common.utils.coder.StandardCoderObject;
42 import org.onap.policy.controlloop.actorserviceprovider.Util;
44 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
45 @ExtendWith(MockitoExtension.class)
47 private static final String TEXT = "some text";
49 private static final String KEY1 = "requestId";
50 private static final String KEY2 = "container";
51 private static final String SUBKEY = "subRequestId";
53 private static final String VALUEA_REQID = "hello";
54 private static final String VALUEA_SUBREQID = "world";
56 // request id is shared with value A
57 private static final String VALUEB_REQID = "hello";
58 private static final String VALUEB_SUBREQID = "another world";
61 private static final String VALUEC_REQID = "bye";
62 private static final String VALUEC_SUBREQID = "bye-bye";
65 private BiConsumer<String, StandardCoderObject> listener1;
68 private BiConsumer<String, StandardCoderObject> listener1b;
71 private BiConsumer<String, StandardCoderObject> listener2;
74 private BiConsumer<String, StandardCoderObject> listener3;
76 private Forwarder forwarder;
84 forwarder = new Forwarder(Arrays.asList(new SelectorKey(KEY1), new SelectorKey(KEY2, SUBKEY)));
86 forwarder.register(Arrays.asList(VALUEA_REQID, VALUEA_SUBREQID), listener1);
87 forwarder.register(Arrays.asList(VALUEA_REQID, VALUEA_SUBREQID), listener1b);
88 forwarder.register(Arrays.asList(VALUEB_REQID, VALUEB_SUBREQID), listener2);
89 forwarder.register(Arrays.asList(VALUEC_REQID, VALUEC_SUBREQID), listener3);
94 // key size mismatches
95 assertThatIllegalArgumentException().isThrownBy(() -> forwarder.register(Arrays.asList(), listener1))
96 .withMessage("key/value mismatch");
97 assertThatIllegalArgumentException()
98 .isThrownBy(() -> forwarder.register(Arrays.asList(VALUEA_REQID), listener1))
99 .withMessage("key/value mismatch");
103 void testUnregister() {
105 forwarder.unregister(Arrays.asList(VALUEA_REQID, VALUEA_SUBREQID), listener1b);
107 StandardCoderObject sco = makeMessage(Map.of(KEY1, VALUEA_REQID, KEY2, Map.of(SUBKEY, VALUEA_SUBREQID)));
108 forwarder.onMessage(TEXT, sco);
110 verify(listener1).accept(TEXT, sco);
111 verify(listener1b, never()).accept(any(), any());
114 forwarder.unregister(Arrays.asList(VALUEA_REQID, VALUEA_SUBREQID), listener1);
115 forwarder.onMessage(TEXT, sco);
117 // route a message to listener2
118 sco = makeMessage(Map.of(KEY1, VALUEB_REQID, KEY2, Map.of(SUBKEY, VALUEB_SUBREQID)));
119 forwarder.onMessage(TEXT, sco);
120 verify(listener2).accept(TEXT, sco);
122 // no more messages to listener1 or 1b
123 verify(listener1).accept(any(), any());
124 verify(listener1b, never()).accept(any(), any());
128 void testOnMessage() {
129 StandardCoderObject sco = makeMessage(Map.of(KEY1, VALUEA_REQID, KEY2, Map.of(SUBKEY, VALUEA_SUBREQID)));
130 forwarder.onMessage(TEXT, sco);
132 verify(listener1).accept(TEXT, sco);
133 verify(listener1b).accept(TEXT, sco);
135 // repeat - counts should increment
136 forwarder.onMessage(TEXT, sco);
138 verify(listener1, times(2)).accept(TEXT, sco);
139 verify(listener1b, times(2)).accept(TEXT, sco);
141 // should not have been invoked
142 verify(listener2, never()).accept(any(), any());
143 verify(listener3, never()).accept(any(), any());
145 // try other listeners now
146 sco = makeMessage(Map.of(KEY1, VALUEB_REQID, KEY2, Map.of(SUBKEY, VALUEB_SUBREQID)));
147 forwarder.onMessage(TEXT, sco);
148 verify(listener2).accept(TEXT, sco);
150 sco = makeMessage(Map.of(KEY1, VALUEC_REQID, KEY2, Map.of(SUBKEY, VALUEC_SUBREQID)));
151 forwarder.onMessage(TEXT, sco);
152 verify(listener3).accept(TEXT, sco);
154 // message has no listeners
155 sco = makeMessage(Map.of(KEY1, "xyzzy", KEY2, Map.of(SUBKEY, VALUEB_SUBREQID)));
156 forwarder.onMessage(TEXT, sco);
158 // message doesn't have both keys
159 sco = makeMessage(Map.of(KEY1, VALUEA_REQID));
160 forwarder.onMessage(TEXT, sco);
162 // counts should not have incremented
163 verify(listener1, times(2)).accept(any(), any());
164 verify(listener1b, times(2)).accept(any(), any());
165 verify(listener2).accept(any(), any());
166 verify(listener3).accept(any(), any());
170 * Tests onMessage() when listener1 throws an exception.
173 void testOnMessageListenerException1() {
174 doThrow(new IllegalStateException("expected exception")).when(listener1).accept(any(), any());
176 StandardCoderObject sco = makeMessage(Map.of(KEY1, VALUEA_REQID, KEY2, Map.of(SUBKEY, VALUEA_SUBREQID)));
177 forwarder.onMessage(TEXT, sco);
179 verify(listener1b).accept(TEXT, sco);
183 * Tests onMessage() when listener1b throws an exception.
186 void testOnMessageListenerException1b() {
187 doThrow(new IllegalStateException("expected exception")).when(listener1b).accept(any(), any());
189 StandardCoderObject sco = makeMessage(Map.of(KEY1, VALUEA_REQID, KEY2, Map.of(SUBKEY, VALUEA_SUBREQID)));
190 forwarder.onMessage(TEXT, sco);
192 verify(listener1).accept(TEXT, sco);
196 * Makes a message from a map.
198 private StandardCoderObject makeMessage(Map<String, Object> map) {
199 return Util.translate("", map, StandardCoderObject.class);