1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.testsuite.transport.socket;
17
18 import io.netty.bootstrap.Bootstrap;
19 import io.netty.bootstrap.ServerBootstrap;
20 import io.netty.channel.Channel;
21 import io.netty.channel.ChannelHandlerContext;
22 import io.netty.channel.ChannelInboundHandlerAdapter;
23 import io.netty.channel.ChannelInitializer;
24 import io.netty.channel.ChannelOption;
25 import org.junit.jupiter.api.Test;
26 import org.junit.jupiter.api.TestInfo;
27 import org.junit.jupiter.api.Timeout;
28
29 import java.io.IOException;
30 import java.util.Locale;
31 import java.util.concurrent.CountDownLatch;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.atomic.AtomicReference;
34
35 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
36 import static org.junit.jupiter.api.Assertions.assertNull;
37 import static org.junit.jupiter.api.Assertions.assertTrue;
38
39 public class SocketRstTest extends AbstractSocketTest {
40 protected void assertRstOnCloseException(IOException cause, Channel clientChannel) {
41 if (Locale.getDefault() == Locale.US || Locale.getDefault() == Locale.UK) {
42 assertTrue(cause.getMessage().contains("reset") || cause.getMessage().contains("closed"),
43 "actual message: " + cause.getMessage());
44 }
45 }
46
47 @Test
48 @Timeout(value = 30)
49 public void testSoLingerZeroCausesOnlyRstOnClose(TestInfo testInfo) throws Throwable {
50 run(testInfo, new Runner<ServerBootstrap, Bootstrap>() {
51 @Override
52 public void run(ServerBootstrap serverBootstrap, Bootstrap bootstrap) throws Throwable {
53 testSoLingerZeroCausesOnlyRstOnClose(serverBootstrap, bootstrap);
54 }
55 });
56 }
57
58 public void testSoLingerZeroCausesOnlyRstOnClose(ServerBootstrap sb, Bootstrap cb) throws Throwable {
59 final AtomicReference<Channel> serverChannelRef = new AtomicReference<Channel>();
60 final AtomicReference<Throwable> throwableRef = new AtomicReference<Throwable>();
61 final CountDownLatch latch = new CountDownLatch(1);
62 final CountDownLatch latch2 = new CountDownLatch(1);
63
64 sb.childOption(ChannelOption.SO_LINGER, 0);
65 sb.childHandler(new ChannelInitializer<Channel>() {
66 @Override
67 protected void initChannel(Channel ch) throws Exception {
68 serverChannelRef.compareAndSet(null, ch);
69 latch.countDown();
70 }
71 });
72 cb.handler(new ChannelInitializer<Channel>() {
73 @Override
74 protected void initChannel(Channel ch) throws Exception {
75 ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
76 @Override
77 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
78 throwableRef.compareAndSet(null, cause);
79 }
80
81 @Override
82 public void channelInactive(ChannelHandlerContext ctx) {
83 latch2.countDown();
84 }
85 });
86 }
87 });
88 Channel sc = sb.bind().sync().channel();
89 Channel cc = cb.connect(sc.localAddress()).sync().channel();
90
91
92 latch.await();
93
94
95 serverChannelRef.get().close();
96
97
98 latch2.await();
99
100
101 Throwable cause = throwableRef.get();
102 assertInstanceOf(IOException.class, cause,
103 "actual [type, message]: [" + cause.getClass() + ", " + cause.getMessage() + "]");
104
105 assertRstOnCloseException((IOException) cause, cc);
106 }
107
108 @Test
109 @Timeout(value = 30)
110 public void testNoRstIfSoLingerOnClose(TestInfo testInfo) throws Throwable {
111 run(testInfo, new Runner<ServerBootstrap, Bootstrap>() {
112 @Override
113 public void run(ServerBootstrap serverBootstrap, Bootstrap bootstrap) throws Throwable {
114 testNoRstIfSoLingerOnClose(serverBootstrap, bootstrap);
115 }
116 });
117 }
118
119 public void testNoRstIfSoLingerOnClose(ServerBootstrap sb, Bootstrap cb) throws Throwable {
120 final AtomicReference<Channel> serverChannelRef = new AtomicReference<Channel>();
121 final AtomicReference<Throwable> throwableRef = new AtomicReference<Throwable>();
122 final CountDownLatch latch = new CountDownLatch(1);
123 final CountDownLatch latch2 = new CountDownLatch(1);
124 sb.childHandler(new ChannelInitializer<Channel>() {
125 @Override
126 protected void initChannel(Channel ch) throws Exception {
127 serverChannelRef.compareAndSet(null, ch);
128 latch.countDown();
129 }
130 });
131 cb.handler(new ChannelInitializer<Channel>() {
132 @Override
133 protected void initChannel(Channel ch) throws Exception {
134 ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
135 @Override
136 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
137 throwableRef.compareAndSet(null, cause);
138 }
139
140 @Override
141 public void channelInactive(ChannelHandlerContext ctx) {
142 latch2.countDown();
143 }
144 });
145 }
146 });
147 Channel sc = sb.bind().sync().channel();
148 cb.connect(sc.localAddress()).syncUninterruptibly();
149
150
151 latch.await();
152
153
154 serverChannelRef.get().close();
155
156
157 latch2.await();
158
159
160 assertNull(throwableRef.get());
161 }
162 }