136d5055aa81f20280120a0e0f10e121e21273dc
[netconf.git] / netconf / callhome-protocol / src / test / java / org / opendaylight / netconf / callhome / protocol / NetconfCallHomeServerTest.java
1 /*
2  * Copyright (c) 2016 Brocade Communication Systems 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 package org.opendaylight.netconf.callhome.protocol;
9
10 import static org.junit.Assert.assertFalse;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.Mockito.doNothing;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.spy;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18
19 import io.netty.channel.EventLoopGroup;
20 import io.netty.channel.nio.NioEventLoopGroup;
21 import java.io.IOException;
22 import java.net.InetSocketAddress;
23 import java.net.SocketAddress;
24 import java.security.PublicKey;
25 import java.util.HashMap;
26 import java.util.Map;
27 import org.junit.AfterClass;
28 import org.junit.Before;
29 import org.junit.BeforeClass;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 import org.mockito.Mock;
33 import org.mockito.Mockito;
34 import org.mockito.junit.MockitoJUnitRunner;
35 import org.opendaylight.netconf.shaded.sshd.client.SshClient;
36 import org.opendaylight.netconf.shaded.sshd.client.future.AuthFuture;
37 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSession;
38 import org.opendaylight.netconf.shaded.sshd.client.session.ClientSessionImpl;
39 import org.opendaylight.netconf.shaded.sshd.common.future.SshFutureListener;
40 import org.opendaylight.netconf.shaded.sshd.common.io.IoAcceptor;
41 import org.opendaylight.netconf.shaded.sshd.common.io.IoHandler;
42 import org.opendaylight.netconf.shaded.sshd.common.io.IoServiceFactory;
43 import org.opendaylight.netconf.shaded.sshd.common.session.Session;
44 import org.opendaylight.netconf.shaded.sshd.common.session.SessionListener;
45
46 @RunWith(MockitoJUnitRunner.class)
47 public class NetconfCallHomeServerTest {
48     private static EventLoopGroup EVENT_LOOP_GROUP;
49     private static InetSocketAddress MOCK_ADDRESS;
50
51     private SshClient mockSshClient;
52     @Mock
53     private CallHomeAuthorizationProvider mockCallHomeAuthProv;
54     @Mock
55     private CallHomeAuthorization mockAuth;
56     @Mock
57     private CallHomeSessionContext.Factory mockFactory;
58     @Mock
59     private ClientSession mockSession;
60     @Mock
61     private StatusRecorder mockStatusRecorder;
62
63     private NetconfCallHomeServer instance;
64
65     @BeforeClass
66     public static void beforeClass() {
67         EVENT_LOOP_GROUP = new NioEventLoopGroup();
68         MOCK_ADDRESS = InetSocketAddress.createUnresolved("127.0.0.1", 123);
69     }
70
71     @AfterClass
72     public static void afterClass() {
73         EVENT_LOOP_GROUP.shutdownGracefully();
74         EVENT_LOOP_GROUP = null;
75         MOCK_ADDRESS = null;
76     }
77
78     @Before
79     public void setup() {
80         mockSshClient = spy(SshClient.setUpDefaultClient());
81         mockCallHomeAuthProv = mock(CallHomeAuthorizationProvider.class);
82         mockAuth = mock(CallHomeAuthorization.class);
83         mockFactory = mock(CallHomeSessionContext.Factory.class);
84         mockSession = mock(ClientSession.class);
85         mockStatusRecorder = mock(StatusRecorder.class);
86
87         Map<String, String> props = new HashMap<>();
88         props.put("nio-workers", "1");
89         doReturn(EVENT_LOOP_GROUP).when(mockFactory).getNettyGroup();
90         instance = new NetconfCallHomeServer(
91             mockSshClient, mockCallHomeAuthProv, mockFactory, MOCK_ADDRESS, mockStatusRecorder);
92     }
93
94     @Test
95     public void sessionListenerShouldHandleEventsOfKeyEstablishedAndAuthenticated() throws IOException {
96         // Weird - IJ was ok but command line compile failed using the usual array initializer syntax ????
97         SessionListener.Event[] evt = new SessionListener.Event[2];
98         evt[0] = SessionListener.Event.KeyEstablished;
99         evt[1] = SessionListener.Event.Authenticated;
100
101         int[] hitOpen = new int[2];
102         hitOpen[0] = 0;
103         hitOpen[1] = 1;
104
105         int[] hitAuth = new int[2];
106         hitAuth[0] = 1;
107         hitAuth[1] = 0;
108
109         for (int pass = 0; pass < evt.length; pass++) {
110             // given
111             AuthFuture mockAuthFuture = mock(AuthFuture.class);
112             doReturn(null).when(mockAuthFuture).addListener(any(SshFutureListener.class));
113             CallHomeSessionContext mockContext = mock(CallHomeSessionContext.class);
114             doNothing().when(mockContext).openNetconfChannel();
115             doReturn(mockContext).when(mockSession).getAttribute(any(Session.AttributeKey.class));
116
117             final PublicKey serverKey = mock(PublicKey.class);
118             doReturn(serverKey).when(mockSession).getServerKey();
119
120             final SessionListener listener = instance.createSessionListener();
121             doReturn(mockAuthFuture).when(mockContext).authorize();
122             doReturn(false).when(mockSession).isAuthenticated();
123             // when
124             listener.sessionEvent(mockSession, evt[pass]);
125             // then
126             verify(mockContext, times(hitOpen[pass])).openNetconfChannel();
127             verify(mockContext, times(hitAuth[pass])).authorize();
128         }
129     }
130
131     @Test
132     public void verificationOfTheServerKeyShouldBeSuccessfulForServerIsAllowed() {
133         // given
134         ClientSessionImpl mockClientSession = mock(ClientSessionImpl.class);
135         Mockito.doReturn("test").when(mockClientSession).toString();
136         SocketAddress mockSocketAddr = mock(SocketAddress.class);
137         PublicKey mockPublicKey = mock(PublicKey.class);
138
139         Mockito.doReturn(true).when(mockAuth).isServerAllowed();
140         Mockito.doReturn("some-session-name").when(mockAuth).getSessionName();
141         Mockito.doReturn(mockAuth).when(mockCallHomeAuthProv).provideAuth(mockSocketAddr, mockPublicKey);
142         Mockito.doReturn(null).when(mockFactory).createIfNotExists(mockClientSession, mockAuth);
143
144         // expect
145         assertFalse(instance.verifyServerKey(mockClientSession, mockSocketAddr, mockPublicKey));
146     }
147
148     @Test
149     public void verificationOfTheServerKeyShouldFailIfTheServerIsNotAllowed() {
150         // given
151
152         ClientSessionImpl mockClientSession = mock(ClientSessionImpl.class);
153         SocketAddress mockSocketAddr = mock(SocketAddress.class);
154         PublicKey mockPublicKey = mock(PublicKey.class);
155
156         Mockito.doReturn(false).when(mockAuth).isServerAllowed();
157         Mockito.doReturn(mockAuth).when(mockCallHomeAuthProv).provideAuth(mockSocketAddr, mockPublicKey);
158         Mockito.doReturn("").when(mockClientSession).toString();
159
160         // expect
161         assertFalse(instance.verifyServerKey(mockClientSession, mockSocketAddr, mockPublicKey));
162     }
163
164     @Test
165     public void bindShouldStartTheClientAndBindTheAddress() throws IOException {
166         // given
167         IoAcceptor mockAcceptor = mock(IoAcceptor.class);
168         IoServiceFactory mockMinaFactory = mock(IoServiceFactory.class);
169
170         Mockito.doReturn(mockAcceptor).when(mockMinaFactory).createAcceptor(any(IoHandler.class));
171         Mockito.doNothing().when(mockAcceptor).bind(any(SocketAddress.class));
172         instance = new NetconfCallHomeServer(
173                 mockSshClient, mockCallHomeAuthProv, mockFactory, MOCK_ADDRESS, mockStatusRecorder, mockMinaFactory);
174         // when
175         instance.bind();
176         // then
177         verify(mockSshClient, times(1)).start();
178         verify(mockAcceptor, times(1)).bind(MOCK_ADDRESS);
179     }
180 }