Capturing CTRL+D EOF to exit the shell

* Capturing CTRL+D (EOF) to exit the shell
* replace junit to assertj
* fix hang on testing
This commit is contained in:
Yubi Lee
2022-06-08 02:20:52 +09:00
committed by GitHub
parent 3556352ab3
commit 38ce78434a
2 changed files with 136 additions and 0 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.shell.jline;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.UserInterruptException;
import org.jline.utils.AttributedString;
@@ -101,6 +102,9 @@ public class InteractiveShellRunner implements ShellRunner {
return Input.EMPTY;
}
}
catch (EndOfFileException e) {
throw new ExitRequest(1);
}
return new ParsedLineInput(lineReader.getParsedLine());
}
}

View File

@@ -0,0 +1,132 @@
package org.springframework.shell.jline;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.terminal.Attributes;
import org.jline.terminal.impl.ExternalTerminal;
import org.jline.utils.AttributedString;
import org.jline.utils.AttributedStyle;
import org.junit.jupiter.api.Test;
import org.springframework.shell.ExitRequest;
import static org.assertj.core.api.Assertions.*;
import java.io.ByteArrayOutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
public class InteractiveShellRunnerTests {
private PipedOutputStream outIn;
private InteractiveShellRunner.JLineInputProvider jLineInputProvider;
private PromptProvider dummyPromptProvider() {
return () -> new AttributedString("dummy-shell:>", AttributedStyle.DEFAULT.foreground(AttributedStyle.YELLOW));
}
private void initForShortcutKeyTest() throws Exception {
PipedInputStream in = new PipedInputStream();
outIn = new PipedOutputStream(in);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ExternalTerminal terminal = new ExternalTerminal("foo", "ansi", in, out, StandardCharsets.UTF_8);
Attributes attributes = terminal.getAttributes();
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
attributes.setControlChar(Attributes.ControlChar.VINTR, 3);
terminal.setAttributes(attributes);
LineReaderBuilder builder =
LineReaderBuilder.builder()
.terminal(terminal);
LineReader lineReader = builder.build();
jLineInputProvider = new InteractiveShellRunner.JLineInputProvider(lineReader, dummyPromptProvider());
}
@Test
public void testClearWithCtrlC() throws Exception {
initForShortcutKeyTest();
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch endLatch = new CountDownLatch(1);
Thread writeThread = new Thread(() -> {
try {
startLatch.await();
outIn.write('a');
outIn.write(3);
endLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread readThread = new Thread(() -> {
assertThatNoException().isThrownBy(() -> assertThat(jLineInputProvider.readInput().rawText()).isEqualTo(""));
endLatch.countDown();
});
readThread.start();
startLatch.countDown();
writeThread.start();
readThread.join();
writeThread.join();
}
@Test
public void testExitWithCtrlC() throws Exception {
initForShortcutKeyTest();
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch endLatch = new CountDownLatch(1);
Thread writeThread = new Thread(() -> {
try {
startLatch.await();
outIn.write(3);
endLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread readThread = new Thread(() -> {
assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class);
endLatch.countDown();
});
readThread.start();
startLatch.countDown();
writeThread.start();
readThread.join();
writeThread.join();
}
@Test
public void testExitWithCtrlD() throws Exception {
initForShortcutKeyTest();
CountDownLatch startLatch = new CountDownLatch(1);
CountDownLatch endLatch = new CountDownLatch(1);
Thread writeThread = new Thread(() -> {
try {
startLatch.await();
outIn.write(4);
endLatch.await();
} catch (Exception e) {
e.printStackTrace();
}
});
Thread readThread = new Thread(() -> {
assertThatThrownBy(jLineInputProvider::readInput).isInstanceOf(ExitRequest.class);
endLatch.countDown();
});
readThread.start();
startLatch.countDown();
writeThread.start();
readThread.join();
writeThread.join();
}
}