2 * Copyright (c) 2014 Pantheon Technologies s.r.o. and others. All rights reserved.
\r
4 * This program and the accompanying materials are made available under the
\r
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
\r
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
\r
9 package org.opendaylight.openflowjava.protocol.impl.core.connection;
\r
11 import static org.mockito.Matchers.any;
\r
12 import static org.mockito.Mockito.times;
\r
13 import static org.mockito.Mockito.verify;
\r
14 import static org.mockito.Mockito.when;
\r
15 import io.netty.channel.ChannelFuture;
\r
16 import io.netty.channel.ChannelPipeline;
\r
17 import io.netty.channel.socket.SocketChannel;
\r
19 import java.net.InetSocketAddress;
\r
20 import java.util.concurrent.TimeUnit;
\r
22 import org.junit.Assert;
\r
23 import org.junit.Before;
\r
24 import org.junit.Test;
\r
25 import org.mockito.Mock;
\r
26 import org.mockito.MockitoAnnotations;
\r
27 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionReadyListener;
\r
28 import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
\r
29 import org.opendaylight.openflowjava.protocol.impl.core.connection.ConnectionAdapterImpl;
\r
30 import org.opendaylight.openflowjava.protocol.impl.core.connection.ResponseExpectedRpcListener;
\r
31 import org.opendaylight.openflowjava.protocol.impl.core.connection.RpcResponseKey;
\r
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInput;
\r
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierInputBuilder;
\r
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput;
\r
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutputBuilder;
\r
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessage;
\r
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.EchoRequestMessageBuilder;
\r
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessage;
\r
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ErrorMessageBuilder;
\r
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessage;
\r
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.ExperimenterMessageBuilder;
\r
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessage;
\r
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemovedMessageBuilder;
\r
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessage;
\r
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.HelloMessageBuilder;
\r
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessage;
\r
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReplyMessageBuilder;
\r
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OfHeader;
\r
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.OpenflowProtocolListener;
\r
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessage;
\r
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PacketInMessageBuilder;
\r
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessage;
\r
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.PortStatusMessageBuilder;
\r
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEvent;
\r
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.DisconnectEventBuilder;
\r
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEvent;
\r
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SwitchIdleEventBuilder;
\r
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.system.rev130927.SystemNotificationsListener;
\r
59 import org.opendaylight.yangtools.yang.binding.DataObject;
\r
61 import com.google.common.cache.Cache;
\r
62 import com.google.common.cache.CacheBuilder;
\r
63 import com.google.common.cache.RemovalListener;
\r
64 import com.google.common.cache.RemovalNotification;
\r
67 * @author michal.polkorab
\r
71 public class ConnectionAdapterImplTest {
\r
73 private static final int RPC_RESPONSE_EXPIRATION = 1;
\r
74 private static final RemovalListener<RpcResponseKey, ResponseExpectedRpcListener<?>> REMOVAL_LISTENER =
\r
75 new RemovalListener<RpcResponseKey, ResponseExpectedRpcListener<?>>() {
\r
77 public void onRemoval(
\r
78 final RemovalNotification<RpcResponseKey, ResponseExpectedRpcListener<?>> notification) {
\r
79 notification.getValue().discard();
\r
83 @Mock SocketChannel channel;
\r
84 @Mock ChannelPipeline pipeline;
\r
85 @Mock OpenflowProtocolListener messageListener;
\r
86 @Mock SystemNotificationsListener systemListener;
\r
87 @Mock ConnectionReadyListener readyListener;
\r
88 @Mock Cache<RpcResponseKey, ResponseExpectedRpcListener<?>> mockCache;
\r
89 @Mock ChannelFuture channelFuture;
\r
91 private ConnectionAdapterImpl adapter;
\r
92 private Cache<RpcResponseKey, ResponseExpectedRpcListener<?>> cache;
\r
95 * Initializes ConnectionAdapter
\r
98 public void setUp() {
\r
99 MockitoAnnotations.initMocks(this);
\r
100 when(channel.pipeline()).thenReturn(pipeline);
\r
101 adapter = new ConnectionAdapterImpl(channel, InetSocketAddress.createUnresolved("10.0.0.1", 6653));
\r
102 adapter.setMessageListener(messageListener);
\r
103 adapter.setSystemListener(systemListener);
\r
104 adapter.setConnectionReadyListener(readyListener);
\r
105 cache = CacheBuilder.newBuilder().concurrencyLevel(1).expireAfterWrite(RPC_RESPONSE_EXPIRATION, TimeUnit.MINUTES)
\r
106 .removalListener(REMOVAL_LISTENER).build();
\r
107 adapter.setResponseCache(cache);
108 when(channel.disconnect()).thenReturn(channelFuture);
112 * Tests {@link ConnectionAdapterImpl#consume(DataObject)} with notifications
\r
115 public void testConsume() {
\r
116 DataObject message = new EchoRequestMessageBuilder().build();
\r
117 adapter.consume(message);
\r
118 verify(messageListener, times(1)).onEchoRequestMessage((EchoRequestMessage) message);
\r
119 message = new ErrorMessageBuilder().build();
\r
120 adapter.consume(message);
\r
121 verify(messageListener, times(1)).onErrorMessage((ErrorMessage) message);
\r
122 message = new ExperimenterMessageBuilder().build();
\r
123 adapter.consume(message);
\r
124 verify(messageListener, times(1)).onExperimenterMessage((ExperimenterMessage) message);
\r
125 message = new FlowRemovedMessageBuilder().build();
\r
126 adapter.consume(message);
\r
127 verify(messageListener, times(1)).onFlowRemovedMessage((FlowRemovedMessage) message);
\r
128 message = new HelloMessageBuilder().build();
\r
129 adapter.consume(message);
\r
130 verify(messageListener, times(1)).onHelloMessage((HelloMessage) message);
\r
131 message = new MultipartReplyMessageBuilder().build();
\r
132 adapter.consume(message);
\r
133 verify(messageListener, times(1)).onMultipartReplyMessage((MultipartReplyMessage) message);
\r
134 message = new PacketInMessageBuilder().build();
\r
135 adapter.consume(message);
\r
136 verify(messageListener, times(1)).onPacketInMessage((PacketInMessage) message);
\r
137 message = new PortStatusMessageBuilder().build();
\r
138 adapter.consume(message);
\r
139 verify(messageListener, times(1)).onPortStatusMessage((PortStatusMessage) message);
\r
140 message = new SwitchIdleEventBuilder().build();
\r
141 adapter.consume(message);
\r
142 verify(systemListener, times(1)).onSwitchIdleEvent((SwitchIdleEvent) message);
\r
143 message = new DisconnectEventBuilder().build();
\r
144 adapter.consume(message);
\r
145 verify(systemListener, times(1)).onDisconnectEvent((DisconnectEvent) message);
\r
146 message = new EchoRequestMessageBuilder().build();
\r
147 adapter.consume(message);
\r
148 verify(messageListener, times(1)).onEchoRequestMessage((EchoRequestMessage) message);
\r
152 * Tests {@link ConnectionAdapterImpl#consume(DataObject)} with unexpected rpc
\r
155 public void testConsume2() {
\r
156 adapter.setResponseCache(mockCache);
\r
157 BarrierOutputBuilder barrierBuilder = new BarrierOutputBuilder();
\r
158 barrierBuilder.setXid(42L);
\r
159 BarrierOutput barrier = barrierBuilder.build();
\r
160 adapter.consume(barrier);
\r
161 verify(mockCache, times(1)).getIfPresent(any(RpcResponseKey.class));
\r
165 * Tests {@link ConnectionAdapterImpl#consume(DataObject)} with expected rpc
\r
168 public void testConsume3() {
\r
169 BarrierInputBuilder inputBuilder = new BarrierInputBuilder();
\r
170 inputBuilder.setVersion((short) EncodeConstants.OF13_VERSION_ID);
\r
171 inputBuilder.setXid(42L);
\r
172 BarrierInput barrierInput = inputBuilder.build();
\r
173 RpcResponseKey key = new RpcResponseKey(42L, "org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.BarrierOutput");
\r
174 ResponseExpectedRpcListener<OfHeader> listener = new ResponseExpectedRpcListener<>(barrierInput,
\r
175 "failure", mockCache, key);
\r
176 cache.put(key, listener);
\r
177 BarrierOutputBuilder barrierBuilder = new BarrierOutputBuilder();
\r
178 barrierBuilder.setXid(42L);
\r
179 BarrierOutput barrierOutput = barrierBuilder.build();
\r
180 adapter.consume(barrierOutput);
\r
181 ResponseExpectedRpcListener<?> ifPresent = cache.getIfPresent(key);
\r
182 Assert.assertNull("Listener was not discarded", ifPresent);
\r
185 * Test IsAlive method
188 public void testIsAlive(){
190 String host ="localhost";
191 InetSocketAddress inetSockAddr = InetSocketAddress.createUnresolved(host, port);
192 ConnectionAdapterImpl connAddapter = new ConnectionAdapterImpl(channel,inetSockAddr);
193 Assert.assertEquals("Wrong - diffrence between channel.isOpen() and ConnectionAdapterImpl.isAlive()", channel.isOpen(), connAddapter.isAlive());
195 connAddapter.disconnect();
196 Assert.assertFalse("Wrong - ConnectionAdapterImpl can not be alive after disconnet.", connAddapter.isAlive());
200 * Test throw exception if no listeners are present
202 @Test(expected = java.lang.IllegalStateException.class)
203 public void testMissingListeners(){
205 String host ="localhost";
206 InetSocketAddress inetSockAddr = InetSocketAddress.createUnresolved(host, port);
207 ConnectionAdapterImpl connAddapter = new ConnectionAdapterImpl(channel,inetSockAddr);
208 connAddapter.setSystemListener(null);
209 connAddapter.setMessageListener(null);
210 connAddapter.setConnectionReadyListener(null);
211 connAddapter.checkListeners();