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
9 package org.opendaylight.netconf.impl;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.argThat;
13 import static org.mockito.Mockito.doNothing;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.doThrow;
16 import static org.mockito.Mockito.verify;
18 import io.netty.channel.embedded.EmbeddedChannel;
19 import org.custommonkey.xmlunit.Diff;
20 import org.custommonkey.xmlunit.XMLUnit;
21 import org.hamcrest.CustomMatcher;
22 import org.junit.Assert;
23 import org.junit.Before;
24 import org.junit.BeforeClass;
25 import org.junit.Test;
26 import org.mockito.Mock;
27 import org.mockito.MockitoAnnotations;
28 import org.opendaylight.controller.config.util.xml.XmlUtil;
29 import org.opendaylight.netconf.api.NetconfMessage;
30 import org.opendaylight.netconf.api.NetconfTerminationReason;
31 import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
32 import org.opendaylight.netconf.api.monitoring.SessionEvent;
33 import org.opendaylight.netconf.api.monitoring.SessionListener;
34 import org.opendaylight.netconf.impl.osgi.NetconfOperationRouter;
35 import org.opendaylight.netconf.notifications.NetconfNotification;
36 import org.w3c.dom.Document;
38 public class NetconfServerSessionListenerTest {
41 private NetconfOperationRouter router;
43 private NetconfMonitoringService monitoring;
45 private AutoCloseable closeable;
47 private SessionListener monitoringListener;
48 private NetconfServerSession session;
49 private EmbeddedChannel channel;
50 private NetconfServerSessionListener listener;
53 public static void classSetUp() throws Exception {
54 XMLUnit.setIgnoreWhitespace(true);
58 public void setUp() throws Exception {
59 MockitoAnnotations.initMocks(this);
60 doReturn(monitoringListener).when(monitoring).getSessionListener();
61 doNothing().when(monitoringListener).onSessionUp(any());
62 doNothing().when(monitoringListener).onSessionDown(any());
63 doNothing().when(monitoringListener).onSessionEvent(any());
64 channel = new EmbeddedChannel();
65 session = new NetconfServerSession(null, channel, 0L, null);
66 listener = new NetconfServerSessionListener(router, monitoring, closeable);
70 public void testOnSessionUp() throws Exception {
71 listener.onSessionUp(session);
72 verify(monitoringListener).onSessionUp(session);
76 public void testOnSessionDown() throws Exception {
77 final Exception cause = new RuntimeException("cause");
78 listener.onSessionDown(session, cause);
79 verify(monitoringListener).onSessionDown(session);
80 verify(closeable).close();
81 verify(router).close();
85 public void testOnSessionTerminated() throws Exception {
86 listener.onSessionTerminated(session, new NetconfTerminationReason("reason"));
87 verify(monitoringListener).onSessionDown(session);
88 verify(closeable).close();
89 verify(router).close();
93 public void testOnMessage() throws Exception {
94 final Document reply = XmlUtil.readXmlToDocument("<rpc-reply message-id=\"101\" " +
95 "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc-reply>");
96 doReturn(reply).when(router).onNetconfMessage(any(), any());
97 final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"101\" " +
98 "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc>"));
99 listener.onMessage(session, msg);
100 verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_SUCCESS)));
101 channel.runPendingTasks();
102 final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
103 final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
104 Assert.assertTrue(diff.toString(), diff.similar());
108 public void testOnMessageRuntimeFail() throws Exception {
109 doThrow(new RuntimeException("runtime fail")).when(router).onNetconfMessage(any(), any());
110 final Document reply =
111 XmlUtil.readXmlToDocument("<rpc message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" +
113 final NetconfMessage msg = new NetconfMessage(reply);
115 listener.onMessage(session, msg);
116 Assert.fail("Expected exception " + IllegalStateException.class);
117 } catch (final IllegalStateException e) {
118 verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
123 public void testOnMessageDocumentedFail() throws Exception {
124 final Document reply =
125 XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
127 "<error-type>PROTOCOL</error-type>\n" +
128 "<error-tag>unknown-element</error-tag>\n" +
129 "<error-severity>ERROR</error-severity>\n" +
130 "<error-message>Unknown tag bad-rpc in message:\n" +
131 "<bad-rpc/>\n" +
132 "</error-message>\n" +
134 "<bad-element>bad-rpc</bad-element>\n" +
138 final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<bad-rpc/>"));
139 listener.onMessage(session, msg);
140 verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
141 verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.OUT_RPC_ERROR)));
142 channel.runPendingTasks();
143 final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
144 System.out.println(XmlUtil.toString(sentMsg.getDocument()));
145 System.out.println(XmlUtil.toString(reply));
146 final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
147 Assert.assertTrue(diff.toString(), diff.similar());
151 public void testOnNotification() throws Exception {
152 listener.onNotification(session, new NetconfNotification(XmlUtil.readXmlToDocument("<notification/>")));
153 verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.NOTIFICATION)));
156 private CustomMatcher<SessionEvent> sessionEventIs(final SessionEvent.Type type) {
157 return new CustomMatcher<SessionEvent>(type.name()) {
159 public boolean matches(final Object item) {
160 if (!(item instanceof SessionEvent)) {
163 final SessionEvent e = (SessionEvent) item;
164 return e.getType().equals(type) && e.getSession().equals(session);