changeset 52104:331fbd2db6b5

8189366: SocketInputStream.available() should check for eof Reviewed-by: chegar
author vtewari
date Fri, 12 Oct 2018 12:37:13 +0530
parents 4acfd9b6c2f9
children 537dbfcef4a7
files src/java.base/share/classes/java/net/SocketInputStream.java test/jdk/java/net/Socket/CloseAvailable.java
diffstat 2 files changed, 64 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/net/SocketInputStream.java	Fri Oct 12 08:33:18 2018 +0200
+++ b/src/java.base/share/classes/java/net/SocketInputStream.java	Fri Oct 12 12:37:13 2018 +0530
@@ -232,7 +232,11 @@
      * @return the number of immediately available bytes
      */
     public int available() throws IOException {
-        return impl.available();
+        if (eof) {
+            return 0;
+        } else {
+            return impl.available();
+        }
     }
 
     /**
--- a/test/jdk/java/net/Socket/CloseAvailable.java	Fri Oct 12 08:33:18 2018 +0200
+++ b/test/jdk/java/net/Socket/CloseAvailable.java	Fri Oct 12 12:37:13 2018 +0530
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4091859
+ * @bug 4091859 8189366
  * @summary Test Socket.available()
  * @run main CloseAvailable
  * @run main/othervm -Djava.net.preferIPv4Stack=true CloseAvailable
@@ -33,18 +33,32 @@
 import java.io.*;
 
 
-public class CloseAvailable implements Runnable {
-    static ServerSocket ss;
-    static InetAddress addr;
-    static int port;
+public class CloseAvailable {
 
     public static void main(String[] args) throws Exception {
+        testClose();
+
+        testEOF(true);
+        testEOF(false);
+    }
+
+    static void testClose() throws IOException {
         boolean error = true;
-        addr = InetAddress.getLocalHost();
-        ss = new ServerSocket(0);
-        port = ss.getLocalPort();
+        InetAddress addr = InetAddress.getLocalHost();
+        ServerSocket ss = new ServerSocket(0);
+        int port = ss.getLocalPort();
 
-        Thread t = new Thread(new CloseAvailable());
+        Thread t = new Thread(new Thread("Close-Available-1") {
+            public void run() {
+                try {
+                    Socket s = new Socket(addr, port);
+                    s.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
         t.start();
 
         Socket  soc = ss.accept();
@@ -63,13 +77,42 @@
             throw new RuntimeException("Available() can be called after stream closed.");
     }
 
-    public void run() {
-        try {
-            Socket s = new Socket(addr, port);
-            s.close();
-        } catch (Exception e) {
-            e.printStackTrace();
+    // Verifies consistency of `available` behaviour when EOF reached, both
+    // explicitly and implicitly.
+    static void testEOF(boolean readUntilEOF) throws IOException {
+        System.out.println("testEOF, readUntilEOF: " + readUntilEOF);
+        InetAddress addr = InetAddress.getLoopbackAddress();
+        ServerSocket ss = new ServerSocket();
+        ss.bind(new InetSocketAddress(addr, 0), 0);
+        int port = ss.getLocalPort();
+
+        try (Socket s = new Socket(addr, port)) {
+            s.getOutputStream().write(0x42);
+            s.shutdownOutput();
+
+            try (Socket soc = ss.accept()) {
+                ss.close();
+
+                InputStream is = soc.getInputStream();
+                int b = is.read();
+                assert b == 0x42;
+                assert !s.isClosed();
+                if (readUntilEOF) {
+                    b = is.read();
+                    assert b == -1;
+                }
+
+                int a;
+                for (int i = 0; i < 100; i++) {
+                    a = is.available();
+                    System.out.print(a + ", ");
+                    if (a != 0)
+                        throw new RuntimeException("Unexpected non-zero available: " + a);
+                }
+                assert !s.isClosed();
+                assert is.read() == -1;
+            }
         }
+        System.out.println("\ncomplete");
     }
-
 }