ExternalEditorTest.java revision 3717:2a3e23ee1b65
176116Sdcs/* 276116Sdcs * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 376116Sdcs * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 476116Sdcs * 576116Sdcs * This code is free software; you can redistribute it and/or modify it 676116Sdcs * under the terms of the GNU General Public License version 2 only, as 794290Sdcs * published by the Free Software Foundation. 876116Sdcs * 976116Sdcs * This code is distributed in the hope that it will be useful, but WITHOUT 1076116Sdcs * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1176116Sdcs * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1276116Sdcs * version 2 for more details (a copy is included in the LICENSE file that 1376116Sdcs * accompanied this code). 1476116Sdcs * 1594290Sdcs * You should have received a copy of the GNU General Public License version 1694290Sdcs * 2 along with this work; if not, write to the Free Software Foundation, 1794290Sdcs * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1894290Sdcs * 1994290Sdcs * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2076116Sdcs * or visit www.oracle.com if you need additional information or have any 2176116Sdcs * questions. 2276116Sdcs */ 2376116Sdcs 2476116Sdcs/* 2576116Sdcs * @test 2676116Sdcs * @summary Testing external editor. 2776116Sdcs * @bug 8143955 8080843 2876116Sdcs * @modules jdk.jshell/jdk.internal.jshell.tool 2976116Sdcs * @build ReplToolTesting CustomEditor EditorTestBase 3076116Sdcs * @run testng ExternalEditorTest 3176116Sdcs */ 3276116Sdcs 3376116Sdcsimport java.io.BufferedWriter; 3476116Sdcsimport java.io.DataInputStream; 3576116Sdcsimport java.io.DataOutputStream; 3676116Sdcsimport java.io.IOException; 3776116Sdcsimport java.io.UncheckedIOException; 3876116Sdcsimport java.net.ServerSocket; 3976116Sdcsimport java.net.Socket; 4076116Sdcsimport java.net.SocketTimeoutException; 4176116Sdcsimport java.nio.charset.StandardCharsets; 4276116Sdcsimport java.nio.file.Files; 4376116Sdcsimport java.nio.file.Path; 4476116Sdcsimport java.nio.file.Paths; 4576116Sdcsimport java.util.concurrent.ExecutionException; 4676116Sdcsimport java.util.concurrent.Future; 4776116Sdcsimport java.util.function.Consumer; 4876116Sdcs 4976116Sdcsimport org.testng.annotations.AfterClass; 5076116Sdcsimport org.testng.annotations.BeforeClass; 5176116Sdcsimport org.testng.annotations.Test; 5276116Sdcs 5376116Sdcsimport static org.testng.Assert.fail; 5476116Sdcs 5576116Sdcspublic class ExternalEditorTest extends EditorTestBase { 5676116Sdcs 5776116Sdcs private static Path executionScript; 5876116Sdcs private static ServerSocket listener; 5976116Sdcs 6094290Sdcs private DataInputStream inputStream; 6176116Sdcs private DataOutputStream outputStream; 6276116Sdcs 6376116Sdcs @Override 6476116Sdcs public void writeSource(String s) { 6576116Sdcs try { 6676116Sdcs outputStream.writeInt(CustomEditor.SOURCE_CODE); 6776116Sdcs byte[] bytes = s.getBytes(StandardCharsets.UTF_8); 6876116Sdcs outputStream.writeInt(bytes.length); 6976116Sdcs outputStream.write(bytes); 7076116Sdcs } catch (IOException e) { 7176116Sdcs throw new UncheckedIOException(e); 7276116Sdcs } 7376116Sdcs } 7476116Sdcs 7576116Sdcs @Override 7676116Sdcs public String getSource() { 7776116Sdcs try { 7876116Sdcs outputStream.writeInt(CustomEditor.GET_SOURCE_CODE); 7976116Sdcs int length = inputStream.readInt(); 8076116Sdcs byte[] bytes = new byte[length]; 8176116Sdcs inputStream.readFully(bytes); 8294290Sdcs return new String(bytes, StandardCharsets.UTF_8); 8376116Sdcs } catch (IOException e) { 8476116Sdcs throw new UncheckedIOException(e); 8576116Sdcs } 8676116Sdcs } 8776116Sdcs 8876116Sdcs private void sendCode(int code) { 8976116Sdcs try { 9076116Sdcs outputStream.writeInt(code); 9176116Sdcs } catch (IOException e) { 9276116Sdcs throw new UncheckedIOException(e); 9376116Sdcs } 9476116Sdcs } 9576116Sdcs 9694290Sdcs @Override 9776116Sdcs public void accept() { 9876116Sdcs sendCode(CustomEditor.ACCEPT_CODE); 9976116Sdcs } 10076116Sdcs 10176116Sdcs @Override 10276116Sdcs public void exit() { 10376116Sdcs sendCode(CustomEditor.EXIT_CODE); 10476116Sdcs inputStream = null; 10576116Sdcs outputStream = null; 10676116Sdcs } 10776116Sdcs 10876116Sdcs @Override 10976116Sdcs public void cancel() { 11076116Sdcs sendCode(CustomEditor.CANCEL_CODE); 11176116Sdcs } 11294290Sdcs 11376116Sdcs @Override 11476116Sdcs public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) { 11576116Sdcs ReplTest[] t = new ReplTest[tests.length + 1]; 11676116Sdcs t[0] = a -> assertCommandCheckOutput(a, "/set editor " + executionScript, 11776116Sdcs assertStartsWith("| Editor set to: " + executionScript)); 11876116Sdcs System.arraycopy(tests, 0, t, 1, tests.length); 11976116Sdcs super.testEditor(defaultStartup, args, t); 12076116Sdcs } 12176116Sdcs 12276116Sdcs private static boolean isWindows() { 12376116Sdcs return System.getProperty("os.name").startsWith("Windows"); 12476116Sdcs } 12576116Sdcs 12676116Sdcs @BeforeClass 12776116Sdcs public static void setUpExternalEditorTest() throws IOException { 12876116Sdcs listener = new ServerSocket(0); 12976116Sdcs listener.setSoTimeout(30000); 13076116Sdcs int localPort = listener.getLocalPort(); 13176116Sdcs 13276116Sdcs executionScript = Paths.get(isWindows() ? "editor.bat" : "editor.sh").toAbsolutePath(); 13376116Sdcs Path java = Paths.get(System.getProperty("java.home")).resolve("bin").resolve("java"); 13476116Sdcs try (BufferedWriter writer = Files.newBufferedWriter(executionScript)) { 13576116Sdcs if(!isWindows()) { 13676116Sdcs writer.append(java.toString()).append(" ") 13776116Sdcs .append(" -cp ").append(System.getProperty("java.class.path")) 13876116Sdcs .append(" CustomEditor ").append(Integer.toString(localPort)).append(" $@"); 13976116Sdcs executionScript.toFile().setExecutable(true); 14076116Sdcs } else { 14176116Sdcs writer.append(java.toString()).append(" ") 14276116Sdcs .append(" -cp ").append(System.getProperty("java.class.path")) 14376116Sdcs .append(" CustomEditor ").append(Integer.toString(localPort)).append(" %*"); 14476116Sdcs } 14576116Sdcs } 14676116Sdcs } 14776116Sdcs 14876116Sdcs private Future<?> task; 14976116Sdcs @Override 15076116Sdcs public void assertEdit(boolean after, String cmd, 15176116Sdcs Consumer<String> checkInput, Consumer<String> checkOutput, Action action) { 15276116Sdcs if (!after) { 15376116Sdcs setCommandInput(cmd + "\n"); 15476116Sdcs task = getExecutor().submit(() -> { 15576116Sdcs try (Socket socket = listener.accept()) { 15676116Sdcs inputStream = new DataInputStream(socket.getInputStream()); 15776116Sdcs outputStream = new DataOutputStream(socket.getOutputStream()); 15876116Sdcs checkInput.accept(getSource()); 15976116Sdcs action.accept(); 16076116Sdcs } catch (SocketTimeoutException e) { 16176116Sdcs fail("Socket timeout exception.\n Output: " + getCommandOutput() + 16276116Sdcs "\n, error: " + getCommandErrorOutput()); 16376116Sdcs } catch (Throwable e) { 16476116Sdcs shutdownEditor(); 16576116Sdcs if (e instanceof AssertionError) { 16676116Sdcs throw (AssertionError) e; 16776116Sdcs } 16876116Sdcs throw new RuntimeException(e); 16976116Sdcs } 17076116Sdcs }); 17176116Sdcs } else { 17276116Sdcs try { 17394290Sdcs task.get(); 17476116Sdcs checkOutput.accept(getCommandOutput()); 17576116Sdcs } catch (ExecutionException e) { 17676116Sdcs if (e.getCause() instanceof AssertionError) { 17776116Sdcs throw (AssertionError) e.getCause(); 17876116Sdcs } 17976116Sdcs throw new RuntimeException(e); 18076116Sdcs } catch (Exception e) { 18176116Sdcs throw new RuntimeException(e); 18276116Sdcs } 18376116Sdcs } 18476116Sdcs } 18576116Sdcs 18676116Sdcs @Override 18776116Sdcs public void shutdownEditor() { 18876116Sdcs if (outputStream != null) { 18976116Sdcs exit(); 19076116Sdcs } 19176116Sdcs } 19276116Sdcs 19376116Sdcs @Test 19476116Sdcs public void setUnknownEditor() { 19576116Sdcs test( 19694290Sdcs a -> assertCommand(a, "/set editor UNKNOWN", "| Editor set to: UNKNOWN"), 19776116Sdcs a -> assertCommand(a, "int a;", null), 19876116Sdcs a -> assertCommandOutputStartsWith(a, "/ed 1", 19976116Sdcs "| Edit Error:") 20076116Sdcs ); 20176116Sdcs } 20276116Sdcs 20376116Sdcs @Test(enabled = false) // TODO 8159229 20476116Sdcs public void testRemoveTempFile() { 20576116Sdcs test(new String[]{"--no-startup"}, 20676116Sdcs a -> assertCommandCheckOutput(a, "/set editor " + executionScript, 20776116Sdcs assertStartsWith("| Editor set to: " + executionScript)), 20876116Sdcs a -> assertVariable(a, "int", "a", "0", "0"), 20976116Sdcs a -> assertEditOutput(a, "/ed 1", assertStartsWith("| Edit Error: Failure in read edit file:"), () -> { 21076116Sdcs sendCode(CustomEditor.REMOVE_CODE); 21176116Sdcs exit(); 21276116Sdcs }), 21376116Sdcs a -> assertCommandCheckOutput(a, "/vars", assertVariables()) 21476116Sdcs ); 21576116Sdcs } 21676116Sdcs 21776116Sdcs @AfterClass 21876116Sdcs public static void shutdown() throws IOException { 21976116Sdcs executorShutdown(); 22076116Sdcs if (listener != null) { 22176116Sdcs listener.close(); 22276116Sdcs } 22376116Sdcs } 22476116Sdcs} 22576116Sdcs