From 1c2dadc31e8b732d43df5494437720bfbc3f5c8b Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Tue, 25 Apr 2023 20:26:45 +0000 Subject: [PATCH] 8306683: Open source several clipboard and color AWT tests Reviewed-by: prr --- .../java/awt/Clipboard/DelayedQueryTest.java | 252 ++++++++++++++++++ .../java/awt/Clipboard/NullContentsTest.java | 58 ++++ .../Clipboard/SerializeLocalFlavorTest.java | 198 ++++++++++++++ .../ColorClass/ColorSerializationTest.java | 62 +++++ 4 files changed, 570 insertions(+) create mode 100644 test/jdk/java/awt/Clipboard/DelayedQueryTest.java create mode 100644 test/jdk/java/awt/Clipboard/NullContentsTest.java create mode 100644 test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java create mode 100644 test/jdk/java/awt/ColorClass/ColorSerializationTest.java diff --git a/test/jdk/java/awt/Clipboard/DelayedQueryTest.java b/test/jdk/java/awt/Clipboard/DelayedQueryTest.java new file mode 100644 index 00000000000..857a6f79707 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/DelayedQueryTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2000, 2023, 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 4085183 8000630 + @summary tests that clipboard contents is retrieved even if the app didn't + receive native events for a long time. + @requires (os.family != "mac") + @key headful + @run main DelayedQueryTest +*/ + +import java.awt.AWTException; +import java.awt.Button; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.event.InputEvent; +import java.io.File; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; + +public class DelayedQueryTest implements ClipboardOwner, Runnable { + int returnCode = Child.CHILD_RETURN_CODE_NOT_READY; + + Process childProcess = null; + Frame frame; + + public static void main(String[] args) + throws InterruptedException, InvocationTargetException { + String osName = System.getProperty("os.name"); + if (osName.toLowerCase().contains("os x")) { + System.out.println("This test is not for MacOS, considered passed."); + return; + } + DelayedQueryTest delayedQueryTest = new DelayedQueryTest(); + EventQueue.invokeAndWait(delayedQueryTest::initAndShowGui); + try { + delayedQueryTest.start(); + } finally { + EventQueue.invokeAndWait(() -> delayedQueryTest.frame.dispose()); + } + } + + public void initAndShowGui(){ + frame = new Frame("DelayedQueryTest"); + frame.add(new Panel()); + frame.setBounds(200,200, 200, 200); + frame.setVisible(true); + } + + public void start() { + try { + Robot robot = new Robot(); + // Some mouse activity to update the Xt time stamp at + // the parent process. + robot.delay(1000); + robot.waitForIdle(); + + Point p = frame.getLocationOnScreen(); + robot.mouseMove(p.x + 100, p.y + 100); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } catch (AWTException e) { + e.printStackTrace(); + throw new RuntimeException("The test failed."); + } + Child.sysClipboard.setContents(Child.transferable, this); + + String javaPath = System.getProperty("java.home", ""); + String[] command = { + javaPath + File.separator + "bin" + File.separator + "java", + "-cp", System.getProperty("test.classes", "."), + "Child" + }; + + try { + Process process = Runtime.getRuntime().exec(command); + childProcess = process; + returnCode = process.waitFor(); + childProcess = null; + + InputStream errorStream = process.getErrorStream(); + int count = errorStream.available(); + if (count > 0) { + byte[] b = new byte[count]; + errorStream.read(b); + System.err.println("========= Child VM System.err ========"); + System.err.print(new String(b)); + System.err.println("======================================"); + } + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException("The test failed."); + } + if (returnCode != Child.CHILD_RETURN_CODE_OK) { + System.err.println("Child VM: returned " + returnCode); + throw new RuntimeException("The test failed."); + } + } // start() + + public void lostOwnership(Clipboard clipboard, + Transferable contents) { + // At this moment the child process has definitely started. + // So we can try to retrieve the clipboard contents set + // by the child process. + new Thread(this).start(); + } + + public void run() { + // We are going to check if it is possible to retrieve the data + // after the child process has set the clipboard contents twice, + // since after the first setting the retrieval is always successful. + // So we wait to let the child process set the clipboard contents + // twice. + try { + Thread.sleep(Child.CHILD_SELECTION_CHANGE_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + try { + String s = (String)Child.sysClipboard + .getContents(null) + .getTransferData(DataFlavor.stringFlavor); + if (!"String".equals(s)) { + System.err.println("Data retrieved: " + s); + throw new RuntimeException("Retrieved data is incorrect."); + } + } catch (Exception e) { + e.printStackTrace(); + if (childProcess != null) { + childProcess.destroy(); + childProcess = null; + } + throw new RuntimeException("Failed to retrieve the data."); + } + Child.sysClipboard.setContents(Child.transferable, null); + } +} + +class Child { + static final Clipboard sysClipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + static final Transferable transferable = new StringSelection("String"); + + /* + * Timeouts. + */ + static final int FRAME_ACTIVATION_TIMEOUT = 1000; + static final int PARENT_TIME_STAMP_TIMEOUT = 1000; + static final int CHILD_SELECTION_CHANGE_TIMEOUT = + FRAME_ACTIVATION_TIMEOUT + PARENT_TIME_STAMP_TIMEOUT + 5000; + static final int PARENT_RETRIEVE_DATA_TIMEOUT = 10000; + + /* + * Child process return codes. + */ + static final int CHILD_RETURN_CODE_NOT_READY = -1; + static final int CHILD_RETURN_CODE_OK = 0; + static final int CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION = 1; + static final int CHILD_RETURN_CODE_OTHER_FAILURE = 2; + static Button button; + + static void initAndShowGui() { + final Frame frame = new Frame(); + button = new Button("button"); + frame.add(button); + frame.pack(); + frame.setLocation(100, 100); + frame.setVisible(true); + } + + public static void main(String[] args) { + sysClipboard.setContents( + new StringSelection("First String"), null); + + // Some mouse activity to update the Xt time stamp at + // the child process. + try { + EventQueue.invokeAndWait(Child::initAndShowGui); + try { + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + + Robot robot = new Robot(); + robot.waitForIdle(); + + Point p = button.getLocationOnScreen(); + robot.mouseMove(p.x + 10, p.y + 10); + // Wait to let the Xt time stamp become out-of-date. + try { + Thread.sleep(PARENT_TIME_STAMP_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } catch (Exception e) { + e.printStackTrace(); + System.exit(CHILD_RETURN_CODE_UNEXPECTED_EXCEPTION); + } + + sysClipboard.setContents(transferable, new ClipboardOwner() { + public void lostOwnership(Clipboard clipboard, + Transferable contents) { + System.exit(CHILD_RETURN_CODE_OK); + } + }); + // Wait to let the parent process retrieve the data. + try { + Thread.sleep(PARENT_RETRIEVE_DATA_TIMEOUT); + } catch (InterruptedException e) { + e.printStackTrace(); + } + // Parent failed to set clipboard contents, so we signal test failure + System.exit(CHILD_RETURN_CODE_OTHER_FAILURE); + } +} diff --git a/test/jdk/java/awt/Clipboard/NullContentsTest.java b/test/jdk/java/awt/Clipboard/NullContentsTest.java new file mode 100644 index 00000000000..6d4031b49eb --- /dev/null +++ b/test/jdk/java/awt/Clipboard/NullContentsTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2000, 2023, 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 4378007 4250859 + @summary Verifies that setting the contents of the system Clipboard to null + throws a NullPointerException + @key headful + @run main NullContentsTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +public class NullContentsTest { + + public static void main(String[] args) { + // Clipboard.setContents(null, foo) should throw an NPE, but + // Clipboard.setContents(bar, foo), where bar.getTransferData(baz) + // returns null, should not. + Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); + try { + clip.setContents(null, null); + } catch (NullPointerException e) { + StringSelection ss = new StringSelection(null); + try { + clip.setContents(ss, null); + } catch (NullPointerException ee) { + throw new RuntimeException("test failed: null transfer data"); + } + System.err.println("test passed"); + return; + } + throw new RuntimeException("test failed: null Transferable"); + } +} diff --git a/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java b/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java new file mode 100644 index 00000000000..90b9f0cd305 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/SerializeLocalFlavorTest.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2006, 2023, 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 4696186 + @summary tests that NotSerializableException is not printed in the console if + non-serializable object with DataFlavor.javaJVMLocalObjectMimeType + is set into the clipboard + @key headful + @run main SerializeLocalFlavorTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.File; +import java.io.InputStream; +import java.io.Serializable; + + +public class SerializeLocalFlavorTest { + private boolean failed = false; + + public static void main(String[] args) { + new SerializeLocalFlavorTest().start(); + } + + public void start () { + try { + String[] command = { + System.getProperty("java.home", "") + + File.separator + "bin" + File.separator + + "java", + "-cp", + System.getProperty("test.classes", "."), + "Child" + }; + + Process process = Runtime.getRuntime().exec(command); + ProcessResults pres = ProcessResults.doWaitFor(process); + + if (pres.stderr != null && pres.stderr.length() > 0) { + System.err.println("========= Child err ========"); + System.err.print(pres.stderr); + System.err.println("======================================"); + } + + if (pres.stdout != null && pres.stdout.length() > 0) { + System.err.println("========= Child out ========"); + System.err.print(pres.stdout); + System.err.println("======================================"); + } + + if (pres.stderr.indexOf("java.io.NotSerializableException") >= 0) { + failed = true; + } + + } catch (Exception e) { + e.printStackTrace(); + } + + if (failed) { + throw new RuntimeException( + "The test failed: java.io.NotSerializableException printed!"); + } else { + System.err.println("The test passed!"); + } + } +} + +class Child { + public static void main (String [] args) throws Exception { + NotSerializableLocalTransferable t = + new NotSerializableLocalTransferable(new NotSer()); + Toolkit.getDefaultToolkit() + .getSystemClipboard().setContents(t, null); + } +} + +class NotSerializableLocalTransferable implements Transferable { + public final DataFlavor flavor; + + private final DataFlavor[] flavors; + + private final Object data; + + + public NotSerializableLocalTransferable(Object data) throws Exception { + this.data = data; + flavor = new DataFlavor( + DataFlavor.javaJVMLocalObjectMimeType + + ";class=" + "\"" + data.getClass().getName() + "\""); + this.flavors = new DataFlavor[] { flavor }; + } + + public DataFlavor[] getTransferDataFlavors() { + return flavors.clone(); + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + return this.flavor.equals(flavor); + } + + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException + { + if (this.flavor.equals(flavor)) { + return (Object)data; + } + throw new UnsupportedFlavorException(flavor); + } + +} + +class NotSer implements Serializable { + private Object field = new Object(); // not serializable field +} + +class ProcessResults { + public int exitValue; + public String stdout; + public String stderr; + + public ProcessResults() { + exitValue = -1; + stdout = ""; + stderr = ""; + } + + /** + * Method to perform a "wait" for a process and return its exit value. + * This is a workaround for Process.waitFor() never returning. + */ + public static ProcessResults doWaitFor(Process p) { + ProcessResults pres = new ProcessResults(); + + InputStream in = null; + InputStream err = null; + + try { + in = p.getInputStream(); + err = p.getErrorStream(); + + boolean finished = false; + + while (!finished) { + try { + while (in.available() > 0) { + pres.stdout += (char)in.read(); + } + while (err.available() > 0) { + pres.stderr += (char)err.read(); + } + // Ask the process for its exitValue. If the process + // is not finished, an IllegalThreadStateException + // is thrown. If it is finished, we fall through and + // the variable finished is set to true. + pres.exitValue = p.exitValue(); + finished = true; + } + catch (IllegalThreadStateException e) { + // Process is not finished yet; + // Sleep a little to save on CPU cycles + Thread.sleep(500); + } + } + if (in != null) in.close(); + if (err != null) err.close(); + } + catch (Throwable e) { + System.err.println("doWaitFor(): unexpected exception"); + e.printStackTrace(); + } + return pres; + } +} diff --git a/test/jdk/java/awt/ColorClass/ColorSerializationTest.java b/test/jdk/java/awt/ColorClass/ColorSerializationTest.java new file mode 100644 index 00000000000..b0e661b3cfb --- /dev/null +++ b/test/jdk/java/awt/ColorClass/ColorSerializationTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2006, 2023, 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 4330102 + @summary Tests that Color object is serializable + @run main ColorSerializationTest +*/ + +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.image.IndexColorModel; +import java.io.ObjectOutputStream; +import java.io.ByteArrayOutputStream; + +public class ColorSerializationTest { + + public static void main(String[] args) { + java.awt.Color cobj = new java.awt.Color(255, 255, 255); + try { + cobj.createContext( + new IndexColorModel( + 8, 1, + new byte[]{0}, new byte[]{0}, new byte[]{0}), + new Rectangle(1, 1, 2, 3), + new Rectangle(3, 3), + new AffineTransform(), + new RenderingHints(null)); + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + ObjectOutputStream objos = new ObjectOutputStream(ostream); + objos.writeObject(cobj); + objos.close(); + System.out.println("Test PASSED"); + } catch (java.io.IOException e) { + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED: Color is not serializable: " + e.getMessage()); + } + + } +}