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