From 69fd3e37d8f14a26cfbe36bbf7614b8c1b249f7a Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Mon, 17 Jun 2024 17:50:28 +0100 Subject: [PATCH] Refactor to ParameterizedTest. Do not test for refused connection on Windows Server 2016 --- .../nio/channels/SocketChannel/OpenLeak.java | 113 +++++++++++------- 1 file changed, 73 insertions(+), 40 deletions(-) diff --git a/test/jdk/java/nio/channels/SocketChannel/OpenLeak.java b/test/jdk/java/nio/channels/SocketChannel/OpenLeak.java index 8d3192f43c8ae..0ddea31e59ca1 100644 --- a/test/jdk/java/nio/channels/SocketChannel/OpenLeak.java +++ b/test/jdk/java/nio/channels/SocketChannel/OpenLeak.java @@ -25,73 +25,106 @@ * @bug 6548464 * @summary SocketChannel.open(SocketAddress) leaks file descriptor if * connection cannot be established + * @requires vm.flagless * @build OpenLeak * @run junit/othervm OpenLeak */ +import java.io.IOException; import java.net.ConnectException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SocketChannel; import java.nio.channels.UnresolvedAddressException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertThrows; + public class OpenLeak { + static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.ROOT); + static final boolean IS_WINDOWS_2016 = OS_NAME.contains("windows") && OS_NAME.contains("2016"); + + // On Windows Server 2016 trying to connect to port 47 consumes the + // whole connect timeout - which makes the test fail in timeout. + // We skip this part of the test on Windows Server 2016 + static final boolean TEST_WITH_RESERVED_PORT = !IS_WINDOWS_2016; + private static final int MAX_LOOP = 250000; - @Test - public void test() throws Exception { - InetAddress lo = InetAddress.getLoopbackAddress(); - // Try to find a suitable port that will cause a - // Connection Rejected exception - // port 47 is reserved - there should be nothing there... - InetSocketAddress isa = new InetSocketAddress(lo, 47); + // Try to find a suitable port to provoke a "Connection Refused" + // error. + private static InetSocketAddress findSuitableRefusedAddress(InetSocketAddress isa) + throws IOException { + if (!TEST_WITH_RESERVED_PORT) return null; + var addr = isa.getAddress(); try (SocketChannel sc1 = SocketChannel.open(isa)) { // If we manage to connect, let's try to use some other // port. // port 51 is reserved too - there should be nothing there... - isa = new InetSocketAddress(lo, 51); - try (SocketChannel sc2 = SocketChannel.open(isa)) {}; + isa = new InetSocketAddress(addr, 51); + try (SocketChannel sc2 = SocketChannel.open(isa)) { + } // OK, last attempt... // port 61 is reserved too - there should be nothing there... - isa = new InetSocketAddress(lo, 61); - try (SocketChannel sc3 = SocketChannel.open(isa)) {}; - Assumptions.abort("Could not find a suitable port"); - return; - } catch (ConnectException x) { } - - // create an unresolved address to test another path - // where close should be called - SocketAddress sa = InetSocketAddress.createUnresolved(isa.getHostString(), isa.getPort()); - - System.err.println("Expecting Connection Refused for " + isa); - System.err.println("Expecting UnresolvedAddressException for " + sa); + isa = new InetSocketAddress(addr, 61); + try (SocketChannel sc3 = SocketChannel.open(isa)) { + } + System.err.println("Could not find a suitable port"); + return null; + } catch (ConnectException x) { + } + return isa; + } + + private static InetSocketAddress createUnresolved(InetSocketAddress isa, InetSocketAddress def) { + var sa = isa == null ? def : isa; + return InetSocketAddress.createUnresolved(sa.getHostString(), sa.getPort()); + } + + + // Builds a list of test cases + static List testCases() throws Exception { + InetAddress lo = InetAddress.getLoopbackAddress(); + + // Try to find a suitable port that will cause a + // Connection Refused exception + // port 47 is reserved - there should be nothing there... + InetSocketAddress def = new InetSocketAddress(lo, 47); + InetSocketAddress isa = findSuitableRefusedAddress(def); + InetSocketAddress sa = createUnresolved(isa, def); + + final List cases = new ArrayList<>(); + cases.add(new Object[]{sa, UnresolvedAddressException.class}); + cases.add(new Object[]{isa, ConnectException.class}); + return cases; + } + + @ParameterizedTest + @MethodSource("testCases") + public void test(SocketAddress sa, Class expectedException) throws Exception { + if (sa == null) { + Assumptions.abort("No suitable port could be found for " + expectedException); + } + System.err.printf("%nExpecting %s for %s%n", expectedException, sa); + int i = 0; try { for (i = 0; i < MAX_LOOP; i++) { - try { - SocketChannel.open(sa); - fail("This should not happen"); - } catch (UnresolvedAddressException x) { - if (i < 5 || i >= MAX_LOOP - 5) { - // print a message for the first five and last 5 exceptions - System.err.println(x); - } - } - try { - SocketChannel.open(isa); - fail("This should not happen"); - } catch (ConnectException x) { - if (i < 5 || i >= MAX_LOOP - 5) { - // print a message for the first five and last 5 exceptions - System.err.println(x); - } + Throwable x = + assertThrows(expectedException, () -> SocketChannel.open(sa)); + if (i < 5 || i >= MAX_LOOP - 5) { + // print a message for the first five and last 5 exceptions + System.err.println(x); } } } catch (Throwable t) {