1/* 2 * Copyright (c) 2014, 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 54import java.applet.Applet; 55import java.awt.*; 56import java.awt.datatransfer.*; 57import java.awt.dnd.*; 58import java.awt.event.*; 59import 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 73public 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 //Create instructions for the user here, as well as set up 138 // the environment -- set the layout manager, add buttons, 139 // etc. 140 141 String[] instructions = 142 { 143 "This is an AUTOMATIC test", 144 "simply wait until it is done" 145 }; 146 Sysout.createDialog( ); 147 Sysout.printInstructions( instructions ); 148 149 frame.setTitle("Drop target frame"); 150 frame.setLocation(200, 200); 151 152 } // init() 153 154 public void start() { 155 DropTargetPanel panel = new DropTargetPanel(); 156 frame.add(panel); 157 frame.pack(); 158 frame.setVisible(true); 159 160 try { 161 Thread.sleep(FRAME_ACTIVATION_TIMEOUT); 162 163 Point p = frame.getLocationOnScreen(); 164 Dimension d = frame.getSize(); 165 166 String javaPath = System.getProperty("java.home", ""); 167 String command = javaPath + File.separator + "bin" + 168 File.separator + "java -cp " + System.getProperty("test.classes", ".") + 169 " NoFormatsCrashTest " + 170 p.x + " " + p.y + " " + d.width + " " + d.height; 171 172 process = Runtime.getRuntime().exec(command); 173 ProcessResults pres = ProcessResults.doWaitFor(process); 174 System.err.println("Child VM return code: " + pres.exitValue); 175 176 if (pres.stderr != null && pres.stderr.length() > 0) { 177 System.err.println("========= Child VM System.err ========"); 178 System.err.print(pres.stderr); 179 System.err.println("======================================"); 180 } 181 182 if (pres.stdout != null && pres.stdout.length() > 0) { 183 System.err.println("========= Child VM System.out ========"); 184 System.err.print(pres.stdout); 185 System.err.println("======================================"); 186 } 187 188 } catch (Throwable e) { 189 e.printStackTrace(); 190 throw new RuntimeException(e); 191 } 192 193 if (panel.isTestFailed()) { 194 throw new RuntimeException(); 195 } 196 } // start() 197 198 public static int sign(int n) { 199 return n < 0 ? -1 : n > 0 ? 1 : 0; 200 } 201} // class NoFormatsCrashTest 202 203class TestTransferable implements Transferable { 204 205 public static DataFlavor dataFlavor = null; 206 static final Object data = new Object(); 207 208 static { 209 DataFlavor df = null; 210 try { 211 df = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + 212 "; class=java.lang.Object"); 213 } catch (ClassNotFoundException e) { 214 throw new ExceptionInInitializerError(e); 215 } 216 dataFlavor = df; 217 } 218 219 public DataFlavor[] getTransferDataFlavors() { 220 return new DataFlavor[] { dataFlavor }; 221 } 222 223 public boolean isDataFlavorSupported(DataFlavor df) { 224 return dataFlavor.equals(df); 225 } 226 227 public Object getTransferData(DataFlavor df) 228 throws UnsupportedFlavorException, IOException { 229 if (!isDataFlavorSupported(df)) { 230 throw new UnsupportedFlavorException(df); 231 } 232 return data; 233 } 234} 235 236class DragSourcePanel extends Panel { 237 public DragSourcePanel() { 238 final Transferable t = new TestTransferable(); 239 final DragSourceListener dsl = new DragSourceAdapter() { 240 public void dragDropEnd(DragSourceDropEvent dtde) { 241 try { 242 Thread.sleep(100); 243 } catch (InterruptedException e) { 244 e.printStackTrace(); 245 } 246 // This finishes child VM 247 System.exit(0); 248 } 249 }; 250 final DragGestureListener dgl = new DragGestureListener() { 251 public void dragGestureRecognized(DragGestureEvent dge) { 252 dge.startDrag(null, t, dsl); 253 } 254 }; 255 final DragSource ds = DragSource.getDefaultDragSource(); 256 final DragGestureRecognizer dgr = 257 ds.createDefaultDragGestureRecognizer(this, DnDConstants.ACTION_COPY, 258 dgl); 259 } 260 261 public Dimension getPreferredSize() { 262 return new Dimension(100, 100); 263 } 264} 265 266class DropTargetPanel extends Panel { 267 private boolean testFailed = false; 268 public DropTargetPanel() { 269 final DropTargetListener dtl = new DropTargetAdapter() { 270 public void dragOver(DropTargetDragEvent dtde) { 271 try { 272 dtde.getCurrentDataFlavorsAsList(); 273 } catch (Exception e) { 274 testFailed = true; 275 e.printStackTrace(); 276 } 277 } 278 public void drop(DropTargetDropEvent dtde) { 279 dtde.rejectDrop(); 280 } 281 }; 282 final DropTarget dt = new DropTarget(this, dtl); 283 } 284 285 public boolean isTestFailed() { 286 return testFailed; 287 } 288 289 public Dimension getPreferredSize() { 290 return new Dimension(100, 100); 291 } 292} 293 294class ProcessResults { 295 public int exitValue; 296 public String stdout; 297 public String stderr; 298 299 public ProcessResults() { 300 exitValue = -1; 301 stdout = ""; 302 stderr = ""; 303 } 304 305 /** 306 * Method to perform a "wait" for a process and return its exit value. 307 * This is a workaround for <code>Process.waitFor()</code> never returning. 308 */ 309 public static ProcessResults doWaitFor(Process p) { 310 ProcessResults pres = new ProcessResults(); 311 312 InputStream in = null; 313 InputStream err = null; 314 315 try { 316 in = p.getInputStream(); 317 err = p.getErrorStream(); 318 319 boolean finished = false; 320 321 while (!finished) { 322 try { 323 while (in.available() > 0) { 324 pres.stdout += (char)in.read(); 325 } 326 while (err.available() > 0) { 327 pres.stderr += (char)err.read(); 328 } 329 // Ask the process for its exitValue. If the process 330 // is not finished, an IllegalThreadStateException 331 // is thrown. If it is finished, we fall through and 332 // the variable finished is set to true. 333 pres.exitValue = p.exitValue(); 334 finished = true; 335 } 336 catch (IllegalThreadStateException e) { 337 // Process is not finished yet; 338 // Sleep a little to save on CPU cycles 339 Thread.currentThread().sleep(500); 340 } 341 } 342 if (in != null) in.close(); 343 if (err != null) err.close(); 344 } 345 catch (Throwable e) { 346 System.err.println("doWaitFor(): unexpected exception"); 347 e.printStackTrace(); 348 throw new RuntimeException(e); 349 } 350 return pres; 351 } 352} 353 354/**************************************************** 355 Standard Test Machinery 356 DO NOT modify anything below -- it's a standard 357 chunk of code whose purpose is to make user 358 interaction uniform, and thereby make it simpler 359 to read and understand someone else's test. 360 ****************************************************/ 361 362/** 363 This is part of the standard test machinery. 364 It creates a dialog (with the instructions), and is the interface 365 for sending text messages to the user. 366 To print the instructions, send an array of strings to Sysout.createDialog 367 WithInstructions method. Put one line of instructions per array entry. 368 To display a message for the tester to see, simply call Sysout.println 369 with the string to be displayed. 370 This mimics System.out.println but works within the test harness as well 371 as standalone. 372 */ 373 374class Sysout 375 { 376 private static TestDialog dialog; 377 378 public static void createDialogWithInstructions( String[] instructions ) 379 { 380 dialog = new TestDialog( new Frame(), "Instructions" ); 381 dialog.printInstructions( instructions ); 382 dialog.show(); 383 println( "Any messages for the tester will display here." ); 384 } 385 386 public static void createDialog( ) 387 { 388 dialog = new TestDialog( new Frame(), "Instructions" ); 389 String[] defInstr = { "Instructions will appear here. ", "" } ; 390 dialog.printInstructions( defInstr ); 391 dialog.show(); 392 println( "Any messages for the tester will display here." ); 393 } 394 395 396 public static void printInstructions( String[] instructions ) 397 { 398 dialog.printInstructions( instructions ); 399 } 400 401 402 public static void println( String messageIn ) 403 { 404 dialog.displayMessage( messageIn ); 405 } 406 407 }// Sysout class 408 409/** 410 This is part of the standard test machinery. It provides a place for the 411 test instructions to be displayed, and a place for interactive messages 412 to the user to be displayed. 413 To have the test instructions displayed, see Sysout. 414 To have a message to the user be displayed, see Sysout. 415 Do not call anything in this dialog directly. 416 */ 417class TestDialog extends Dialog 418 { 419 420 TextArea instructionsText; 421 TextArea messageText; 422 int maxStringLength = 80; 423 424 //DO NOT call this directly, go through Sysout 425 public TestDialog( Frame frame, String name ) 426 { 427 super( frame, name ); 428 int scrollBoth = TextArea.SCROLLBARS_BOTH; 429 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 430 add( "North", instructionsText ); 431 432 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 433 add("South", messageText); 434 435 pack(); 436 437 show(); 438 }// TestDialog() 439 440 //DO NOT call this directly, go through Sysout 441 public void printInstructions( String[] instructions ) 442 { 443 //Clear out any current instructions 444 instructionsText.setText( "" ); 445 446 //Go down array of instruction strings 447 448 String printStr, remainingStr; 449 for( int i=0; i < instructions.length; i++ ) 450 { 451 //chop up each into pieces maxSringLength long 452 remainingStr = instructions[ i ]; 453 while( remainingStr.length() > 0 ) 454 { 455 //if longer than max then chop off first max chars to print 456 if( remainingStr.length() >= maxStringLength ) 457 { 458 //Try to chop on a word boundary 459 int posOfSpace = remainingStr. 460 lastIndexOf( ' ', maxStringLength - 1 ); 461 462 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 463 464 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 465 remainingStr = remainingStr.substring( posOfSpace + 1 ); 466 } 467 //else just print 468 else 469 { 470 printStr = remainingStr; 471 remainingStr = ""; 472 } 473 474 instructionsText.append( printStr + "\n" ); 475 476 }// while 477 478 }// for 479 480 }//printInstructions() 481 482 //DO NOT call this directly, go through Sysout 483 public void displayMessage( String messageIn ) 484 { 485 messageText.append( messageIn + "\n" ); 486 } 487 488 }// TestDialog class 489