Perform cross-tests between NIO and epoll transport

Motivation:

The epoll testsuite tests the epoll transport only against itself (i.e. epoll x epoll only).  We should test the epoll transport also against the well-tested NIO transport, too.

Modifications:

- Make SocketTestPermutation extensible and reusable so that the epoll testsuite can take advantage of it.
- Rename EpollTestUtils to EpollSocketTestPermutation and make it extend SocketTestPermutation.
- Overall clean-up of SocketTestPermutation
  - Use Arrays.asList() for simplicity
  - Add combo() method to remove code duplication

Result:

The epoll transport is now also tested against the NIO transport.  SocketTestPermutation got cleaner.
This commit is contained in:
Trustin Lee 2014-03-17 10:35:48 +09:00
parent da98b119d1
commit 6490c2bb8b
15 changed files with 200 additions and 178 deletions

View File

@ -36,7 +36,7 @@ public abstract class AbstractClientSocketTest extends AbstractTestsuiteTest<Boo
@Override
protected List<TestsuitePermutation.BootstrapFactory<Bootstrap>> newFactories() {
return SocketTestPermutation.clientSocket();
return SocketTestPermutation.INSTANCE.clientSocket();
}
@Override

View File

@ -36,7 +36,7 @@ public abstract class AbstractDatagramTest extends AbstractComboTestsuiteTest<Bo
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
return SocketTestPermutation.datagram();
return SocketTestPermutation.INSTANCE.datagram();
}
@Override

View File

@ -36,7 +36,7 @@ public abstract class AbstractServerSocketTest extends AbstractTestsuiteTest<Ser
@Override
protected List<TestsuitePermutation.BootstrapFactory<ServerBootstrap>> newFactories() {
return SocketTestPermutation.serverSocket();
return SocketTestPermutation.INSTANCE.serverSocket();
}
@Override

View File

@ -37,7 +37,7 @@ public abstract class AbstractSocketTest extends AbstractComboTestsuiteTest<Serv
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return SocketTestPermutation.socket();
return SocketTestPermutation.INSTANCE.socket();
}
@Override

View File

@ -15,10 +15,12 @@
*/
package io.netty.testsuite.transport.socket;
import io.netty.bootstrap.AbstractBootstrap;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ChannelFactory;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
@ -35,28 +37,55 @@ import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public final class SocketTestPermutation {
private SocketTestPermutation() {
// utility
}
public class SocketTestPermutation {
private static final int BOSSES = 2;
private static final int WORKERS = 3;
private static final EventLoopGroup nioBossGroup =
static final SocketTestPermutation INSTANCE = new SocketTestPermutation();
protected static final int BOSSES = 2;
protected static final int WORKERS = 3;
protected static final int OIO_SO_TIMEOUT = 10; // Use short timeout for faster runs.
protected final EventLoopGroup nioBossGroup =
new NioEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-nio-boss", true));
private static final EventLoopGroup nioWorkerGroup =
protected final EventLoopGroup nioWorkerGroup =
new NioEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-nio-worker", true));
private static final EventLoopGroup oioBossGroup =
protected final EventLoopGroup oioBossGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-oio-boss", true));
private static final EventLoopGroup oioWorkerGroup =
protected final EventLoopGroup oioWorkerGroup =
new OioEventLoopGroup(Integer.MAX_VALUE, new DefaultThreadFactory("testsuite-oio-worker", true));
static List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {
List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
new ArrayList<BootstrapComboFactory<ServerBootstrap, Bootstrap>>();
protected <A extends AbstractBootstrap<?, ?>, B extends AbstractBootstrap<?, ?>>
List<BootstrapComboFactory<A, B>> combo(List<BootstrapFactory<A>> sbfs, List<BootstrapFactory<B>> cbfs) {
List<BootstrapComboFactory<A, B>> list = new ArrayList<BootstrapComboFactory<A, B>>();
// Populate the combinations
for (BootstrapFactory<A> sbf: sbfs) {
for (BootstrapFactory<B> cbf: cbfs) {
final BootstrapFactory<A> sbf0 = sbf;
final BootstrapFactory<B> cbf0 = cbf;
list.add(new BootstrapComboFactory<A, B>() {
@Override
public A newServerInstance() {
return sbf0.newInstance();
}
@Override
public B newClientInstance() {
return cbf0.newInstance();
}
});
}
}
return list;
}
public List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {
// Make the list of ServerBootstrap factories.
List<BootstrapFactory<ServerBootstrap>> sbfs = serverSocket();
@ -64,23 +93,7 @@ public final class SocketTestPermutation {
List<BootstrapFactory<Bootstrap>> cbfs = clientSocket();
// Populate the combinations
for (BootstrapFactory<ServerBootstrap> sbf: sbfs) {
for (BootstrapFactory<Bootstrap> cbf: cbfs) {
final BootstrapFactory<ServerBootstrap> sbf0 = sbf;
final BootstrapFactory<Bootstrap> cbf0 = cbf;
list.add(new BootstrapComboFactory<ServerBootstrap, Bootstrap>() {
@Override
public ServerBootstrap newServerInstance() {
return sbf0.newInstance();
}
@Override
public Bootstrap newClientInstance() {
return cbf0.newInstance();
}
});
}
}
List<BootstrapComboFactory<ServerBootstrap, Bootstrap>> list = combo(sbfs, cbfs);
// Remove the OIO-OIO case which often leads to a dead lock by its nature.
list.remove(list.size() - 1);
@ -88,95 +101,72 @@ public final class SocketTestPermutation {
return list;
}
static List<BootstrapComboFactory<Bootstrap, Bootstrap>> datagram() {
List<BootstrapComboFactory<Bootstrap, Bootstrap>> list =
new ArrayList<BootstrapComboFactory<Bootstrap, Bootstrap>>();
public List<BootstrapComboFactory<Bootstrap, Bootstrap>> datagram() {
// Make the list of Bootstrap factories.
List<BootstrapFactory<Bootstrap>> bfs =
new ArrayList<BootstrapFactory<Bootstrap>>();
bfs.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() {
List<BootstrapFactory<Bootstrap>> bfs = Arrays.asList(
new BootstrapFactory<Bootstrap>() {
@Override
public Channel newChannel(EventLoop eventLoop) {
return new NioDatagramChannel(eventLoop, InternetProtocolFamily.IPv4);
}
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channelFactory(new ChannelFactory<Channel>() {
@Override
public Channel newChannel(EventLoop loop) {
return new NioDatagramChannel(loop, InternetProtocolFamily.IPv4);
}
@Override
public String toString() {
return NioDatagramChannel.class.getSimpleName() + ".class";
}
});
}
},
new BootstrapFactory<Bootstrap>() {
@Override
public String toString() {
return NioDatagramChannel.class.getSimpleName() + ".class";
public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioDatagramChannel.class);
}
});
}
});
bfs.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioDatagramChannel.class);
}
});
}
);
// Populate the combinations
for (BootstrapFactory<Bootstrap> sbf: bfs) {
for (BootstrapFactory<Bootstrap> cbf: bfs) {
final BootstrapFactory<Bootstrap> sbf0 = sbf;
final BootstrapFactory<Bootstrap> cbf0 = cbf;
list.add(new BootstrapComboFactory<Bootstrap, Bootstrap>() {
@Override
public Bootstrap newServerInstance() {
return sbf0.newInstance();
}
@Override
public Bootstrap newClientInstance() {
return cbf0.newInstance();
}
});
}
}
return list;
// Populare the combinations.
return combo(bfs, bfs);
}
static List<BootstrapFactory<ServerBootstrap>> serverSocket() {
List<BootstrapFactory<ServerBootstrap>> list = new ArrayList<BootstrapFactory<ServerBootstrap>>();
// Make the list of ServerBootstrap factories.
list.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
.channel(NioServerSocketChannel.class);
}
});
list.add(new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(oioBossGroup, oioWorkerGroup)
.channel(OioServerSocketChannel.class);
}
});
return list;
public List<BootstrapFactory<ServerBootstrap>> serverSocket() {
return Arrays.asList(
new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
.channel(NioServerSocketChannel.class);
}
},
new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(oioBossGroup, oioWorkerGroup)
.channel(OioServerSocketChannel.class)
.option(ChannelOption.SO_TIMEOUT, OIO_SO_TIMEOUT);
}
}
);
}
static List<BootstrapFactory<Bootstrap>> clientSocket() {
List<BootstrapFactory<Bootstrap>> list = new ArrayList<BootstrapFactory<Bootstrap>>();
list.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channel(NioSocketChannel.class);
}
});
list.add(new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioSocketChannel.class);
}
});
return list;
public List<BootstrapFactory<Bootstrap>> clientSocket() {
return Arrays.asList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channel(NioSocketChannel.class);
}
},
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(oioWorkerGroup).channel(OioSocketChannel.class)
.option(ChannelOption.SO_TIMEOUT, OIO_SO_TIMEOUT);
}
}
);
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketEchoTest extends SocketEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketFileRegionTest extends SocketFileRegionTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketFixedLengthEchoTest extends SocketFixedLengthEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketGatheringWriteTest extends SocketGatheringWriteTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketObjectEchoTest extends SocketObjectEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -31,6 +31,6 @@ public class EpollSocketSslEchoTest extends SocketSslEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketStartTlsTest extends SocketStartTlsTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -26,6 +26,6 @@ public class EpollSocketStringEchoTest extends SocketStringEchoTest {
@Override
protected List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return EpollTestUtils.newFactories();
return EpollSocketTestPermutation.INSTANCE.socket();
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.testsuite.transport.TestsuitePermutation.BootstrapFactory;
import io.netty.testsuite.transport.socket.SocketTestPermutation;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.Arrays;
import java.util.List;
class EpollSocketTestPermutation extends SocketTestPermutation {
static final SocketTestPermutation INSTANCE = new EpollSocketTestPermutation();
private final EventLoopGroup epollBossGroup =
new EpollEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-epoll-boss", true));
private final EventLoopGroup epollWorkerGroup =
new EpollEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-epoll-worker", true));
@Override
public List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> socket() {
List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> list =
combo(serverSocket(), clientSocket());
list.remove(list.size() - 1); // Exclude NIO x NIO test
return list;
}
@Override
public List<BootstrapFactory<ServerBootstrap>> serverSocket() {
return Arrays.asList(
new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(epollBossGroup, epollWorkerGroup)
.channel(EpollServerSocketChannel.class);
}
},
new BootstrapFactory<ServerBootstrap>() {
@Override
public ServerBootstrap newInstance() {
return new ServerBootstrap().group(nioBossGroup, nioWorkerGroup)
.channel(NioServerSocketChannel.class);
}
}
);
}
@Override
public List<BootstrapFactory<Bootstrap>> clientSocket() {
return Arrays.asList(
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(epollWorkerGroup).channel(EpollSocketChannel.class);
}
},
new BootstrapFactory<Bootstrap>() {
@Override
public Bootstrap newInstance() {
return new Bootstrap().group(nioWorkerGroup).channel(NioSocketChannel.class);
}
}
);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright 2014 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.channel.epoll;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.testsuite.transport.TestsuitePermutation;
import io.netty.util.concurrent.DefaultThreadFactory;
import java.util.Collections;
import java.util.List;
final class EpollTestUtils {
private static final int BOSSES = 2;
private static final int WORKERS = 3;
private static final EventLoopGroup epollBossGroup =
new EpollEventLoopGroup(BOSSES, new DefaultThreadFactory("testsuite-epoll-boss", true));
private static final EventLoopGroup epollWorkerGroup =
new EpollEventLoopGroup(WORKERS, new DefaultThreadFactory("testsuite-epoll-worker", true));
static List<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>> newFactories() {
return Collections.<TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>>singletonList(
new TestsuitePermutation.BootstrapComboFactory<ServerBootstrap, Bootstrap>() {
@Override
public ServerBootstrap newServerInstance() {
return new ServerBootstrap().group(
epollBossGroup, epollWorkerGroup).channel(EpollServerSocketChannel.class);
}
@Override
public Bootstrap newClientInstance() {
return new Bootstrap().group(epollWorkerGroup).channel(EpollSocketChannel.class);
}
});
}
private EpollTestUtils() {
// utility class
}
}