| /* |
| * Copyright (c) 2015, 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 8167636 8167639 8168972 |
| * @summary Testing built-in editor. |
| * @modules java.desktop/java.awt |
| * jdk.internal.ed/jdk.internal.editor.spi |
| * jdk.editpad/jdk.editpad |
| * @run testng EditPadTest |
| */ |
| |
| import java.awt.AWTException; |
| import java.awt.Component; |
| import java.awt.Container; |
| import java.awt.Dimension; |
| import java.awt.Frame; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.Point; |
| import java.awt.Robot; |
| import java.awt.event.InputEvent; |
| import java.awt.event.WindowEvent; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.ServiceLoader; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.ExecutorService; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.Future; |
| import java.util.function.Consumer; |
| |
| import javax.swing.JButton; |
| import javax.swing.JFrame; |
| import javax.swing.JPanel; |
| import javax.swing.JScrollPane; |
| import javax.swing.JTextArea; |
| import javax.swing.JViewport; |
| import javax.swing.SwingUtilities; |
| |
| import org.testng.annotations.AfterClass; |
| import org.testng.annotations.BeforeClass; |
| import org.testng.annotations.Test; |
| import jdk.internal.editor.spi.BuildInEditorProvider; |
| import static org.testng.Assert.assertEquals; |
| import static org.testng.Assert.assertTrue; |
| |
| @Test |
| public class EditPadTest { |
| |
| private static final int DELAY = 500; |
| private static final String WINDOW_LABEL = "Test Edit Pad"; |
| |
| private static ExecutorService executor; |
| private static Robot robot; |
| private static JFrame frame = null; |
| private static JTextArea area = null; |
| private static JButton cancel = null; |
| private static JButton accept = null; |
| private static JButton exit = null; |
| |
| @BeforeClass |
| public static void setUpEditorPadTest() { |
| if (!GraphicsEnvironment.isHeadless()) { |
| try { |
| robot = new Robot(); |
| robot.setAutoWaitForIdle(true); |
| robot.setAutoDelay(DELAY); |
| } catch (AWTException e) { |
| throw new ExceptionInInitializerError(e); |
| } |
| } |
| } |
| |
| @AfterClass |
| public static void shutdown() { |
| executorShutdown(); |
| } |
| |
| public void testSimple() { |
| testEdit("abcdef", 1, "xyz", |
| () -> assertSource("abcdef"), |
| () -> writeSource("xyz"), |
| () -> accept(), |
| () -> assertSource("xyz"), |
| () -> shutdownEditor()); |
| } |
| |
| public void testCancel() { |
| testEdit("abcdef", 0, "abcdef", |
| () -> assertSource("abcdef"), |
| () -> writeSource("xyz"), |
| () -> cancel()); |
| } |
| |
| public void testAbort() { |
| testEdit("abcdef", 0, "abcdef", |
| () -> assertSource("abcdef"), |
| () -> writeSource("xyz"), |
| () -> shutdownEditor()); |
| } |
| |
| public void testAcceptCancel() { |
| testEdit("abcdef", 1, "xyz", |
| () -> assertSource("abcdef"), |
| () -> writeSource("xyz"), |
| () -> accept(), |
| () -> assertSource("xyz"), |
| () -> writeSource("!!!!!!!!!"), |
| () -> cancel()); |
| } |
| |
| public void testAcceptEdit() { |
| testEdit("abcdef", 2, "xyz", |
| () -> assertSource("abcdef"), |
| () -> writeSource("NoNo"), |
| () -> accept(), |
| () -> assertSource("NoNo"), |
| () -> writeSource("xyz"), |
| () -> exit()); |
| } |
| |
| private void testEdit(String initialText, |
| int savedCount, String savedText, Runnable... actions) { |
| class Handler { |
| |
| String text = null; |
| int count = 0; |
| |
| void handle(String s) { |
| ++count; |
| text = s; |
| } |
| } |
| Handler save = new Handler(); |
| Handler error = new Handler(); |
| |
| if (GraphicsEnvironment.isHeadless()) { |
| // Do not actually run if we are headless |
| return; |
| } |
| Future<?> task = doActions(actions); |
| builtInEdit(initialText, save::handle, error::handle); |
| complete(task); |
| assertEquals(error.count, 0, "Error: " + error.text); |
| assertTrue(save.count != savedCount |
| || save.text == null |
| ? savedText != null |
| : savedText.equals(save.text), |
| "Expected " + savedCount + " saves, got " + save.count |
| + ", expected \"" + savedText + "\" got \"" + save.text + "\""); |
| } |
| |
| private static ExecutorService getExecutor() { |
| if (executor == null) { |
| executor = Executors.newSingleThreadExecutor(); |
| } |
| return executor; |
| } |
| |
| private static void executorShutdown() { |
| if (executor != null) { |
| executor.shutdown(); |
| executor = null; |
| } |
| } |
| |
| private void builtInEdit(String initialText, |
| Consumer<String> saveHandler, Consumer<String> errorHandler) { |
| ServiceLoader<BuildInEditorProvider> sl |
| = ServiceLoader.load(BuildInEditorProvider.class); |
| // Find the highest ranking provider |
| BuildInEditorProvider provider = null; |
| for (BuildInEditorProvider p : sl) { |
| if (provider == null || p.rank() > provider.rank()) { |
| provider = p; |
| } |
| } |
| if (provider != null) { |
| provider.edit(WINDOW_LABEL, |
| initialText, saveHandler, errorHandler); |
| } else { |
| throw new InternalError("Cannot find provider"); |
| } |
| } |
| |
| private Future<?> doActions(Runnable... actions) { |
| return getExecutor().submit(() -> { |
| try { |
| waitForIdle(); |
| SwingUtilities.invokeLater(this::seekElements); |
| waitForIdle(); |
| for (Runnable act : actions) { |
| act.run(); |
| } |
| } catch (Throwable e) { |
| shutdownEditor(); |
| if (e instanceof AssertionError) { |
| throw (AssertionError) e; |
| } |
| throw new RuntimeException(e); |
| } |
| }); |
| } |
| |
| private void complete(Future<?> task) { |
| try { |
| task.get(); |
| waitForIdle(); |
| } catch (ExecutionException e) { |
| if (e.getCause() instanceof AssertionError) { |
| throw (AssertionError) e.getCause(); |
| } |
| throw new RuntimeException(e); |
| } catch (Exception e) { |
| throw new RuntimeException(e); |
| } finally { |
| shutdownEditor(); |
| } |
| } |
| |
| private void writeSource(String s) { |
| SwingUtilities.invokeLater(() -> area.setText(s)); |
| } |
| |
| private void assertSource(String expected) { |
| String[] s = new String[1]; |
| try { |
| SwingUtilities.invokeAndWait(() -> s[0] = area.getText()); |
| } catch (InvocationTargetException | InterruptedException e) { |
| throw new RuntimeException(e); |
| } |
| assertEquals(s[0], expected); |
| } |
| |
| private void accept() { |
| clickOn(accept); |
| } |
| |
| private void exit() { |
| clickOn(exit); |
| } |
| |
| private void cancel() { |
| clickOn(cancel); |
| } |
| |
| private void shutdownEditor() { |
| SwingUtilities.invokeLater(this::clearElements); |
| waitForIdle(); |
| } |
| |
| private void waitForIdle() { |
| robot.waitForIdle(); |
| robot.delay(DELAY); |
| } |
| |
| private void seekElements() { |
| for (Frame f : Frame.getFrames()) { |
| if (f.getTitle().equals(WINDOW_LABEL)) { |
| frame = (JFrame) f; |
| // workaround |
| frame.setLocation(0, 0); |
| Container root = frame.getContentPane(); |
| for (Component c : root.getComponents()) { |
| if (c instanceof JScrollPane) { |
| JScrollPane scrollPane = (JScrollPane) c; |
| for (Component comp : scrollPane.getComponents()) { |
| if (comp instanceof JViewport) { |
| JViewport view = (JViewport) comp; |
| area = (JTextArea) view.getComponent(0); |
| } |
| } |
| } |
| if (c instanceof JPanel) { |
| JPanel p = (JPanel) c; |
| for (Component comp : p.getComponents()) { |
| if (comp instanceof JButton) { |
| JButton b = (JButton) comp; |
| switch (b.getText()) { |
| case "Cancel": |
| cancel = b; |
| break; |
| case "Exit": |
| exit = b; |
| break; |
| case "Accept": |
| accept = b; |
| break; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| private void clearElements() { |
| if (frame != null) { |
| frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); |
| frame = null; |
| } |
| area = null; |
| accept = null; |
| cancel = null; |
| exit = null; |
| } |
| |
| private void clickOn(JButton button) { |
| waitForIdle(); |
| waitForIdle(); |
| waitForIdle(); |
| waitForIdle(); |
| waitForIdle(); |
| waitForIdle(); |
| Point p = button.getLocationOnScreen(); |
| Dimension d = button.getSize(); |
| robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2); |
| robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); |
| robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); |
| } |
| } |