8218287: jshell tool: input behavior unstable after 12-ea+24 on Windows
Summary: Ensure correct wrapping of input on Windows.
Reviewed-by: rfield
--- 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!");
+ }
+ }
+}