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