import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyObject;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;
-import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelConfig;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.channel.DefaultChannelPromise;
-import io.netty.channel.EventLoop;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.netconf.shaded.sshd.client.SshClient;
-import org.opendaylight.netconf.shaded.sshd.client.channel.ChannelSubsystem;
import org.opendaylight.netconf.shaded.sshd.client.channel.ClientChannel;
import org.opendaylight.netconf.shaded.sshd.client.future.AuthFuture;
import org.opendaylight.netconf.shaded.sshd.client.future.ConnectFuture;
import org.opendaylight.netconf.shaded.sshd.common.util.buffer.Buffer;
import org.opendaylight.netconf.shaded.sshd.common.util.buffer.ByteArrayBuffer;
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class AsyncSshHandlerTest {
@Mock
- private SshClient sshClient;
+ private NetconfSshClient sshClient;
@Mock
private AuthenticationHandler authHandler;
@Mock
@Mock
private SocketAddress localAddress;
@Mock
- private EventLoop eventLoop;
- @Mock
private ChannelConfig channelConfig;
private AsyncSshHandler asyncSshHandler;
private SshFutureListener<ConnectFuture> sshConnectListener;
private SshFutureListener<AuthFuture> sshAuthListener;
private SshFutureListener<OpenFuture> sshChannelOpenListener;
-
private ChannelPromise promise;
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
stubAuth();
stubSshClient();
stubChannel();
- stubEventLoop();
stubCtx();
- stubRemoteAddress();
promise = getMockedPromise();
return listenerSettableFuture;
}
- private void stubRemoteAddress() {
- doReturn("remote").when(remoteAddress).toString();
- }
-
private void stubCtx() {
doReturn(channel).when(ctx).channel();
doReturn(ctx).when(ctx).fireChannelActive();
doReturn(ctx).when(ctx).fireChannelInactive();
- doReturn(ctx).when(ctx).fireChannelRead(anyObject());
doReturn(mock(ChannelFuture.class)).when(ctx).disconnect(any(ChannelPromise.class));
doReturn(getMockedPromise()).when(ctx).newPromise();
}
doReturn("channel").when(channel).toString();
}
- private void stubEventLoop() {
- doReturn(eventLoop).when(channel).eventLoop();
- doReturn(Boolean.TRUE).when(eventLoop).inEventLoop();
- }
-
private void stubSshClient() throws IOException {
- doNothing().when(sshClient).start();
final ConnectFuture connectFuture = mock(ConnectFuture.class);
Futures.addCallback(stubAddListener(connectFuture), new SuccessFutureListener<ConnectFuture>() {
@Override
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
verify(promise).setSuccess();
verify(ctx).fireChannelActive();
- }
-
- @Test
- public void testRead() throws Exception {
- asyncSshHandler.connect(ctx, remoteAddress, localAddress, promise);
-
- final IoInputStream asyncOut = getMockedIoInputStream();
- final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
- final ClientSession sshSession = getMockedSshSession(subsystemChannel);
- final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
-
- sshConnectListener.operationComplete(connectFuture);
- sshAuthListener.operationComplete(getSuccessAuthFuture());
- sshChannelOpenListener.operationComplete(getSuccessOpenFuture());
-
- verify(ctx).fireChannelRead(any(ByteBuf.class));
- }
-
- @Test
- public void testReadClosed() throws Exception {
- asyncSshHandler.connect(ctx, remoteAddress, localAddress, promise);
-
- final IoInputStream asyncOut = getMockedIoInputStream();
- final IoReadFuture mockedReadFuture = asyncOut.read(null);
-
- Futures.addCallback(stubAddListener(mockedReadFuture), new SuccessFutureListener<IoReadFuture>() {
- @Override
- public void onSuccess(final SshFutureListener<IoReadFuture> result) {
- doReturn(new IllegalStateException()).when(mockedReadFuture).getException();
- doReturn(mockedReadFuture).when(mockedReadFuture).removeListener(any());
- doReturn(true).when(asyncOut).isClosing();
- doReturn(true).when(asyncOut).isClosed();
- result.operationComplete(mockedReadFuture);
- }
- }, MoreExecutors.directExecutor());
-
- final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
- final ClientSession sshSession = getMockedSshSession(subsystemChannel);
- final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
-
- sshConnectListener.operationComplete(connectFuture);
- sshAuthListener.operationComplete(getSuccessAuthFuture());
- sshChannelOpenListener.operationComplete(getSuccessOpenFuture());
-
- verify(ctx).fireChannelInactive();
- }
-
- @Test
- public void testReadFail() throws Exception {
- asyncSshHandler.connect(ctx, remoteAddress, localAddress, promise);
-
- final IoInputStream asyncOut = getMockedIoInputStream();
- final IoReadFuture mockedReadFuture = asyncOut.read(null);
-
- Futures.addCallback(stubAddListener(mockedReadFuture), new SuccessFutureListener<IoReadFuture>() {
- @Override
- public void onSuccess(final SshFutureListener<IoReadFuture> result) {
- doReturn(new IllegalStateException()).when(mockedReadFuture).getException();
- doReturn(mockedReadFuture).when(mockedReadFuture).removeListener(any());
- result.operationComplete(mockedReadFuture);
- }
- }, MoreExecutors.directExecutor());
-
- final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
- final ClientSession sshSession = getMockedSshSession(subsystemChannel);
- final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
-
- sshConnectListener.operationComplete(connectFuture);
- sshAuthListener.operationComplete(getSuccessAuthFuture());
- sshChannelOpenListener.operationComplete(getSuccessOpenFuture());
-
+ asyncSshHandler.close(ctx, getMockedPromise());
verify(ctx).fireChannelInactive();
}
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final IoWriteFuture ioWriteFuture = asyncIn.writePacket(new ByteArrayBuffer());
+ final IoWriteFuture ioWriteFuture = asyncIn.writeBuffer(new ByteArrayBuffer());
Futures.addCallback(stubAddListener(ioWriteFuture), new SuccessFutureListener<IoWriteFuture>() {
@Override
public void onSuccess(final SshFutureListener<IoWriteFuture> result) {
doReturn(false).when(ioWriteFuture).isWritten();
doReturn(new IllegalStateException()).when(ioWriteFuture).getException();
- doReturn(true).when(asyncIn).isClosing();
- doReturn(true).when(asyncIn).isClosed();
result.operationComplete(ioWriteFuture);
}
}, MoreExecutors.directExecutor());
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final IoWriteFuture ioWriteFuture = asyncIn.writePacket(new ByteArrayBuffer());
+ final IoWriteFuture ioWriteFuture = asyncIn.writeBuffer(new ByteArrayBuffer());
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
final ListenableFuture<SshFutureListener<IoWriteFuture>> pendingListener = stubAddListener(ioWriteFuture);
final ChannelPromise secondWritePromise = getMockedPromise();
- // now make write throw pending exception
- doThrow(WritePendingException.class).when(asyncIn).writePacket(any(Buffer.class));
asyncSshHandler.write(ctx, Unpooled.copiedBuffer(new byte[]{0, 1, 2, 3, 4, 5}), secondWritePromise);
- doReturn(ioWriteFuture).when(asyncIn).writePacket(any(Buffer.class));
+ doReturn(ioWriteFuture).when(asyncIn).writeBuffer(any(Buffer.class));
- verifyZeroInteractions(firstWritePromise, secondWritePromise);
+ verifyNoMoreInteractions(firstWritePromise, secondWritePromise);
// make first write stop pending
firstWriteListener.operationComplete(ioWriteFuture);
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final IoWriteFuture ioWriteFuture = asyncIn.writePacket(new ByteArrayBuffer());
+ final IoWriteFuture ioWriteFuture = asyncIn.writeBuffer(new ByteArrayBuffer());
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
final ChannelPromise secondWritePromise = getMockedPromise();
// now make write throw pending exception
- doThrow(WritePendingException.class).when(asyncIn).writePacket(any(Buffer.class));
+ doThrow(WritePendingException.class).when(asyncIn).writeBuffer(any(Buffer.class));
for (int i = 0; i < 1001; i++) {
asyncSshHandler.write(ctx, Unpooled.copiedBuffer(new byte[]{0, 1, 2, 3, 4, 5}), secondWritePromise);
}
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
verify(sshSession).close(anyBoolean());
verify(disconnectPromise).setSuccess();
- verify(ctx).fireChannelInactive();
+ //verify(ctx).fireChannelInactive();
}
private static OpenFuture getSuccessOpenFuture() {
private static ConnectFuture getSuccessConnectFuture(final ClientSession sshSession) {
final ConnectFuture connectFuture = mock(ConnectFuture.class);
- doReturn(true).when(connectFuture).isConnected();
+ doReturn(null).when(connectFuture).getException();
doReturn(sshSession).when(connectFuture).getSession();
return connectFuture;
}
- private static ClientSession getMockedSshSession(final ChannelSubsystem subsystemChannel) throws IOException {
- final ClientSession sshSession = mock(ClientSession.class);
+ private static NettyAwareClientSession getMockedSshSession(final NettyAwareChannelSubsystem subsystemChannel)
+ throws IOException {
+ final NettyAwareClientSession sshSession = mock(NettyAwareClientSession.class);
- doReturn("sshSession").when(sshSession).toString();
doReturn("serverVersion").when(sshSession).getServerVersion();
doReturn(false).when(sshSession).isClosed();
doReturn(false).when(sshSession).isClosing();
}, MoreExecutors.directExecutor());
doReturn(closeFuture).when(sshSession).close(false);
- doReturn(subsystemChannel).when(sshSession).createSubsystemChannel(anyString());
+ doReturn(subsystemChannel).when(sshSession).createSubsystemChannel(eq("netconf"), any());
return sshSession;
}
- private ChannelSubsystem getMockedSubsystemChannel(final IoInputStream asyncOut,
+ private NettyAwareChannelSubsystem getMockedSubsystemChannel(final IoInputStream asyncOut,
final IoOutputStream asyncIn) throws IOException {
- final ChannelSubsystem subsystemChannel = mock(ChannelSubsystem.class);
- doReturn("subsystemChannel").when(subsystemChannel).toString();
+ final NettyAwareChannelSubsystem subsystemChannel = mock(NettyAwareChannelSubsystem.class);
doNothing().when(subsystemChannel).setStreaming(any(ClientChannel.Streaming.class));
final OpenFuture openFuture = mock(OpenFuture.class);
}
}, MoreExecutors.directExecutor());
- doReturn(asyncOut).when(subsystemChannel).getAsyncOut();
-
doReturn(openFuture).when(subsystemChannel).open();
doReturn(asyncIn).when(subsystemChannel).getAsyncIn();
+ doNothing().when(subsystemChannel).onClose(any());
+ doNothing().when(subsystemChannel).close();
return subsystemChannel;
}
private static IoOutputStream getMockedIoOutputStream() throws IOException {
final IoOutputStream mock = mock(IoOutputStream.class);
final IoWriteFuture ioWriteFuture = mock(IoWriteFuture.class);
- doReturn(ioWriteFuture).when(ioWriteFuture).addListener(any());
doReturn(true).when(ioWriteFuture).isWritten();
Futures.addCallback(stubAddListener(ioWriteFuture), new SuccessFutureListener<IoWriteFuture>() {
}
}, MoreExecutors.directExecutor());
- doReturn(ioWriteFuture).when(mock).writePacket(any(Buffer.class));
+ doReturn(ioWriteFuture).when(mock).writeBuffer(any(Buffer.class));
doReturn(false).when(mock).isClosed();
doReturn(false).when(mock).isClosing();
return mock;
private static IoInputStream getMockedIoInputStream() {
final IoInputStream mock = mock(IoInputStream.class);
final IoReadFuture ioReadFuture = mock(IoReadFuture.class);
- doReturn(null).when(ioReadFuture).getException();
- doReturn(ioReadFuture).when(ioReadFuture).removeListener(any());
- doReturn(ioReadFuture).when(mock).read(any());
- doReturn(5).when(ioReadFuture).getRead();
- doReturn(new ByteArrayBuffer(new byte[]{0, 1, 2, 3, 4})).when(ioReadFuture).getBuffer();
- doReturn(ioReadFuture).when(ioReadFuture).addListener(any());
-
// Always success for read
Futures.addCallback(stubAddListener(ioReadFuture), new SuccessFutureListener<IoReadFuture>() {
@Override
result.operationComplete(ioReadFuture);
}
}, MoreExecutors.directExecutor());
-
- doReturn(ioReadFuture).when(mock).read(any(Buffer.class));
- doReturn(false).when(mock).isClosed();
- doReturn(false).when(mock).isClosing();
return mock;
}
final IoInputStream asyncOut = getMockedIoInputStream();
final IoOutputStream asyncIn = getMockedIoOutputStream();
- final ChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
+ final NettyAwareChannelSubsystem subsystemChannel = getMockedSubsystemChannel(asyncOut, asyncIn);
final ClientSession sshSession = getMockedSshSession(subsystemChannel);
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
public void testConnectFailAuth() throws Exception {
asyncSshHandler.connect(ctx, remoteAddress, localAddress, promise);
- final ClientSession sshSession = mock(ClientSession.class);
+ final NettyAwareClientSession sshSession = mock(NettyAwareClientSession.class);
doReturn(true).when(sshSession).isClosed();
final ConnectFuture connectFuture = getSuccessConnectFuture(sshSession);
sshAuthListener.operationComplete(authFuture);
verify(promise).setFailure(any(Throwable.class));
+ asyncSshHandler.close(ctx, getMockedPromise());
+ verify(ctx, times(0)).fireChannelInactive();
}
private static AuthFuture getFailedAuthFuture() {
private static ConnectFuture getFailedConnectFuture() {
final ConnectFuture connectFuture = mock(ConnectFuture.class);
- doReturn(false).when(connectFuture).isConnected();
doReturn(new IllegalStateException()).when(connectFuture).getException();
return connectFuture;
}