Merge "Add EPL license declaration"
[bgpcep.git] / bgp / parser-impl / src / test / java / org / opendaylight / protocol / bgp / parser / impl / ParserTest.java
1 /*
2  * Copyright (c) 2013 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.parser.impl;
9
10 import static org.junit.Assert.assertArrayEquals;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNull;
13 import static org.junit.Assert.assertThat;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16 import static org.junit.matchers.JUnitMatchers.containsString;
17
18 import java.net.UnknownHostException;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
26 import org.opendaylight.protocol.bgp.parser.BGPError;
27 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
28 import org.opendaylight.protocol.bgp.parser.BgpTableTypeImpl;
29 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
30 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
31 import org.opendaylight.protocol.util.ByteArray;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateAddressFamily;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.LinkstateSubsequentAddressFamily;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParameters;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.open.BgpParametersBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.BgpTableType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.CMultiprotocolBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.open.bgp.parameters.c.parameters.c.multiprotocol.MultiprotocolCapabilityBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.UnicastSubsequentAddressFamily;
49 import org.opendaylight.yangtools.yang.binding.Notification;
50
51 import com.google.common.collect.Lists;
52 import com.google.common.collect.Maps;
53
54 public class ParserTest {
55
56         public static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
57                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
58                 (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
59                 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
60
61         public static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
62                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
63                 (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
64
65         public static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
66                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
67                 (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
68
69         public static final byte[] openWithCpblt1 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
70                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
71                 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
72                 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
73                 (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x40,
74                 (byte) 0x04, (byte) 0x00, (byte) 0x47 };
75
76         public static final byte[] openWithCpblt2 = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
77                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
78                 (byte) 0xff, (byte) 0x00, (byte) 0x2d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x48, (byte) 0x00, (byte) 0xb4,
79                 (byte) 0xac, (byte) 0x14, (byte) 0xa0, (byte) 0xaa, (byte) 0x10, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04,
80                 (byte) 0x40, (byte) 0x04, (byte) 0x00, (byte) 0x47, (byte) 0x02, (byte) 0x06, (byte) 0x01, (byte) 0x04, (byte) 0x00,
81                 (byte) 0x01, (byte) 0x00, (byte) 0x01 };
82
83         static MessageRegistry reg;
84
85         @BeforeClass
86         public static void setupClass() throws Exception {
87                 reg = ServiceLoaderBGPExtensionProviderContext.createConsumerContext().getMessageRegistry();
88         }
89
90         @Test
91         public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
92                 byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
93                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00 };
94                 wrong = ByteArray.cutBytes(wrong, 16);
95                 try {
96                         ParserTest.reg.parseMessage(wrong);
97                         fail("Exception should have occcured.");
98                 } catch (final IllegalArgumentException e) {
99                         assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
100                         return;
101                 }
102                 fail();
103         }
104
105         @Test
106         public void testBadMsgType() throws BGPParsingException {
107                 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
108                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
109                                 (byte) 0x00, (byte) 0x13, (byte) 0x08 };
110                 try {
111                         ParserTest.reg.parseMessage(bytes);
112                         fail("Exception should have occured.");
113                 } catch (final BGPDocumentedException e) {
114                         assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
115                         return;
116                 }
117                 fail();
118         }
119
120         @Test
121         public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
122                 final Notification keepAlive = new KeepaliveBuilder().build();
123                 final byte[] bytes = ParserTest.reg.serializeMessage(keepAlive);
124                 assertArrayEquals(keepAliveBMsg, bytes);
125
126                 final Notification m = ParserTest.reg.parseMessage(bytes);
127
128                 assertTrue(m instanceof Keepalive);
129         }
130
131         @Test
132         public void testBadKeepAliveMsg() throws BGPParsingException {
133                 final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
134                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
135                                 (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
136
137                 try {
138                         ParserTest.reg.parseMessage(bytes);
139                         fail("Exception should have occured.");
140                 } catch (final BGPDocumentedException e) {
141                         assertThat(e.getMessage(), containsString("Message length field not within valid range."));
142                         assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
143                         return;
144                 }
145                 fail();
146         }
147
148         @Test
149         public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
150                 final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
151                                 new ProtocolVersion((short) 4)).build();
152                 final byte[] bytes = ParserTest.reg.serializeMessage(open);
153                 assertArrayEquals(openBMsg, bytes);
154
155                 final Notification m = ParserTest.reg.parseMessage(bytes);
156
157                 assertTrue(m instanceof Open);
158                 assertEquals(100, ((Open) m).getMyAsNumber().intValue());
159                 assertEquals(180, ((Open) m).getHoldTimer().intValue());
160                 assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
161                 assertTrue(((Open) m).getBgpParameters().isEmpty());
162         }
163
164         @Test
165         public void testBadHoldTimeError() throws BGPParsingException {
166                 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
167                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
168                                 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
169                                 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
170
171                 try {
172                         ParserTest.reg.parseMessage(bMsg);
173                         fail("Exception should have occured.");
174                 } catch (final BGPDocumentedException e) {
175                         assertEquals("Hold time value not acceptable.", e.getMessage());
176                         assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
177                         return;
178                 }
179                 fail();
180         }
181
182         @Test
183         public void testBadMsgLength() throws BGPParsingException {
184                 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
185                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
186                                 (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
187                                 (byte) 0xff, (byte) 0xff };
188
189                 try {
190                         ParserTest.reg.parseMessage(bMsg);
191                         fail("Exception should have occured.");
192                 } catch (final BGPDocumentedException e) {
193                         assertEquals("Open message too small.", e.getMessage());
194                         assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
195                 }
196         }
197
198         @Test
199         public void testBadVersion() throws BGPParsingException {
200                 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
201                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
202                                 (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
203                                 (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
204
205                 try {
206                         ParserTest.reg.parseMessage(bMsg);
207                         fail("Exception should have occured.");
208                 } catch (final BGPDocumentedException e) {
209                         assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
210                         assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
211                         return;
212                 }
213                 fail();
214         }
215
216         @Test
217         public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
218                 Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
219                                 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
220                 byte[] bytes = ParserTest.reg.serializeMessage(notMsg);
221                 assertArrayEquals(notificationBMsg, bytes);
222
223                 Notification m = ParserTest.reg.parseMessage(bytes);
224
225                 assertTrue(m instanceof Notify);
226                 assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
227                 assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
228
229                 notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
230                                 BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
231                 bytes = ParserTest.reg.serializeMessage(notMsg);
232
233                 m = ParserTest.reg.parseMessage(bytes);
234
235                 assertTrue(m instanceof Notify);
236                 assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
237                 assertNull(((Notify) m).getData());
238         }
239
240         @Test
241         public void testWrongLength() throws BGPParsingException {
242                 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
243                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
244                                 (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
245
246                 try {
247                         ParserTest.reg.parseMessage(bMsg);
248                         fail("Exception should have occured.");
249                 } catch (final BGPDocumentedException e) {
250                         assertEquals("Notification message too small.", e.getMessage());
251                         assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
252                         return;
253                 }
254                 fail();
255         }
256
257         @Test
258         public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
259                 final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
260                                 (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
261                                 (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
262
263                 try {
264                         ParserTest.reg.parseMessage(bMsg);
265                         fail("Exception should have occured.");
266                 } catch (final IllegalArgumentException e) {
267                         assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
268                         return;
269                 }
270                 fail();
271         }
272
273         @Test
274         public void testTLVParser() throws UnknownHostException {
275
276                 final BgpTableType t1 = new BgpTableTypeImpl(Ipv4AddressFamily.class, UnicastSubsequentAddressFamily.class);
277                 final BgpTableType t2 = new BgpTableTypeImpl(LinkstateAddressFamily.class, UnicastSubsequentAddressFamily.class);
278
279                 final List<BgpParameters> tlvs = Lists.newArrayList();
280
281                 tlvs.add(new BgpParametersBuilder().setCParameters(
282                                 new CMultiprotocolBuilder().setMultiprotocolCapability(
283                                                 new MultiprotocolCapabilityBuilder().setAfi(LinkstateAddressFamily.class).setSafi(
284                                                                 LinkstateSubsequentAddressFamily.class).build()).build()).build());
285                 tlvs.add(new BgpParametersBuilder().setCParameters(
286                                 new CMultiprotocolBuilder().setMultiprotocolCapability(
287                                                 new MultiprotocolCapabilityBuilder().setAfi(Ipv4AddressFamily.class).setSafi(UnicastSubsequentAddressFamily.class).build()).build()).build());
288
289                 final Map<BgpTableType, Boolean> tableTypes = Maps.newHashMap();
290                 tableTypes.put(t1, true);
291                 tableTypes.put(t2, true);
292                 final Open open = new OpenBuilder().setMyAsNumber(72).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("172.20.160.170")).setVersion(
293                                 new ProtocolVersion((short) 4)).setBgpParameters(tlvs).build();
294
295                 final byte[] result = ParserTest.reg.serializeMessage(open);
296
297                 // the capabilities can be swapped.
298                 assertTrue(Arrays.equals(openWithCpblt1, result) || Arrays.equals(openWithCpblt2, result));
299         }
300 }