2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.netconf.impl;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.eq;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.verify;
17 import io.netty.channel.ChannelHandler;
18 import io.netty.channel.ChannelInboundHandlerAdapter;
19 import io.netty.channel.ChannelOutboundHandlerAdapter;
20 import io.netty.channel.embedded.EmbeddedChannel;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.Mock;
25 import org.mockito.junit.MockitoJUnitRunner;
26 import org.opendaylight.netconf.api.NetconfMessage;
27 import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader;
28 import org.opendaylight.netconf.api.xml.XmlUtil;
29 import org.opendaylight.netconf.nettyutil.AbstractChannelInitializer;
30 import org.opendaylight.netconf.nettyutil.handler.NetconfEXICodec;
31 import org.opendaylight.netconf.nettyutil.handler.NetconfEXIToMessageDecoder;
32 import org.opendaylight.netconf.nettyutil.handler.NetconfMessageToEXIEncoder;
33 import org.opendaylight.netconf.nettyutil.handler.NetconfMessageToXMLEncoder;
34 import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
35 import org.opendaylight.netconf.nettyutil.handler.exi.EXIParameters;
36 import org.opendaylight.netconf.notifications.NetconfNotification;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.extension.rev131210.NetconfTcp;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.NetconfSsh;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.sessions.Session;
40 import org.w3c.dom.Document;
42 @RunWith(MockitoJUnitRunner.StrictStubs.class)
43 public class NetconfServerSessionTest {
44 private static final String HOST = "127.0.0.1";
45 private static final String PORT = "17830";
46 private static final String SSH_TRANSPORT = "ssh";
47 private static final String TCP_TRANSPORT = "tcp";
48 private static final String SESSION_ID = "1";
49 private static final String USER = "admin";
51 private NetconfServerSession session;
52 private EmbeddedChannel channel;
53 private NetconfMessage msg;
55 private NetconfServerSessionListener listener;
58 public void setUp() throws Exception {
59 final NetconfHelloMessageAdditionalHeader header =
60 new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, SSH_TRANSPORT, SESSION_ID);
61 channel = new EmbeddedChannel();
62 session = new NetconfServerSession(listener, channel, 1L, header);
63 doNothing().when(listener).onSessionUp(any());
64 msg = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc-reply></rpc-reply>"));
68 public void testSessionUp() throws Exception {
70 verify(listener).onSessionUp(session);
74 public void testDelayedClose() throws Exception {
75 doNothing().when(listener).onSessionTerminated(eq(session), any());
76 session.delayedClose();
77 session.sendMessage(msg);
78 channel.runPendingTasks();
79 final Object o = channel.readOutbound();
81 verify(listener).onSessionTerminated(eq(session), any());
85 public void testSendMessage() throws Exception {
86 session.sendMessage(msg);
87 channel.runPendingTasks();
88 final Object o = channel.readOutbound();
93 public void testSendNotification() throws Exception {
94 doNothing().when(listener).onNotification(any(), any());
95 final Document msgDoc = XmlUtil.readXmlToDocument("<notification></notification>");
96 final NetconfNotification notif = new NetconfNotification(msgDoc);
97 session.sendMessage(notif);
98 channel.runPendingTasks();
99 final Object o = channel.readOutbound();
100 assertEquals(notif, o);
101 verify(listener).onNotification(session, notif);
105 public void testOnIncommingRpcSuccess() throws Exception {
107 final Session managementSession = this.session.toManagementSession();
108 this.session.onIncommingRpcSuccess();
109 final Session afterRpcSuccess = this.session.toManagementSession();
110 assertEquals(managementSession.getInRpcs().getValue().toJava() + 1,
111 afterRpcSuccess.getInRpcs().getValue().longValue());
115 public void testOnIncommingRpcFail() throws Exception {
117 final Session managementSession = this.session.toManagementSession();
118 this.session.onIncommingRpcFail();
119 final Session afterRpcSuccess = this.session.toManagementSession();
120 assertEquals(managementSession.getInBadRpcs().getValue().toJava() + 1,
121 afterRpcSuccess.getInBadRpcs().getValue().longValue());
125 public void testOnOutgoingRpcError() throws Exception {
127 final Session managementSession = this.session.toManagementSession();
128 this.session.onOutgoingRpcError();
129 final Session afterRpcSuccess = this.session.toManagementSession();
130 assertEquals(managementSession.getOutRpcErrors().getValue().toJava() + 1,
131 afterRpcSuccess.getOutRpcErrors().getValue().longValue());
135 public void testToManagementSession() throws Exception {
136 final NetconfHelloMessageAdditionalHeader header =
137 new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, TCP_TRANSPORT, SESSION_ID);
138 final EmbeddedChannel ch = new EmbeddedChannel();
139 final NetconfServerSession tcpSession = new NetconfServerSession(listener, ch, 1L, header);
140 tcpSession.sessionUp();
141 final Session managementSession = tcpSession.toManagementSession();
142 assertEquals(HOST, managementSession.getSourceHost().getIpAddress().getIpv4Address().getValue());
143 assertEquals(managementSession.getUsername(), USER);
144 assertEquals(managementSession.getSessionId().toString(), SESSION_ID);
145 assertEquals(managementSession.getTransport(), NetconfTcp.class);
148 @Test(expected = IllegalArgumentException.class)
149 public void testToManagementSessionUnknownTransport() throws Exception {
150 final NetconfHelloMessageAdditionalHeader header =
151 new NetconfHelloMessageAdditionalHeader(USER, HOST, PORT, "http", SESSION_ID);
152 final EmbeddedChannel ch = new EmbeddedChannel();
153 final NetconfServerSession tcpSession = new NetconfServerSession(listener, ch, 1L, header);
154 tcpSession.sessionUp();
155 tcpSession.toManagementSession();
160 public void testToManagementSessionIpv6() throws Exception {
161 final NetconfHelloMessageAdditionalHeader header =
162 new NetconfHelloMessageAdditionalHeader(USER, "::1", PORT, SSH_TRANSPORT, SESSION_ID);
163 final EmbeddedChannel ch = new EmbeddedChannel();
164 final NetconfServerSession tcpSession = new NetconfServerSession(listener, ch, 1L, header);
165 tcpSession.sessionUp();
166 final Session managementSession = tcpSession.toManagementSession();
167 assertEquals("::1", managementSession.getSourceHost().getIpAddress().getIpv6Address().getValue());
168 assertEquals(managementSession.getUsername(), USER);
169 assertEquals(managementSession.getSessionId().toString(), SESSION_ID);
170 assertEquals(managementSession.getTransport(), NetconfSsh.class);
174 public void testThisInstance() throws Exception {
175 assertEquals(session, session.thisInstance());
179 public void testAddExiHandlers() throws Exception {
180 channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER,
181 new NetconfXMLToMessageDecoder());
182 channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER,
183 new NetconfMessageToXMLEncoder());
184 final NetconfEXICodec codec = NetconfEXICodec.forParameters(EXIParameters.empty());
185 session.addExiHandlers(NetconfEXIToMessageDecoder.create(codec), NetconfMessageToEXIEncoder.create(codec));
189 public void testStopExiCommunication() throws Exception {
190 channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER,
191 new ChannelInboundHandlerAdapter());
192 channel.pipeline().addLast(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER,
193 new ChannelOutboundHandlerAdapter());
194 session.stopExiCommunication();
195 //handler is replaced only after next send message call
196 final ChannelHandler exiEncoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER);
197 assertTrue(ChannelOutboundHandlerAdapter.class.equals(exiEncoder.getClass()));
198 session.sendMessage(msg);
199 channel.runPendingTasks();
200 final ChannelHandler decoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_DECODER);
201 assertTrue(NetconfXMLToMessageDecoder.class.equals(decoder.getClass()));
202 final ChannelHandler encoder = channel.pipeline().get(AbstractChannelInitializer.NETCONF_MESSAGE_ENCODER);
203 assertTrue(NetconfMessageToXMLEncoder.class.equals(encoder.getClass()));