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