Merge "Clean up netconf-parent root pom"
[netconf.git] / netconf / netconf-client / src / test / java / org / opendaylight / netconf / client / NetconfClientSessionNegotiatorTest.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.netconf.client;
10
11 import static junit.framework.Assert.assertEquals;
12 import static junit.framework.Assert.assertTrue;
13 import static org.junit.Assert.assertNotEquals;
14 import static org.mockito.Matchers.any;
15 import static org.mockito.Matchers.anyObject;
16 import static org.mockito.Matchers.anyString;
17 import static org.mockito.Mockito.doAnswer;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.times;
21 import static org.mockito.Mockito.verify;
22
23 import com.google.common.base.Optional;
24 import com.google.common.collect.ImmutableSet;
25 import io.netty.channel.Channel;
26 import io.netty.channel.ChannelFuture;
27 import io.netty.channel.ChannelHandler;
28 import io.netty.channel.ChannelHandlerContext;
29 import io.netty.channel.ChannelInboundHandlerAdapter;
30 import io.netty.channel.ChannelPipeline;
31 import io.netty.channel.ChannelProgressivePromise;
32 import io.netty.channel.EventLoop;
33 import io.netty.handler.ssl.SslHandler;
34 import io.netty.util.HashedWheelTimer;
35 import io.netty.util.Timer;
36 import io.netty.util.concurrent.GenericFutureListener;
37 import io.netty.util.concurrent.Promise;
38 import java.io.InputStream;
39 import java.util.Set;
40 import org.junit.Before;
41 import org.junit.Test;
42 import org.mockito.internal.util.collections.Sets;
43 import org.mockito.invocation.InvocationOnMock;
44 import org.mockito.stubbing.Answer;
45 import org.opendaylight.controller.config.util.xml.XmlUtil;
46 import org.opendaylight.netconf.api.NetconfClientSessionPreferences;
47 import org.opendaylight.netconf.api.NetconfMessage;
48 import org.opendaylight.netconf.api.messages.NetconfHelloMessage;
49 import org.opendaylight.netconf.api.messages.NetconfHelloMessageAdditionalHeader;
50 import org.opendaylight.netconf.nettyutil.handler.ChunkedFramingMechanismEncoder;
51 import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToHelloMessageDecoder;
52 import org.opendaylight.netconf.nettyutil.handler.NetconfXMLToMessageDecoder;
53 import org.opendaylight.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
54 import org.opendaylight.netconf.util.messages.NetconfMessageUtil;
55 import org.opendaylight.netconf.util.test.XmlFileLoader;
56 import org.openexi.proc.common.EXIOptions;
57 import org.w3c.dom.Document;
58
59 public class NetconfClientSessionNegotiatorTest {
60
61     private NetconfHelloMessage helloMessage;
62     private ChannelPipeline pipeline;
63     private ChannelFuture future;
64     private Channel channel;
65     private ChannelInboundHandlerAdapter channelInboundHandlerAdapter;
66
67     @Before
68     public void setUp() throws Exception {
69         helloMessage = NetconfHelloMessage.createClientHello(Sets.newSet("exi:1.0"), Optional
70                 .<NetconfHelloMessageAdditionalHeader>absent());
71         pipeline = mockChannelPipeline();
72         future = mockChannelFuture();
73         channel = mockChannel();
74         mockEventLoop();
75     }
76
77     private static ChannelHandler mockChannelHandler() {
78         ChannelHandler handler = mock(ChannelHandler.class);
79         return handler;
80     }
81
82     private Channel mockChannel() {
83         Channel ret = mock(Channel.class);
84         ChannelHandler channelHandler = mockChannelHandler();
85         doReturn("").when(ret).toString();
86         doReturn(future).when(ret).close();
87         doReturn(future).when(ret).writeAndFlush(anyObject());
88         doReturn(true).when(ret).isOpen();
89         doReturn(pipeline).when(ret).pipeline();
90         doReturn("").when(pipeline).toString();
91         doReturn(pipeline).when(pipeline).remove(any(ChannelHandler.class));
92         doReturn(channelHandler).when(pipeline).remove(anyString());
93         return ret;
94     }
95
96     private static ChannelFuture mockChannelFuture() {
97         ChannelFuture future = mock(ChannelFuture.class);
98         doReturn(future).when(future).addListener(any(GenericFutureListener.class));
99         return future;
100     }
101
102     private static ChannelPipeline mockChannelPipeline() {
103         ChannelPipeline pipeline = mock(ChannelPipeline.class);
104         ChannelHandler handler = mock(ChannelHandler.class);
105         doReturn(pipeline).when(pipeline).addAfter(anyString(), anyString(), any(ChannelHandler.class));
106         doReturn(null).when(pipeline).get(SslHandler.class);
107         doReturn(pipeline).when(pipeline).addLast(anyString(), any(ChannelHandler.class));
108         doReturn(handler).when(pipeline).replace(anyString(), anyString(), any(ChunkedFramingMechanismEncoder.class));
109
110         NetconfXMLToHelloMessageDecoder messageDecoder = new NetconfXMLToHelloMessageDecoder();
111         doReturn(messageDecoder).when(pipeline).replace(anyString(), anyString(), any(NetconfXMLToMessageDecoder
112                 .class));
113         doReturn(pipeline).when(pipeline).replace(any(ChannelHandler.class), anyString(), any(NetconfClientSession
114                 .class));
115         return pipeline;
116     }
117
118     private void mockEventLoop() {
119         final EventLoop eventLoop = mock(EventLoop.class);
120         doReturn(eventLoop).when(channel).eventLoop();
121         doAnswer(new Answer<Void>() {
122             @Override
123             public Void answer(InvocationOnMock invocation) throws Throwable {
124                 final Object[] args = invocation.getArguments();
125                 final Runnable runnable = (Runnable) args[0];
126                 runnable.run();
127                 return null;
128             }
129         }).when(eventLoop).execute(any(Runnable.class));
130     }
131
132     private NetconfClientSessionNegotiator createNetconfClientSessionNegotiator(
133             final Promise<NetconfClientSession> promise,
134             final NetconfMessage startExi) {
135         ChannelProgressivePromise progressivePromise = mock(ChannelProgressivePromise.class);
136         NetconfClientSessionPreferences preferences = new NetconfClientSessionPreferences(helloMessage, startExi);
137         doReturn(progressivePromise).when(promise).setFailure(any(Throwable.class));
138
139         long timeout = 10L;
140         NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
141         Timer timer = new HashedWheelTimer();
142         return new NetconfClientSessionNegotiator(preferences, promise, channel, timer, sessionListener, timeout);
143     }
144
145     private NetconfHelloMessage createHelloMsg(final String name) throws Exception {
146         final InputStream stream = NetconfClientSessionNegotiatorTest.class.getResourceAsStream(name);
147         final Document doc = XmlUtil.readXmlToDocument(stream);
148
149         return new NetconfHelloMessage(doc);
150     }
151
152     private Set<String> createCapabilities(String name) throws Exception {
153         NetconfHelloMessage hello = createHelloMsg(name);
154
155         return ImmutableSet.copyOf(NetconfMessageUtil.extractCapabilitiesFromHello(hello.getDocument()));
156     }
157
158     @Test
159     public void testNetconfClientSessionNegotiator() throws Exception {
160         Promise promise = mock(Promise.class);
161         doReturn(promise).when(promise).setSuccess(anyObject());
162         NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, null);
163
164         negotiator.channelActive(null);
165         Set<String> caps = Sets.newSet("a", "b");
166         NetconfHelloMessage helloServerMessage = NetconfHelloMessage.createServerHello(caps, 10);
167         negotiator.handleMessage(helloServerMessage);
168         verify(promise).setSuccess(anyObject());
169     }
170
171     @Test
172     public void testNetconfClientSessionNegotiatorWithEXI() throws Exception {
173         Promise promise = mock(Promise.class);
174         EXIOptions exiOptions = new EXIOptions();
175         NetconfStartExiMessage exiMessage = NetconfStartExiMessage.create(exiOptions, "msg-id");
176         doReturn(promise).when(promise).setSuccess(anyObject());
177         NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, exiMessage);
178
179         negotiator.channelActive(null);
180         Set<String> caps = Sets.newSet("exi:1.0");
181         NetconfHelloMessage message = NetconfHelloMessage.createServerHello(caps, 10);
182
183         doAnswer(new Answer<Object>() {
184             @Override
185             public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
186                 channelInboundHandlerAdapter = ((ChannelInboundHandlerAdapter) invocationOnMock.getArguments()[2]);
187                 return null;
188             }
189         }).when(pipeline).addAfter(anyString(), anyString(), any(ChannelHandler.class));
190
191         ChannelHandlerContext handlerContext = mock(ChannelHandlerContext.class);
192         doReturn(pipeline).when(handlerContext).pipeline();
193         negotiator.handleMessage(message);
194         Document expectedResult = XmlFileLoader.xmlFileToDocument("netconfMessages/rpc-reply_ok.xml");
195         channelInboundHandlerAdapter.channelRead(handlerContext, new NetconfMessage(expectedResult));
196
197         verify(promise).setSuccess(anyObject());
198
199         // two calls for exiMessage, 2 for hello message
200         verify(pipeline, times(4)).replace(anyString(), anyString(), any(ChannelHandler.class));
201     }
202
203     @Test
204     public void testNetconfClientSessionNegotiatorGetCached() throws Exception {
205         Promise promise = mock(Promise.class);
206         doReturn(promise).when(promise).setSuccess(anyObject());
207         NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
208         NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, null);
209
210         Set<String> set = createCapabilities("/helloMessage3.xml");
211
212         final Set<String> cachedS1 = (Set<String>) negotiator.getSession(sessionListener, channel,
213                 createHelloMsg("/helloMessage1.xml")).getServerCapabilities();
214
215         //helloMessage2 and helloMessage3 are the same with different order
216         final Set<String> cachedS2 = (Set<String>) negotiator.getSession(sessionListener, channel,
217                 createHelloMsg("/helloMessage2.xml")).getServerCapabilities();
218         final Set<String> cachedS3 = (Set<String>) negotiator.getSession(sessionListener, channel,
219                 createHelloMsg("/helloMessage3.xml")).getServerCapabilities();
220
221         assertEquals(cachedS3, set);
222         assertNotEquals(cachedS1, set);
223         assertEquals(cachedS2, set);
224         assertEquals(cachedS3, cachedS2);
225         assertNotEquals(cachedS3, cachedS1);
226         assertNotEquals(cachedS2, cachedS1);
227         assertTrue(cachedS2 == cachedS3);
228     }
229 }