# HG changeset patch # User alanb # Date 1550767009 0 # Node ID f946ae816b8ace2b6342de2d35006c6552137756 # Parent b15114decb015bc058b2fb37b5b1075034d29a4e Add test for connection reset diff -r b15114decb01 -r f946ae816b8a test/jdk/java/net/Socket/ConnectionReset.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/jdk/java/net/Socket/ConnectionReset.java Thu Feb 21 16:36:49 2019 +0000 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @requires os.family != "solaris" + * @run testng ConnectionReset + * @run testng/othervm -Djdk.net.usePlainSocketImpl ConnectionReset + * @summary Test behavior of read and available when a connection is reset + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.ServerSocket; +import java.net.Socket; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class ConnectionReset { + + static final int REPEAT_COUNT = 5; + + /** + * Tests available before read when there are no bytes to read + */ + public void testAvailableBeforeRead1() throws IOException { + System.out.println("testAvailableBeforeRead1"); + acceptResetConnection(null, s -> { + InputStream in = s.getInputStream(); + for (int i=0; i %d%n", bytesAvailable); + assertTrue(bytesAvailable == 0); + try { + int bytesRead = in.read(); + if (bytesRead == -1) { + System.out.println("read => EOF"); + } else { + System.out.println("read => 1 byte"); + } + assertTrue(false); + } catch (IOException ioe) { + System.out.format("read => %s (expected)%n", ioe); + } + } + }); + } + + /** + * Tests available before read when there are bytes to read + */ + public void testAvailableBeforeRead2() throws IOException { + System.out.println("testAvailableBeforeRead2"); + byte[] data = { 1, 2, 3 }; + acceptResetConnection(data, s -> { + InputStream in = s.getInputStream(); + int remaining = data.length; + for (int i=0; i %d%n", bytesAvailable); + assertTrue(bytesAvailable <= remaining); + try { + int bytesRead = in.read(); + if (bytesRead == -1) { + System.out.println("read => EOF"); + assertTrue(false); + } else { + System.out.println("read => 1 byte"); + assertTrue(remaining > 0); + remaining--; + } + } catch (IOException ioe) { + System.out.format("read => %s%n", ioe); + remaining = 0; + } + } + }); + } + + /** + * Tests read before available when there are no bytes to read + */ + public void testReadBeforeAvailable1() throws IOException { + System.out.println("testReadBeforeAvailable1"); + acceptResetConnection(null, s -> { + InputStream in = s.getInputStream(); + for (int i=0; i EOF"); + } else { + System.out.println("read => 1 byte"); + } + assertTrue(false); + } catch (IOException ioe) { + System.out.format("read => %s (expected)%n", ioe); + } + int bytesAvailable = in.available(); + System.out.format("available => %d%n", bytesAvailable); + assertTrue(bytesAvailable == 0); + } + }); + } + + /** + * Tests read before available when there are bytes to read + */ + public void testReadBeforeAvailable2() throws IOException { + System.out.println("testReadBeforeAvailable2"); + byte[] data = { 1, 2, 3 }; + acceptResetConnection(data, s -> { + InputStream in = s.getInputStream(); + int remaining = data.length; + for (int i=0; i EOF"); + assertTrue(false); + } else { + System.out.println("read => 1 byte"); + assertTrue(remaining > 0); + remaining--; + } + } catch (IOException ioe) { + System.out.format("read => %s%n", ioe); + remaining = 0; + } + int bytesAvailable = in.available(); + System.out.format("available => %d%n", bytesAvailable); + assertTrue(bytesAvailable <= remaining); + } + }); + } + + interface ThrowingConsumer { + void accept(T t) throws IOException; + } + + /** + * Invokes a consumer with a Socket connected to a peer that has closed the + * connection with a "connection reset". The peer sends the given data bytes + * before closing (when data is not null). + */ + static void acceptResetConnection(byte[] data, ThrowingConsumer consumer) + throws IOException + { + try (var listener = new ServerSocket(0)) { + try (var socket = new Socket()) { + socket.connect(listener.getLocalSocketAddress()); + try (Socket peer = listener.accept()) { + if (data != null) { + peer.getOutputStream().write(data); + } + peer.setSoLinger(true, 0); + } + consumer.accept(socket); + } + } + } +} diff -r b15114decb01 -r f946ae816b8a test/jdk/java/net/SocketImpl/SocketImplCombinations.java --- a/test/jdk/java/net/SocketImpl/SocketImplCombinations.java Thu Feb 21 08:29:16 2019 +0000 +++ b/test/jdk/java/net/SocketImpl/SocketImplCombinations.java Thu Feb 21 16:36:49 2019 +0000 @@ -52,8 +52,9 @@ @Test public class SocketImplCombinations { - // Tests to ensure that a Socket is created with the expected SocketImpl - + /** + * Test creating an unconnected Socket, it should be created with a default SocketImpl. + */ public void testNewSocket1() throws IOException { try (Socket s = new Socket()) { SocketImpl si = getSocketImpl(s); @@ -63,6 +64,9 @@ } } + /** + * Test creating a connected Socket, it should be created with a default SocketImpl. + */ public void testNewSocket2() throws IOException { try (ServerSocket ss = new ServerSocket(0)) { try (Socket s = new Socket(ss.getInetAddress(), ss.getLocalPort())) { @@ -74,6 +78,10 @@ } } + /** + * Test creating a Socket for a DIRECT connection, it should be created with a + * platform SocketImpl. + */ public void testNewSocket3() throws IOException { try (Socket s = new Socket(Proxy.NO_PROXY)) { SocketImpl si = getSocketImpl(s); @@ -81,6 +89,10 @@ } } + /** + * Test creating a Socket for a SOCKS connection, it should be created with a + * SOCKS SocketImpl. + */ public void testNewSocket4() throws IOException { var address = new InetSocketAddress("127.0.0.1", 1080); var socksProxy = new Proxy(Proxy.Type.SOCKS, address); @@ -92,6 +104,10 @@ } } + /** + * Test creating a Socket for a HTTP proxy connection, it should be created with + * a HTTP proxy SocketImpl. + */ public void testNewSocket5() throws IOException { var address = new InetSocketAddress("127.0.0.1", 8080); var httpProxy = new Proxy(Proxy.Type.HTTP, address); @@ -103,6 +119,10 @@ } } + /** + * Test creating a Socket with "null" as the SocketImpl. A default SocketImpl + * should be lazily created. + */ public void testNewSocket6() throws IOException { Socket s = new Socket((SocketImpl) null) { }; try (s) { @@ -115,6 +135,9 @@ } } + /** + * Test creating a Socket with a custom SocketImpl. + */ public void testNewSocket7() throws IOException { Socket s = new Socket(new CustomSocketImpl(false)) { }; try (s) { @@ -123,6 +146,9 @@ } } + /** + * Test creating a Socket when there is a SocketImplFactory set. + */ public void testNewSocket8() throws IOException { setSocketSocketImplFactory(() -> new CustomSocketImpl(false)); try (Socket s = new Socket()) { @@ -133,6 +159,10 @@ } } + /** + * Test creating a Socket for a DIRECT connection when there is a + * SocketImplFactory set. + */ public void testNewSocket9() throws IOException { setSocketSocketImplFactory(() -> new CustomSocketImpl(false)); try (Socket s = new Socket(Proxy.NO_PROXY)) { @@ -143,7 +173,47 @@ } } + /** + * Test creating a Socket for a SOCKS connection when there is a + * SocketImplFactory set. + */ public void testNewSocket10() throws IOException { + var address = new InetSocketAddress("127.0.0.1", 1080); + var socksProxy = new Proxy(Proxy.Type.SOCKS, address); + setSocketSocketImplFactory(() -> new CustomSocketImpl(false)); + try (Socket s = new Socket(socksProxy)) { + SocketImpl si = getSocketImpl(s); + assertTrue(isSocksSocketImpl(si)); + SocketImpl delegate = getDelegate(si); + assertTrue(isPlatformSocketImpl(delegate)); + } finally { + setSocketSocketImplFactory(null); + } + } + + /** + * Test creating a Socket for a HTTP proxy connection when there is a + * SocketImplFactory set. + */ + public void testNewSocket11() throws IOException { + var address = new InetSocketAddress("127.0.0.1", 8080); + var httpProxy = new Proxy(Proxy.Type.HTTP, address); + setSocketSocketImplFactory(() -> new CustomSocketImpl(false)); + try (Socket s = new Socket(httpProxy)) { + SocketImpl si = getSocketImpl(s); + assertTrue(isHttpConnectSocketImpl(si)); + SocketImpl delegate = getDelegate(si); + assertTrue(isPlatformSocketImpl(delegate)); + } finally { + setSocketSocketImplFactory(null); + } + } + + /** + * Test creating a Socket with a "null" SocketImpl when there is a + * SocketImplFactory set. + */ + public void testNewSocket20() throws IOException { setSocketSocketImplFactory(() -> new CustomSocketImpl(false)); try { Socket s = new Socket((SocketImpl) null) { }; @@ -157,8 +227,10 @@ } } - // Tests to ensure that a ServerSocket is created with the expected SocketImpl - + /** + * Test creating an unbound ServerSocket, it should be created with a default + * SocketImpl. + */ public void testNewServerSocket1() throws IOException { try (ServerSocket ss = new ServerSocket()) { SocketImpl si = getSocketImpl(ss); @@ -166,6 +238,10 @@ } } + /** + * Test creating a bound ServerSocket, it should be created with a default + * SocketImpl. + */ public void testNewServerSocket2() throws IOException { try (ServerSocket ss = new ServerSocket(0)) { SocketImpl si = getSocketImpl(ss); @@ -173,6 +249,9 @@ } } + /** + * Test creating a ServerSocket with a custom SocketImpl. + */ public void testNewServerSocket3() throws IOException { ServerSocket ss = new ServerSocket(new CustomSocketImpl(true)) { }; try (ss) { @@ -181,6 +260,9 @@ } } + /** + * Test creating an unbound ServerSocket when there is a SocketImplFactory set. + */ public void testNewServerSocket4() throws IOException { setServerSocketImplFactory(() -> new CustomSocketImpl(true)); try (ServerSocket ss = new ServerSocket()) { @@ -191,8 +273,18 @@ } } - // Tests to ensure that a ServerSocket.accept returns a Socket with the - // expected SocketImpl + /** + * Test creating a bound ServerSocket when there is a SocketImplFactory set. + */ + public void testNewServerSocket5() throws IOException { + setServerSocketImplFactory(() -> new CustomSocketImpl(true)); + try (ServerSocket ss = new ServerSocket(0)) { + SocketImpl si = getSocketImpl(ss); + assertTrue(si instanceof CustomSocketImpl); + } finally { + setServerSocketImplFactory(null); + } + } /** * Test ServerSocket.accept returning a Socket that initially doesn't have a