View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty5.testsuite.transport.socket;
17  
18  import io.netty5.bootstrap.AbstractBootstrap;
19  import io.netty5.bootstrap.Bootstrap;
20  import io.netty5.bootstrap.ServerBootstrap;
21  import io.netty5.channel.Channel;
22  import io.netty5.channel.ChannelFactory;
23  import io.netty5.channel.EventLoop;
24  import io.netty5.channel.EventLoopGroup;
25  import io.netty5.channel.MultithreadEventLoopGroup;
26  import io.netty5.channel.nio.NioHandler;
27  import io.netty5.channel.socket.DomainSocketAddress;
28  import io.netty5.channel.socket.nio.NioDatagramChannel;
29  import io.netty5.channel.socket.nio.NioServerSocketChannel;
30  import io.netty5.channel.socket.nio.NioSocketChannel;
31  import io.netty5.testsuite.transport.TestsuitePermutation.BootstrapComboFactory;
32  import io.netty5.testsuite.transport.TestsuitePermutation.BootstrapFactory;
33  import io.netty5.util.concurrent.DefaultThreadFactory;
34  import io.netty5.util.internal.PlatformDependent;
35  import io.netty5.util.internal.SystemPropertyUtil;
36  import io.netty5.util.internal.logging.InternalLogger;
37  import io.netty5.util.internal.logging.InternalLoggerFactory;
38  
39  import java.io.File;
40  import java.io.IOException;
41  import java.net.ProtocolFamily;
42  import java.util.ArrayList;
43  import java.util.Collections;
44  import java.util.List;
45  
46  public class SocketTestPermutation {
47  
48      static final String BAD_HOST = SystemPropertyUtil.get("io.netty5.testsuite.badHost", "198.51.100.254");
49      static final int BAD_PORT = SystemPropertyUtil.getInt("io.netty5.testsuite.badPort", 65535);
50  
51      static {
52          InternalLogger logger = InternalLoggerFactory.getInstance(SocketConnectionAttemptTest.class);
53          logger.debug("-Dio.netty5.testsuite.badHost: {}", BAD_HOST);
54          logger.debug("-Dio.netty5.testsuite.badPort: {}", BAD_PORT);
55      }
56  
57      static final SocketTestPermutation INSTANCE = new SocketTestPermutation();
58  
59      protected static final int BOSSES = 2;
60      protected static final int WORKERS = 3;
61  
62      protected final EventLoopGroup nioBossGroup =
63              new MultithreadEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-nio-boss", true),
64                      NioHandler.newFactory());
65      protected final EventLoopGroup nioWorkerGroup =
66              new MultithreadEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-nio-worker", true),
67                      NioHandler.newFactory());
68  
69      protected <A extends AbstractBootstrap<?, ?, ?>, B extends AbstractBootstrap<?, ?, ?>>
70      List<BootstrapComboFactory<A, B>> combo(List<BootstrapFactory<A>> sbfs, List<BootstrapFactory<B>> cbfs) {
71  
72          List<BootstrapComboFactory<A, B>> list = new ArrayList<>();
73  
74          // Populate the combinations
75          for (BootstrapFactory<A> sbf: sbfs) {
76              for (BootstrapFactory<B> cbf: cbfs) {
77                  final BootstrapFactory<A> sbf0 = sbf;
78                  final BootstrapFactory<B> cbf0 = cbf;
79                  list.add(new BootstrapComboFactory<>() {
80                      @Override
81                      public A newServerInstance() {
82                          return sbf0.newInstance();
83                      }
84  
85                      @Override
86                      public B newClientInstance() {
87                          return cbf0.newInstance();
88                      }
89                  });
90              }
91          }
92  
93          return list;
94      }
95  
96      public List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {
97          // Make the list of ServerBootstrap factories.
98          List<BootstrapFactory<ServerBootstrap>> sbfs = serverSocket();
99  
100         // Make the list of Bootstrap factories.
101         List<BootstrapFactory<Bootstrap>> cbfs = clientSocket();
102 
103         // Populate the combinations
104         return combo(sbfs, cbfs);
105     }
106 
107     public List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> domainSocket() {
108         // Make the list of ServerBootstrap factories.
109         List<BootstrapFactory<ServerBootstrap>> sbfs = serverDomainSocket();
110 
111         // Make the list of Bootstrap factories.
112         List<BootstrapFactory<Bootstrap>> cbfs = clientDomainSocket();
113 
114         // Populate the combinations
115         return combo(sbfs, cbfs);
116     }
117 
118     public List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> socketWithFastOpen() {
119         // Make the list of ServerBootstrap factories.
120         List<BootstrapFactory<ServerBootstrap>> sbfs = serverSocket();
121 
122         // Make the list of Bootstrap factories.
123         List<BootstrapFactory<Bootstrap>> cbfs = clientSocketWithFastOpen();
124 
125         // Populate the combinations
126         List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> list = combo(sbfs, cbfs);
127 
128         // Remove the OIO-OIO case which often leads to a dead lock by its nature.
129         list.remove(list.size() - 1);
130 
131         return list;
132     }
133 
134     public List<BootstrapComboFactory<Bootstrap, Bootstrap>> datagram(final ProtocolFamily family) {
135         final ChannelFactory<?> channelFactory;
136         if (NioDomainSocketTestUtil.isDomainSocketFamily(family)) {
137             channelFactory = NioDomainSocketTestUtil.newDomainSocketDatagramChannelFactory();
138         } else {
139             channelFactory = new ChannelFactory<>() {
140                 @Override
141                 public Channel newChannel(EventLoop eventLoop) {
142                     return new NioDatagramChannel(eventLoop, family);
143                 }
144 
145                 @Override
146                 public String toString() {
147                     return NioDatagramChannel.class.getSimpleName() + ".class";
148                 }
149             };
150         }
151         // Make the list of Bootstrap factories.
152         List<BootstrapFactory<Bootstrap>> bfs = Collections.singletonList(
153                 () -> new Bootstrap().group(nioWorkerGroup).channelFactory(channelFactory)
154         );
155 
156         // Populare the combinations.
157         return combo(bfs, bfs);
158     }
159 
160     public List<BootstrapFactory<Bootstrap>> domainDatagramSocket() {
161         if (!NioDomainSocketTestUtil.isDatagramSupported()) {
162             throw new UnsupportedOperationException();
163         }
164         return Collections.singletonList(
165                 () -> new Bootstrap().group(nioWorkerGroup)
166                         .channelFactory(NioDomainSocketTestUtil.newDomainSocketDatagramChannelFactory())
167         );
168     }
169 
170     public List<BootstrapFactory<ServerBootstrap>> serverSocket() {
171         return Collections.singletonList(
172                 () -> new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
173                         .channel(NioServerSocketChannel.class)
174         );
175     }
176 
177     public List<BootstrapFactory<Bootstrap>> clientSocket() {
178         return Collections.singletonList(
179                 () -> new Bootstrap().group(nioWorkerGroup).channel(NioSocketChannel.class)
180         );
181     }
182 
183     public List<BootstrapFactory<ServerBootstrap>> serverDomainSocket() {
184         return Collections.singletonList(
185                 () -> new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
186                         .channelFactory(NioDomainSocketTestUtil.newDomainSocketServerChannelFactory())
187         );
188     }
189 
190     public List<BootstrapFactory<Bootstrap>> clientDomainSocket() {
191         return Collections.singletonList(
192                 () -> new Bootstrap().group(nioWorkerGroup)
193                         .channelFactory(NioDomainSocketTestUtil.newDomainSocketChannelFactory())
194         );
195     }
196 
197     public List<BootstrapFactory<Bootstrap>> clientSocketWithFastOpen() {
198         return clientSocket();
199     }
200 
201     public List<BootstrapFactory<Bootstrap>> datagramSocket() {
202         return Collections.singletonList(
203                 () -> new Bootstrap().group(nioWorkerGroup).channel(NioDatagramChannel.class)
204         );
205     }
206     public static DomainSocketAddress newDomainSocketAddress() {
207         try {
208             File file;
209             do {
210                 file = PlatformDependent.createTempFile("NETTY", "UDS", null);
211                 if (!file.delete()) {
212                     throw new IOException("failed to delete: " + file);
213                 }
214             } while (file.getAbsolutePath().length() > 128);
215             return new DomainSocketAddress(file);
216         } catch (IOException e) {
217             throw new IllegalStateException(e);
218         }
219     }
220 
221     public static boolean isJdkDomainSocketSupported() {
222         return NioDomainSocketTestUtil.isSocketSupported();
223     }
224 
225     public static boolean isJdkDomainDatagramSupported() {
226         return NioDomainSocketTestUtil.isDatagramSupported();
227     }
228 }