Merge "Removed linkstate dependency from bgp-parser-impl."
[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.hamcrest.CoreMatchers.containsString;
11 import static org.junit.Assert.assertArrayEquals;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertThat;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import java.net.UnknownHostException;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
23 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
24 import org.opendaylight.protocol.bgp.parser.BGPError;
25 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
26 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
27 import org.opendaylight.protocol.bgp.parser.spi.pojo.ServiceLoaderBGPExtensionProviderContext;
28 import org.opendaylight.protocol.util.ByteArray;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Keepalive;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.KeepaliveBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Notify;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.NotifyBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.Open;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.OpenBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.ProtocolVersion;
37 import org.opendaylight.yangtools.yang.binding.Notification;
38
39 public class ParserTest {
40
41     private static final byte[] openBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
42         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
43         (byte) 0xff, (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4,
44         (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
45
46     private static final byte[] keepAliveBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
47         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
48         (byte) 0xff, (byte) 0x00, (byte) 0x13, (byte) 0x04 };
49
50     private static final byte[] notificationBMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
51         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
52         (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x17, (byte) 0x03, (byte) 0x02, (byte) 0x04, (byte) 0x04, (byte) 0x09 };
53
54     private static final byte[] updMsgWithUnrecognizedAttribute = new byte[] {
55         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
56         (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x79, (byte) 0x02,
57         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x62, (byte) 0x90, (byte) 0x0e, (byte) 0x00, (byte) 0x34, (byte) 0x40, (byte) 0x04, (byte) 0x47, (byte) 0x04, (byte) 0x0a, (byte) 0x19,
58         (byte) 0x02, (byte) 0x1b, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x27, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte)0x00,
59         (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x1a, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x48, (byte) 0x02, (byte)0x01,
60         (byte) 0x00, (byte) 0x04, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x28, (byte) 0x02, (byte) 0x03, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte)0x00,
61         (byte) 0x43, (byte) 0x40, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x40, (byte) 0x02, (byte) 0x00, (byte) 0x40, (byte) 0x05, (byte) 0x04, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte)0x64,
62         (byte) 0x80, (byte) 0x63, (byte) 0x19, (byte) 0x04, (byte) 0x02, (byte) 0x00, (byte) 0x08, (byte) 0x4f, (byte) 0x66, (byte) 0x2d, (byte) 0x39, (byte) 0x6b, (byte) 0x2d, (byte) 0x30, (byte)0x33,
63         (byte) 0x04, (byte) 0x03, (byte) 0x00, (byte) 0x01, (byte) 0x72, (byte) 0x04, (byte) 0x04, (byte) 0x00, (byte) 0x04, (byte) 0x2b, (byte) 0x2b, (byte) 0x2b, (byte) 0x2b
64     };
65
66     static MessageRegistry reg;
67
68     @BeforeClass
69     public static void setupClass() throws Exception {
70         reg = ServiceLoaderBGPExtensionProviderContext.getSingletonInstance().getMessageRegistry();
71     }
72
73     @Test
74     public void testHeaderErrors() throws BGPParsingException, BGPDocumentedException {
75         byte[] wrong = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0x00 };
76         wrong = ByteArray.cutBytes(wrong, 16);
77         try {
78             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(wrong));
79             fail("Exception should have occcured.");
80         } catch (final IllegalArgumentException e) {
81             assertEquals("Too few bytes in passed array. Passed: " + wrong.length + ". Expected: >= 19.", e.getMessage());
82             return;
83         }
84         fail();
85     }
86
87     @Test
88     public void testBadMsgType() throws BGPParsingException {
89         final byte[] bytes = { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
90             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
91             (byte) 0x00, (byte) 0x13, (byte) 0x08 };
92         try {
93             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
94             fail("Exception should have occured.");
95         } catch (final BGPDocumentedException e) {
96             assertEquals(BGPError.BAD_MSG_TYPE, e.getError());
97             return;
98         }
99         fail();
100     }
101
102     @Test
103     public void testKeepAliveMsg() throws BGPParsingException, BGPDocumentedException {
104         final Notification keepAlive = new KeepaliveBuilder().build();
105         final ByteBuf buffer = Unpooled.buffer();
106         ParserTest.reg.serializeMessage(keepAlive, buffer);
107         assertArrayEquals(keepAliveBMsg, ByteArray.getAllBytes(buffer));
108
109         final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(ByteArray.getAllBytes(buffer)));
110
111         assertTrue(m instanceof Keepalive);
112     }
113
114     @Test
115     public void testBadKeepAliveMsg() throws BGPParsingException {
116         final byte[] bytes = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
117             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
118             (byte) 0x00, (byte) 0x14, (byte) 0x04, (byte) 0x05 };
119
120         try {
121             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
122             fail("Exception should have occured.");
123         } catch (final BGPDocumentedException e) {
124             assertThat(e.getMessage(), containsString("Message length field not within valid range."));
125             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
126             return;
127         }
128         fail();
129     }
130
131     @Test
132     public void testOpenMessage() throws UnknownHostException, BGPParsingException, BGPDocumentedException {
133         final Notification open = new OpenBuilder().setMyAsNumber(100).setHoldTimer(180).setBgpIdentifier(new Ipv4Address("20.20.20.20")).setVersion(
134                 new ProtocolVersion((short) 4)).build();
135         final ByteBuf bytes = Unpooled.buffer();
136         ParserTest.reg.serializeMessage(open, bytes);
137         assertArrayEquals(openBMsg, ByteArray.getAllBytes(bytes));
138
139         final Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
140
141         assertTrue(m instanceof Open);
142         assertEquals(100, ((Open) m).getMyAsNumber().intValue());
143         assertEquals(180, ((Open) m).getHoldTimer().intValue());
144         assertEquals(new Ipv4Address("20.20.20.20"), ((Open) m).getBgpIdentifier());
145         assertTrue(((Open) m).getBgpParameters().isEmpty());
146     }
147
148     @Test
149     public void testBadHoldTimeError() throws BGPParsingException {
150         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
151             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
152             (byte) 0x00, (byte) 0x1d, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0x01, (byte) 0x14,
153             (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
154
155         try {
156             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
157             fail("Exception should have occured.");
158         } catch (final BGPDocumentedException e) {
159             assertEquals("Hold time value not acceptable.", e.getMessage());
160             assertEquals(BGPError.HOLD_TIME_NOT_ACC, e.getError());
161             return;
162         }
163         fail();
164     }
165
166     @Test
167     public void testBadMsgLength() throws BGPParsingException {
168         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
169             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
170             (byte) 0x00, (byte) 0x1b, (byte) 0x01, (byte) 0x04, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0xff,
171             (byte) 0xff, (byte) 0xff };
172
173         try {
174             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
175             fail("Exception should have occured.");
176         } catch (final BGPDocumentedException e) {
177             assertEquals("Open message too small.", e.getMessage());
178             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
179         }
180     }
181
182     @Test
183     public void testBadVersion() 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) 0x1d, (byte) 0x01, (byte) 0x08, (byte) 0x00, (byte) 0x64, (byte) 0x00, (byte) 0xb4, (byte) 0x14,
187             (byte) 0x14, (byte) 0x14, (byte) 0x14, (byte) 0x00 };
188
189         try {
190             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
191             fail("Exception should have occured.");
192         } catch (final BGPDocumentedException e) {
193             assertEquals("BGP Protocol version 8 not supported.", e.getMessage());
194             assertEquals(BGPError.VERSION_NOT_SUPPORTED, e.getError());
195             return;
196         }
197         fail();
198     }
199
200     @Test
201     public void testNotificationMsg() throws BGPParsingException, BGPDocumentedException {
202         Notification notMsg = new NotifyBuilder().setErrorCode(BGPError.OPT_PARAM_NOT_SUPPORTED.getCode()).setErrorSubcode(
203                 BGPError.OPT_PARAM_NOT_SUPPORTED.getSubcode()).setData(new byte[] { 4, 9 }).build();
204         final ByteBuf bytes = Unpooled.buffer();
205         ParserTest.reg.serializeMessage(notMsg, bytes);
206         assertArrayEquals(notificationBMsg, ByteArray.subByte(bytes.array(),0,bytes.writerIndex()));
207
208         Notification m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
209
210         assertTrue(m instanceof Notify);
211         assertEquals(BGPError.OPT_PARAM_NOT_SUPPORTED, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
212         assertArrayEquals(new byte[] { 4, 9 }, ((Notify) m).getData());
213
214         notMsg = new NotifyBuilder().setErrorCode(BGPError.CONNECTION_NOT_SYNC.getCode()).setErrorSubcode(
215             BGPError.CONNECTION_NOT_SYNC.getSubcode()).build();
216
217         bytes.clear();
218
219         ParserTest.reg.serializeMessage(notMsg, bytes);
220
221         m = ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bytes));
222
223         assertTrue(m instanceof Notify);
224         assertEquals(BGPError.CONNECTION_NOT_SYNC, BGPError.forValue(((Notify) m).getErrorCode(), ((Notify) m).getErrorSubcode()));
225         assertNull(((Notify) m).getData());
226     }
227
228     @Test
229     public void testWrongLength() throws BGPParsingException {
230         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
231             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
232             (byte) 0x00, (byte) 0x14, (byte) 0x03, (byte) 0x02 };
233
234         try {
235             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
236             fail("Exception should have occured.");
237         } catch (final BGPDocumentedException e) {
238             assertEquals("Notification message too small.", e.getMessage());
239             assertEquals(BGPError.BAD_MSG_LENGTH, e.getError());
240             return;
241         }
242         fail();
243     }
244
245     @Test
246     public void testUnrecognizedError() throws BGPParsingException, BGPDocumentedException {
247         final byte[] bMsg = new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
248             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
249             (byte) 0x00, (byte) 0x15, (byte) 0x03, (byte) 0x02, (byte) 0xaa };
250
251         try {
252             ParserTest.reg.parseMessage(Unpooled.copiedBuffer(bMsg));
253             fail("Exception should have occured.");
254         } catch (final IllegalArgumentException e) {
255             assertEquals("BGP Error code 2 and subcode 170 not recognized.", e.getMessage());
256             return;
257         }
258         fail();
259     }
260
261     @Test
262     public void testParseUpdMsgWithUnrecognizedAttribute() throws BGPDocumentedException, BGPParsingException {
263         try {
264             reg.parseMessage(Unpooled.copiedBuffer(updMsgWithUnrecognizedAttribute));
265             fail("Exception should have occured.");
266         } catch (final BGPDocumentedException e) {
267             assertEquals("Well known attribute not recognized.", e.getMessage());
268             assertEquals(BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED, e.getError());
269             return;
270         }
271         fail();
272     }
273 }