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.buffer.ByteBuf;
21 import io.netty.buffer.Unpooled;
22 import io.netty.channel.Channel;
23 import io.netty.channel.ChannelHandlerContext;
24 import io.netty.channel.ChannelInboundHandlerAdapter;
25 import io.netty.channel.EventLoopGroup;
26 import io.netty.channel.MultiThreadIoEventLoopGroup;
27 import io.netty.channel.nio.NioIoHandler;
28 import io.netty.channel.socket.SocketChannel;
29 import io.netty.channel.socket.nio.NioServerSocketChannel;
30 import io.netty.handler.codec.ByteToMessageDecoder;
31 import org.junit.jupiter.api.Test;
32 import org.junit.jupiter.api.TestInfo;
33 import org.junit.jupiter.api.Timeout;
34
35 import java.net.SocketException;
36 import java.nio.channels.NotYetConnectedException;
37 import java.util.List;
38 import java.util.concurrent.CountDownLatch;
39
40 import static org.assertj.core.api.Assertions.assertThat;
41 import static org.junit.jupiter.api.Assertions.assertFalse;
42 import static org.junit.jupiter.api.Assertions.assertThrows;
43
44 public class SocketChannelNotYetConnectedTest extends AbstractClientSocketTest {
45 @Test
46 @Timeout(30)
47 public void testShutdownNotYetConnected(TestInfo testInfo) throws Throwable {
48 run(testInfo, new Runner<Bootstrap>() {
49 @Override
50 public void run(Bootstrap bootstrap) throws Throwable {
51 testShutdownNotYetConnected(bootstrap);
52 }
53 });
54 }
55
56 public void testShutdownNotYetConnected(Bootstrap cb) throws Throwable {
57 SocketChannel ch = (SocketChannel) cb.handler(new ChannelInboundHandlerAdapter())
58 .bind(newSocketAddress()).syncUninterruptibly().channel();
59 try {
60 Throwable cause = assertThrows(Throwable.class, () -> ch.shutdownInput().syncUninterruptibly());
61 checkThrowable(cause);
62
63 cause = assertThrows(Throwable.class, () -> ch.shutdownOutput().syncUninterruptibly());
64 checkThrowable(cause);
65 } finally {
66 ch.close().syncUninterruptibly();
67 }
68 }
69
70 private static void checkThrowable(Throwable cause) throws Throwable {
71
72 if (!(cause instanceof NotYetConnectedException) && !(cause instanceof SocketException)) {
73 throw cause;
74 }
75 }
76
77 @Test
78 @Timeout(30)
79 public void readMustBePendingUntilChannelIsActive(TestInfo info) throws Throwable {
80 run(info, new Runner<Bootstrap>() {
81 @Override
82 public void run(Bootstrap bootstrap) throws Throwable {
83 EventLoopGroup group = new MultiThreadIoEventLoopGroup(1, NioIoHandler.newFactory());
84 ServerBootstrap sb = new ServerBootstrap().group(group);
85 Channel serverChannel = sb.childHandler(new ChannelInboundHandlerAdapter() {
86 @Override
87 public void channelActive(ChannelHandlerContext ctx) throws Exception {
88 ctx.writeAndFlush(Unpooled.copyInt(42));
89 }
90 }).channel(NioServerSocketChannel.class).bind(0).sync().channel();
91
92 final CountDownLatch readLatch = new CountDownLatch(1);
93 bootstrap.handler(new ByteToMessageDecoder() {
94 @Override
95 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
96 assertFalse(ctx.channel().isActive());
97 ctx.read();
98 }
99
100 @Override
101 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
102 assertThat(in.readableBytes()).isLessThanOrEqualTo(Integer.BYTES);
103 if (in.readableBytes() == Integer.BYTES) {
104 assertThat(in.readInt()).isEqualTo(42);
105 readLatch.countDown();
106 }
107 }
108 });
109 bootstrap.connect(serverChannel.localAddress()).sync();
110
111 readLatch.await();
112 group.shutdownGracefully().await();
113 }
114 });
115 }
116 }