/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.netconf.impl;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import io.netty.channel.embedded.EmbeddedChannel;
import org.custommonkey.xmlunit.Diff;
import org.custommonkey.xmlunit.XMLUnit;
import org.hamcrest.CustomMatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.opendaylight.controller.config.util.xml.XmlUtil;
import org.opendaylight.netconf.api.NetconfMessage;
import org.opendaylight.netconf.api.NetconfTerminationReason;
import org.opendaylight.netconf.api.monitoring.NetconfMonitoringService;
import org.opendaylight.netconf.api.monitoring.SessionEvent;
import org.opendaylight.netconf.api.monitoring.SessionListener;
import org.opendaylight.netconf.impl.osgi.NetconfOperationRouter;
import org.opendaylight.netconf.notifications.NetconfNotification;
import org.w3c.dom.Document;
public class NetconfServerSessionListenerTest {
@Mock
private NetconfOperationRouter router;
@Mock
private NetconfMonitoringService monitoring;
@Mock
private AutoCloseable closeable;
@Mock
private SessionListener monitoringListener;
private NetconfServerSession session;
private EmbeddedChannel channel;
private NetconfServerSessionListener listener;
@BeforeClass
public static void classSetUp() throws Exception {
XMLUnit.setIgnoreWhitespace(true);
}
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn(monitoringListener).when(monitoring).getSessionListener();
doNothing().when(monitoringListener).onSessionUp(any());
doNothing().when(monitoringListener).onSessionDown(any());
doNothing().when(monitoringListener).onSessionEvent(any());
channel = new EmbeddedChannel();
session = new NetconfServerSession(null, channel, 0L, null);
listener = new NetconfServerSessionListener(router, monitoring, closeable);
}
@Test
public void testOnSessionUp() throws Exception {
listener.onSessionUp(session);
verify(monitoringListener).onSessionUp(session);
}
@Test
public void testOnSessionDown() throws Exception {
final Exception cause = new RuntimeException("cause");
listener.onSessionDown(session, cause);
verify(monitoringListener).onSessionDown(session);
verify(closeable).close();
verify(router).close();
}
@Test
public void testOnSessionTerminated() throws Exception {
listener.onSessionTerminated(session, new NetconfTerminationReason("reason"));
verify(monitoringListener).onSessionDown(session);
verify(closeable).close();
verify(router).close();
}
@Test
public void testOnMessage() throws Exception {
final Document reply = XmlUtil.readXmlToDocument("");
doReturn(reply).when(router).onNetconfMessage(any(), any());
final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument(""));
listener.onMessage(session, msg);
verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_SUCCESS)));
channel.runPendingTasks();
final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
Assert.assertTrue(diff.toString(), diff.similar());
}
@Test
public void testOnMessageRuntimeFail() throws Exception {
doThrow(new RuntimeException("runtime fail")).when(router).onNetconfMessage(any(), any());
final Document reply =
XmlUtil.readXmlToDocument("" +
"");
final NetconfMessage msg = new NetconfMessage(reply);
try {
listener.onMessage(session, msg);
Assert.fail("Expected exception " + IllegalStateException.class);
} catch (final IllegalStateException e) {
verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
}
}
@Test
public void testOnMessageDocumentedFail() throws Exception {
final Document reply =
XmlUtil.readXmlToDocument("\n" +
"\n" +
"PROTOCOL\n" +
"unknown-element\n" +
"ERROR\n" +
"Unknown tag bad-rpc in message:\n" +
"<bad-rpc/>\n" +
"\n" +
"\n" +
"bad-rpc\n" +
"\n" +
"\n" +
"");
final NetconfMessage msg = new NetconfMessage(XmlUtil.readXmlToDocument(""));
listener.onMessage(session, msg);
verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.IN_RPC_FAIL)));
verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.OUT_RPC_ERROR)));
channel.runPendingTasks();
final NetconfMessage sentMsg = (NetconfMessage) channel.readOutbound();
System.out.println(XmlUtil.toString(sentMsg.getDocument()));
System.out.println(XmlUtil.toString(reply));
final Diff diff = XMLUnit.compareXML(reply, sentMsg.getDocument());
Assert.assertTrue(diff.toString(), diff.similar());
}
@Test
public void testOnNotification() throws Exception {
listener.onNotification(session, new NetconfNotification(XmlUtil.readXmlToDocument("")));
verify(monitoringListener).onSessionEvent(argThat(sessionEventIs(SessionEvent.Type.NOTIFICATION)));
}
private CustomMatcher sessionEventIs(final SessionEvent.Type type) {
return new CustomMatcher(type.name()) {
@Override
public boolean matches(final Object item) {
if (!(item instanceof SessionEvent)) {
return false;
}
final SessionEvent e = (SessionEvent) item;
return e.getType().equals(type) && e.getSession().equals(session);
}
};
}
}