Bug 546641 - [console] IOConsoleInputStream throws unwanted IOExceptions

If IOConsoleInputStream methods are called in some particular sequences
they throw unwanted exceptions.

Change-Id: I0a3dcd2f8dd6c77b31cf3f693122bf06f5ae123a
Signed-off-by: Paul Pazderski <paul-eclipse@ppazderski.de>
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleTests.java
index cd9d51e..a291dcb 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/ConsoleTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2017, 2018 Andreas Loth and others.
+ * Copyright (c) 2017, 2019 Andreas Loth and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -37,7 +37,6 @@
 
 import junit.framework.TestCase;
 
-
 public class ConsoleTests extends AbstractDebugTest {
 
 	public ConsoleTests() {
@@ -189,15 +188,36 @@
 		}
 	}
 
+	/**
+	 * Tests for IOConsoleInputStream#available().
+	 *
+	 * @throws Exception if test fails
+	 */
 	public void testIOConsoleAvailable() throws Exception {
-
-		final IOConsole console = new IOConsole("", null);
-
+		IOConsole console = new IOConsole("", null);
 		try (InputStream consoleInput = console.getInputStream()) {
 			consoleInput.available();
 			consoleInput.available();
-		} catch (IOException ioe) {
-			TestCase.assertEquals("Input Stream is closed", ioe.getMessage()); //$NON-NLS-1$
+		}
+
+		console = new IOConsole("", null);
+		try (InputStream consoleInput = console.getInputStream()) {
+			consoleInput.available();
+			new Thread(() -> {
+				try {
+					Thread.sleep(100);
+					consoleInput.close();
+				} catch (Exception e) {
+				}
+			}).start();
+			assertEquals("read() did not signal EOF.", -1, consoleInput.read());
+		}
+
+		console = new IOConsole("", null);
+		try (InputStream consoleInput = console.getInputStream()) {
+			consoleInput.close();
+			consoleInput.available();
+			consoleInput.available();
 		}
 	}
 }
diff --git a/org.eclipse.ui.console/src/org/eclipse/ui/console/IOConsoleInputStream.java b/org.eclipse.ui.console/src/org/eclipse/ui/console/IOConsoleInputStream.java
index 04bc946..d4442f4 100644
--- a/org.eclipse.ui.console/src/org/eclipse/ui/console/IOConsoleInputStream.java
+++ b/org.eclipse.ui.console/src/org/eclipse/ui/console/IOConsoleInputStream.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -54,11 +54,6 @@
 	private int size = 0;
 
 	/**
-	 * Flag to indicate that EOF has been sent already.
-	 */
-	private boolean eofSent = false;
-
-	/**
 	 * Flag to indicate that the stream has been closed.
 	 */
 	private boolean closed = false;
@@ -90,8 +85,12 @@
 
 	@Override
 	public synchronized int read(byte[] b, int off, int len) throws IOException {
+		if (len == 0) {
+			return 0; // behavior as specified in InputStream#read(byte[], int, int)
+		}
+
 		waitForData();
-		if (available() == -1) {
+		if (available() <= 0) {
 			return -1;
 		}
 
@@ -118,7 +117,7 @@
 	@Override
 	public synchronized int read() throws IOException {
 		waitForData();
-		if (available() == -1) {
+		if (available() <= 0) {
 			return -1;
 		}
 
@@ -252,14 +251,6 @@
 
 	@Override
 	public int available() throws IOException {
-		if (closed && eofSent) {
-			throw new IOException("Input Stream Closed"); //$NON-NLS-1$
-		} else if (size == 0) {
-			if (!eofSent) {
-				eofSent = true;
-				return -1;
-			}
-		}
 		return size;
 	}