1 /* 2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 test 26 @bug 4870762 27 @summary tests that a drop target JVM doesn't crash if the source doesn't export 28 data in native formats. 29 @author das@sparc.spb.su area=dnd 30 @compile NoFormatsCrashTest.java 31 @run applet NoFormatsCrashTest.html 32 */ 33 34 // Note there is no @ in front of test above. This is so that the 35 // harness will not mistake this file as a test file. It should 36 // only see the html file as a test file. (the harness runs all 37 // valid test files, so it would run this test twice if this file 38 // were valid as well as the html file.) 39 // Also, note the area= after Your Name in the author tag. Here, you 40 // should put which functional area the test falls in. See the 41 // AWT-core home page -> test areas and/or -> AWT team for a list of 42 // areas. 43 // Note also the 'NoFormatsCrashTest.html' in the run tag. This should 44 // be changed to the name of the test. 45 46 47 /** 48 * NoFormatsCrashTest.java 49 * 50 * summary: tests that a drop target JVM doesn't crash if the source doesn't export 51 * data in native formats. 52 */ 53 54 import java.applet.Applet; 55 import java.awt.*; 56 import java.awt.datatransfer.*; 57 import java.awt.dnd.*; 58 import java.awt.event.*; 59 import java.io.*; 60 61 62 //Automated tests should run as applet tests if possible because they 63 // get their environments cleaned up, including AWT threads, any 64 // test created threads, and any system resources used by the test 65 // such as file descriptors. (This is normally not a problem as 66 // main tests usually run in a separate VM, however on some platforms 67 // such as the Mac, separate VMs are not possible and non-applet 68 // tests will cause problems). Also, you don't have to worry about 69 // synchronisation stuff in Applet tests they way you do in main 70 // tests... 71 72 73 public class NoFormatsCrashTest extends Applet { 74 75 final Frame frame = new Frame(); 76 private volatile Process process; 77 78 static final int FRAME_ACTIVATION_TIMEOUT = 2000; 79 80 public static void main(String[] args) { 81 NoFormatsCrashTest test = new NoFormatsCrashTest(); 82 test.run(args); 83 } 84 85 public void run(String[] args) { 86 try { 87 if (args.length != 4) { 88 throw new RuntimeException("Incorrect command line arguments."); 89 } 90 91 int x = Integer.parseInt(args[0]); 92 int y = Integer.parseInt(args[1]); 93 int w = Integer.parseInt(args[2]); 94 int h = Integer.parseInt(args[3]); 95 96 Panel panel = new DragSourcePanel(); 97 98 frame.setTitle("Drag source frame"); 99 frame.setLocation(500, 200); 100 frame.add(panel); 101 frame.pack(); 102 frame.setVisible(true); 103 104 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 105 106 Point sourcePoint = panel.getLocationOnScreen(); 107 Dimension d = panel.getSize(); 108 sourcePoint.translate(d.width / 2, d.height / 2); 109 110 Point targetPoint = new Point(x + w / 2, y + h / 2); 111 112 Robot robot = new Robot(); 113 robot.mouseMove(sourcePoint.x, sourcePoint.y); 114 robot.keyPress(KeyEvent.VK_CONTROL); 115 robot.mousePress(InputEvent.BUTTON1_MASK); 116 for (; !sourcePoint.equals(targetPoint); 117 sourcePoint.translate(sign(targetPoint.x - sourcePoint.x), 118 sign(targetPoint.y - sourcePoint.y))) { 119 robot.mouseMove(sourcePoint.x, sourcePoint.y); 120 Thread.sleep(50); 121 } 122 robot.mouseRelease(InputEvent.BUTTON1_MASK); 123 robot.keyRelease(KeyEvent.VK_CONTROL); 124 125 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 126 127 if (process.isAlive()) { 128 process.destroy(); 129 } 130 } catch (Throwable e) { 131 e.printStackTrace(); 132 throw new RuntimeException(e); 133 } 134 } // run() 135 136 public void init() { 137 frame.setTitle("Drop target frame"); 138 frame.setLocation(200, 200); 139 140 } // init() 141 142 public void start() { 143 DropTargetPanel panel = new DropTargetPanel(); 144 frame.add(panel); 145 frame.pack(); 146 frame.setVisible(true); 147 148 try { 149 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 150 151 Point p = frame.getLocationOnScreen(); 152 Dimension d = frame.getSize(); 153 154 String javaPath = System.getProperty("java.home", ""); 155 String command = javaPath + File.separator + "bin" + 156 File.separator + "java -cp " + System.getProperty("test.classes", ".") + 157 " NoFormatsCrashTest " + 158 p.x + " " + p.y + " " + d.width + " " + d.height; 159 160 process = Runtime.getRuntime().exec(command); 161 ProcessResults pres = ProcessResults.doWaitFor(process); 162 System.err.println("Child VM return code: " + pres.exitValue); 163 164 if (pres.stderr != null && pres.stderr.length() > 0) { 165 System.err.println("========= Child VM System.err ========"); 166 System.err.print(pres.stderr); 167 System.err.println("======================================"); 168 } 169 170 if (pres.stdout != null && pres.stdout.length() > 0) { 171 System.err.println("========= Child VM System.out ========"); 172 System.err.print(pres.stdout); 173 System.err.println("======================================"); 174 } 175 176 } catch (Throwable e) { 177 e.printStackTrace(); 178 throw new RuntimeException(e); 179 } 180 181 if (panel.isTestFailed()) { 182 throw new RuntimeException(); 183 } 184 } // start() 185 186 public static int sign(int n) { 187 return n < 0 ? -1 : n > 0 ? 1 : 0; 188 } 189 } // class NoFormatsCrashTest 190 191 class TestTransferable implements Transferable { 192 193 public static DataFlavor dataFlavor = null; 194 static final Object data = new Object(); 195 196 static { 197 DataFlavor df = null; 198 try { 199 df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + 200 "; class=java.lang.Object"); 201 } catch (ClassNotFoundException e) { 202 throw new ExceptionInInitializerError(e); 203 } 204 dataFlavor = df; 205 } 206 207 public DataFlavor[] getTransferDataFlavors() { 208 return new DataFlavor[] { dataFlavor }; 209 } 210 211 public boolean isDataFlavorSupported(DataFlavor df) { 212 return dataFlavor.equals(df); 213 } 214 215 public Object getTransferData(DataFlavor df) 216 throws UnsupportedFlavorException, IOException { 217 if (!isDataFlavorSupported(df)) { 218 throw new UnsupportedFlavorException(df); 219 } 220 return data; 221 } 222 } 223 224 class DragSourcePanel extends Panel { 225 public DragSourcePanel() { 226 final Transferable t = new TestTransferable(); 227 final DragSourceListener dsl = new DragSourceAdapter() { 228 public void dragDropEnd(DragSourceDropEvent dtde) { 229 try { 230 Thread.sleep(100); 231 } catch (InterruptedException e) { 232 e.printStackTrace(); 233 } 234 // This finishes child VM 235 System.exit(0); 236 } 237 }; 238 final DragGestureListener dgl = new DragGestureListener() { 239 public void dragGestureRecognized(DragGestureEvent dge) { 240 dge.startDrag(null, t, dsl); 241 } 242 }; 243 final DragSource ds = DragSource.getDefaultDragSource(); 244 final DragGestureRecognizer dgr = 245 ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, 246 dgl); 247 } 248 249 public Dimension getPreferredSize() { 250 return new Dimension(100, 100); 251 } 252 } 253 254 class DropTargetPanel extends Panel { 255 private boolean testFailed = false; 256 public DropTargetPanel() { 257 final DropTargetListener dtl = new DropTargetAdapter() { 258 public void dragOver(DropTargetDragEvent dtde) { 259 try { 260 dtde.getCurrentDataFlavorsAsList(); 261 } catch (Exception e) { 262 testFailed = true; 263 e.printStackTrace(); 264 } 265 } 266 public void drop(DropTargetDropEvent dtde) { 267 dtde.rejectDrop(); 268 } 269 }; 270 final DropTarget dt = new DropTarget(this, dtl); 271 } 272 273 public boolean isTestFailed() { 274 return testFailed; 275 } 276 277 public Dimension getPreferredSize() { 278 return new Dimension(100, 100); 279 } 280 } 281 282 class ProcessResults { 283 public int exitValue; 284 public String stdout; 285 public String stderr; 286 287 public ProcessResults() { 288 exitValue = -1; 289 stdout = ""; 290 stderr = ""; 291 } 292 293 /** 294 * Method to perform a "wait" for a process and return its exit value. 295 * This is a workaround for <code>Process.waitFor()</code> never returning. 296 */ 297 public static ProcessResults doWaitFor(Process p) { 298 ProcessResults pres = new ProcessResults(); 299 300 InputStream in = null; 301 InputStream err = null; 302 303 try { 304 in = p.getInputStream(); 305 err = p.getErrorStream(); 306 307 boolean finished = false; 308 309 while (!finished) { 310 try { 311 while (in.available() > 0) { 312 pres.stdout += (char)in.read(); 313 } 314 while (err.available() > 0) { 315 pres.stderr += (char)err.read(); 316 } 317 // Ask the process for its exitValue. If the process 318 // is not finished, an IllegalThreadStateException 319 // is thrown. If it is finished, we fall through and 320 // the variable finished is set to true. 321 pres.exitValue = p.exitValue(); 322 finished = true; 323 } 324 catch (IllegalThreadStateException e) { 325 // Process is not finished yet; 326 // Sleep a little to save on CPU cycles 327 Thread.currentThread().sleep(500); 328 } 329 } 330 if (in != null) in.close(); 331 if (err != null) err.close(); 332 } 333 catch (Throwable e) { 334 System.err.println("doWaitFor(): unexpected exception"); 335 e.printStackTrace(); 336 throw new RuntimeException(e); 337 } 338 return pres; 339 } 340 }