8152296: langtools/test/jdk/jshell/ToolReloadTest.java failing if there is not persisted history

Create a custom Terminal for use in tests; avoid use of global Preferences in tests.

Reviewed-by: rfield
This commit is contained in:
Jan Lahoda 2016-03-23 13:40:42 +01:00
parent 5be151ebda
commit a981a56c45
4 changed files with 106 additions and 15 deletions

View file

@ -48,7 +48,7 @@ import java.util.function.Supplier;
import jdk.internal.jline.NoInterruptUnixTerminal; import jdk.internal.jline.NoInterruptUnixTerminal;
import jdk.internal.jline.Terminal; import jdk.internal.jline.Terminal;
import jdk.internal.jline.TerminalFactory; import jdk.internal.jline.TerminalFactory;
import jdk.internal.jline.UnsupportedTerminal; import jdk.internal.jline.TerminalSupport;
import jdk.internal.jline.WindowsTerminal; import jdk.internal.jline.WindowsTerminal;
import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.ConsoleReader;
import jdk.internal.jline.console.KeyMap; import jdk.internal.jline.console.KeyMap;
@ -70,7 +70,7 @@ class ConsoleIOContext extends IOContext {
this.input = new StopDetectingInputStream(() -> repl.state.stop(), ex -> repl.hard("Error on input: %s", ex)); this.input = new StopDetectingInputStream(() -> repl.state.stop(), ex -> repl.hard("Error on input: %s", ex));
Terminal term; Terminal term;
if (System.getProperty("test.jdk") != null) { if (System.getProperty("test.jdk") != null) {
term = new UnsupportedTerminal(); term = new TestTerminal(input);
} else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { } else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) {
term = new JShellWindowsTerminal(input); term = new JShellWindowsTerminal(input);
} else { } else {
@ -80,7 +80,7 @@ class ConsoleIOContext extends IOContext {
in = new ConsoleReader(cmdin, cmdout, term); in = new ConsoleReader(cmdin, cmdout, term);
in.setExpandEvents(false); in.setExpandEvents(false);
in.setHandleUserInterrupt(true); in.setHandleUserInterrupt(true);
in.setHistory(history = new EditingHistory(JShellTool.PREFS) { in.setHistory(history = new EditingHistory(repl.prefs) {
@Override protected CompletionInfo analyzeCompletion(String input) { @Override protected CompletionInfo analyzeCompletion(String input) {
return repl.analysis.analyzeCompletion(input); return repl.analysis.analyzeCompletion(input);
} }
@ -538,4 +538,22 @@ class ConsoleIOContext extends IOContext {
} }
} }
private static final class TestTerminal extends TerminalSupport {
private final StopDetectingInputStream input;
public TestTerminal(StopDetectingInputStream input) throws Exception {
super(true);
setAnsiSupported(false);
setEchoEnabled(true);
this.input = input;
}
@Override
public InputStream wrapInIfNeeded(InputStream in) throws IOException {
return input.setInputStream(super.wrapInIfNeeded(in));
}
}
} }

View file

@ -121,6 +121,7 @@ public class JShellTool {
final InputStream userin; final InputStream userin;
final PrintStream userout; final PrintStream userout;
final PrintStream usererr; final PrintStream usererr;
final Preferences prefs;
final Feedback feedback = new Feedback(); final Feedback feedback = new Feedback();
@ -137,7 +138,8 @@ public class JShellTool {
*/ */
public JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr, public JShellTool(InputStream cmdin, PrintStream cmdout, PrintStream cmderr,
PrintStream console, PrintStream console,
InputStream userin, PrintStream userout, PrintStream usererr) { InputStream userin, PrintStream userout, PrintStream usererr,
Preferences prefs) {
this.cmdin = cmdin; this.cmdin = cmdin;
this.cmdout = cmdout; this.cmdout = cmdout;
this.cmderr = cmderr; this.cmderr = cmderr;
@ -145,6 +147,7 @@ public class JShellTool {
this.userin = userin; this.userin = userin;
this.userout = userout; this.userout = userout;
this.usererr = usererr; this.usererr = usererr;
this.prefs = prefs;
initializeFeedbackModes(); initializeFeedbackModes();
} }
@ -230,8 +233,6 @@ public class JShellTool {
private List<String> replayableHistory; private List<String> replayableHistory;
private List<String> replayableHistoryPrevious; private List<String> replayableHistoryPrevious;
static final Preferences PREFS = Preferences.userRoot().node("tool/JShell");
static final String STARTUP_KEY = "STARTUP"; static final String STARTUP_KEY = "STARTUP";
static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE"; static final String REPLAY_RESTORE_KEY = "REPLAY_RESTORE";
@ -387,7 +388,8 @@ public class JShellTool {
*/ */
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
new JShellTool(System.in, System.out, System.err, System.out, new JShellTool(System.in, System.out, System.err, System.out,
new ByteArrayInputStream(new byte[0]), System.out, System.err) new ByteArrayInputStream(new byte[0]), System.out, System.err,
Preferences.userRoot().node("tool/JShell"))
.start(args); .start(args);
} }
@ -406,7 +408,7 @@ public class JShellTool {
resetState(); // Initialize resetState(); // Initialize
// Read replay history from last jshell session into previous history // Read replay history from last jshell session into previous history
String prevReplay = PREFS.get(REPLAY_RESTORE_KEY, null); String prevReplay = prefs.get(REPLAY_RESTORE_KEY, null);
if (prevReplay != null) { if (prevReplay != null) {
replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR)); replayableHistoryPrevious = Arrays.asList(prevReplay.split(RECORD_SEPARATOR));
} }
@ -558,10 +560,10 @@ public class JShellTool {
String start; String start;
if (cmdlineStartup == null) { if (cmdlineStartup == null) {
start = PREFS.get(STARTUP_KEY, "<nada>"); start = prefs.get(STARTUP_KEY, "<nada>");
if (start.equals("<nada>")) { if (start.equals("<nada>")) {
start = DEFAULT_STARTUP; start = DEFAULT_STARTUP;
PREFS.put(STARTUP_KEY, DEFAULT_STARTUP); prefs.put(STARTUP_KEY, DEFAULT_STARTUP);
} }
} else { } else {
start = cmdlineStartup; start = cmdlineStartup;
@ -1198,7 +1200,7 @@ public class JShellTool {
try { try {
byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename));
String init = new String(encoded); String init = new String(encoded);
PREFS.put(STARTUP_KEY, init); prefs.put(STARTUP_KEY, init);
} catch (AccessDeniedException e) { } catch (AccessDeniedException e) {
hard("File '%s' for /set start is not accessible.", filename); hard("File '%s' for /set start is not accessible.", filename);
return false; return false;
@ -1347,7 +1349,7 @@ public class JShellTool {
regenerateOnDeath = false; regenerateOnDeath = false;
live = false; live = false;
if (!replayableHistory.isEmpty()) { if (!replayableHistory.isEmpty()) {
PREFS.put(REPLAY_RESTORE_KEY, replayableHistory.stream().reduce( prefs.put(REPLAY_RESTORE_KEY, replayableHistory.stream().reduce(
(a, b) -> a + RECORD_SEPARATOR + b).get()); (a, b) -> a + RECORD_SEPARATOR + b).get());
} }
fluff("Goodbye\n"); fluff("Goodbye\n");

View file

@ -33,6 +33,9 @@ import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
import java.util.prefs.AbstractPreferences;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -41,6 +44,8 @@ import java.util.stream.Stream;
import jdk.internal.jshell.tool.JShellTool; import jdk.internal.jshell.tool.JShellTool;
import jdk.jshell.SourceCodeAnalysis.Suggestion; import jdk.jshell.SourceCodeAnalysis.Suggestion;
import org.testng.annotations.BeforeMethod;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
@ -83,6 +88,7 @@ public class ReplToolTesting {
private Map<String, ClassInfo> classes; private Map<String, ClassInfo> classes;
private Map<String, ImportInfo> imports; private Map<String, ImportInfo> imports;
private boolean isDefaultStartUp = true; private boolean isDefaultStartUp = true;
private Preferences prefs;
public JShellTool repl = null; public JShellTool repl = null;
@ -219,6 +225,11 @@ public class ReplToolTesting {
} }
} }
@BeforeMethod
public void setUp() {
prefs = new MemoryPreferences();
}
public void testRaw(String[] args, ReplTest... tests) { public void testRaw(String[] args, ReplTest... tests) {
cmdin = new WaitingTestingInputStream(); cmdin = new WaitingTestingInputStream();
cmdout = new ByteArrayOutputStream(); cmdout = new ByteArrayOutputStream();
@ -234,7 +245,8 @@ public class ReplToolTesting {
new PrintStream(console), new PrintStream(console),
userin, userin,
new PrintStream(userout), new PrintStream(userout),
new PrintStream(usererr)); new PrintStream(usererr),
prefs);
repl.testPrompt = true; repl.testPrompt = true;
try { try {
repl.start(args); repl.start(args);
@ -447,7 +459,7 @@ public class ReplToolTesting {
private List<String> computeCompletions(String code, boolean isSmart) { private List<String> computeCompletions(String code, boolean isSmart) {
JShellTool js = this.repl != null ? this.repl JShellTool js = this.repl != null ? this.repl
: new JShellTool(null, null, null, null, null, null, null); : new JShellTool(null, null, null, null, null, null, null, prefs);
int cursor = code.indexOf('|'); int cursor = code.indexOf('|');
code = code.replace("|", ""); code = code.replace("|", "");
assertTrue(cursor > -1, "'|' not found: " + code); assertTrue(cursor > -1, "'|' not found: " + code);
@ -762,4 +774,62 @@ public class ReplToolTesting {
} }
} }
} }
public static final class MemoryPreferences extends AbstractPreferences {
private final Map<String, String> values = new HashMap<>();
private final Map<String, MemoryPreferences> nodes = new HashMap<>();
public MemoryPreferences() {
this(null, "");
}
public MemoryPreferences(MemoryPreferences parent, String name) {
super(parent, name);
}
@Override
protected void putSpi(String key, String value) {
values.put(key, value);
}
@Override
protected String getSpi(String key) {
return values.get(key);
}
@Override
protected void removeSpi(String key) {
values.remove(key);
}
@Override
protected void removeNodeSpi() throws BackingStoreException {
((MemoryPreferences) parent()).nodes.remove(name());
}
@Override
protected String[] keysSpi() throws BackingStoreException {
return values.keySet().toArray(new String[0]);
}
@Override
protected String[] childrenNamesSpi() throws BackingStoreException {
return nodes.keySet().toArray(new String[0]);
}
@Override
protected AbstractPreferences childSpi(String name) {
return nodes.computeIfAbsent(name, n -> new MemoryPreferences(this, name));
}
@Override
protected void syncSpi() throws BackingStoreException {
}
@Override
protected void flushSpi() throws BackingStoreException {
}
}
} }

View file

@ -54,7 +54,8 @@ public class StartOptionTest {
private ByteArrayOutputStream err; private ByteArrayOutputStream err;
private JShellTool getShellTool() { private JShellTool getShellTool() {
return new JShellTool(null, new PrintStream(out), new PrintStream(err), null, null, null, null); return new JShellTool(null, new PrintStream(out), new PrintStream(err), null, null, null,
null, new ReplToolTesting.MemoryPreferences());
} }
private String getOutput() { private String getOutput() {