Merge "Cleanup root pom "name"."
[controller.git] / opendaylight / md-sal / sal-netconf-connector / src / test / java / org / opendaylight / controller / sal / connect / netconf / listener / NetconfDeviceCommunicatorTest.java
index 001b9a8d3abc411b041d3f3624ea27505722560c..68fe87fb6036b0cab08cb277682416df49415f26 100644 (file)
@@ -19,6 +19,8 @@ import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.RPC_REPLY_KEY;
 import static org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0;
@@ -27,9 +29,15 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Sets;
 import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timer;
 import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.util.concurrent.GlobalEventExecutor;
 import java.io.ByteArrayInputStream;
+import java.net.InetSocketAddress;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.UUID;
@@ -45,11 +53,18 @@ import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
+import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl;
 import org.opendaylight.controller.netconf.client.NetconfClientSession;
+import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.controller.netconf.client.conf.NetconfReconnectingClientConfigurationBuilder;
+import org.opendaylight.controller.netconf.nettyutil.handler.ssh.authentication.LoginPassword;
 import org.opendaylight.controller.sal.connect.api.RemoteDevice;
-import org.opendaylight.controller.sal.connect.api.RemoteDeviceCommunicator;
 import org.opendaylight.controller.sal.connect.netconf.util.NetconfMessageTransformUtil;
 import org.opendaylight.controller.sal.connect.util.RemoteDeviceId;
+import org.opendaylight.protocol.framework.ReconnectStrategy;
+import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
+import org.opendaylight.protocol.framework.TimedReconnectStrategy;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -62,7 +77,7 @@ public class NetconfDeviceCommunicatorTest {
     NetconfClientSession mockSession;
 
     @Mock
-    RemoteDevice<NetconfSessionCapabilities, NetconfMessage> mockDevice;
+    RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> mockDevice;
 
     NetconfDeviceCommunicator communicator;
 
@@ -70,16 +85,15 @@ public class NetconfDeviceCommunicatorTest {
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks( this );
 
-        communicator = new NetconfDeviceCommunicator( new RemoteDeviceId( "test" ), mockDevice );
+        communicator = new NetconfDeviceCommunicator( new RemoteDeviceId( "test" ), mockDevice);
     }
 
     @SuppressWarnings("unchecked")
-    void setupSession()
-    {
-        doReturn( Collections.<String>emptySet() ).when( mockSession ).getServerCapabilities();
-        doNothing().when( mockDevice ).onRemoteSessionUp( any( NetconfSessionCapabilities.class ),
-                                                          any( RemoteDeviceCommunicator.class ) );
-        communicator.onSessionUp( mockSession );
+    void setupSession() {
+        doReturn(Collections.<String>emptySet()).when(mockSession).getServerCapabilities();
+        doNothing().when(mockDevice).onRemoteSessionUp(any(NetconfSessionPreferences.class),
+                any(NetconfDeviceCommunicator.class));
+        communicator.onSessionUp(mockSession);
     }
 
     private ListenableFuture<RpcResult<NetconfMessage>> sendRequest() throws Exception {
@@ -115,16 +129,16 @@ public class NetconfDeviceCommunicatorTest {
                                  testCapability );
         doReturn( serverCapabilities ).when( mockSession ).getServerCapabilities();
 
-        ArgumentCaptor<NetconfSessionCapabilities> netconfSessionCapabilities =
-                                              ArgumentCaptor.forClass( NetconfSessionCapabilities.class );
-        doNothing().when( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+        ArgumentCaptor<NetconfSessionPreferences> NetconfSessionPreferences =
+                                              ArgumentCaptor.forClass( NetconfSessionPreferences.class );
+        doNothing().when( mockDevice ).onRemoteSessionUp( NetconfSessionPreferences.capture(), eq( communicator ) );
 
         communicator.onSessionUp( mockSession );
 
         verify( mockSession ).getServerCapabilities();
-        verify( mockDevice ).onRemoteSessionUp( netconfSessionCapabilities.capture(), eq( communicator ) );
+        verify( mockDevice ).onRemoteSessionUp( NetconfSessionPreferences.capture(), eq( communicator ) );
 
-        NetconfSessionCapabilities actualCapabilites = netconfSessionCapabilities.getValue();
+        NetconfSessionPreferences actualCapabilites = NetconfSessionPreferences.getValue();
         assertEquals( "containsModuleCapability", true, actualCapabilites.containsNonModuleCapability(
                 NetconfMessageTransformUtil.NETCONF_ROLLBACK_ON_ERROR_URI.toString()) );
         assertEquals( "containsModuleCapability", false, actualCapabilites.containsNonModuleCapability(testCapability) );
@@ -320,6 +334,59 @@ public class NetconfDeviceCommunicatorTest {
                       errorInfo.contains( "<bad-element>bar</bad-element>" ) );
     }
 
+    /**
+     * Test whether reconnect is scheduled properly
+     */
+    @Test
+    public void testNetconfDeviceReconnectInCommunicator() throws Exception {
+        final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device = mock(RemoteDevice.class);
+
+        final TimedReconnectStrategy timedReconnectStrategy = new TimedReconnectStrategy(GlobalEventExecutor.INSTANCE, 10000, 0, 1.0, null, 100L, null);
+        final ReconnectStrategy reconnectStrategy = spy(new ReconnectStrategy() {
+            @Override
+            public int getConnectTimeout() throws Exception {
+                return timedReconnectStrategy.getConnectTimeout();
+            }
+
+            @Override
+            public Future<Void> scheduleReconnect(final Throwable cause) {
+                return timedReconnectStrategy.scheduleReconnect(cause);
+            }
+
+            @Override
+            public void reconnectSuccessful() {
+                timedReconnectStrategy.reconnectSuccessful();
+            }
+        });
+
+        final EventLoopGroup group = new NioEventLoopGroup();
+        final Timer time = new HashedWheelTimer();
+        try {
+            final NetconfDeviceCommunicator listener = new NetconfDeviceCommunicator(new RemoteDeviceId("test"), device);
+            final NetconfReconnectingClientConfiguration cfg = NetconfReconnectingClientConfigurationBuilder.create()
+                    .withAddress(new InetSocketAddress("localhost", 65000))
+                    .withReconnectStrategy(reconnectStrategy)
+                    .withConnectStrategyFactory(new ReconnectStrategyFactory() {
+                        @Override
+                        public ReconnectStrategy createReconnectStrategy() {
+                            return reconnectStrategy;
+                        }
+                    })
+                    .withAuthHandler(new LoginPassword("admin", "admin"))
+                    .withConnectionTimeoutMillis(10000)
+                    .withProtocol(NetconfClientConfiguration.NetconfClientProtocol.SSH)
+                    .withSessionListener(listener)
+                    .build();
+
+            listener.initializeRemoteConnection(new NetconfClientDispatcherImpl(group, group, time), cfg);
+
+            verify(reconnectStrategy, timeout((int) TimeUnit.MINUTES.toMillis(3)).times(101)).scheduleReconnect(any(Throwable.class));
+        } finally {
+            time.stop();
+            group.shutdownGracefully();
+        }
+    }
+
     @Test
     public void testOnResponseMessageWithWrongMessageID() throws Exception {
         setupSession();