79b13a233c1aac2ea3fc229e2efeca786a4cae6f
[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.EXIParameters;
54 import org.opendaylight.netconf.nettyutil.handler.exi.NetconfStartExiMessage;
55 import org.opendaylight.netconf.util.messages.NetconfMessageUtil;
56 import org.opendaylight.netconf.util.test.XmlFileLoader;
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<NetconfClientSession> 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<NetconfClientSession> promise = mock(Promise.class);
174         NetconfStartExiMessage exiMessage = NetconfStartExiMessage.create(EXIParameters.empty(), "msg-id");
175         doReturn(promise).when(promise).setSuccess(anyObject());
176         NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, exiMessage);
177
178         negotiator.channelActive(null);
179         Set<String> caps = Sets.newSet("exi:1.0");
180         NetconfHelloMessage message = NetconfHelloMessage.createServerHello(caps, 10);
181
182         doAnswer(new Answer<Object>() {
183             @Override
184             public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
185                 channelInboundHandlerAdapter = ((ChannelInboundHandlerAdapter) invocationOnMock.getArguments()[2]);
186                 return null;
187             }
188         }).when(pipeline).addAfter(anyString(), anyString(), any(ChannelHandler.class));
189
190         ChannelHandlerContext handlerContext = mock(ChannelHandlerContext.class);
191         doReturn(pipeline).when(handlerContext).pipeline();
192         negotiator.handleMessage(message);
193         Document expectedResult = XmlFileLoader.xmlFileToDocument("netconfMessages/rpc-reply_ok.xml");
194         channelInboundHandlerAdapter.channelRead(handlerContext, new NetconfMessage(expectedResult));
195
196         verify(promise).setSuccess(anyObject());
197
198         // two calls for exiMessage, 2 for hello message
199         verify(pipeline, times(4)).replace(anyString(), anyString(), any(ChannelHandler.class));
200     }
201
202     @Test
203     public void testNetconfClientSessionNegotiatorGetCached() throws Exception {
204         Promise promise = mock(Promise.class);
205         doReturn(promise).when(promise).setSuccess(anyObject());
206         NetconfClientSessionListener sessionListener = mock(NetconfClientSessionListener.class);
207         NetconfClientSessionNegotiator negotiator = createNetconfClientSessionNegotiator(promise, null);
208
209         Set<String> set = createCapabilities("/helloMessage3.xml");
210
211         final Set<String> cachedS1 = (Set<String>) negotiator.getSession(sessionListener, channel,
212                 createHelloMsg("/helloMessage1.xml")).getServerCapabilities();
213
214         //helloMessage2 and helloMessage3 are the same with different order
215         final Set<String> cachedS2 = (Set<String>) negotiator.getSession(sessionListener, channel,
216                 createHelloMsg("/helloMessage2.xml")).getServerCapabilities();
217         final Set<String> cachedS3 = (Set<String>) negotiator.getSession(sessionListener, channel,
218                 createHelloMsg("/helloMessage3.xml")).getServerCapabilities();
219
220         assertEquals(cachedS3, set);
221         assertNotEquals(cachedS1, set);
222         assertEquals(cachedS2, set);
223         assertEquals(cachedS3, cachedS2);
224         assertNotEquals(cachedS3, cachedS1);
225         assertNotEquals(cachedS2, cachedS1);
226         assertTrue(cachedS2 == cachedS3);
227     }
228 }