1 /* 2 * Copyright (c) 2007, 2017, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package org.jemmy.input; 26 27 28 import java.awt.AWTException; 29 import java.awt.BorderLayout; 30 import java.awt.Button; 31 import java.awt.EventQueue; 32 import java.awt.Frame; 33 import java.awt.Robot; 34 import java.awt.event.InputEvent; 35 import java.awt.event.KeyAdapter; 36 import java.awt.event.KeyEvent; 37 import java.awt.event.MouseAdapter; 38 import java.awt.event.MouseEvent; 39 import java.io.File; 40 import java.lang.reflect.InvocationTargetException; 41 import java.util.HashMap; 42 import java.util.HashSet; 43 import java.util.Queue; 44 import java.util.Random; 45 import java.util.concurrent.ConcurrentLinkedQueue; 46 import org.jemmy.Point; 47 import org.jemmy.control.Wrap; 48 import org.jemmy.env.Environment; 49 import org.jemmy.env.Timeout; 50 import org.jemmy.image.AWTImage; 51 import org.jemmy.interfaces.Keyboard.KeyboardButton; 52 import org.jemmy.interfaces.Modifier; 53 import org.jemmy.interfaces.Mouse.MouseButton; 54 import org.jemmy.interfaces.Mouse.MouseButtons; 55 import org.jemmy.timing.State; 56 import org.jemmy.timing.Waiter; 57 import org.testng.annotations.AfterClass; 58 import org.testng.annotations.AfterMethod; 59 import org.testng.annotations.BeforeClass; 60 import org.testng.annotations.BeforeMethod; 61 import org.testng.annotations.Test; 62 63 64 /** 65 * 66 * @author Alexander Kouznetsov <mrkam@mail.ru> 67 */ 68 public class RobotDriver2Test { 69 70 final static Timeout TIMEOUT = new Timeout("Wait for state to be reached", 10000); 71 final static Timeout DELTA_TIMEOUT = new Timeout("Delta timeout of wait for state to be reached", 1000); 72 73 public RobotDriver2Test() { 74 } 75 76 @BeforeClass 77 public static void setUpClass() throws Exception { 78 File workdir = new File(System.getProperty("user.dir") + File.separator + 79 "build" + File.separator + 80 "test" + File.separator + 81 "results"); 82 workdir.mkdirs(); 83 AWTImage.setImageRoot(workdir); 84 } 85 86 @AfterClass 87 public static void tearDownClass() throws Exception { 88 RobotDriver.exit(); 89 } 90 91 Frame frm; 92 Button btn; 93 Wrap<Object> area; 94 RobotDriver instance; 95 Robot rb; 96 Queue<InputEvent> queue = new ConcurrentLinkedQueue<InputEvent>(); 97 static Random r = new Random(); 98 99 @BeforeMethod 100 public void setUp() throws InterruptedException, AWTException, InvocationTargetException { 101 EventQueue.invokeAndWait(new Runnable() { 102 103 public void run() { 104 frm = new Frame("some frame"); 105 frm.setSize(100, 100); 106 frm.setLocation(100, 100); 107 btn = new Button("some button"); 108 MouseAdapter m = new MouseAdapter() { 109 110 @Override 111 public void mousePressed(MouseEvent e) { 112 System.out.println("mousePressed event triggered: " + e); 113 System.out.flush(); 114 queue.add(e); 115 } 116 117 @Override 118 public void mouseReleased(MouseEvent e) { 119 System.out.println("mouseReleased event triggered: " + e); 120 System.out.flush(); 121 queue.add(e); 122 } 123 124 @Override 125 public void mouseMoved(MouseEvent e) { 126 System.out.println("mouseMoved event triggered: " + e); 127 System.out.flush(); 128 queue.add(e); 129 } 130 131 @Override 132 public void mouseClicked(MouseEvent e) { 133 System.out.println("mouseClicked event triggered: " + e); 134 System.out.flush(); 135 queue.add(e); 136 } 137 138 @Override 139 public void mouseDragged(MouseEvent e) { 140 System.out.println("mouseDragged event triggered: " + e); 141 System.out.flush(); 142 queue.add(e); 143 } 144 145 }; 146 btn.addMouseListener(m); 147 btn.addMouseMotionListener(m); 148 btn.addKeyListener(new KeyAdapter() { 149 150 @Override 151 public void keyPressed(KeyEvent e) { 152 System.out.println("keyPressed event triggered: " + e); 153 System.out.flush(); 154 queue.add(e); 155 } 156 157 @Override 158 public void keyReleased(KeyEvent e) { 159 System.out.println("keyReleased event triggered: " + e); 160 System.out.flush(); 161 queue.add(e); 162 } 163 164 }); 165 frm.add(btn, BorderLayout.SOUTH); 166 frm.doLayout(); 167 instance = new RobotDriver(Environment.getEnvironment()); 168 frm.setVisible(true); 169 btn.requestFocusInWindow(); 170 } 171 }); 172 173 rb = new Robot(); 174 rb.waitForIdle(); 175 176 RobotExecutor.get().setRunInOtherJVM(true); 177 178 } 179 180 @AfterMethod 181 public void tearDown() throws InterruptedException, InvocationTargetException { 182 EventQueue.invokeAndWait(new Runnable() { 183 184 public void run() { 185 frm.setVisible(false); 186 } 187 }); 188 } 189 190 // /** 191 // * Test of createScreenCapture method, of class RobotDriver. 192 // */ 193 // @Test 194 // public void testCreateScreenCaptureLocally() throws AWTException, InterruptedException { 195 // System.out.println("testCreateScreenCaptureLocally"); 196 // Thread.sleep(3000); 197 // Rectangle screenRect = new Rectangle(100, 100, 100, 100); 198 // RobotExecutor.get().setRunInOtherJVM(false); 199 // Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100))); 200 // Image result = RobotDriver.createScreenCapture(screenRect); 201 // Image diff = expResult.compareTo(result); 202 // if (diff != null) { 203 // diff.save("testCreateScreenCaptureLocally.png"); 204 // fail(); 205 // } 206 // } 207 // 208 // /** 209 // * Test of createScreenCapture method, of class RobotDriver. 210 // */ 211 // @Test 212 // public void testCreateScreenCaptureRemotely() throws AWTException, InterruptedException { 213 // System.out.println("testCreateScreenCaptureRemotely"); 214 // Thread.sleep(3000); 215 // Rectangle screenRect = new Rectangle(100, 100, 100, 100); 216 // RobotExecutor.get().setRunInOtherJVM(true); 217 // Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100))); 218 // Image result = RobotDriver.createScreenCapture(screenRect); 219 // RobotDriver.createScreenCapture(screenRect); 220 // Image diff = expResult.compareTo(result); 221 // if (diff != null) { 222 // diff.save("testCreateScreenCaptureRemotely.png"); 223 // fail(); 224 // } 225 // } 226 // 227 // /** 228 // * Test of createScreenCapture method, of class RobotDriver. 229 // */ 230 // @Test 231 // public void testCreateScreenCaptureRemotely2() throws AWTException, InterruptedException { 232 // System.out.println("testCreateScreenCaptureRemotely2"); 233 // Thread.sleep(3000); 234 // Rectangle screenRect = new Rectangle(100, 100, 100, 100); 235 // RobotExecutor.get().setRunInOtherJVM(true); 236 // Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100))); 237 // Image result = RobotDriver.createScreenCapture(screenRect); 238 // Image diff = expResult.compareTo(result); 239 // if (diff != null) { 240 // diff.save("testCreateScreenCaptureRemotely2.png"); 241 // fail(); 242 // } 243 // } 244 245 /** 246 * Test of all RobotDriver methods invoked multiple times 247 * @throws InterruptedException 248 */ 249 // @Test 250 public void testAll() throws InterruptedException { 251 for(int i = 0; i < 10; i++) { 252 testPressMouse(); 253 } 254 } 255 256 public void test() throws InterruptedException { 257 // testPressMouse(); 258 testPressKey(); 259 } 260 261 @Test 262 public void test0() throws InterruptedException { 263 test(); 264 } 265 266 @Test 267 public void test1() throws InterruptedException { 268 test(); 269 } 270 271 @Test 272 public void test2() throws InterruptedException { 273 test(); 274 } 275 276 @Test 277 public void test3() throws InterruptedException { 278 test(); 279 } 280 281 @Test 282 public void test4() throws InterruptedException { 283 test(); 284 } 285 286 @Test 287 public void test5() throws InterruptedException { 288 test(); 289 } 290 291 @Test 292 public void test6() throws InterruptedException { 293 test(); 294 } 295 296 @Test 297 public void test7() throws InterruptedException { 298 test(); 299 } 300 301 @Test 302 public void test8() throws InterruptedException { 303 test(); 304 } 305 306 @Test 307 public void test9() throws InterruptedException { 308 test(); 309 } 310 311 protected static final int[] MODIFIERS = new int[] { 312 InputEvent.SHIFT_DOWN_MASK, 313 InputEvent.CTRL_DOWN_MASK, 314 InputEvent.ALT_DOWN_MASK, 315 InputEvent.SHIFT_MASK, 316 InputEvent.CTRL_MASK, 317 InputEvent.ALT_MASK, 318 // MouseEvent.ALT_GRAPH_DOWN_MASK, 319 // MouseEvent.META_DOWN_MASK 320 }; 321 322 public static int getModifiers() { 323 int modifiersMask = r.nextInt(1 << MODIFIERS.length/2); 324 int m = 0; 325 System.out.print("Modifiers:"); 326 for (int i = 0; i < MODIFIERS.length/2; i++) { 327 if ((modifiersMask & (1 << i)) != 0 ) { 328 m |= MODIFIERS[i]; 329 System.out.print(" " + i); 330 } 331 } 332 System.out.println(""); 333 return m; 334 } 335 336 protected static HashMap<Integer, Integer> normalizeMap = new HashMap<Integer, Integer>(); 337 static { 338 normalizeMap.put(InputEvent.SHIFT_MASK,InputEvent.SHIFT_DOWN_MASK); 339 normalizeMap.put(InputEvent.CTRL_MASK,InputEvent.CTRL_DOWN_MASK); 340 normalizeMap.put(InputEvent.ALT_MASK,InputEvent.ALT_DOWN_MASK); 341 normalizeMap.put(InputEvent.META_MASK,InputEvent.META_DOWN_MASK); 342 } 343 344 protected static HashSet<Integer> normalize(HashSet<Integer> modifiers) { 345 HashSet<Integer> normalized = new HashSet<Integer>(); 346 for (Integer mod : modifiers) { 347 Integer n = normalizeMap.get(mod); 348 if (n != null) { 349 normalized.add(n); 350 } else { 351 normalized.add(mod); 352 } 353 } 354 return normalized; 355 } 356 357 protected static HashSet<Integer> modifiers2Set(int mods) { 358 HashSet<Integer> set = new HashSet<Integer>(); 359 for (int i = 0; i < MODIFIERS.length; i++) { 360 if ((mods & MODIFIERS[i]) > 0) { 361 set.add(MODIFIERS[i]); 362 } 363 } 364 return set; 365 } 366 367 protected static boolean compareModifiers(int m1, int m2) { 368 return normalize(modifiers2Set(m1)).equals(normalize(modifiers2Set(m2))); 369 } 370 /** 371 * Test of pressMouse method, of class RobotDriver. 372 */ 373 public void testPressMouse() throws InterruptedException { 374 System.out.println("pressMouse"); 375 Thread.sleep(3000); 376 final int[] MOUSE_BUTTONS_1 = new int[] { 377 MouseEvent.BUTTON1_MASK, 378 MouseEvent.BUTTON2_MASK, 379 MouseEvent.BUTTON3_MASK 380 }; 381 final int[] MOUSE_BUTTONS_2 = new int[] { 382 MouseEvent.BUTTON1, 383 MouseEvent.BUTTON2, 384 MouseEvent.BUTTON3 385 }; 386 int bIndex = r.nextInt(MOUSE_BUTTONS_1.length); 387 final int mouseButton1 = MOUSE_BUTTONS_1[bIndex]; 388 final int mouseButton2 = MOUSE_BUTTONS_2[bIndex]; 389 System.out.print("Button: " + bIndex + " Modifier:"); 390 final int modifiers = getModifiers(); 391 queue.clear(); 392 java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 393 System.out.println("Pressing mouse"); 394 instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2)); 395 AWTMap map = new AWTMap(); 396 MouseButton button = map.convertMouseButton(mouseButton1); 397 Modifier[] converted_modifiers = map.convertModifiers(modifiers); 398 instance.pressMouse(button, converted_modifiers); 399 instance.releaseMouse(button, converted_modifiers); 400 401 rb.waitForIdle(); 402 new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 403 404 public Boolean reached() { 405 while(true) { 406 InputEvent e = queue.poll(); 407 if (e != null) { 408 if (e instanceof MouseEvent) { 409 MouseEvent me = (MouseEvent) e; 410 if (me.getID() == MouseEvent.MOUSE_PRESSED && me.getButton() == mouseButton2 && (compareModifiers(me.getModifiers(), modifiers))) { 411 return true; 412 } 413 if (me.getID() == MouseEvent.MOUSE_PRESSED) { 414 System.out.println("Wrong combination of button and modifiers triggered:"); 415 System.out.println("me.getModifiers() = " + Integer.toString(me.getModifiers(), 2) + ", modifiers = " + Integer.toString(modifiers, 2)); 416 System.out.println("expected: " + new MouseEvent( 417 me.getComponent(), MouseEvent.MOUSE_PRESSED, 418 me.getWhen(), modifiers, me.getX(), me.getY(), me.getClickCount(), me.isPopupTrigger(), mouseButton2)); 419 System.out.println(" got: " + me); 420 } 421 } 422 } else { 423 break; 424 } 425 } 426 return null; 427 } 428 429 }); 430 431 System.out.println("PASSED"); 432 433 } 434 435 // /** 436 // * Test of releaseMouse method, of class RobotDriver. 437 // */ 438 // @Test 439 // public void testReleaseMouse() throws InterruptedException { 440 // System.out.println("releaseMouse"); 441 // Thread.sleep(3000); 442 // int mouseButton = MouseEvent.BUTTON2_MASK; 443 // int modifiers = MouseEvent.CTRL_DOWN_MASK; 444 // mouseReleased = false; 445 // java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 446 // instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2)); 447 // System.out.println("Pressing mouse"); 448 // instance.pressMouse(mouseButton, modifiers); 449 // System.out.println("Releasing mouse"); 450 // instance.releaseMouse(mouseButton, modifiers); 451 // 452 // rb.waitForIdle(); 453 // new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 454 // 455 // public Boolean reached() { 456 // return mouseReleased ? true: null; 457 // } 458 // 459 // }); 460 // assertTrue(mouseReleased); 461 // } 462 // 463 // /** 464 // * Test of moveMouse method, of class RobotDriver. 465 // */ 466 // @Test 467 // public void testMoveMouse() throws InterruptedException { 468 // System.out.println("moveMouse"); 469 // Thread.sleep(3000); 470 // mouseMoved = false; 471 // java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 472 // System.out.println("Moving mouse"); 473 // Point startPoint = new Point(locationOnScreen.x, locationOnScreen.y); 474 // Point endPoint = new Point(locationOnScreen.x + btn.getWidth(), locationOnScreen.y + btn.getHeight()); 475 // double steps = 5; //Math.max(btn.getWidth(), btn.getHeight()); 476 // double dx = (endPoint.x - startPoint.x) / steps; 477 // double dy = (endPoint.y - startPoint.y) / steps; 478 // for(int i = 0; i < steps; i++) { 479 // Point point = new Point(startPoint.x + dx * i, startPoint.y + dy * i); 480 // instance.moveMouse(point); 481 // Thread.sleep(100); 482 // } 483 // 484 // rb.waitForIdle(); 485 // new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 486 // 487 // public Boolean reached() { 488 // return mouseMoved ? true: null; 489 // } 490 // 491 // }); 492 // assertTrue(mouseMoved); 493 // } 494 // 495 // /** 496 // * Test of clickMouse method, of class RobotDriver. 497 // */ 498 // @Test 499 // public void testClickMouse() throws InterruptedException { 500 // System.out.println("clickMouse"); 501 // Thread.sleep(3000); 502 // mouseClicked = false; 503 // java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 504 // Point point = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2); 505 // int clickCount = 1; 506 // int mouseButton = MouseEvent.BUTTON3_MASK; 507 // int modifiers = InputEvent.ALT_DOWN_MASK; 508 // Timeout mouseClick = new Timeout("mouseClick", 100); 509 // System.out.println("Clicking mouse"); 510 // instance.clickMouse(point, clickCount, mouseButton, modifiers, mouseClick); 511 // 512 // rb.waitForIdle(); 513 // new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 514 // 515 // public Boolean reached() { 516 // return mouseClicked ? true: null; 517 // } 518 // 519 // }); 520 // assertTrue(mouseClicked); 521 // } 522 // 523 // /** 524 // * Test of dragNDrop method, of class RobotDriver. 525 // */ 526 // @Test 527 // public void testDragNDrop() throws InterruptedException { 528 // System.out.println("dragNDrop"); 529 // java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 530 // Point startPoint = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2); 531 // Point endPoint = new Point(frm.getLocationOnScreen().x + frm.getWidth() / 2, frm.getLocationOnScreen().y + frm.getHeight() / 2); 532 // int mouseButton = MouseEvent.BUTTON2_MASK; 533 // int modifiers = 0; 534 // Timeout before = new Timeout("before", 500); 535 // Timeout after = new Timeout("after", 500); 536 // mouseDragged = false; 537 // instance.dragNDrop(startPoint, endPoint, mouseButton, modifiers, before, after); 538 // 539 // rb.waitForIdle(); 540 // new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 541 // 542 // public Boolean reached() { 543 // return mouseDragged ? true: null; 544 // } 545 // 546 // }); 547 // assertTrue(mouseDragged); 548 // } 549 550 /** 551 * Test of pressKey method, of class RobotDriver. 552 */ 553 public void testPressKey() throws InterruptedException { 554 System.out.println("pressKey"); 555 Thread.sleep(3000); 556 557 final int keyCode = KeyEvent.VK_A; 558 final int modifiers = getModifiers(); 559 AWTMap map = new AWTMap(); 560 KeyboardButton button = map.convertKeyboardButton(keyCode); 561 Modifier[] converted_modifiers = map.convertModifiers(modifiers); 562 563 queue.clear(); 564 565 java.awt.Point locationOnScreen = btn.getLocationOnScreen(); 566 instance.clickMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2), 1, 567 MouseButtons.BUTTON1, DELTA_TIMEOUT); 568 569 rb.waitForIdle(); 570 571 instance.pressKey(button, converted_modifiers); 572 instance.releaseKey(button, converted_modifiers); 573 574 rb.waitForIdle(); 575 new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 576 577 public Boolean reached() { 578 while(true) { 579 InputEvent e = queue.poll(); 580 if (e != null) { 581 if (e instanceof KeyEvent) { 582 KeyEvent ke = (KeyEvent) e; 583 if (ke.getID() == KeyEvent.KEY_PRESSED && ke.getKeyCode() == keyCode && compareModifiers(ke.getModifiers(), modifiers)) { 584 return true; 585 } 586 if (ke.getID() == KeyEvent.KEY_PRESSED) { 587 System.out.println("Wrong combination of button and modifiers triggered:"); 588 System.out.println("ke.getModifiers() = " + Integer.toString(ke.getModifiers(), 2) + ", modifiers = " + Integer.toString(modifiers, 2)); 589 System.out.println("expected: " + new KeyEvent(ke.getComponent(), KeyEvent.KEY_PRESSED, ke.getWhen(), modifiers, keyCode, KeyEvent.CHAR_UNDEFINED)); 590 System.out.println(" got: " + ke); 591 } 592 } 593 } else { 594 break; 595 } 596 } 597 return null; 598 } 599 600 }); 601 602 System.out.println("PASSED"); 603 } 604 605 // /** 606 // * Test of releaseKey method, of class RobotDriver. 607 // */ 608 // @Test 609 // public void testReleaseKey() throws InterruptedException { 610 // System.out.println("releaseKey"); 611 // int keyCode = KeyEvent.VK_B; 612 // int modifiers = 0; 613 // keyReleased = false; 614 // instance.pressKey(keyCode, modifiers); 615 // instance.releaseKey(keyCode, modifiers); 616 // 617 // rb.waitForIdle(); 618 // new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){ 619 // 620 // public Boolean reached() { 621 // return keyReleased ? true: null; 622 // } 623 // 624 // }); 625 // assertTrue(keyReleased); 626 // } 627 628 }