Skip to content

Commit

Permalink
Adjust terminal tests to new behavior in JDK 22. (elastic#103614) (el…
Browse files Browse the repository at this point in the history
…astic#106049)

JDK 22 may return a console even if the terminal is redirected. These cases are detected using the new Console#isTerminal() to maintain the current behavior (closes elastic#98033).

Co-authored-by: Moritz Mack <[email protected]>
  • Loading branch information
rjernst and mosche authored Mar 6, 2024
1 parent 770c3d8 commit fb56cb7
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
5 changes: 4 additions & 1 deletion libs/cli/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ apply plugin: 'elasticsearch.publish'
dependencies {
api 'net.sf.jopt-simple:jopt-simple:5.0.2'
api project(':libs:elasticsearch-core')

testImplementation(project(":test:framework")) {
exclude group: 'org.elasticsearch', module: 'elasticsearch-cli'
}
}

tasks.named("test").configure { enabled = false }
// Since CLI does not depend on :server, it cannot run the jarHell task
tasks.named("jarHell").configure { enabled = false }

Expand Down
23 changes: 21 additions & 2 deletions libs/cli/src/main/java/org/elasticsearch/cli/Terminal.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
Expand Down Expand Up @@ -274,8 +276,8 @@ public boolean isHeadless() {
}

private static class ConsoleTerminal extends Terminal {

private static final Console CONSOLE = System.console();
private static final int JDK_VERSION_WITH_IS_TERMINAL = 22;
private static final Console CONSOLE = detectTerminal();

ConsoleTerminal() {
super(CONSOLE.reader(), CONSOLE.writer(), ERROR_WRITER);
Expand All @@ -285,6 +287,23 @@ static boolean isSupported() {
return CONSOLE != null;
}

static Console detectTerminal() {
// JDK >= 22 returns a console even if the terminal is redirected unless using -Djdk.console=java.base
// https://bugs.openjdk.org/browse/JDK-8308591
Console console = System.console();
if (console != null && Runtime.version().feature() >= JDK_VERSION_WITH_IS_TERMINAL) {
try {
// verify the console is a terminal using isTerminal() on JDK >= 22
// TODO: Remove reflection once Java 22 sources are supported, e.g. using a MRJAR
Method isTerminal = Console.class.getMethod("isTerminal");
return Boolean.TRUE.equals(isTerminal.invoke(console)) ? console : null;
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
throw new AssertionError(e);
}
}
return console;
}

@Override
public String readText(String prompt) {
return CONSOLE.readLine("%s", prompt);
Expand Down
23 changes: 23 additions & 0 deletions libs/cli/src/test/java/org/elasticsearch/cli/TerminalTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.cli;

import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.ESTestCase.WithoutSecurityManager;

@WithoutSecurityManager
public class TerminalTests extends ESTestCase {

public void testSystemTerminalIfRedirected() {
// Expect system terminal if redirected for tests.
// To force new behavior in JDK 22 this should run without security manager.
// Otherwise, JDK 22 doesn't provide a console if redirected.
assertEquals(Terminal.SystemTerminal.class, Terminal.DEFAULT.getClass());
}
}

0 comments on commit fb56cb7

Please sign in to comment.