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 4658741 27 @summary verifies that getDropSuccess() returns correct value for inter-JVM DnD 28 @author das@sparc.spb.su area=dnd 29 @run applet InterJVMGetDropSuccessTest.html 30 */ 31 32 // Note there is no @ in front of test above. This is so that the 33 // harness will not mistake this file as a test file. It should 34 // only see the html file as a test file. (the harness runs all 35 // valid test files, so it would run this test twice if this file 36 // were valid as well as the html file.) 37 // Also, note the area= after Your Name in the author tag. Here, you 38 // should put which functional area the test falls in. See the 39 // AWT-core home page -> test areas and/or -> AWT team for a list of 40 // areas. 41 // Note also the 'InterJVMGetDropSuccessTest.html' in the run tag. This should 42 // be changed to the name of the test. 43 44 45 /** 46 * InterJVMGetDropSuccessTest.java 47 * 48 * summary: verifies that getDropSuccess() returns correct value for inter-JVM DnD 49 */ 50 51 import java.applet.Applet; 52 import java.awt.*; 53 import java.awt.datatransfer.*; 54 import java.awt.dnd.*; 55 import java.awt.event.*; 56 import java.io.*; 57 import javax.swing.*; 58 59 60 //Automated tests should run as applet tests if possible because they 61 // get their environments cleaned up, including AWT threads, any 62 // test created threads, and any system resources used by the test 63 // such as file descriptors. (This is normally not a problem as 64 // main tests usually run in a separate VM, however on some platforms 65 // such as the Mac, separate VMs are not possible and non-applet 66 // tests will cause problems). Also, you don't have to worry about 67 // synchronisation stuff in Applet tests they way you do in main 68 // tests... 69 70 71 public class InterJVMGetDropSuccessTest extends Applet { 72 73 private int returnCode = Util.CODE_NOT_RETURNED; 74 private boolean successCodes[] = { true, false }; 75 private int dropCount = 0; 76 77 final Frame frame = new Frame("Target Frame"); 78 79 final DropTargetListener dropTargetListener = new DropTargetAdapter() { 80 public void drop(DropTargetDropEvent dtde) { 81 dtde.acceptDrop(DnDConstants.ACTION_COPY); 82 dtde.dropComplete(successCodes[dropCount]); 83 dropCount++; 84 } 85 }; 86 final DropTarget dropTarget = new DropTarget(frame, dropTargetListener); 87 88 public void init() { 89 //Create instructions for the user here, as well as set up 90 // the environment -- set the layout manager, add buttons, 91 // etc. 92 93 String[] instructions = 94 { 95 "This is an AUTOMATIC test", 96 "simply wait until it is done" 97 }; 98 Sysout.createDialog( ); 99 Sysout.printInstructions( instructions ); 100 101 frame.setTitle("Test frame"); 102 frame.setBounds(100, 100, 150, 150); 103 } // init() 104 105 public void start() { 106 107 frame.setVisible(true); 108 109 try { 110 Thread.sleep(Util.FRAME_ACTIVATION_TIMEOUT); 111 112 Point p = frame.getLocationOnScreen(); 113 Dimension d = frame.getSize(); 114 115 String javaPath = System.getProperty("java.home", ""); 116 String command = javaPath + File.separator + "bin" + 117 File.separator + "java -cp " + System.getProperty("test.classes", ".") + 118 " Child " + 119 p.x + " " + p.y + " " + d.width + " " + d.height; 120 121 Process process = Runtime.getRuntime().exec(command); 122 returnCode = process.waitFor(); 123 124 InputStream errorStream = process.getErrorStream(); 125 int count = errorStream.available(); 126 if (count > 0) { 127 byte[] b = new byte[count]; 128 errorStream.read(b); 129 System.err.println("========= Child VM System.err ========"); 130 System.err.print(new String(b)); 131 System.err.println("======================================"); 132 } 133 134 InputStream outputStream = process.getInputStream(); 135 count = outputStream.available(); 136 if (count > 0) { 137 byte[] b = new byte[count]; 138 outputStream.read(b); 139 System.err.println("========= Child VM System.out ========"); 140 System.err.print(new String(b)); 141 System.err.println("======================================"); 142 } 143 } catch (Throwable e) { 144 e.printStackTrace(); 145 throw new RuntimeException(e); 146 } 147 switch (returnCode) { 148 case Util.CODE_NOT_RETURNED: 149 throw new RuntimeException("Child VM: failed to start"); 150 case Util.CODE_FAILURE: 151 throw new RuntimeException("Child VM: abnormal termination"); 152 default: 153 if (dropCount == 2) { 154 int expectedRetCode = 0; 155 if (successCodes[0]) { 156 expectedRetCode |= Util.CODE_FIRST_SUCCESS; 157 } 158 if (successCodes[1]) { 159 expectedRetCode |= Util.CODE_SECOND_SUCCESS; 160 } 161 if (expectedRetCode != returnCode) { 162 throw new RuntimeException("The test failed. Expected:" + 163 expectedRetCode + ". Returned:" + 164 returnCode); 165 } 166 } 167 break; 168 } 169 } // start() 170 } // class InterJVMGetDropSuccessTest 171 172 final class Util implements AWTEventListener { 173 public static final int CODE_NOT_RETURNED = -1; 174 public static final int CODE_FIRST_SUCCESS = 0x2; 175 public static final int CODE_SECOND_SUCCESS = 0x2; 176 public static final int CODE_FAILURE = 0x1; 177 178 public static final int FRAME_ACTIVATION_TIMEOUT = 3000; 179 180 static final Object SYNC_LOCK = new Object(); 181 static final int MOUSE_RELEASE_TIMEOUT = 1000; 182 183 static final Util theInstance = new Util(); 184 185 static { 186 Toolkit.getDefaultToolkit().addAWTEventListener(theInstance, AWTEvent.MOUSE_EVENT_MASK); 187 } 188 189 public static Point getCenterLocationOnScreen(Component c) { 190 Point p = c.getLocationOnScreen(); 191 Dimension d = c.getSize(); 192 p.translate(d.width / 2, d.height / 2); 193 return p; 194 } 195 196 public static int sign(int n) { 197 return n < 0 ? -1 : n == 0 ? 0 : 1; 198 } 199 200 private Component clickedComponent = null; 201 202 private void reset() { 203 clickedComponent = null; 204 } 205 206 public void eventDispatched(AWTEvent e) { 207 if (e.getID() == MouseEvent.MOUSE_RELEASED) { 208 clickedComponent = (Component)e.getSource(); 209 synchronized (SYNC_LOCK) { 210 SYNC_LOCK.notifyAll(); 211 } 212 } 213 } 214 215 public static boolean pointInComponent(Robot robot, Point p, Component comp) 216 throws InterruptedException { 217 return theInstance.pointInComponentImpl(robot, p, comp); 218 } 219 220 private boolean pointInComponentImpl(Robot robot, Point p, Component comp) 221 throws InterruptedException { 222 robot.waitForIdle(); 223 reset(); 224 robot.mouseMove(p.x, p.y); 225 robot.mousePress(InputEvent.BUTTON1_MASK); 226 synchronized (SYNC_LOCK) { 227 robot.mouseRelease(InputEvent.BUTTON1_MASK); 228 SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); 229 } 230 231 Component c = clickedComponent; 232 233 while (c != null && c != comp) { 234 c = c.getParent(); 235 } 236 237 return c == comp; 238 } 239 } 240 241 class Child { 242 static class DragSourceDropListener extends DragSourceAdapter { 243 private boolean finished = false; 244 private boolean dropSuccess = false; 245 246 public void reset() { 247 finished = false; 248 dropSuccess = false; 249 } 250 251 public boolean isDropFinished() { 252 return finished; 253 } 254 255 public boolean getDropSuccess() { 256 return dropSuccess; 257 } 258 259 public void dragDropEnd(DragSourceDropEvent dsde) { 260 finished = true; 261 dropSuccess = dsde.getDropSuccess(); 262 synchronized (Util.SYNC_LOCK) { 263 Util.SYNC_LOCK.notifyAll(); 264 } 265 } 266 } 267 268 final Frame frame = new Frame("Source Frame"); 269 final DragSource dragSource = DragSource.getDefaultDragSource(); 270 final DragSourceDropListener dragSourceListener = new DragSourceDropListener(); 271 final Transferable transferable = new StringSelection("TEXT"); 272 final DragGestureListener dragGestureListener = new DragGestureListener() { 273 public void dragGestureRecognized(DragGestureEvent dge) { 274 dge.startDrag(null, transferable, dragSourceListener); 275 } 276 }; 277 final DragGestureRecognizer dragGestureRecognizer = 278 dragSource.createDefaultDragGestureRecognizer(frame, DnDConstants.ACTION_COPY, 279 dragGestureListener); 280 281 public static void main(String[] args) { 282 Child child = new Child(); 283 child.run(args); 284 } 285 286 public void run(String[] args) { 287 try { 288 if (args.length != 4) { 289 throw new RuntimeException("Incorrect command line arguments."); 290 } 291 292 int x = Integer.parseInt(args[0]); 293 int y = Integer.parseInt(args[1]); 294 int w = Integer.parseInt(args[2]); 295 int h = Integer.parseInt(args[3]); 296 297 frame.setBounds(300, 200, 150, 150); 298 frame.setVisible(true); 299 300 Thread.sleep(Util.FRAME_ACTIVATION_TIMEOUT); 301 302 Point sourcePoint = Util.getCenterLocationOnScreen(frame); 303 304 Point targetPoint = new Point(x + w / 2, y + h / 2); 305 306 Robot robot = new Robot(); 307 robot.mouseMove(sourcePoint.x, sourcePoint.y); 308 robot.mousePress(InputEvent.BUTTON1_MASK); 309 for (Point p = new Point(sourcePoint); !p.equals(targetPoint); 310 p.translate(Util.sign(targetPoint.x - p.x), 311 Util.sign(targetPoint.y - p.y))) { 312 robot.mouseMove(p.x, p.y); 313 Thread.sleep(50); 314 } 315 316 synchronized (Util.SYNC_LOCK) { 317 robot.mouseRelease(InputEvent.BUTTON1_MASK); 318 Util.SYNC_LOCK.wait(Util.FRAME_ACTIVATION_TIMEOUT); 319 } 320 321 if (!dragSourceListener.isDropFinished()) { 322 throw new RuntimeException("Drop not finished"); 323 } 324 325 boolean success1 = dragSourceListener.getDropSuccess(); 326 327 dragSourceListener.reset(); 328 robot.mouseMove(sourcePoint.x, sourcePoint.y); 329 robot.mousePress(InputEvent.BUTTON1_MASK); 330 for (Point p = new Point(sourcePoint); !p.equals(targetPoint); 331 p.translate(Util.sign(targetPoint.x - p.x), 332 Util.sign(targetPoint.y - p.y))) { 333 robot.mouseMove(p.x, p.y); 334 Thread.sleep(50); 335 } 336 337 synchronized (Util.SYNC_LOCK) { 338 robot.mouseRelease(InputEvent.BUTTON1_MASK); 339 Util.SYNC_LOCK.wait(Util.FRAME_ACTIVATION_TIMEOUT); 340 } 341 342 if (!dragSourceListener.isDropFinished()) { 343 throw new RuntimeException("Drop not finished"); 344 } 345 346 boolean success2 = dragSourceListener.getDropSuccess(); 347 int retCode = 0; 348 349 if (success1) { 350 retCode |= Util.CODE_FIRST_SUCCESS; 351 } 352 if (success2) { 353 retCode |= Util.CODE_SECOND_SUCCESS; 354 } 355 // This returns the diagnostic code from the child VM 356 System.exit(retCode); 357 } catch (Throwable e) { 358 e.printStackTrace(); 359 // This returns the diagnostic code from the child VM 360 System.exit(Util.CODE_FAILURE); 361 } 362 } // run() 363 } // class child 364 365 /**************************************************** 366 Standard Test Machinery 367 DO NOT modify anything below -- it's a standard 368 chunk of code whose purpose is to make user 369 interaction uniform, and thereby make it simpler 370 to read and understand someone else's test. 371 ****************************************************/ 372 373 /** 374 This is part of the standard test machinery. 375 It creates a dialog (with the instructions), and is the interface 376 for sending text messages to the user. 377 To print the instructions, send an array of strings to Sysout.createDialog 378 WithInstructions method. Put one line of instructions per array entry. 379 To display a message for the tester to see, simply call Sysout.println 380 with the string to be displayed. 381 This mimics System.out.println but works within the test harness as well 382 as standalone. 383 */ 384 385 class Sysout 386 { 387 private static TestDialog dialog; 388 389 public static void createDialogWithInstructions( String[] instructions ) 390 { 391 dialog = new TestDialog( new Frame(), "Instructions" ); 392 dialog.printInstructions( instructions ); 393 dialog.show(); 394 println( "Any messages for the tester will display here." ); 395 } 396 397 public static void createDialog( ) 398 { 399 dialog = new TestDialog( new Frame(), "Instructions" ); 400 String[] defInstr = { "Instructions will appear here. ", "" } ; 401 dialog.printInstructions( defInstr ); 402 dialog.show(); 403 println( "Any messages for the tester will display here." ); 404 } 405 406 407 public static void printInstructions( String[] instructions ) 408 { 409 dialog.printInstructions( instructions ); 410 } 411 412 413 public static void println( String messageIn ) 414 { 415 dialog.displayMessage( messageIn ); 416 } 417 418 }// Sysout class 419 420 /** 421 This is part of the standard test machinery. It provides a place for the 422 test instructions to be displayed, and a place for interactive messages 423 to the user to be displayed. 424 To have the test instructions displayed, see Sysout. 425 To have a message to the user be displayed, see Sysout. 426 Do not call anything in this dialog directly. 427 */ 428 class TestDialog extends Dialog 429 { 430 431 TextArea instructionsText; 432 TextArea messageText; 433 int maxStringLength = 80; 434 435 //DO NOT call this directly, go through Sysout 436 public TestDialog( Frame frame, String name ) 437 { 438 super( frame, name ); 439 int scrollBoth = TextArea.SCROLLBARS_BOTH; 440 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 441 add( "North", instructionsText ); 442 443 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 444 add("South", messageText); 445 446 pack(); 447 448 show(); 449 }// TestDialog() 450 451 //DO NOT call this directly, go through Sysout 452 public void printInstructions( String[] instructions ) 453 { 454 //Clear out any current instructions 455 instructionsText.setText( "" ); 456 457 //Go down array of instruction strings 458 459 String printStr, remainingStr; 460 for( int i=0; i < instructions.length; i++ ) 461 { 462 //chop up each into pieces maxSringLength long 463 remainingStr = instructions[ i ]; 464 while( remainingStr.length() > 0 ) 465 { 466 //if longer than max then chop off first max chars to print 467 if( remainingStr.length() >= maxStringLength ) 468 { 469 //Try to chop on a word boundary 470 int posOfSpace = remainingStr. 471 lastIndexOf( ' ', maxStringLength - 1 ); 472 473 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 474 475 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 476 remainingStr = remainingStr.substring( posOfSpace + 1 ); 477 } 478 //else just print 479 else 480 { 481 printStr = remainingStr; 482 remainingStr = ""; 483 } 484 485 instructionsText.append( printStr + "\n" ); 486 487 }// while 488 489 }// for 490 491 }//printInstructions() 492 493 //DO NOT call this directly, go through Sysout 494 public void displayMessage( String messageIn ) 495 { 496 messageText.append( messageIn + "\n" ); 497 } 498 499 }// TestDialog class