/*
* Copyright (c) 2014 Pantheon Technologies s.r.o. 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.connection;
import static org.mockito.Mockito.when;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.channel.socket.SocketChannel;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
import org.opendaylight.openflowjava.statistics.CounterEventTypes;
import org.opendaylight.openflowjava.statistics.StatisticsCounters;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoReplyInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetAsyncInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetConfigInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetQueueConfigInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GroupModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MeterModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartRequestInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketOutInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.RoleRequestInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetAsyncInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.SetConfigInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.TableModInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
import org.opendaylight.yangtools.yang.binding.DataObject;
/**
* Test counters in ConnectionAdapter (at least DS_ENTERED_OFJAVA, DS_FLOW_MODS_ENTERED and US_MESSAGE_PASS counters have to be enabled)
* @author madamjak
*
*/
public class ConnectionAdapterImplStatisticsTest {
private static final int RPC_RESPONSE_EXPIRATION = 1;
private static final RemovalListener<RpcResponseKey, ResponseExpectedRpcListener<?>> REMOVAL_LISTENER =
new RemovalListener<RpcResponseKey, ResponseExpectedRpcListener<?>>() {
@Override
public void onRemoval(
final RemovalNotification<RpcResponseKey, ResponseExpectedRpcListener<?>> notification) {
notification.getValue().discard();
}
};
@Mock SystemNotificationsListener systemListener;
@Mock ConnectionReadyListener readyListener;
@Mock ChannelFuture channelFuture;
@Mock OpenflowProtocolListener messageListener;
@Mock SocketChannel channel;
@Mock ChannelPipeline pipeline;
@Mock EchoInput echoInput;
@Mock BarrierInput barrierInput;
@Mock EchoReplyInput echoReplyInput;
@Mock ExperimenterInput experimenterInput;
@Mock FlowModInput flowModInput;
@Mock GetConfigInput getConfigInput;
@Mock GetFeaturesInput getFeaturesInput;
@Mock GetQueueConfigInput getQueueConfigInput;
@Mock GroupModInput groupModInput;
@Mock HelloInput helloInput;
@Mock MeterModInput meterModInput;
@Mock PacketOutInput packetOutInput;
@Mock MultipartRequestInput multipartRequestInput;
@Mock PortModInput portModInput;
@Mock RoleRequestInput roleRequestInput;
@Mock SetConfigInput setConfigInput;
@Mock TableModInput tableModInput;
@Mock GetAsyncInput getAsyncInput;
@Mock SetAsyncInput setAsyncInput;
private ConnectionAdapterImpl adapter;
private Cache<RpcResponseKey, ResponseExpectedRpcListener<?>> cache;
private StatisticsCounters statCounters;
/**
* Initialize mocks
* Start counting and reset counters before each test
*/
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
statCounters = StatisticsCounters.getInstance();
statCounters.startCounting(false, 0);
}
/**
* Disconnect adapter
* Stop counting after each test
*/
@After
public void tierDown(){
if (adapter != null && adapter.isAlive()) {
adapter.disconnect();
}
statCounters.stopCounting();
}
/**
* Test statistic counter for all rpc calls (counters DS_ENTERED_OFJAVA and DS_FLOW_MODS_ENTERED have to be enabled)
*/
@Test
public void testEnterOFJavaCounter() {
if(!statCounters.isCounterEnabled(CounterEventTypes.DS_ENTERED_OFJAVA)){
Assert.fail("Counter " + CounterEventTypes.DS_ENTERED_OFJAVA + " is not enabled");
}
if(!statCounters.isCounterEnabled(CounterEventTypes.DS_FLOW_MODS_ENTERED)){
Assert.fail("Counter " + CounterEventTypes.DS_FLOW_MODS_ENTERED + " is not enabled");
}
final EmbeddedChannel embChannel = new EmbeddedChannel(new EmbededChannelHandler());
adapter = new ConnectionAdapterImpl(embChannel, InetSocketAddress.createUnresolved("localhost", 9876), true);
cache = CacheBuilder.newBuilder().concurrencyLevel(1).expireAfterWrite(RPC_RESPONSE_EXPIRATION, TimeUnit.MINUTES)
.removalListener(REMOVAL_LISTENER).build();
adapter.setResponseCache(cache);
adapter.barrier(barrierInput);
embChannel.runPendingTasks();
adapter.echo(echoInput);
embChannel.runPendingTasks();
adapter.echoReply(echoReplyInput);
embChannel.runPendingTasks();
adapter.experimenter(experimenterInput);
embChannel.runPendingTasks();
adapter.flowMod(flowModInput);
embChannel.runPendingTasks();
adapter.getConfig(getConfigInput);
embChannel.runPendingTasks();
adapter.getFeatures(getFeaturesInput);
embChannel.runPendingTasks();
adapter.getQueueConfig(getQueueConfigInput);
embChannel.runPendingTasks();
adapter.groupMod(groupModInput);
embChannel.runPendingTasks();
adapter.hello(helloInput);
embChannel.runPendingTasks();
adapter.meterMod(meterModInput);
embChannel.runPendingTasks();
adapter.packetOut(packetOutInput);
embChannel.runPendingTasks();
adapter.multipartRequest(multipartRequestInput);
embChannel.runPendingTasks();
adapter.portMod(portModInput);
embChannel.runPendingTasks();
adapter.roleRequest(roleRequestInput);
embChannel.runPendingTasks();
adapter.setConfig(setConfigInput);
embChannel.runPendingTasks();
adapter.tableMod(tableModInput);
embChannel.runPendingTasks();
adapter.getAsync(getAsyncInput);
embChannel.runPendingTasks();
adapter.setAsync(setAsyncInput);
embChannel.runPendingTasks();
Assert.assertEquals("Wrong - bad counter value for ConnectionAdapterImpl rpc methods", 19, statCounters.getCounter(CounterEventTypes.DS_ENTERED_OFJAVA).getCounterValue());
Assert.assertEquals("Wrong - bad counter value for ConnectionAdapterImpl flow-mod entered", 1, statCounters.getCounter(CounterEventTypes.DS_FLOW_MODS_ENTERED).getCounterValue());
adapter.disconnect();
}
/**
* Test counter for pass messages to consumer (counter US_MESSAGE_PASS has to be enabled)
*/
@Test
public void testMessagePassCounter() {
if(!statCounters.isCounterEnabled(CounterEventTypes.US_MESSAGE_PASS)){
Assert.fail("Counter " + CounterEventTypes.US_MESSAGE_PASS + " is not enabled");
}
when(channel.pipeline()).thenReturn(pipeline);
adapter = new ConnectionAdapterImpl(channel, InetSocketAddress.createUnresolved("10.0.0.1", 6653), true);
adapter.setMessageListener(messageListener);
adapter.setSystemListener(systemListener);
adapter.setConnectionReadyListener(readyListener);
cache = CacheBuilder.newBuilder().concurrencyLevel(1).expireAfterWrite(RPC_RESPONSE_EXPIRATION, TimeUnit.MINUTES)
.removalListener(REMOVAL_LISTENER).build();
adapter.setResponseCache(cache);
when(channel.disconnect()).thenReturn(channelFuture);
DataObject message = new EchoRequestMessageBuilder().build();
adapter.consume(message);
message = new ErrorMessageBuilder().build();
adapter.consume(message);
message = new ExperimenterMessageBuilder().build();
adapter.consume(message);
message = new FlowRemovedMessageBuilder().build();
adapter.consume(message);
message = new HelloMessageBuilder().build();
adapter.consume(message);
message = new MultipartReplyMessageBuilder().build();
adapter.consume(message);
message = new PacketInMessageBuilder().build();
adapter.consume(message);
message = new PortStatusMessageBuilder().build();
adapter.consume(message);
message = new EchoRequestMessageBuilder().build();
adapter.consume(message);
Assert.assertEquals("Wrong - bad counter value for ConnectionAdapterImpl consume method", 9, statCounters.getCounter(CounterEventTypes.US_MESSAGE_PASS).getCounterValue());
adapter.disconnect();
}
/**
* Empty channel Handler for testing
* @author madamjak
*
*/
private class EmbededChannelHandler extends ChannelOutboundHandlerAdapter {
// no operation need to test
}
}