Bump ietf-tcp-{common,client,server} to 2022-12-12
[netconf.git] / transport / transport-tcp / src / test / java / org / opendaylight / netconf / transport / tcp / TCPClientServerTest.java
1 /*
2  * Copyright (c) 2022 PANTHEON.tech, s.r.o. 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.transport.tcp;
9
10 import static org.hamcrest.CoreMatchers.allOf;
11 import static org.hamcrest.CoreMatchers.containsString;
12 import static org.hamcrest.CoreMatchers.endsWith;
13 import static org.hamcrest.CoreMatchers.startsWith;
14 import static org.hamcrest.MatcherAssert.assertThat;
15 import static org.junit.jupiter.api.Assertions.assertEquals;
16 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
17 import static org.mockito.ArgumentMatchers.any;
18 import static org.mockito.Mockito.doCallRealMethod;
19 import static org.mockito.Mockito.doNothing;
20 import static org.mockito.Mockito.doReturn;
21 import static org.mockito.Mockito.timeout;
22 import static org.mockito.Mockito.verify;
23
24 import io.netty.channel.EventLoopGroup;
25 import io.netty.channel.socket.ServerSocketChannel;
26 import java.net.InetAddress;
27 import java.util.concurrent.TimeUnit;
28 import org.junit.jupiter.api.AfterAll;
29 import org.junit.jupiter.api.BeforeAll;
30 import org.junit.jupiter.api.Test;
31 import org.junit.jupiter.api.extension.ExtendWith;
32 import org.mockito.ArgumentCaptor;
33 import org.mockito.Mock;
34 import org.mockito.junit.jupiter.MockitoExtension;
35 import org.opendaylight.netconf.transport.api.TransportChannel;
36 import org.opendaylight.netconf.transport.api.TransportChannelListener;
37 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.client.rev221212.TcpClientGrouping;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.tcp.server.rev221212.TcpServerGrouping;
42 import org.opendaylight.yangtools.yang.common.Uint16;
43
44 @ExtendWith(MockitoExtension.class)
45 public class TCPClientServerTest {
46     @Mock
47     private TcpClientGrouping clientGrouping;
48     @Mock
49     private TransportChannelListener clientListener;
50     @Mock
51     private TcpServerGrouping serverGrouping;
52     @Mock
53     private TransportChannelListener serverListener;
54
55     private static EventLoopGroup group;
56
57     @BeforeAll
58     public static void beforeAll() {
59         group = NettyTransportSupport.newEventLoopGroup("IntegrationTest");
60     }
61
62     @AfterAll
63     public static void afterAll() {
64         group.shutdownGracefully();
65         group = null;
66     }
67
68     @Test
69     public void integrationTest() throws Exception {
70         // localhost address, so we do not leak things around
71         final var loopbackAddr = IetfInetUtil.INSTANCE.ipAddressFor(InetAddress.getLoopbackAddress());
72
73         // Server-side config
74         doReturn(loopbackAddr).when(serverGrouping).getLocalAddress();
75         doCallRealMethod().when(serverGrouping).requireLocalAddress();
76         // note: this lets the server pick any port, we do not care
77         doReturn(new PortNumber(Uint16.ZERO)).when(serverGrouping).getLocalPort();
78         doCallRealMethod().when(serverGrouping).requireLocalPort();
79
80         // Spin up the server and acquire its port
81         final var server = TCPServer.listen(serverListener, NettyTransportSupport.newServerBootstrap().group(group),
82             serverGrouping).get(2, TimeUnit.SECONDS);
83         try {
84             assertEquals("TCPServer{listener=serverListener}", server.toString());
85
86             final var serverChannel = server.listenChannel();
87             assertInstanceOf(ServerSocketChannel.class, serverChannel);
88             final var serverPort = new PortNumber(
89                 Uint16.valueOf(((ServerSocketChannel) serverChannel).localAddress().getPort()));
90
91             // Client-side config
92             doReturn(new Host(loopbackAddr)).when(clientGrouping).getRemoteAddress();
93             doCallRealMethod().when(clientGrouping).requireRemoteAddress();
94             doReturn(serverPort).when(clientGrouping).getRemotePort();
95             doCallRealMethod().when(clientGrouping).requireRemotePort();
96
97             // Capture client and server channels
98             final var serverCaptor = ArgumentCaptor.forClass(TransportChannel.class);
99             doNothing().when(serverListener).onTransportChannelEstablished(serverCaptor.capture());
100             final var clientCaptor = ArgumentCaptor.forClass(TransportChannel.class);
101             doNothing().when(clientListener).onTransportChannelEstablished(clientCaptor.capture());
102
103             final var client = TCPClient.connect(clientListener, NettyTransportSupport.newBootstrap().group(group),
104                 clientGrouping).get(2, TimeUnit.SECONDS);
105             try {
106                 verify(serverListener, timeout(500)).onTransportChannelEstablished(any());
107                 final var serverTransports = serverCaptor.getAllValues();
108                 assertEquals(1, serverTransports.size());
109                 assertThat(serverTransports.get(0).toString(), allOf(
110                     startsWith("TCPTransportChannel{channel=[id: "),
111                     containsString(":" + serverPort.getValue() + " - R:")));
112
113                 verify(clientListener, timeout(500)).onTransportChannelEstablished(any());
114                 final var clientTransports = clientCaptor.getAllValues();
115                 assertEquals(1, clientTransports.size());
116                 assertThat(clientTransports.get(0).toString(), allOf(
117                     startsWith("TCPTransportChannel{channel=[id: "),
118                     endsWith(":" + serverPort.getValue() + "]}")));
119
120                 assertThat(client.toString(), allOf(
121                     startsWith("TCPClient{listener=clientListener, state=TCPTransportChannel{channel=[id: 0x"),
122                     endsWith(":" + serverPort.getValue() + "]}}")));
123             } finally {
124                 client.shutdown().get(2, TimeUnit.SECONDS);
125             }
126         } finally {
127             server.shutdown().get(2, TimeUnit.SECONDS);
128         }
129     }
130 }