From 438a4d5467d7e1ec3e5a9d7faa8e3cd7990fc6b7 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Mon, 15 Apr 2019 21:39:31 +0200 Subject: [PATCH] Make Multicast tests more robust (#9053) Motivation: 86dd3886374323ac1ac8011b4a4716706bb7c47b reverted the usage of IPv6 Multicast test. This commit makes the whole multicast testing a lot more robust by selecting the correct interface in any case and also reverts the `@Ignore` Modifications: - More robust multicast testing by selecting the right NetworkInterface - Remove the `@Ignore` again for the IPv6 test Result: More robust multicast testing --- .../socket/DatagramMulticastIPv6Test.java | 7 -- .../socket/DatagramMulticastTest.java | 94 ++++++++++++++----- 2 files changed, 70 insertions(+), 31 deletions(-) diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastIPv6Test.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastIPv6Test.java index 8a62e000dc..aa85e65218 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastIPv6Test.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastIPv6Test.java @@ -16,16 +16,9 @@ package io.netty.testsuite.transport.socket; import io.netty.channel.socket.InternetProtocolFamily; -import org.junit.Ignore; public class DatagramMulticastIPv6Test extends DatagramMulticastTest { - @Ignore("Fails on some systems") - @Override - public void testMulticast() throws Throwable { - super.testMulticast(); - } - @Override protected InternetProtocolFamily internetProtocolFamily() { return InternetProtocolFamily.IPv6; diff --git a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastTest.java b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastTest.java index 3111c35fd9..154e80554d 100644 --- a/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastTest.java +++ b/testsuite/src/main/java/io/netty/testsuite/transport/socket/DatagramMulticastTest.java @@ -31,10 +31,15 @@ import org.junit.Assume; import org.junit.Before; import org.junit.Test; +import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; +import java.net.MulticastSocket; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.net.UnknownHostException; import java.util.Enumeration; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -50,6 +55,10 @@ public class DatagramMulticastTest extends AbstractDatagramTest { } public void testMulticast(Bootstrap sb, Bootstrap cb) throws Throwable { + NetworkInterface iface = multicastNetworkInterface(); + Assume.assumeNotNull("No NetworkInterface found that supports multicast and " + + internetProtocolFamily(), iface); + MulticastTestHandler mhandler = new MulticastTestHandler(); sb.handler(new SimpleChannelInboundHandler() { @@ -61,29 +70,27 @@ public class DatagramMulticastTest extends AbstractDatagramTest { cb.handler(mhandler); - sb.option(ChannelOption.IP_MULTICAST_IF, NetUtil.LOOPBACK_IF); + sb.option(ChannelOption.IP_MULTICAST_IF, iface); sb.option(ChannelOption.SO_REUSEADDR, true); - cb.option(ChannelOption.IP_MULTICAST_IF, NetUtil.LOOPBACK_IF); + cb.option(ChannelOption.IP_MULTICAST_IF, iface); cb.option(ChannelOption.SO_REUSEADDR, true); - Channel sc = sb.bind(newSocketAddress()).sync().channel(); + Channel sc = sb.bind(newSocketAddress(iface)).sync().channel(); InetSocketAddress addr = (InetSocketAddress) sc.localAddress(); cb.localAddress(addr.getPort()); DatagramChannel cc = (DatagramChannel) cb.bind().sync().channel(); - String group = internetProtocolFamily() == InternetProtocolFamily.IPv4 ? - "230.0.0.1" : "FF01:0:0:0:0:0:0:101"; - InetSocketAddress groupAddress = SocketUtils.socketAddress(group, addr.getPort()); + InetSocketAddress groupAddress = SocketUtils.socketAddress(groupAddress(), addr.getPort()); - cc.joinGroup(groupAddress, NetUtil.LOOPBACK_IF).sync(); + cc.joinGroup(groupAddress, iface).sync(); sc.writeAndFlush(new DatagramPacket(Unpooled.copyInt(1), groupAddress)).sync(); assertTrue(mhandler.await()); // leave the group - cc.leaveGroup(groupAddress, NetUtil.LOOPBACK_IF).sync(); + cc.leaveGroup(groupAddress, iface).sync(); // sleep a second to make sure we left the group Thread.sleep(1000); @@ -126,24 +133,63 @@ public class DatagramMulticastTest extends AbstractDatagramTest { } } - @Before - public void assumeInternetProtocolFamilySupported() { - Assume.assumeTrue(isSupported(internetProtocolFamily() == InternetProtocolFamily.IPv4 ? - Inet4Address.class : Inet6Address.class)); - } - - private static boolean isSupported(Class addressType) { - Enumeration addresses = NetUtil.LOOPBACK_IF.getInetAddresses(); - while (addresses.hasMoreElements()) { - if (addressType.isAssignableFrom(addresses.nextElement().getClass())) { - return true; - } - } - return false; - } - @Override protected List> newFactories() { return SocketTestPermutation.INSTANCE.datagram(internetProtocolFamily()); } + + private InetSocketAddress newAnySocketAddress() throws UnknownHostException { + switch (internetProtocolFamily()) { + case IPv4: + return new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0); + case IPv6: + return new InetSocketAddress(InetAddress.getByName("::"), 0); + default: + throw new AssertionError(); + } + } + + private InetSocketAddress newSocketAddress(NetworkInterface iface) { + Enumeration addresses = iface.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress address = addresses.nextElement(); + if (internetProtocolFamily().addressType().isAssignableFrom(address.getClass())) { + return new InetSocketAddress(address, 0); + } + } + throw new AssertionError(); + } + + private NetworkInterface multicastNetworkInterface() throws IOException { + Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); + while (interfaces.hasMoreElements()) { + NetworkInterface iface = interfaces.nextElement(); + if (iface.isUp() && iface.supportsMulticast()) { + Enumeration addresses = iface.getInetAddresses(); + while (addresses.hasMoreElements()) { + InetAddress address = addresses.nextElement(); + if (internetProtocolFamily().addressType().isAssignableFrom(address.getClass())) { + MulticastSocket socket = new MulticastSocket(newAnySocketAddress()); + socket.setReuseAddress(true); + socket.setNetworkInterface(iface); + try { + socket.send(new java.net.DatagramPacket(new byte[] { 1, 2, 3, 4 }, 4, + new InetSocketAddress(groupAddress(), 12345))); + return iface; + } catch (IOException ignore) { + // Try the next interface + } finally { + socket.close(); + } + } + } + } + } + return null; + } + + private String groupAddress() { + return internetProtocolFamily() == InternetProtocolFamily.IPv4 ? + "230.0.0.1" : "FF01:0:0:0:0:0:0:101"; + } }