cba8439d8b1fafa61f0fa8b7fa0763b1ea86315c
[netconf.git] / protocol / netconf-server / src / test / java / org / opendaylight / netconf / server / NetconfServerSessionListenerTest.java
1 /*
2  * Copyright (c) 2016 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.netconf.server;
9
10 import static org.junit.Assert.assertThrows;
11 import static org.junit.Assert.assertTrue;
12 import static org.mockito.ArgumentMatchers.any;
13 import static org.mockito.ArgumentMatchers.argThat;
14 import static org.mockito.Mockito.doNothing;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.doThrow;
17 import static org.mockito.Mockito.verify;
18
19 import io.netty.channel.embedded.EmbeddedChannel;
20 import org.custommonkey.xmlunit.Diff;
21 import org.custommonkey.xmlunit.XMLUnit;
22 import org.junit.Before;
23 import org.junit.BeforeClass;
24 import org.junit.Test;
25 import org.junit.runner.RunWith;
26 import org.mockito.ArgumentMatcher;
27 import org.mockito.Mock;
28 import org.mockito.junit.MockitoJUnitRunner;
29 import org.opendaylight.netconf.api.NetconfTerminationReason;
30 import org.opendaylight.netconf.api.messages.NetconfMessage;
31 import org.opendaylight.netconf.api.messages.NotificationMessage;
32 import org.opendaylight.netconf.api.xml.XmlUtil;
33 import org.opendaylight.netconf.server.api.monitoring.NetconfMonitoringService;
34 import org.opendaylight.netconf.server.api.monitoring.SessionEvent;
35 import org.opendaylight.netconf.server.api.monitoring.SessionListener;
36 import org.opendaylight.netconf.server.osgi.NetconfOperationRouterImpl;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.netconf.base._1._0.rev110601.SessionIdType;
38 import org.opendaylight.yangtools.yang.common.Uint32;
39 import org.w3c.dom.Document;
40
41 @RunWith(MockitoJUnitRunner.StrictStubs.class)
42 public class NetconfServerSessionListenerTest {
43     @Mock
44     private NetconfOperationRouterImpl router;
45     @Mock
46     private NetconfMonitoringService monitoring;
47     @Mock
48     private AutoCloseable closeable;
49     @Mock
50     private SessionListener monitoringListener;
51     private NetconfServerSession session;
52     private EmbeddedChannel channel;
53     private NetconfServerSessionListener listener;
54
55     @BeforeClass
56     public static void classSetUp() throws Exception {
57         XMLUnit.setIgnoreWhitespace(true);
58     }
59
60     @Before
61     public void setUp() throws Exception {
62         doReturn(monitoringListener).when(monitoring).getSessionListener();
63         doNothing().when(monitoringListener).onSessionUp(any());
64         doNothing().when(monitoringListener).onSessionDown(any());
65         doNothing().when(monitoringListener).onSessionEvent(any());
66         channel = new EmbeddedChannel();
67         session = new NetconfServerSession(null, channel, new SessionIdType(Uint32.ONE), null);
68         listener = new NetconfServerSessionListener(router, monitoring, closeable);
69     }
70
71     @Test
72     public void testOnSessionUp() throws Exception {
73         listener.onSessionUp(session);
74         verify(monitoringListener).onSessionUp(session);
75     }
76
77     @Test
78     public void testOnSessionDown() throws Exception {
79         final Exception cause = new RuntimeException("cause");
80         listener.onSessionDown(session, cause);
81         verify(monitoringListener).onSessionDown(session);
82         verify(closeable).close();
83         verify(router).close();
84     }
85
86     @Test
87     public void testOnSessionTerminated() throws Exception {
88         listener.onSessionTerminated(session, new NetconfTerminationReason("reason"));
89         verify(monitoringListener).onSessionDown(session);
90         verify(closeable).close();
91         verify(router).close();
92     }
93
94     @Test
95     public void testOnMessage() throws Exception {
96         final Document reply = XmlUtil.readXmlToDocument("<rpc-reply message-id=\"101\" "
97                 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc-reply>");
98         doReturn(reply).when(router).onNetconfMessage(any(), any());
99         final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<rpc message-id=\"101\" "
100                 + "xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\"><example/></rpc>"));
101         listener.onMessage(session, msg);
102         verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_SUCCESS)));
103         channel.runPendingTasks();
104         final NetconfMessage sentMsg = channel.readOutbound();
105         final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
106         assertTrue(diff.toString(), diff.similar());
107     }
108
109     @Test
110     public void testOnMessageRuntimeFail() throws Exception {
111         doThrow(new RuntimeException("runtime fail")).when(router).onNetconfMessage(any(), any());
112         final Document reply =
113                 XmlUtil.readXmlToDocument("<rpc message-id=\"101\" xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">"
114                         + "<example/></rpc>");
115         final NetconfMessage msg = new NetconfMessage(reply);
116         final IllegalStateException ex = assertThrows(IllegalStateException.class,
117             () -> listener.onMessage(session, msg));
118         verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
119     }
120
121     @Test
122     public void testOnMessageDocumentedFail() throws Exception {
123         final Document reply =
124                 XmlUtil.readXmlToDocument("<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n"
125                         + "<rpc-error>\n"
126                         + "<error-type>protocol</error-type>\n"
127                         + "<error-tag>unknown-element</error-tag>\n"
128                         + "<error-severity>error</error-severity>\n"
129                         + "<error-message>Unknown tag bad-rpc in message:\n"
130                         + "&lt;bad-rpc/&gt;\n"
131                         + "</error-message>\n"
132                         + "<error-info>\n"
133                         + "<bad-element>bad-rpc</bad-element>\n"
134                         + "</error-info>\n"
135                         + "</rpc-error>\n"
136                         + "</rpc-reply>");
137         final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument("<bad-rpc/>"));
138         listener.onMessage(session, msg);
139         verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
140         verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.OUT_RPC_ERROR)));
141         channel.runPendingTasks();
142         final NetconfMessage sentMsg = channel.readOutbound();
143         final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
144         assertTrue(diff.toString(), diff.similar());
145     }
146
147     @Test
148     public void testOnNotification() throws Exception {
149         listener.onNotification(session, NotificationMessage.ofNotificationContent(
150             XmlUtil.readXmlToDocument("<notification/>")));
151         verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.NOTIFICATION)));
152     }
153
154     private ArgumentMatcher<SessionEvent> sessionEventIs(final SessionEvent.Type type) {
155         return event -> event.getType().equals(type) && event.getSession().equals(session);
156     }
157 }