8218287: jshell tool: input behavior unstable after 12-ea+24 on Windows
authorjlahoda
Wed, 20 Feb 2019 11:11:38 +0100
changeset 53840 9a0fd1f82406
parent 53839 31dde2f0ddf1
child 53841 48b50573dee4
8218287: jshell tool: input behavior unstable after 12-ea+24 on Windows Summary: Ensure correct wrapping of input on Windows. Reviewed-by: rfield
src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java
src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java
src/jdk.internal.le/windows/native/lible/Kernel32.cpp
test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java	Wed Feb 20 10:48:36 2019 +0100
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/terminal/impl/AbstractWindowsTerminal.java	Wed Feb 20 11:11:38 2019 +0100
@@ -86,8 +86,8 @@
         super(name, type, selectCharset(encoding, codepage), signalHandler);
         NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
         this.slaveInputPipe = reader.getWriter();
-        this.reader = reader;
         this.input = inputStreamWrapper.apply(NonBlocking.nonBlockingStream(reader, encoding()));
+        this.reader = NonBlocking.nonBlocking(name, input, encoding());
         this.writer = new PrintWriter(writer);
         this.output = new WriterOutputStream(writer, encoding());
         parseInfoCmp();
--- a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java	Wed Feb 20 10:48:36 2019 +0100
+++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/utils/NonBlocking.java	Wed Feb 20 11:11:38 2019 +0100
@@ -123,9 +123,9 @@
             }
             if (bytes.hasRemaining()) {
                 if (isPeek) {
-                    return bytes.get(bytes.position());
+                    return Byte.toUnsignedInt(bytes.get(bytes.position()));
                 } else {
-                    return bytes.get();
+                    return Byte.toUnsignedInt(bytes.get());
                 }
             } else {
                 return READ_EXPIRED;
--- a/src/jdk.internal.le/windows/native/lible/Kernel32.cpp	Wed Feb 20 10:48:36 2019 +0100
+++ b/src/jdk.internal.le/windows/native/lible/Kernel32.cpp	Wed Feb 20 11:11:38 2019 +0100
@@ -460,7 +460,7 @@
     HANDLE h = GetStdHandle((jint) env->GetLongField(in_hConsoleOutput, pointerValue));
     INPUT_RECORD *buffer = new INPUT_RECORD[in_nLength];
     DWORD numberOfEventsRead;
-    if (!ReadConsoleInput(h, buffer, in_nLength, &numberOfEventsRead)) {
+    if (!ReadConsoleInputW(h, buffer, in_nLength, &numberOfEventsRead)) {
         delete buffer;
         DWORD error = GetLastError();
         jobject exc = env->NewObject(lastErrorExceptionClass,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/internal/jline/AbstractWindowsTerminalTest.java	Wed Feb 20 11:11:38 2019 +0100
@@ -0,0 +1,93 @@
+/*
+ * 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
+ * @bug 8218287
+ * @summary Verify the wrapper input stream is used when using Terminal.reader()
+ * @modules jdk.internal.le/jdk.internal.org.jline.terminal
+ *          jdk.internal.le/jdk.internal.org.jline.terminal.impl
+ *          jdk.internal.le/jdk.internal.org.jline.utils
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Function;
+
+import jdk.internal.org.jline.terminal.Size;
+import jdk.internal.org.jline.terminal.Terminal.SignalHandler;
+import jdk.internal.org.jline.terminal.impl.AbstractWindowsTerminal;
+
+
+public class AbstractWindowsTerminalTest {
+    public static void main(String... args) throws IOException {
+        new AbstractWindowsTerminalTest().run();
+    }
+
+    void run() throws IOException {
+        var out = new StringWriter();
+        AtomicBoolean called = new AtomicBoolean();
+        Function<InputStream, InputStream> isWrapper = is -> new InputStream() {
+            @Override
+            public int read() throws IOException {
+                called.set(true);
+                return is.read();
+            }
+        };
+        var t = new AbstractWindowsTerminal(out, "test", "vt100", null, -1, false, SignalHandler.SIG_DFL, isWrapper) {
+            @Override
+            protected int getConsoleOutputCP() {
+                throw new UnsupportedOperationException("unexpected.");
+            }
+
+            @Override
+            protected int getConsoleMode() {
+                return -1;
+            }
+
+            @Override
+            protected void setConsoleMode(int mode) {
+                throw new UnsupportedOperationException("unexpected.");
+            }
+
+            @Override
+            protected boolean processConsoleInput() throws IOException {
+                throw new UnsupportedOperationException("unexpected.");
+            }
+
+            @Override
+            public Size getSize() {
+                throw new UnsupportedOperationException("unexpected.");
+            }
+        };
+        t.processInputChar(' ');
+        if (t.reader().read() != ' ') {
+            throw new AssertionError("Unexpected input!");
+        }
+        if (!called.get()) {
+            throw new AssertionError("The wrapper was not called!");
+        }
+    }
+}