/*
* Copyright (c) 2014 Brocade Communications 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.openflowjava.protocol.impl.core;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.ssl.SslHandler;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import javax.net.ssl.SSLEngine;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.api.connection.TlsConfiguration;
import org.opendaylight.openflowjava.protocol.api.connection.TlsConfigurationImpl;
import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterFactory;
import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionFacade;
import org.opendaylight.openflowjava.protocol.impl.deserialization.DeserializationFactory;
import org.opendaylight.openflowjava.protocol.impl.serialization.SerializationFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.KeystoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.config.rev140630.PathType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow._switch.connection.provider.impl.rev140328.Tls;
import com.google.common.collect.Lists;
/**
*
* @author james.hall
*/
public class PublishingChannelInitializerTest {
@Mock SocketChannel mockSocketCh ;
@Mock ChannelPipeline mockChPipeline ;
@Mock SwitchConnectionHandler mockSwConnHandler ;
@Mock ConnectionAdapterFactory mockConnAdaptorFactory;
@Mock DefaultChannelGroup mockChGrp ;
@Mock ConnectionFacade mockConnFacade ;
@Mock Tls mockTls ;
SSLEngine sslEngine ;
@Mock SerializationFactory mockSerializationFactory ;
@Mock DeserializationFactory mockDeserializationFactory ;
TlsConfiguration tlsConfiguration ;
InetSocketAddress inetSockAddr;
TcpChannelInitializer pubChInitializer ;
/**
* Sets up test environment
* @throws Exception
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
pubChInitializer= new TcpChannelInitializer(mockChGrp, mockConnAdaptorFactory) ;
pubChInitializer.setSerializationFactory(mockSerializationFactory);
pubChInitializer.setDeserializationFactory(mockDeserializationFactory);
pubChInitializer.setSwitchIdleTimeout(1) ;
pubChInitializer.getConnectionIterator() ;
pubChInitializer.setUseBarrier(true);
when( mockChGrp.size()).thenReturn(1) ;
pubChInitializer.setSwitchConnectionHandler( mockSwConnHandler ) ;
inetSockAddr = new InetSocketAddress(InetAddress.getLocalHost(), 8675 ) ;
when(mockConnAdaptorFactory.createConnectionFacade(mockSocketCh, null, true))
.thenReturn(mockConnFacade);
when(mockSocketCh.remoteAddress()).thenReturn(inetSockAddr) ;
when(mockSocketCh.localAddress()).thenReturn(inetSockAddr) ;
when(mockSocketCh.remoteAddress()).thenReturn(inetSockAddr) ;
when(mockSwConnHandler.accept(eq(InetAddress.getLocalHost()))).thenReturn(true) ;
when(mockSocketCh.pipeline()).thenReturn(mockChPipeline) ;
tlsConfiguration = new TlsConfigurationImpl(KeystoreType.JKS, "/selfSignedSwitch", PathType.CLASSPATH,
KeystoreType.JKS, "/selfSignedController", PathType.CLASSPATH,
Lists.newArrayList("TLS_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA256"));
}
/**
* Test channel initialization with encryption config set
*/
@Test
public void testinitChannelEncryptionSet() {
pubChInitializer.setTlsConfiguration(tlsConfiguration);
pubChInitializer.initChannel(mockSocketCh) ;
verifyCommonHandlers();
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.SSL_HANDLER.name()),any(SslHandler.class)) ;
}
/**
* Test channel initialization with null encryption config
*/
@Test
public void testinitChannelEncryptionSetNullTls() {
pubChInitializer.setTlsConfiguration(null);
pubChInitializer.initChannel(mockSocketCh) ;
verifyCommonHandlers();
verify(mockChPipeline, times(0)).addLast(eq(PipelineHandlers.SSL_HANDLER.name()),any(SslHandler.class)) ;
}
/**
* Test channel initialization without setting the encryption
*/
@Test
public void testinitChannelEncryptionNotSet() {
// Without encryption, only the common
pubChInitializer.initChannel(mockSocketCh) ;
verifyCommonHandlers();
}
/**
* Test disconnect on new connection rejected
* @throws UnknownHostException
*/
@Test
public void testinitChannelNoEncryptionAcceptFails() throws UnknownHostException {
when(mockSwConnHandler.accept(eq(InetAddress.getLocalHost()))).thenReturn(false) ;
pubChInitializer.initChannel(mockSocketCh) ;
verify(mockSocketCh, times(1)).disconnect();
verify(mockChPipeline, times(0))
.addLast( any(String.class), any(ChannelHandler.class) ) ;
}
/**
* Test channel close on exception during initialization
*/
@Test
public void testExceptionThrown() {
doThrow(new IllegalArgumentException()).when(mockSocketCh).pipeline() ;
pubChInitializer.initChannel(mockSocketCh);
verify( mockSocketCh, times(1)).close() ;
}
/**
* All paths should install these six handlers:
*/
private void verifyCommonHandlers() {
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.IDLE_HANDLER.name()),any(IdleHandler.class)) ;
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.OF_DECODER.name()),any(OFDecoder.class)) ;
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.OF_ENCODER.name()),any(OFEncoder.class)) ;
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.OF_FRAME_DECODER.name()),any(OFFrameDecoder.class)) ;
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.OF_VERSION_DETECTOR.name()),any(OFVersionDetector.class)) ;
verify(mockChPipeline, times(1)).addLast(eq(PipelineHandlers.DELEGATING_INBOUND_HANDLER.name()),any(DelegatingInboundHandler.class));
assertEquals(1, pubChInitializer.size()) ;
}
}