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