Fix findbug and checkstyle issues
[bgpcep.git] / bgp / path-selection-mode / src / test / java / org / opendaylight / protocol / bgp / mode / impl / base / BasePathSelectorTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.mode.impl.base;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12
13 import com.google.common.collect.Lists;
14 import com.google.common.collect.Sets;
15 import com.google.common.primitives.UnsignedInteger;
16 import java.util.ArrayList;
17 import java.util.List;
18 import org.junit.Test;
19 import org.opendaylight.protocol.bgp.mode.impl.BestPathStateImpl;
20 import org.opendaylight.protocol.bgp.rib.spi.RouterIds;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.as.path.Segments;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.as.path.SegmentsBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev171207.PeerId;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.BgpOrigin;
26 import org.opendaylight.yangtools.yang.common.QName;
27 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
29 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
30 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
31 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
32 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
33 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
34 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
35 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeSchemaAwareBuilder;
36 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
37 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListNodeBuilder;
38
39 public class BasePathSelectorTest {
40
41     public static final QName ATTRS_EXTENSION_Q = QName.create("urn:opendaylight:params:xml:ns:yang:bgp-inet",
42             "2017-12-07", "attributes");
43     public static final QName AS_NUMBER_Q = QName.create(ATTRS_EXTENSION_Q, "as-number");
44     public static final NodeIdentifier SEGMENTS_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q,
45             Segments.QNAME.getLocalName()));
46     public static final NodeIdentifier SEQ_LEAFLIST_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q,
47             "as-sequence"));
48     public static final UnkeyedListEntryNode SEQ_SEGMENT = Builders.unkeyedListEntryBuilder()
49             .withNodeIdentifier(SEGMENTS_NID).addChild(Builders.orderedLeafSetBuilder()
50                     .withNodeIdentifier(SEQ_LEAFLIST_NID)
51                     .addChild(Builders.leafSetEntryBuilder()
52                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 1L)).withValue(1L).build())
53                     .addChild(Builders.leafSetEntryBuilder()
54                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 2L)).withValue(2L).build())
55                     .addChild(Builders.leafSetEntryBuilder()
56                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 3L)).withValue(3L).build())
57                     .build()).build();
58     private static final NodeIdentifier SET_LEAFLIST_NID = new NodeIdentifier(QName.create(ATTRS_EXTENSION_Q,
59             "as-set"));
60     public static final UnkeyedListEntryNode SET_SEGMENT = Builders.unkeyedListEntryBuilder()
61             .withNodeIdentifier(SEGMENTS_NID).addChild(Builders.leafSetBuilder().withNodeIdentifier(SET_LEAFLIST_NID)
62                     .addChild(Builders.leafSetEntryBuilder()
63                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 10L)).withValue(10L).build())
64                     .addChild(Builders.leafSetEntryBuilder()
65                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 11L)).withValue(11L).build())
66                     .build()).build();
67     private static final UnkeyedListEntryNode SEQ_SEGMENT2 = Builders.unkeyedListEntryBuilder()
68             .withNodeIdentifier(SEGMENTS_NID).addChild(Builders.orderedLeafSetBuilder()
69                     .withNodeIdentifier(SEQ_LEAFLIST_NID)
70                     .addChild(Builders.leafSetEntryBuilder()
71                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 20L)).withValue(20L).build())
72                     .addChild(Builders.leafSetEntryBuilder()
73                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 2L)).withValue(2L).build())
74                     .addChild(Builders.leafSetEntryBuilder()
75                             .withNodeIdentifier(new NodeWithValue<>(AS_NUMBER_Q, 3L)).withValue(3L).build())
76                     .build()).build();
77     private static final QName LOCAL_PREF_Q_NAME = QName.create(ATTRS_EXTENSION_Q, "local-pref");
78     private static final QName MULTI_EXIT_DISC_Q_NAME = QName.create(ATTRS_EXTENSION_Q, "multi-exit-disc");
79     private static final QName ORIGIN_Q_NAME = QName.create(ATTRS_EXTENSION_Q, "origin");
80     private static final QName AS_PATH_Q_NAME = QName.create(ATTRS_EXTENSION_Q, "as-path");
81     private static final UnsignedInteger ROUTER_ID = RouterIds.routerIdForAddress("127.0.0.1");
82     static final UnsignedInteger ROUTER_ID2 = RouterIds.routerIdForPeerId(new PeerId("bgp://127.0.0.1"));
83     private static final UnsignedInteger ROUTER_ID3 = RouterIds.routerIdForPeerId(new PeerId("bgp://127.0.0.2"));
84     private final BasePathSelector selector = new BasePathSelector(20L);
85     private final BestPathStateImpl state = new BestPathStateImpl(createStateFromPrefMedOriginASPath().build());
86     private final BaseBestPath originBestPath = new BaseBestPath(ROUTER_ID, this.state);
87
88     @Test
89     public void testBestPathForEquality() {
90         this.selector.processPath(ROUTER_ID2, createStateFromPrefMedOriginASPath().build());
91         final BaseBestPath processedPath = this.selector.result();
92
93         assertEquals(this.originBestPath.getPeerId(), processedPath.getPeerId());
94         assertEquals(this.originBestPath.getState().getLocalPref(), processedPath.getState().getLocalPref());
95         assertEquals(this.originBestPath.getState().getMultiExitDisc(), processedPath.getState().getMultiExitDisc());
96         assertEquals(this.originBestPath.getState().getOrigin(), processedPath.getState().getOrigin());
97         assertEquals(this.originBestPath.getState().getPeerAs(), processedPath.getState().getPeerAs());
98         assertEquals(this.originBestPath.getState().getAsPathLength(), processedPath.getState().getAsPathLength());
99     }
100
101     @Test
102     public void testBestPathWithHigherLocalPref() {
103         this.selector.processPath(ROUTER_ID2, createStateFromPrefMedOrigin());   // local-pref 123
104         BaseBestPath processedPath = this.selector.result();
105         assertEquals(123L, processedPath.getState().getLocalPref().longValue());
106
107         this.selector.processPath(ROUTER_ID2, createStateFromPrefMedOriginASPath().build());   // local-pref 321
108         processedPath = this.selector.result();
109         assertEquals(321L, processedPath.getState().getLocalPref().longValue());
110
111         DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder =
112                 createContBuilder(ATTRS_EXTENSION_Q);
113         addLowerLocalRef(dataContBuilder); // prefer path with higher LOCAL_PREF
114         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
115         processedPath = this.selector.result();
116         assertEquals(321L, processedPath.getState().getLocalPref().longValue());
117     }
118
119     @Test
120     public void testBestPathSelectionOptions() {
121         DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder
122                 = createStateFromPrefMedOriginASPath();
123         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
124         BaseBestPath processedPath = this.selector.result();
125         assertEquals(1, processedPath.getState().getOrigin().getIntValue());
126
127         addIgpOrigin(dataContBuilder); // prefer the path with the lowest origin type
128         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
129         processedPath = this.selector.result();
130         assertEquals(0, processedPath.getState().getOrigin().getIntValue());
131
132         addEgpOrigin(dataContBuilder);
133         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
134         processedPath = this.selector.result();
135         assertEquals(0, processedPath.getState().getOrigin().getIntValue());
136
137         // prefer the path with the lowest multi-exit discriminator (MED)
138         assertEquals(4321L, (long) processedPath.getState().getMultiExitDisc());
139         addIgpOrigin(dataContBuilder);
140         addLowerMultiExitDisc(dataContBuilder);
141         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
142         processedPath = this.selector.result();
143         assertEquals(1234L, (long) processedPath.getState().getMultiExitDisc());
144
145         addHigherMultiExitDisc(dataContBuilder);
146         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
147         processedPath = this.selector.result();
148         assertEquals(1234L, (long) processedPath.getState().getMultiExitDisc());
149
150         addLowerMultiExitDisc(dataContBuilder);
151         addAsPath(dataContBuilder, SEQ_SEGMENT2);
152         assertEquals(1L, (long) processedPath.getState().getPeerAs());
153         assertEquals(3, processedPath.getState().getAsPathLength());
154         this.selector.processPath(ROUTER_ID2, dataContBuilder.build());
155         processedPath = this.selector.result();
156         assertEquals(1L, (long) processedPath.getState().getPeerAs());
157         assertEquals(3, processedPath.getState().getAsPathLength());
158     }
159
160     @Test
161     public void testBestPathForNonEquality() {
162         this.selector.processPath(ROUTER_ID3, createStateFromPrefMedOrigin());
163         final BaseBestPath processedPath = this.selector.result();
164
165         assertNotEquals(this.originBestPath.getPeerId(), processedPath.getPeerId());
166         assertNotEquals(this.originBestPath.getState().getLocalPref(), processedPath.getState().getLocalPref());
167         assertNotEquals(this.originBestPath.getState().getMultiExitDisc(), processedPath.getState().getMultiExitDisc());
168         assertNotEquals(this.originBestPath.getState().getOrigin(), processedPath.getState().getOrigin());
169         assertNotEquals(this.originBestPath.getState().getPeerAs(), processedPath.getState().getPeerAs());
170         assertNotEquals(this.originBestPath.getState().getAsPathLength(), processedPath.getState().getAsPathLength());
171     }
172
173     private static ContainerNode createStateFromPrefMedOrigin() {
174         DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder
175                 = createContBuilder(ATTRS_EXTENSION_Q);
176         addLowerLocalRef(dataContBuilder);
177         addLowerMultiExitDisc(dataContBuilder);
178         addIgpOrigin(dataContBuilder);
179         return dataContBuilder.build();
180     }
181
182     static DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createStateFromPrefMedOriginASPath() {
183         DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder
184                 = createContBuilder(ATTRS_EXTENSION_Q);
185         addHigherLocalRef(dataContBuilder);
186         addHigherMultiExitDisc(dataContBuilder);
187         addEgpOrigin(dataContBuilder);
188         addAsPath(dataContBuilder,SEQ_SEGMENT);
189         return dataContBuilder;
190     }
191
192     private static void addLowerLocalRef(
193             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
194         dataContBuilder.addChild(createContBuilder(LOCAL_PREF_Q_NAME)
195                 .addChild(createValueBuilder(123L, LOCAL_PREF_Q_NAME, "pref").build()).build());
196     }
197
198     private static void addHigherLocalRef(
199             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
200         dataContBuilder.addChild(createContBuilder(LOCAL_PREF_Q_NAME)
201                 .addChild(createValueBuilder(321L, LOCAL_PREF_Q_NAME, "pref").build()).build());
202     }
203
204     private static void addLowerMultiExitDisc(
205             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
206         dataContBuilder.addChild(createContBuilder(MULTI_EXIT_DISC_Q_NAME)
207                 .addChild(createValueBuilder(1234L, MULTI_EXIT_DISC_Q_NAME, "med").build()).build());
208     }
209
210     private static void addHigherMultiExitDisc(
211             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
212         dataContBuilder.addChild(createContBuilder(MULTI_EXIT_DISC_Q_NAME)
213                 .addChild(createValueBuilder(4321L, MULTI_EXIT_DISC_Q_NAME, "med").build()).build());
214     }
215
216     private static void addIgpOrigin(
217             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
218         dataContBuilder.addChild(createContBuilder(ORIGIN_Q_NAME)
219                 .addChild(createValueBuilder("igp", ORIGIN_Q_NAME, "value").build()).build());
220     }
221
222     private static void addEgpOrigin(
223             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder) {
224         dataContBuilder.addChild(createContBuilder(ORIGIN_Q_NAME)
225                 .addChild(createValueBuilder("egp", ORIGIN_Q_NAME, "value").build()).build());
226     }
227
228     private static void addAsPath(final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder,
229             final UnkeyedListEntryNode segment) {
230         final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> asPathContBuilder
231                 = ImmutableContainerNodeSchemaAwareBuilder.create();
232         asPathContBuilder.withNodeIdentifier(new NodeIdentifier(AS_PATH_Q_NAME));
233
234         final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> segments
235                 = ImmutableUnkeyedListNodeBuilder.create();
236         segments.withNodeIdentifier(SEGMENTS_NID);
237         segments.addChild(segment);
238         asPathContBuilder.addChild(segments.build());
239         dataContBuilder.addChild(asPathContBuilder.build());
240     }
241
242
243     private static DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> createContBuilder(final QName qname) {
244         return ImmutableContainerNodeSchemaAwareBuilder.create().withNodeIdentifier(new NodeIdentifier(qname));
245     }
246
247     private static <T> ImmutableLeafNodeBuilder<T> createValueBuilder(final T value, final QName qname,
248             final String localName) {
249         final ImmutableLeafNodeBuilder<T> valueBuilder = new ImmutableLeafNodeBuilder<>();
250         valueBuilder.withNodeIdentifier(new NodeIdentifier(QName.create(qname, localName))).withValue(value);
251         return valueBuilder;
252     }
253
254     @Test
255     public void testExtractSegments() {
256         // to be extracted from
257         final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = Builders.unkeyedListBuilder();
258         builder.withNodeIdentifier(SEGMENTS_NID);
259         builder.addChild(SET_SEGMENT);
260         builder.addChild(SEQ_SEGMENT);
261
262         // expected
263         final List<AsNumber> sequences = new ArrayList<>();
264         sequences.add(new AsNumber(1L));
265         sequences.add(new AsNumber(2L));
266         sequences.add(new AsNumber(3L));
267         final List<Segments> expected = new ArrayList<>();
268         expected.add(new SegmentsBuilder()
269                 .setAsSet(Lists.newArrayList(new AsNumber(11L), new AsNumber(10L))).build());
270         expected.add(new SegmentsBuilder().setAsSequence(sequences).build());
271         // test
272         final List<Segments> actual = this.state.extractSegments(builder.build());
273         assertEquals(expected.size(), actual.size());
274         assertEquals(Sets.newHashSet(1, 2, 3), Sets.newHashSet(1, 3, 2));
275         assertEquals(Sets.newHashSet(expected.get(0).getAsSet()), Sets.newHashSet(actual.get(0).getAsSet()));
276         assertEquals(expected.get(1), actual.get(1));
277     }
278
279     @Test(expected = IllegalArgumentException.class)
280     public void testBgpOrigin() {
281         DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> dataContBuilder
282                 = createContBuilder(ATTRS_EXTENSION_Q);
283         final ContainerNode containerIncom = dataContBuilder.addChild(createContBuilder(ORIGIN_Q_NAME)
284                 .addChild(createValueBuilder("incomplete", ORIGIN_Q_NAME, "value")
285                         .build()).build()).build();
286         this.selector.processPath(ROUTER_ID3, containerIncom);
287         final BaseBestPath processedPathIncom = this.selector.result();
288         assertEquals(BgpOrigin.Incomplete, processedPathIncom.getState().getOrigin());
289
290         final ContainerNode containerException = dataContBuilder.addChild(createContBuilder(ORIGIN_Q_NAME)
291                 .addChild(createValueBuilder("LOL", ORIGIN_Q_NAME, "value").build()).build()).build();
292         this.selector.processPath(ROUTER_ID3, containerException);
293         final BaseBestPath processedPathException = this.selector.result();
294         processedPathException.getState().getOrigin();
295     }
296 }