mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 03:58:21 +00:00
8361613: System.console() should only be available for interactive terminal
Reviewed-by: jlahoda, smarks, alanb
This commit is contained in:
parent
19882220ec
commit
ae0dac43c0
@ -237,10 +237,11 @@ public final class System {
|
||||
private static volatile Console cons;
|
||||
|
||||
/**
|
||||
* Returns the unique {@link java.io.Console Console} object associated
|
||||
* Returns the unique {@link Console Console} object associated
|
||||
* with the current Java virtual machine, if any.
|
||||
*
|
||||
* @return The system console, if any, otherwise {@code null}.
|
||||
* @see Console
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
|
||||
@ -50,7 +50,7 @@ public class JdkConsoleProviderImpl implements JdkConsoleProvider {
|
||||
*/
|
||||
@Override
|
||||
public JdkConsole console(boolean isTTY, Charset inCharset, Charset outCharset) {
|
||||
return new LazyDelegatingJdkConsoleImpl(inCharset, outCharset);
|
||||
return isTTY ? new LazyDelegatingJdkConsoleImpl(inCharset, outCharset) : null;
|
||||
}
|
||||
|
||||
private static class LazyDelegatingJdkConsoleImpl implements JdkConsole {
|
||||
|
||||
@ -21,33 +21,66 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static jdk.test.lib.Utils.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8341975 8351435
|
||||
* @bug 8341975 8351435 8361613
|
||||
* @summary Tests the default charset. It should honor `stdout.encoding`
|
||||
* which should be the same as System.out.charset()
|
||||
* @modules jdk.internal.le
|
||||
* @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=UTF-8 DefaultCharsetTest
|
||||
* @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=ISO-8859-1 DefaultCharsetTest
|
||||
* @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=US-ASCII DefaultCharsetTest
|
||||
* @run junit/othervm -Djdk.console=jdk.internal.le -Dstdout.encoding=foo DefaultCharsetTest
|
||||
* @run junit/othervm -Djdk.console=jdk.internal.le DefaultCharsetTest
|
||||
* @requires (os.family == "linux") | (os.family == "mac")
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Utils
|
||||
* jdk.test.lib.JDKToolFinder
|
||||
* jdk.test.lib.process.ProcessTools
|
||||
* @run junit DefaultCharsetTest
|
||||
*/
|
||||
public class DefaultCharsetTest {
|
||||
@Test
|
||||
public void testDefaultCharset() {
|
||||
@BeforeAll
|
||||
static void checkExpectAvailability() {
|
||||
// check "expect" command availability
|
||||
var expect = Paths.get("/usr/bin/expect");
|
||||
Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
|
||||
"'" + expect + "' not found. Test ignored.");
|
||||
}
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"UTF-8", "ISO-8859-1", "US-ASCII", "foo", ""})
|
||||
void testDefaultCharset(String stdoutEncoding) throws Exception {
|
||||
// invoking "expect" command
|
||||
OutputAnalyzer oa = ProcessTools.executeProcess(
|
||||
"expect",
|
||||
"-n",
|
||||
TEST_SRC + "/defaultCharset.exp",
|
||||
TEST_CLASSES,
|
||||
TEST_JDK + "/bin/java",
|
||||
"-Dstdout.encoding=" + stdoutEncoding,
|
||||
getClass().getName());
|
||||
oa.reportDiagnosticSummary();
|
||||
oa.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
public static void main(String... args) {
|
||||
var stdoutEncoding = System.getProperty("stdout.encoding");
|
||||
var sysoutCharset = System.out.charset();
|
||||
var consoleCharset = System.console().charset();
|
||||
System.out.println("""
|
||||
stdout.encoding = %s
|
||||
System.out.charset() = %s
|
||||
System.console().charset() = %s
|
||||
""".formatted(stdoutEncoding, sysoutCharset.name(), consoleCharset.name()));
|
||||
assertEquals(consoleCharset, sysoutCharset,
|
||||
"Charsets for System.out and Console differ for stdout.encoding: %s".formatted(stdoutEncoding));
|
||||
System.out.printf("""
|
||||
stdout.encoding = %s
|
||||
System.out.charset() = %s
|
||||
System.console().charset() = %s
|
||||
""", stdoutEncoding, sysoutCharset.name(), consoleCharset.name());
|
||||
if (!consoleCharset.equals(sysoutCharset)) {
|
||||
System.err.printf("Charsets for System.out and Console differ for stdout.encoding: %s%n", stdoutEncoding);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,28 +21,40 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static jdk.test.lib.Utils.*;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8330276 8351435
|
||||
* @bug 8330276 8351435 8361613
|
||||
* @summary Tests Console methods that have Locale as an argument
|
||||
* @requires (os.family == "linux") | (os.family == "mac")
|
||||
* @library /test/lib
|
||||
* @modules jdk.internal.le jdk.localedata
|
||||
* @build jdk.test.lib.Utils
|
||||
* jdk.test.lib.JDKToolFinder
|
||||
* jdk.test.lib.process.ProcessTools
|
||||
* @modules jdk.localedata
|
||||
* @run junit LocaleTest
|
||||
*/
|
||||
public class LocaleTest {
|
||||
private static Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
|
||||
private static String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
|
||||
private static final Calendar TODAY = new GregorianCalendar(2024, Calendar.APRIL, 22);
|
||||
private static final String FORMAT = "%1$tY-%1$tB-%1$te %1$tA";
|
||||
// We want to limit the expected strings within US-ASCII charset, as
|
||||
// the native encoding is determined as such, which is used by
|
||||
// the `Process` class under jtreg environment.
|
||||
private static List<String> EXPECTED = List.of(
|
||||
private static final List<String> EXPECTED = List.of(
|
||||
String.format(Locale.UK, FORMAT, TODAY),
|
||||
String.format(Locale.FRANCE, FORMAT, TODAY),
|
||||
String.format(Locale.GERMANY, FORMAT, TODAY),
|
||||
@ -53,56 +65,61 @@ public class LocaleTest {
|
||||
String.format((Locale)null, FORMAT, TODAY)
|
||||
);
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
if (args.length == 0) {
|
||||
// no arg will launch the child process that actually perform tests
|
||||
var pb = ProcessTools.createTestJavaProcessBuilder(
|
||||
"-Djdk.console=jdk.internal.le",
|
||||
"LocaleTest", "dummy");
|
||||
var input = new File(System.getProperty("test.src", "."), "input.txt");
|
||||
pb.redirectInput(input);
|
||||
var oa = ProcessTools.executeProcess(pb);
|
||||
if (oa.getExitValue() == -1) {
|
||||
System.out.println("System.console() returns null. Ignoring the test.");
|
||||
} else {
|
||||
var output = oa.asLines();
|
||||
var resultText =
|
||||
"""
|
||||
Actual output: %s
|
||||
Expected output: %s
|
||||
""".formatted(output, EXPECTED);
|
||||
if (!output.equals(EXPECTED)) {
|
||||
throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
|
||||
} else {
|
||||
oa.shouldHaveExitValue(0);
|
||||
System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var con = System.console();
|
||||
if (con != null) {
|
||||
// tests these additional methods that take a Locale
|
||||
con.format(Locale.UK, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.printf(Locale.FRANCE, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readLine(Locale.GERMANY, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readPassword(Locale.of("es"), FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
@Test
|
||||
void testLocale() throws Exception {
|
||||
// check "expect" command availability
|
||||
var expect = Paths.get("/usr/bin/expect");
|
||||
Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
|
||||
"'" + expect + "' not found. Test ignored.");
|
||||
|
||||
// tests null locale
|
||||
con.format((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.printf((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readLine((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readPassword((Locale)null, FORMAT, TODAY);
|
||||
} else {
|
||||
// Exit with -1
|
||||
System.exit(-1);
|
||||
}
|
||||
// invoking "expect" command
|
||||
OutputAnalyzer oa = ProcessTools.executeProcess(
|
||||
"expect",
|
||||
"-n",
|
||||
TEST_SRC + "/locale.exp",
|
||||
TEST_CLASSES,
|
||||
TEST_JDK + "/bin/java",
|
||||
getClass().getName());
|
||||
|
||||
var stdout =
|
||||
oa.stdoutAsLines().stream().filter(Predicate.not(String::isEmpty)).toList();
|
||||
var resultText =
|
||||
"""
|
||||
Actual output: %s
|
||||
Expected output: %s
|
||||
""".formatted(stdout, EXPECTED);
|
||||
if (!stdout.equals(EXPECTED)) {
|
||||
throw new RuntimeException("Standard out had unexpected strings:\n" + resultText);
|
||||
} else {
|
||||
oa.shouldHaveExitValue(0);
|
||||
System.out.println("Formatting with explicit Locale succeeded.\n" + resultText);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
var con = System.console();
|
||||
if (con != null) {
|
||||
// tests these additional methods that take a Locale
|
||||
con.format(Locale.UK, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.printf(Locale.FRANCE, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readLine(Locale.GERMANY, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readPassword(Locale.of("es"), FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
|
||||
// tests null locale
|
||||
con.format((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.printf((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readLine((Locale)null, FORMAT, TODAY);
|
||||
con.printf("\n");
|
||||
con.readPassword((Locale)null, FORMAT, TODAY);
|
||||
} else {
|
||||
// Exit with -1
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,21 +23,71 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8295803 8299689 8351435
|
||||
* @bug 8295803 8299689 8351435 8361613
|
||||
* @summary Tests System.console() returns correct Console (or null) from the expected
|
||||
* module.
|
||||
* @modules java.base/java.io:+open
|
||||
* @run main/othervm ModuleSelectionTest java.base
|
||||
* @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le
|
||||
* @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base
|
||||
* @run main/othervm --limit-modules java.base ModuleSelectionTest java.base
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.Utils
|
||||
* jdk.test.lib.process.ProcessTools
|
||||
* @run junit ModuleSelectionTest
|
||||
*/
|
||||
|
||||
import java.io.Console;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import static jdk.test.lib.Utils.*;
|
||||
|
||||
public class ModuleSelectionTest {
|
||||
private static Stream<Arguments> options() {
|
||||
return Stream.of(
|
||||
Arguments.of("-Djdk.console=foo", "java.base"),
|
||||
Arguments.of("-Djdk.console=java.base", "java.base"),
|
||||
Arguments.of("-Djdk.console=jdk.internal.le", "jdk.internal.le"),
|
||||
Arguments.of("--limit-modules java.base", "java.base")
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("options")
|
||||
void testNonTTY(String opts) throws Exception {
|
||||
opts = opts +
|
||||
" --add-opens java.base/java.io=ALL-UNNAMED ModuleSelectionTest null";
|
||||
OutputAnalyzer output = ProcessTools.executeTestJava(opts.split(" "));
|
||||
output.reportDiagnosticSummary();
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("options")
|
||||
void testTTY(String opts, String expected) throws Exception {
|
||||
// check "expect" command availability
|
||||
var expect = Paths.get("/usr/bin/expect");
|
||||
Assumptions.assumeTrue(Files.exists(expect) && Files.isExecutable(expect),
|
||||
"'" + expect + "' not found. Test ignored.");
|
||||
|
||||
opts = "expect -n " + TEST_SRC + "/moduleSelection.exp " +
|
||||
TEST_CLASSES + " " +
|
||||
expected + " " +
|
||||
TEST_JDK + "/bin/java" +
|
||||
" --add-opens java.base/java.io=ALL-UNNAMED "
|
||||
+ opts;
|
||||
// invoking "expect" command
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(opts.split(" "));
|
||||
output.reportDiagnosticSummary();
|
||||
output.shouldHaveExitValue(0);
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
var con = System.console();
|
||||
var pc = Class.forName("java.io.ProxyingConsole");
|
||||
@ -49,10 +99,7 @@ public class ModuleSelectionTest {
|
||||
.findGetter(pc, "delegate", jdkc)
|
||||
.invoke(con) : null;
|
||||
|
||||
var expected = switch (args[0]) {
|
||||
case "java.base" -> istty ? "java.base" : "null";
|
||||
default -> args[0];
|
||||
};
|
||||
var expected = args[0];
|
||||
var actual = con == null ? "null" : impl.getClass().getModule().getName();
|
||||
|
||||
if (!actual.equals(expected)) {
|
||||
@ -62,7 +109,7 @@ public class ModuleSelectionTest {
|
||||
Actual: %s
|
||||
""".formatted(expected, actual));
|
||||
} else {
|
||||
System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty);
|
||||
System.out.printf("%s is the expected implementation. (tty: %s)\n", actual, istty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
test/jdk/java/io/Console/defaultCharset.exp
Normal file
32
test/jdk/java/io/Console/defaultCharset.exp
Normal file
@ -0,0 +1,32 @@
|
||||
#
|
||||
# Copyright (c) 2025, 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.
|
||||
#
|
||||
|
||||
# simply invoking java under expect command
|
||||
set classpath [lrange $argv 0 0]
|
||||
set java [lrange $argv 1 1]
|
||||
set stdoutProp [lrange $argv 2 2]
|
||||
set clsname [lrange $argv 3 3]
|
||||
eval spawn $java -classpath $classpath $stdoutProp $clsname
|
||||
expect eof
|
||||
set result [wait]
|
||||
exit [lindex $result 3]
|
||||
37
test/jdk/java/io/Console/locale.exp
Normal file
37
test/jdk/java/io/Console/locale.exp
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# Copyright (c) 2025, 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.
|
||||
#
|
||||
|
||||
# simply invoking java under expect command
|
||||
set classpath [lrange $argv 0 0]
|
||||
set java [lrange $argv 1 1]
|
||||
set clsname [lrange $argv 2 2]
|
||||
eval spawn -noecho $java -classpath $classpath $clsname
|
||||
|
||||
# sends CR 4 times (readLine x 2, readPassword x 2)
|
||||
send "\r"
|
||||
send "\r"
|
||||
send "\r"
|
||||
send "\r"
|
||||
expect eof
|
||||
set result [wait]
|
||||
exit [lindex $result 3]
|
||||
30
test/jdk/java/io/Console/moduleSelection.exp
Normal file
30
test/jdk/java/io/Console/moduleSelection.exp
Normal file
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) 2025, 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.
|
||||
#
|
||||
|
||||
# simply invoking java under expect command
|
||||
set classpath [lrange $argv 0 0]
|
||||
set expected [lrange $argv 1 1]
|
||||
set java [lrange $argv 2 2]
|
||||
set opts [lrange $argv 3 end]
|
||||
eval spawn $java $opts -classpath $classpath ModuleSelectionTest $expected
|
||||
expect eof
|
||||
@ -50,10 +50,9 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8305457 8342936 8351435 8344706
|
||||
* @bug 8305457 8342936 8351435 8344706 8361613
|
||||
* @summary java.lang.IO tests
|
||||
* @library /test/lib
|
||||
* @modules jdk.internal.le
|
||||
* @run junit IO
|
||||
*/
|
||||
@ExtendWith(IO.TimingExtension.class)
|
||||
@ -78,22 +77,6 @@ public class IO {
|
||||
} catch (Exception _) { }
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlike printTest, which tests a _default_ console that is normally
|
||||
* jdk.internal.org.jline.JdkConsoleProviderImpl, this test tests
|
||||
* jdk.internal.io.JdkConsoleImpl. Those console implementations operate
|
||||
* in different conditions and, thus, are tested separately.
|
||||
*
|
||||
* To test jdk.internal.io.JdkConsoleImpl one needs to ensure that both
|
||||
* conditions are met:
|
||||
*
|
||||
* - a non-existent console provider is requested
|
||||
* - isatty is true
|
||||
*
|
||||
* To achieve isatty, the test currently uses the EXPECT(1) Unix command,
|
||||
* which does not work for Windows. Later, a library like pty4j or JPty
|
||||
* might be used instead of EXPECT, to cover both Unix and Windows.
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"println", "print"})
|
||||
public void outputTestInteractive(String mode) throws Exception {
|
||||
@ -102,8 +85,6 @@ public class IO {
|
||||
expect.toString(),
|
||||
Path.of(testSrc, "output.exp").toAbsolutePath().toString(),
|
||||
System.getProperty("test.jdk") + "/bin/java",
|
||||
"--enable-preview",
|
||||
"-Djdk.console=gibberish",
|
||||
Path.of(testSrc, "Output.java").toAbsolutePath().toString(),
|
||||
mode);
|
||||
assertEquals(0, output.getExitValue());
|
||||
@ -130,7 +111,7 @@ public class IO {
|
||||
*/
|
||||
@ParameterizedTest
|
||||
@MethodSource("args")
|
||||
public void inputTestInteractive(String console, String prompt) throws Exception {
|
||||
public void inputTestInteractive(String prompt) throws Exception {
|
||||
var testSrc = System.getProperty("test.src", ".");
|
||||
var command = new ArrayList<String>();
|
||||
command.add(expect.toString());
|
||||
@ -138,9 +119,6 @@ public class IO {
|
||||
: "input";
|
||||
command.add(Path.of(testSrc, expectInputName + ".exp").toAbsolutePath().toString());
|
||||
command.add(System.getProperty("test.jdk") + "/bin/java");
|
||||
command.add("--enable-preview");
|
||||
if (console != null)
|
||||
command.add("-Djdk.console=" + console);
|
||||
command.add(Path.of(testSrc, "Input.java").toAbsolutePath().toString());
|
||||
command.add(prompt == null ? "0" : PROMPT_NONE.equals(prompt) ? "2" : "1");
|
||||
command.add(String.valueOf(prompt));
|
||||
@ -152,33 +130,11 @@ public class IO {
|
||||
private static final String PROMPT_NONE = "prompt-none";
|
||||
|
||||
public static Stream<Arguments> args() {
|
||||
// cross product: consoles x prompts
|
||||
return Stream.of("jdk.internal.le", "gibberish").flatMap(console -> Stream.of(null, "?", "%s", PROMPT_NONE)
|
||||
.map(prompt -> new String[]{console, prompt}).map(Arguments::of));
|
||||
// prompts
|
||||
return Stream.of(null, "?", "%s", PROMPT_NONE).map(Arguments::of);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"println", "print"})
|
||||
public void printTest(String mode) throws Exception {
|
||||
var file = Path.of(System.getProperty("test.src", "."), "Output.java")
|
||||
.toAbsolutePath().toString();
|
||||
var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file, mode);
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(pb);
|
||||
assertEquals(0, output.getExitValue());
|
||||
assertTrue(output.getStderr().isEmpty());
|
||||
output.reportDiagnosticSummary();
|
||||
String out = output.getStdout();
|
||||
// The first half of the output is produced by Console, the second
|
||||
// half is produced by IO: those halves must match.
|
||||
// Executing Console and IO in the same VM (as opposed to
|
||||
// consecutive VM runs, which are cleaner) to be able to compare string
|
||||
// representation of objects.
|
||||
assertFalse(out.isBlank());
|
||||
assertEquals(out.substring(0, out.length() / 2),
|
||||
out.substring(out.length() / 2));
|
||||
}
|
||||
|
||||
@Test //JDK-8342936
|
||||
public void printlnNoParamsTest() throws Exception {
|
||||
var file = Path.of("PrintlnNoParams.java");
|
||||
@ -193,7 +149,7 @@ public class IO {
|
||||
}
|
||||
""");
|
||||
}
|
||||
var pb = ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", "--enable-preview", file.toString());
|
||||
var pb = ProcessTools.createTestJavaProcessBuilder(file.toString());
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(pb);
|
||||
assertEquals(0, output.getExitValue());
|
||||
assertTrue(output.getStderr().isEmpty());
|
||||
|
||||
@ -23,16 +23,19 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8331535 8351435 8347050
|
||||
* @bug 8331535 8351435 8347050 8361613
|
||||
* @summary Verify the jdk.internal.le's console provider works properly.
|
||||
* @modules jdk.internal.le
|
||||
* @modules java.base/jdk.internal.io
|
||||
* jdk.internal.le/jdk.internal.org.jline
|
||||
* @library /test/lib
|
||||
* @run main/othervm -Djdk.console=jdk.internal.le JLineConsoleProviderTest
|
||||
* @run main JLineConsoleProviderTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.org.jline.JdkConsoleProviderImpl;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
@ -66,8 +69,13 @@ public class JLineConsoleProviderTest {
|
||||
String input,
|
||||
String expectedOut) throws Exception {
|
||||
ProcessBuilder builder =
|
||||
ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName(),
|
||||
testName);
|
||||
ProcessTools.createTestJavaProcessBuilder(
|
||||
"--add-exports",
|
||||
"java.base/jdk.internal.io=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED",
|
||||
ConsoleTest.class.getName(),
|
||||
testName);
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(builder, input);
|
||||
|
||||
output.waitFor();
|
||||
@ -98,16 +106,18 @@ public class JLineConsoleProviderTest {
|
||||
|
||||
public static class ConsoleTest {
|
||||
public static void main(String... args) {
|
||||
// directly instantiate JLine JdkConsole, simulating isTTY=true
|
||||
var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8);
|
||||
switch (args[0]) {
|
||||
case "testCorrectOutputReadLine" ->
|
||||
System.console().readLine("%%s");
|
||||
impl.readLine(null, "%%s");
|
||||
case "testCorrectOutputReadPassword" ->
|
||||
System.console().readPassword("%%s");
|
||||
impl.readPassword(null, "%%s");
|
||||
case "readAndPrint" ->
|
||||
System.out.println("'" + System.console().readLine() + "'");
|
||||
System.out.println("'" + impl.readLine() + "'");
|
||||
case "readAndPrint2" -> {
|
||||
System.out.println("1: '" +System.console().readLine() + "'");
|
||||
System.out.println("2: '" + System.console().readLine() + "'");
|
||||
System.out.println("1: '" + impl.readLine() + "'");
|
||||
System.out.println("2: '" + impl.readLine() + "'");
|
||||
}
|
||||
default -> throw new UnsupportedOperationException(args[0]);
|
||||
}
|
||||
|
||||
@ -23,15 +23,19 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8333086 8344706
|
||||
* @bug 8333086 8344706 8361613
|
||||
* @summary Verify the JLine backend is not initialized for simple printing.
|
||||
* @enablePreview
|
||||
* @modules jdk.internal.le/jdk.internal.org.jline.reader
|
||||
* @modules java.base/jdk.internal.io
|
||||
* jdk.internal.le/jdk.internal.org.jline
|
||||
* jdk.internal.le/jdk.internal.org.jline.reader
|
||||
* jdk.internal.le/jdk.internal.org.jline.terminal
|
||||
* @library /test/lib
|
||||
* @run main LazyJdkConsoleProvider
|
||||
*/
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import jdk.internal.org.jline.JdkConsoleProviderImpl;
|
||||
import jdk.internal.org.jline.reader.LineReader;
|
||||
import jdk.internal.org.jline.terminal.Terminal;
|
||||
|
||||
@ -41,19 +45,18 @@ import jdk.test.lib.process.ProcessTools;
|
||||
public class LazyJdkConsoleProvider {
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
// directly instantiate JLine JdkConsole, simulating isTTY=true
|
||||
switch (args.length > 0 ? args[0] : "default") {
|
||||
case "write" -> {
|
||||
System.console().printf("Hello!\n");
|
||||
System.console().printf("Hello!");
|
||||
System.console().format("\nHello!\n");
|
||||
System.console().flush();
|
||||
IO.println("Hello!");
|
||||
IO.print("Hello!");
|
||||
}
|
||||
case "read" -> System.console().readLine("Hello!");
|
||||
case "IO-read" -> {
|
||||
IO.readln("Hello!");
|
||||
var impl = new JdkConsoleProviderImpl().console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8);
|
||||
impl.println("Hello!\n");
|
||||
impl.println("Hello!");
|
||||
impl.format(null, "\nHello!\n");
|
||||
impl.flush();
|
||||
}
|
||||
case "read" -> new JdkConsoleProviderImpl()
|
||||
.console(true, StandardCharsets.UTF_8, StandardCharsets.UTF_8)
|
||||
.readLine(null, "Hello!");
|
||||
case "default" -> {
|
||||
new LazyJdkConsoleProvider().runTest();
|
||||
}
|
||||
@ -64,14 +67,15 @@ public class LazyJdkConsoleProvider {
|
||||
record TestCase(String testKey, String expected, String notExpected) {}
|
||||
TestCase[] testCases = new TestCase[] {
|
||||
new TestCase("write", null, Terminal.class.getName()),
|
||||
new TestCase("read", LineReader.class.getName(), null),
|
||||
new TestCase("IO-read", null, Terminal.class.getName())
|
||||
new TestCase("read", LineReader.class.getName(), null)
|
||||
};
|
||||
for (TestCase tc : testCases) {
|
||||
ProcessBuilder builder =
|
||||
ProcessTools.createTestJavaProcessBuilder("--enable-preview",
|
||||
"-verbose:class",
|
||||
"-Djdk.console=jdk.internal.le",
|
||||
ProcessTools.createTestJavaProcessBuilder("-verbose:class",
|
||||
"--add-exports",
|
||||
"java.base/jdk.internal.io=ALL-UNNAMED",
|
||||
"--add-exports",
|
||||
"jdk.internal.le/jdk.internal.org.jline=ALL-UNNAMED",
|
||||
LazyJdkConsoleProvider.class.getName(),
|
||||
tc.testKey());
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(builder, "");
|
||||
|
||||
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024, 2025, 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 8330998 8351435
|
||||
* @summary Verify that even if the stdout is redirected java.io.Console will
|
||||
* use it for writing.
|
||||
* @modules jdk.internal.le
|
||||
* @library /test/lib
|
||||
* @run main RedirectedStdOut runRedirectAllTest
|
||||
* @run main/othervm --enable-native-access=ALL-UNNAMED RedirectedStdOut runRedirectOutOnly
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.foreign.Arena;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.SymbolLookup;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class RedirectedStdOut {
|
||||
private static final String OUTPUT = "Hello!";
|
||||
|
||||
public static void main(String... args) throws Throwable {
|
||||
RedirectedStdOut.class.getDeclaredMethod(args[0])
|
||||
.invoke(new RedirectedStdOut());
|
||||
}
|
||||
|
||||
//verify the case where neither stdin/out/err is attached to a terminal,
|
||||
//this test is weaker, but more reliable:
|
||||
void runRedirectAllTest() throws Exception {
|
||||
ProcessBuilder builder =
|
||||
ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName());
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(builder);
|
||||
|
||||
output.waitFor();
|
||||
|
||||
if (output.getExitValue() != 0) {
|
||||
throw new AssertionError("Unexpected return value: " + output.getExitValue() +
|
||||
", actualOut: " + output.getStdout() +
|
||||
", actualErr: " + output.getStderr());
|
||||
}
|
||||
|
||||
String expectedOut = OUTPUT;
|
||||
String actualOut = output.getStdout();
|
||||
|
||||
if (!Objects.equals(expectedOut, actualOut)) {
|
||||
throw new AssertionError("Unexpected stdout content. " +
|
||||
"Expected: '" + expectedOut + "'" +
|
||||
", got: '" + actualOut + "'");
|
||||
}
|
||||
|
||||
String expectedErr = "";
|
||||
String actualErr = output.getStderr();
|
||||
|
||||
if (!Objects.equals(expectedErr, actualErr)) {
|
||||
throw new AssertionError("Unexpected stderr content. " +
|
||||
"Expected: '" + expectedErr + "'" +
|
||||
", got: '" + actualErr + "'");
|
||||
}
|
||||
}
|
||||
|
||||
//verify the case where stdin is attached to a terminal,
|
||||
//this test allocates pty, and it might be skipped, if the appropriate
|
||||
//native functions cannot be found
|
||||
//it also leaves the VM in a broken state (with a pty attached), and so
|
||||
//should run in a separate VM instance
|
||||
void runRedirectOutOnly() throws Throwable {
|
||||
Path stdout = Path.of(".", "stdout.txt").toAbsolutePath();
|
||||
|
||||
Files.deleteIfExists(stdout);
|
||||
|
||||
Linker linker = Linker.nativeLinker();
|
||||
SymbolLookup stdlib = linker.defaultLookup();
|
||||
MemorySegment parent = Arena.global().allocate(ValueLayout.ADDRESS);
|
||||
MemorySegment child = Arena.global().allocate(ValueLayout.ADDRESS);
|
||||
Optional<MemorySegment> openptyAddress = stdlib.find("openpty");
|
||||
|
||||
if (openptyAddress.isEmpty()) {
|
||||
System.out.println("Cannot lookup openpty.");
|
||||
//does not have forkpty, ignore
|
||||
return ;
|
||||
}
|
||||
|
||||
Optional<MemorySegment> loginttyAddress = stdlib.find("login_tty");
|
||||
|
||||
if (loginttyAddress.isEmpty()) {
|
||||
System.out.println("Cannot lookup login_tty.");
|
||||
//does not have forkpty, ignore
|
||||
return ;
|
||||
}
|
||||
|
||||
FunctionDescriptor openttyDescriptor =
|
||||
FunctionDescriptor.of(ValueLayout.JAVA_INT,
|
||||
ValueLayout.ADDRESS,
|
||||
ValueLayout.ADDRESS,
|
||||
ValueLayout.ADDRESS,
|
||||
ValueLayout.ADDRESS,
|
||||
ValueLayout.ADDRESS);
|
||||
MethodHandle forkpty = linker.downcallHandle(openptyAddress.get(),
|
||||
openttyDescriptor);
|
||||
int res = (int) forkpty.invoke(parent,
|
||||
child,
|
||||
MemorySegment.NULL,
|
||||
MemorySegment.NULL,
|
||||
MemorySegment.NULL);
|
||||
|
||||
if (res != 0) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
//set the current VM's in/out to the terminal:
|
||||
FunctionDescriptor loginttyDescriptor =
|
||||
FunctionDescriptor.of(ValueLayout.JAVA_INT,
|
||||
ValueLayout.JAVA_INT);
|
||||
MethodHandle logintty = linker.downcallHandle(loginttyAddress.get(),
|
||||
loginttyDescriptor);
|
||||
logintty.invoke(child.get(ValueLayout.JAVA_INT, 0));
|
||||
|
||||
//createTestJavaProcessBuilder logs to (current process') System.out, but
|
||||
//that may not work since the redirect. Setting System.out to a scratch value:
|
||||
System.setOut(new PrintStream(new ByteArrayOutputStream()));
|
||||
|
||||
ProcessBuilder builder =
|
||||
ProcessTools.createTestJavaProcessBuilder("-Djdk.console=jdk.internal.le", ConsoleTest.class.getName());
|
||||
|
||||
builder.inheritIO();
|
||||
builder.redirectOutput(stdout.toFile());
|
||||
|
||||
OutputAnalyzer output = ProcessTools.executeProcess(builder);
|
||||
|
||||
output.waitFor();
|
||||
|
||||
String expectedOut = OUTPUT;
|
||||
String actualOut = Files.readString(stdout);
|
||||
|
||||
if (!Objects.equals(expectedOut, actualOut)) {
|
||||
throw new AssertionError("Unexpected stdout content. " +
|
||||
"Expected: '" + expectedOut + "'" +
|
||||
", got: '" + actualOut + "'");
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConsoleTest {
|
||||
public static void main(String... args) {
|
||||
System.console().printf(OUTPUT);
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user