2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.lispflowmapping.implementation;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNull;
13 import com.google.common.collect.Lists;
14 import java.lang.reflect.Field;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.apache.commons.lang3.tuple.ImmutablePair;
18 import org.apache.commons.lang3.tuple.MutablePair;
19 import org.apache.commons.lang3.tuple.Pair;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.mockito.ArgumentMatcher;
23 import org.mockito.InjectMocks;
24 import org.mockito.Mock;
25 import org.mockito.Mockito;
26 import org.mockito.junit.MockitoJUnitRunner;
27 import org.opendaylight.lispflowmapping.implementation.lisp.MapServer;
28 import org.opendaylight.lispflowmapping.interfaces.lisp.IMapResolverAsync;
29 import org.opendaylight.lispflowmapping.interfaces.mappingservice.IMappingService;
30 import org.opendaylight.lispflowmapping.lisp.type.LispMessage;
31 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
32 import org.opendaylight.mdsal.binding.api.NotificationService;
33 import org.opendaylight.mdsal.binding.api.RpcProviderService;
34 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.Ipv4AddressBinary;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.AddMapping;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapNotify;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.GotMapReply;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapNotify;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapRegister;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MapReply;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.MappingKeepAlive;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.RequestMapping;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrReplyMapping;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrRequestMapping;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.list.EidItemBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.MapRegisterCacheMetadata;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.MapRegisterCacheMetadataBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddress;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.map.register.cache.metadata.container.map.register.cache.metadata.EidLispAddressBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapnotifymessage.MapNotifyBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.container.MappingRecordBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping._record.list.MappingRecordItemBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapreplymessage.MapReplyBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequest.SourceEidBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestmessage.MapRequest;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestmessage.MapRequestBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.rloc.container.Rloc;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddress;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.transport.address.TransportAddressBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.OdlLispSbService;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapNotifyInput;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapNotifyInputBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapReplyInputBuilder;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.sb.rev150904.SendMapRequestInputBuilder;
69 import org.opendaylight.yangtools.concepts.Registration;
70 import org.opendaylight.yangtools.yang.binding.util.BindingMap;
71 import org.opendaylight.yangtools.yang.common.Uint16;
73 @RunWith(MockitoJUnitRunner.class)
74 public class LispMappingServiceTest {
75 @Mock private static MapRegister mapRegisterMock;
76 @Mock(name = "mapServer") private static MapServer mapServerMock;
77 @Mock(name = "mapResolver") private static IMapResolverAsync mapResolverMock;
78 @Mock(name = "tlsMapReply") private static ThreadLocal<MapReply> tlsMapReplyMock;
79 @Mock(name = "tlsMapNotify") private static ThreadLocal<Pair<MapNotify, List<TransportAddress>>> tlsMapNotifyMock;
80 @Mock(name = "tlsMapRequest") private static ThreadLocal<Pair<MapRequest, TransportAddress>> tlsMapRequestMock;
81 @Mock private static Registration rpcRegistration;
82 @Mock(name = "listenerRegistration") private static Registration listenerRegistration;
83 @Mock(name = "cssRegistration") private static Registration cssRegistration;
85 private final NotificationService notificationService = Mockito.mock(NotificationService.class);
86 private final RpcProviderService rpcProviderService = Mockito.mock(RpcProviderService.class);
87 private final IMappingService mappingService = Mockito.mock(IMappingService.class);
88 private final OdlLispSbService odlLispSbService = Mockito.mock(OdlLispSbService.class);
89 private final ClusterSingletonServiceProvider clusterSingletonService = Mockito.mock(
90 ClusterSingletonServiceProvider.class);
93 private final LispMappingService lispMappingService = new LispMappingService(
94 mappingService, odlLispSbService, clusterSingletonService, rpcProviderService, notificationService);
96 private static final byte[] IPV4_BYTES_1 = new byte[] {1, 2, 3, 0};
97 private static final byte[] IPV4_BYTES_2 = new byte[] {1, 2, 4, 0};
98 private static final String IPV4_STRING_1 = "1.2.3.0";
99 private static final String IPV4_STRING_2 = "1.2.3.1";
100 private static final String IPV4_SOURCE_STRING = "192.168.0.1";
101 private static final String IPV4_PREFIX_STRING = "/24";
102 private static final long TIMESTAMP = 1L;
104 private static final Eid IPV4_PREFIX_EID_1 = LispAddressUtil.asIpv4PrefixEid(IPV4_STRING_1 + IPV4_PREFIX_STRING);
105 private static final Eid IPV4_SOURCE_EID = LispAddressUtil.asIpv4Eid(IPV4_SOURCE_STRING);
106 private static final Eid IPV4_EID_1 = LispAddressUtil.asIpv4Eid(IPV4_STRING_1);
107 private static final Eid IPV4_EID_2 = LispAddressUtil.asIpv4Eid(IPV4_STRING_2);
108 private static final EidItemBuilder EID_ITEM_BUILDER = new EidItemBuilder()
109 .setEidItemId("eid-item-id")
110 .setEid(IPV4_PREFIX_EID_1);
111 private static final MappingRecordItemBuilder MAPPING_RECORD_ITEM_BUILDER = new MappingRecordItemBuilder()
112 .setMappingRecord(new MappingRecordBuilder().setEid(IPV4_PREFIX_EID_1).build());
114 private static final TransportAddress TRANSPORT_ADDRESS_1 = new TransportAddressBuilder()
115 .setIpAddress(new IpAddressBinary(new Ipv4AddressBinary(IPV4_BYTES_1)))
116 .setPort(new PortNumber(Uint16.valueOf(9999))).build();
117 private static final TransportAddress TRANSPORT_ADDRESS_2 = new TransportAddressBuilder()
118 .setIpAddress(new IpAddressBinary(new Ipv4AddressBinary(IPV4_BYTES_2)))
119 .setPort(new PortNumber(Uint16.valueOf(8888))).build();
120 private static final TransportAddress TRANSPORT_ADDRESS = new TransportAddressBuilder()
121 .setIpAddress(new IpAddressBinary(new Ipv4AddressBinary(IPV4_BYTES_1)))
122 .setPort(new PortNumber(LispMessage.PORT_NUMBER)).build();
125 * Tests {@link LispMappingService#handleMapRequest} method.
128 public void handleMapRequestTest() {
129 final MapRequest mapRequest = Mockito.mock(MapRequest.class);
130 final MapReply mapReply = new MapReplyBuilder().build();
131 Mockito.when(tlsMapRequestMock.get()).thenReturn(null);
132 Mockito.when(tlsMapReplyMock.get()).thenReturn(mapReply);
134 final MapReply result = lispMappingService.handleMapRequest(mapRequest);
136 Mockito.verify(tlsMapRequestMock).set(null);
137 Mockito.verify(tlsMapRequestMock).get();
138 Mockito.verifyNoMoreInteractions(tlsMapRequestMock);
139 Mockito.verify(mapResolverMock).handleMapRequest(mapRequest);
140 Mockito.verify(tlsMapReplyMock).set(Mockito.any());
141 Mockito.verify(tlsMapReplyMock).get();
143 assertEquals(result, mapReply);
147 * Tests {@link LispMappingService#handleMapRequest} method request from non-proxy xTR.
150 public void handleMapRequestTest_NonProxy() {
151 final MapRequest mapRequest = Mockito.mock(MapRequest.class);
152 final Pair<MapRequest, TransportAddress> pair = getDefaultMapRequestPair();
153 final SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder()
154 .setMapRequest(pair.getLeft())
155 .setTransportAddress(pair.getRight());
157 Mockito.when(tlsMapRequestMock.get()).thenReturn(pair);
159 assertNull(lispMappingService.handleMapRequest(mapRequest));
160 Mockito.verify(odlLispSbService).sendMapRequest(smrib.build());
164 * Tests {@link LispMappingService#handleMapRegister} method.
167 @SuppressWarnings("unchecked")
168 public void handleMapRegisterTest() {
169 final Pair<MapNotify, List<TransportAddress>> pairMock = Mockito.mock(Pair.class);
171 Mockito.when(tlsMapNotifyMock.get()).thenReturn(pairMock);
173 lispMappingService.handleMapRegister(mapRegisterMock);
174 Mockito.verify(mapServerMock).handleMapRegister(mapRegisterMock);
175 Mockito.verify(tlsMapNotifyMock).set(Mockito.any());
179 * Tests {@link LispMappingService#onAddMapping} method.
182 public void onAddMappingTest() {
183 final org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregisternotification.MapRegister
184 mapRegister = Mockito.mock(org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
185 .mapregisternotification.MapRegister.class);
186 final AddMapping addMapping = Mockito.mock(AddMapping.class);
188 Mockito.when(addMapping.getMapRegister()).thenReturn(mapRegister);
189 Mockito.when(tlsMapNotifyMock.get()).thenReturn(getDefaultMapNotifyPair());
191 lispMappingService.onAddMapping(addMapping);
192 Mockito.verify(odlLispSbService, Mockito.times(2)).sendMapNotify(Mockito.argThat(new TransportAddressMatch()));
196 * Tests {@link LispMappingService#onAddMapping} method with no TransportAddress.
199 public void onAddMappingTest_noTransportAddress() {
200 final org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapregisternotification.MapRegister
201 mapRegister = Mockito.mock(org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
202 .mapregisternotification.MapRegister.class);
203 final AddMapping addMapping = Mockito.mock(AddMapping.class);
204 final MapNotify mapNotify = new MapNotifyBuilder().setKeyId((short) 1).build();
206 Mockito.when(addMapping.getMapRegister()).thenReturn(mapRegister);
207 Mockito.when(tlsMapNotifyMock.get()).thenReturn(new MutablePair<>(mapNotify, null));
208 Mockito.when(addMapping.getTransportAddress()).thenReturn(TRANSPORT_ADDRESS_1);
211 final SendMapNotifyInputBuilder smnib = new SendMapNotifyInputBuilder()
212 .setMapNotify(new org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
213 .mapnotifymessage.MapNotifyBuilder().setKeyId((short) 1).build())
214 .setTransportAddress(TRANSPORT_ADDRESS);
216 lispMappingService.onAddMapping(addMapping);
217 Mockito.verify(odlLispSbService).sendMapNotify(smnib.build());
221 * Tests {@link LispMappingService#onRequestMapping} method.
224 public void onRequestMappingTest() {
225 final RequestMapping requestMapping = Mockito.mock(RequestMapping.class);
226 final org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequest
227 mapRequest = Mockito.mock(org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
228 .maprequestnotification.MapRequest.class);
229 final MapReply mapReply = new MapReplyBuilder().build();
231 Mockito.when(requestMapping.getMapRequest()).thenReturn(mapRequest);
232 Mockito.when(requestMapping.getTransportAddress()).thenReturn(TRANSPORT_ADDRESS_1);
233 Mockito.when(tlsMapReplyMock.get()).thenReturn(mapReply);
236 final SendMapReplyInputBuilder smrib = new SendMapReplyInputBuilder()
237 .setMapReply(new MapReplyBuilder(mapReply).build())
238 .setTransportAddress(TRANSPORT_ADDRESS_1);
240 lispMappingService.onRequestMapping(requestMapping);
241 Mockito.verify(odlLispSbService).sendMapReply(smrib.build());
245 * Tests {@link LispMappingService#onRequestMapping} method with mapReply == null.
248 public void onRequestMappingTest_withNullMapReply() {
249 final RequestMapping requestMapping = Mockito.mock(RequestMapping.class);
250 final org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.maprequestnotification.MapRequest
251 mapRequest = Mockito.mock(org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105
252 .maprequestnotification.MapRequest.class);
254 Mockito.when(requestMapping.getMapRequest()).thenReturn(mapRequest);
255 Mockito.when(tlsMapReplyMock.get()).thenReturn(null);
257 lispMappingService.onRequestMapping(requestMapping);
258 Mockito.verifyZeroInteractions(odlLispSbService);
262 * Tests {@link LispMappingService#onMappingKeepAlive} method.
265 public void onMappingKeepAliveTest() {
266 final MappingKeepAlive mappingKeepAlive = Mockito.mock(MappingKeepAlive.class);
267 Mockito.when(mappingKeepAlive.getMapRegisterCacheMetadata()).thenReturn(getDefaultMapRegisterCacheMetadata());
269 lispMappingService.onMappingKeepAlive(mappingKeepAlive);
270 Mockito.verify(mappingService).refreshMappingRegistration(IPV4_EID_1, null, TIMESTAMP);
271 Mockito.verify(mappingService).refreshMappingRegistration(IPV4_EID_2, null, TIMESTAMP);
275 * Tests {@link LispMappingService#handleSMR} method.
278 public void handleSmrTest() {
279 final MapRequest mapRequest = Mockito.mock(MapRequest.class);
280 final Rloc subscriber = LispAddressUtil.asIpv4Rloc(IPV4_STRING_1);
282 Mockito.when(mapRequest.getSourceEid()).thenReturn(new SourceEidBuilder().setEid(IPV4_SOURCE_EID).build());
283 Mockito.when(mapRequest.getEidItem()).thenReturn(Lists.newArrayList(EID_ITEM_BUILDER.build()));
286 final SendMapRequestInputBuilder smrib = new SendMapRequestInputBuilder()
287 .setMapRequest(new MapRequestBuilder(mapRequest).build())
288 .setTransportAddress(TRANSPORT_ADDRESS);
290 lispMappingService.handleSMR(mapRequest, subscriber);
291 Mockito.verify(odlLispSbService).sendMapRequest(smrib.build());
295 * Tests {@link LispMappingService#setShouldUseSmr} method.
298 public void setShouldUseSmrTest() {
299 final boolean value = true;
301 lispMappingService.setShouldUseSmr(value);
302 Mockito.verify(mapServerMock).setSubscriptionService(value);
303 Mockito.verify(mapResolverMock).setSubscriptionService(value);
307 * Tests {@link LispMappingService#handleMapNotify} method.
310 @SuppressWarnings("unchecked")
311 public void handleMapNotifyTest() {
312 final MapNotify mapNotify = Mockito.mock(MapNotify.class);
313 final List<TransportAddress> list = Mockito.mock(ArrayList.class);
315 lispMappingService.handleMapNotify(mapNotify, list);
316 Mockito.verify(tlsMapNotifyMock).set(Mockito.any(MutablePair.class));
320 * Tests {@link LispMappingService#handleNonProxyMapRequest} method.
323 @SuppressWarnings("unchecked")
324 public void handleNonProxyMapRequestTest() {
325 final MapRequest mapRequest = Mockito.mock(MapRequest.class);
326 final TransportAddress transportAddress = Mockito.mock(TransportAddress.class);
328 lispMappingService.handleNonProxyMapRequest(mapRequest, transportAddress);
329 Mockito.verify(tlsMapRequestMock).set(Mockito.any(MutablePair.class));
333 * Tests {@link LispMappingService#handleMapReply} method.
336 public void handleMapReplyTest() {
337 final MapReply mapReply = Mockito.mock(MapReply.class);
339 lispMappingService.handleMapReply(mapReply);
340 Mockito.verify(tlsMapReplyMock).set(Mockito.any(MapReply.class));
344 * Tests {@link LispMappingService#close} method.
347 public void closeTest() throws Exception {
348 setMock("rpcRegistration", rpcRegistration);
349 setMock("listenerRegistration", listenerRegistration);
350 setMock("cssRegistration", cssRegistration);
351 lispMappingService.close();
352 Mockito.verify(rpcRegistration).close();
353 Mockito.verify(listenerRegistration).close();
354 Mockito.verify(cssRegistration).close();
355 assertNull(getField("mapResolver"));
356 assertNull(getField("mapServer"));
360 * Tests {@link LispMappingService} other setter and getter methods.
363 public void otherTest() throws Exception {
364 assertEquals(notificationService, lispMappingService.getNotificationService());
365 assertEquals(true, lispMappingService.shouldUseSmr());
367 lispMappingService.setShouldAuthenticate(true);
368 Mockito.verify(mapResolverMock).setShouldAuthenticate(true);
370 lispMappingService.onGotMapReply(Mockito.mock(GotMapReply.class));
371 lispMappingService.onGotMapNotify(Mockito.mock(GotMapNotify.class));
372 lispMappingService.onXtrRequestMapping(Mockito.mock(XtrRequestMapping.class));
373 lispMappingService.onXtrReplyMapping(Mockito.mock(XtrReplyMapping.class));
376 private void setMock(final String fieldName, final Object value)
377 throws IllegalAccessException, NoSuchFieldException {
378 final Field field = LispMappingService.class.getDeclaredField(fieldName);
379 field.setAccessible(true);
380 field.set(lispMappingService, value);
383 @SuppressWarnings("unchecked")
384 private <T> T getField(String fieldName) throws NoSuchFieldException, IllegalAccessException {
385 final Field field = LispMappingService.class.getDeclaredField(fieldName);
386 field.setAccessible(true);
388 return (T) field.get(lispMappingService);
391 private static Pair<MapNotify, List<TransportAddress>> getDefaultMapNotifyPair() {
392 final MapNotify mapNotify = new MapNotifyBuilder().setKeyId((short) 1).build();
393 return new MutablePair<>(mapNotify, Lists.newArrayList(TRANSPORT_ADDRESS_1, TRANSPORT_ADDRESS_2));
396 private static Pair<MapRequest, TransportAddress> getDefaultMapRequestPair() {
397 final MapRequestBuilder mapRequestBuilder = new MapRequestBuilder()
398 .setEidItem(Lists.newArrayList(EID_ITEM_BUILDER.build()));
400 return new ImmutablePair<>(mapRequestBuilder.build(), TRANSPORT_ADDRESS_1);
403 private static MapRegisterCacheMetadata getDefaultMapRegisterCacheMetadata() {
404 final EidLispAddress eidLispAddress_1 = new EidLispAddressBuilder()
405 .setEidLispAddressId("id-1")
406 .setEid(IPV4_EID_1).build();
407 final EidLispAddress eidLispAddress_2 = new EidLispAddressBuilder()
408 .setEidLispAddressId("id-2")
409 .setEid(IPV4_EID_2).build();
411 return new MapRegisterCacheMetadataBuilder()
412 .setEidLispAddress(BindingMap.ordered(eidLispAddress_1, eidLispAddress_2))
413 .setTimestamp(TIMESTAMP).build();
416 class TransportAddressMatch implements ArgumentMatcher<SendMapNotifyInput> {
418 public boolean matches(SendMapNotifyInput sendMapNotify) {
419 final TransportAddress notifyTransportAddress = sendMapNotify.getTransportAddress();
420 return TRANSPORT_ADDRESS_1.equals(notifyTransportAddress)
421 || TRANSPORT_ADDRESS_2.equals(notifyTransportAddress);