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.awt;
  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.KeyAdapter;
  35 import java.awt.event.KeyEvent;
  36 import java.awt.event.MouseAdapter;
  37 import java.awt.event.MouseEvent;
  38 import java.io.File;
  39 import java.lang.reflect.InvocationTargetException;
  40 import org.jemmy.Point;
  41 import org.jemmy.control.Wrap;
  42 import org.jemmy.env.Environment;
  43 import org.jemmy.env.Timeout;
  44 import org.jemmy.image.awt.AWTImage;
  45 import org.jemmy.input.awt.RobotDriver;
  46 import org.jemmy.input.awt.RobotExecutor;
  47 import org.jemmy.interfaces.Keyboard.KeyboardButton;
  48 import org.jemmy.interfaces.Keyboard.KeyboardButtons;
  49 import org.jemmy.interfaces.Keyboard.KeyboardModifiers;
  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 import static org.testng.Assert.assertFalse;
  62 import static org.testng.Assert.assertTrue;
  63 
  64 
  65 /**
  66  *
  67  * @author Alexander Kouznetsov <mrkam@mail.ru>
  68  */
  69 public class RobotDriverTest {
  70 
  71     final static Timeout TIMEOUT = new Timeout("Wait for state to be reached", 10000);
  72     final static Timeout DELTA_TIMEOUT = new Timeout("Delta timeout of wait for state to be reached", 1000);
  73 
  74     public RobotDriverTest() {
  75     }
  76 
  77     @BeforeClass
  78     public static void setUpClass() throws Exception {
  79         File workdir = new File(System.getProperty("user.dir") + File.separator +
  80                 "build" + File.separator +
  81                 "test" + File.separator +
  82                 "results");
  83         workdir.mkdirs();
  84         AWTImage.setImageRoot(workdir);
  85     }
  86 
  87     @AfterClass
  88     public static void tearDownClass() throws Exception {
  89         RobotDriver.exit();
  90     }
  91 
  92     Frame frm;
  93     Button btn;
  94     Wrap<Object> area;
  95     private volatile boolean mousePressed;
  96     private volatile boolean mouseReleased;
  97     private volatile boolean mouseMoved;
  98     private volatile boolean mouseClicked;
  99     private volatile boolean mouseDragged;
 100     private volatile boolean keyPressed;
 101     private volatile boolean keyReleased;
 102     RobotDriver instance;
 103     Robot rb;
 104 
 105     @BeforeMethod
 106     public void setUp() throws InterruptedException, AWTException, InvocationTargetException {
 107         EventQueue.invokeAndWait(new Runnable() {
 108 
 109             public void run() {
 110                 frm = new Frame("some frame");
 111                 frm.setSize(100, 100);
 112                 frm.setLocation(100, 100);
 113                 btn = new Button("some button");
 114                 MouseAdapter m = new MouseAdapter() {
 115 
 116                     @Override
 117                     public void mousePressed(MouseEvent e) {
 118                         System.out.println("mousePressed event triggered: " + e);
 119                         System.out.flush();
 120                         if ((e.getButton() & MouseEvent.BUTTON1) != 0 && e.isShiftDown()) {
 121                             mousePressed = true;
 122                         }
 123                     }
 124 
 125                     @Override
 126                     public void mouseReleased(MouseEvent e) {
 127                         System.out.println("mouseReleased event triggered: " + e);
 128                         System.out.flush();
 129                         if ((e.getButton() & MouseEvent.BUTTON2) != 0 && e.isControlDown()) {
 130                             mouseReleased = true;
 131                         }
 132                     }
 133 
 134                     @Override
 135                     public void mouseMoved(MouseEvent e) {
 136                         System.out.println("mouseMoved event triggered: " + e);
 137                         System.out.flush();
 138                         mouseMoved = true;
 139                     }
 140 
 141                     @Override
 142                     public void mouseClicked(MouseEvent e) {
 143                         System.out.println("mouseClicked event triggered: " + e);
 144                         System.out.flush();
 145                         if ((e.getButton() & MouseEvent.BUTTON3) != 0 && e.isAltDown()) {
 146                             mouseClicked = true;
 147                         }
 148                     }
 149 
 150                     @Override
 151                     public void mouseDragged(MouseEvent e) {
 152                         System.out.println("mouseDragged event triggered: " + e);
 153                         System.out.flush();
 154                         if ((e.getModifiers() & MouseEvent.BUTTON2_MASK) != 0) {
 155                             mouseDragged = true;
 156                         }
 157                     }
 158 
 159                 };
 160                 btn.addMouseListener(m);
 161                 btn.addMouseMotionListener(m);
 162                 btn.addKeyListener(new KeyAdapter() {
 163 
 164                     @Override
 165                     public void keyPressed(KeyEvent e) {
 166                         System.out.println("keyPressed event triggered: " + e);
 167                         System.out.flush();
 168                         if (e.getKeyCode() == KeyEvent.VK_A && e.isShiftDown()) {
 169                             keyPressed = true;
 170                         }
 171                     }
 172 
 173                     @Override
 174                     public void keyReleased(KeyEvent e) {
 175                         System.out.println("keyReleased event triggered: " + e);
 176                         System.out.flush();
 177                         if (e.getKeyCode() == KeyEvent.VK_B) {
 178                             keyReleased = true;
 179                         }
 180                     }
 181 
 182                 });
 183                 frm.add(btn, BorderLayout.SOUTH);
 184                 frm.doLayout();
 185                 instance = new RobotDriver(Environment.getEnvironment());
 186                 frm.setVisible(true);
 187                 btn.requestFocusInWindow();
 188             }
 189         });
 190 
 191         rb = new Robot();
 192         rb.waitForIdle();
 193 
 194         RobotExecutor.get().setRunInOtherJVM(true);
 195     }
 196 
 197     @AfterMethod
 198     public void tearDown() throws InterruptedException, InvocationTargetException {
 199         EventQueue.invokeAndWait(new Runnable() {
 200 
 201             public void run() {
 202                 frm.setVisible(false);
 203             }
 204         });
 205     }
 206 
 207 //    /**
 208 //     * Test of createScreenCapture method, of class RobotDriver.
 209 //     */
 210 //    @Test
 211 //    public void testCreateScreenCaptureLocally() throws AWTException, InterruptedException {
 212 //        System.out.println("testCreateScreenCaptureLocally");
 213 //        Thread.sleep(3000);
 214 //        Rectangle screenRect = new Rectangle(100, 100, 100, 100);
 215 //        RobotExecutor.get().setRunInOtherJVM(false);
 216 //        Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100)));
 217 //        Image result = RobotDriver.createScreenCapture(screenRect);
 218 //        Image diff = expResult.compareTo(result);
 219 //        if (diff != null) {
 220 //            diff.save("testCreateScreenCaptureLocally.png");
 221 //            fail();
 222 //        }
 223 //    }
 224 //
 225 //    /**
 226 //     * Test of createScreenCapture method, of class RobotDriver.
 227 //     */
 228 //    @Test
 229 //    public void testCreateScreenCaptureRemotely() throws AWTException, InterruptedException {
 230 //        System.out.println("testCreateScreenCaptureRemotely");
 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 //        RobotDriver.createScreenCapture(screenRect);
 237 //        Image diff = expResult.compareTo(result);
 238 //        if (diff != null) {
 239 //            diff.save("testCreateScreenCaptureRemotely.png");
 240 //            fail();
 241 //        }
 242 //    }
 243 //
 244 //    /**
 245 //     * Test of createScreenCapture method, of class RobotDriver.
 246 //     */
 247 //    @Test
 248 //    public void testCreateScreenCaptureRemotely2() throws AWTException, InterruptedException {
 249 //        System.out.println("testCreateScreenCaptureRemotely2");
 250 //        Thread.sleep(3000);
 251 //        Rectangle screenRect = new Rectangle(100, 100, 100, 100);
 252 //        RobotExecutor.get().setRunInOtherJVM(true);
 253 //        Image expResult = new AWTImage(new Robot().createScreenCapture(new java.awt.Rectangle(100, 100, 100, 100)));
 254 //        Image result = RobotDriver.createScreenCapture(screenRect);
 255 //        Image diff = expResult.compareTo(result);
 256 //        if (diff != null) {
 257 //            diff.save("testCreateScreenCaptureRemotely2.png");
 258 //            fail();
 259 //        }
 260 //    }
 261 
 262     /**
 263      * Test of pressMouse method, of class RobotDriver.
 264      */
 265     @Test
 266     public void testPressMouse() throws InterruptedException {
 267         System.out.println("pressMouse");
 268         Thread.sleep(3000);
 269 //        new Thread() {
 270 //
 271 //            @Override
 272 //            public void run() {
 273                 MouseButton mouseButton = MouseButtons.BUTTON1;
 274                 Modifier modifiers[] = new Modifier[] {KeyboardModifiers.SHIFT_DOWN_MASK};
 275                 mousePressed = false;
 276                 java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 277                 System.out.println("Pressing mouse");
 278                 instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2));
 279                 instance.pressMouse(mouseButton, modifiers);
 280                 instance.releaseMouse(mouseButton, modifiers);
 281 
 282                 rb.waitForIdle();
 283                 new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 284 
 285                     public Boolean reached() {
 286                         return mousePressed ? true: null;
 287                     }
 288 
 289                 });
 290 
 291 //            }
 292 //
 293 //        }.start();
 294     }
 295 
 296     /**
 297      * Test of releaseMouse method, of class RobotDriver.
 298      */
 299     @Test
 300     public void testReleaseMouse() throws InterruptedException {
 301         System.out.println("releaseMouse");
 302         Thread.sleep(3000);
 303         MouseButton mouseButton = MouseButtons.BUTTON2;
 304         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.CTRL_DOWN_MASK};
 305         mouseReleased = false;
 306         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 307         instance.moveMouse(new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2));
 308         System.out.println("Pressing mouse");
 309         instance.pressMouse(mouseButton, modifiers);
 310         System.out.println("Releasing mouse");
 311         instance.releaseMouse(mouseButton, modifiers);
 312 
 313         rb.waitForIdle();
 314         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 315 
 316             public Boolean reached() {
 317                 return mouseReleased ? true: null;
 318             }
 319 
 320         });
 321         assertTrue(mouseReleased);
 322     }
 323 
 324     /**
 325      * Test of moveMouse method, of class RobotDriver.
 326      */
 327     @Test
 328     public void testMoveMouse() throws InterruptedException {
 329         System.out.println("moveMouse");
 330         Thread.sleep(3000);
 331         mouseMoved = false;
 332         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 333         System.out.println("Moving mouse");
 334         Point startPoint = new Point(locationOnScreen.x, locationOnScreen.y);
 335         Point endPoint = new Point(locationOnScreen.x + btn.getWidth(), locationOnScreen.y + btn.getHeight());
 336         double steps = 5; //Math.max(btn.getWidth(), btn.getHeight());
 337         double dx = (endPoint.x - startPoint.x) / steps;
 338         double dy = (endPoint.y - startPoint.y) / steps;
 339         for(int i = 0; i < steps; i++) {
 340             Point point = new Point(startPoint.x + dx * i, startPoint.y + dy * i);
 341             instance.moveMouse(point);
 342             Thread.sleep(100);
 343         }
 344 
 345         rb.waitForIdle();
 346         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 347 
 348             public Boolean reached() {
 349                 return mouseMoved ? true: null;
 350             }
 351 
 352         });
 353         assertTrue(mouseMoved);
 354     }
 355 
 356     /**
 357      * Test of moveMouse method with smoothness set Integer.MAX_VALUE
 358      * of class RobotDriver.
 359      */
 360     @Test
 361     public void testMoveNonSmoothMouse() throws InterruptedException {
 362         System.out.println("testMoveNonSmoothMouse");
 363         Thread.sleep(3000);
 364         mouseMoved = false;
 365         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 366         System.out.println("Moving mouse");
 367         Point startPoint = new Point(locationOnScreen.x - 10, locationOnScreen.y - 10);
 368         Point endPoint = new Point(locationOnScreen.x + btn.getWidth() + 10, locationOnScreen.y + btn.getHeight() + 10);
 369         instance.moveMouse(startPoint);
 370         Thread.sleep(100);
 371         instance.moveMouse(endPoint);
 372         Thread.sleep(2000);
 373 
 374         rb.waitForIdle();
 375         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 376 
 377             public Boolean reached() {
 378                 return !mouseMoved ? true : null;
 379             }
 380 
 381         });
 382         assertFalse(mouseMoved);
 383     }
 384 
 385     /**
 386      * Test of clickMouse method, of class RobotDriver.
 387      */
 388     @Test
 389     public void testClickMouse() throws InterruptedException {
 390         System.out.println("clickMouse");
 391         Thread.sleep(3000);
 392         mouseClicked = false;
 393         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 394         Point point = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2);
 395         int clickCount = 1;
 396         MouseButton mouseButton = MouseButtons.BUTTON3;
 397         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.ALT_DOWN_MASK};
 398         Timeout mouseClick = new Timeout("mouseClick", 100);
 399         System.out.println("Clicking mouse");
 400         instance.clickMouse(point, clickCount, mouseButton, mouseClick, modifiers);
 401 
 402         rb.waitForIdle();
 403         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 404 
 405             public Boolean reached() {
 406                 return mouseClicked ? true: null;
 407             }
 408 
 409         });
 410         assertTrue(mouseClicked);
 411     }
 412 
 413     /**
 414      * Test of dragNDrop method, of class RobotDriver.
 415      */
 416     @Test
 417     public void testDragNDrop() throws InterruptedException {
 418         System.out.println("dragNDrop");
 419         java.awt.Point locationOnScreen = btn.getLocationOnScreen();
 420         Point startPoint = new Point(locationOnScreen.x + btn.getWidth() / 2, locationOnScreen.y + btn.getHeight() / 2);
 421         Point endPoint = new Point(frm.getLocationOnScreen().x + frm.getWidth() / 2, frm.getLocationOnScreen().y + frm.getHeight() / 2);
 422         MouseButton mouseButton = MouseButtons.BUTTON2;
 423         Modifier modifiers[] = new Modifier[] {};
 424         Timeout before = new Timeout("before", 500);
 425         Timeout after = new Timeout("after", 500);
 426         mouseDragged = false;
 427         instance.dragNDrop(startPoint, endPoint, mouseButton, modifiers, before, after);
 428 
 429         rb.waitForIdle();
 430         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 431 
 432             public Boolean reached() {
 433                 return mouseDragged ? true: null;
 434             }
 435 
 436         });
 437         assertTrue(mouseDragged);
 438     }
 439 
 440     /**
 441      * Test of pressKey method, of class RobotDriver.
 442      */
 443     @Test
 444     public void testPressKey() throws InterruptedException {
 445         System.out.println("pressKey");
 446         KeyboardButton kbdButton = KeyboardButtons.A;
 447         Modifier modifiers[] = new Modifier[] {KeyboardModifiers.SHIFT_DOWN_MASK};
 448         keyPressed = false;
 449         instance.pressKey(kbdButton, modifiers);
 450         instance.releaseKey(kbdButton, modifiers);
 451 
 452         rb.waitForIdle();
 453         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 454 
 455             public Boolean reached() {
 456                 return keyPressed ? true: null;
 457             }
 458 
 459         });
 460         assertTrue(keyPressed);
 461     }
 462 
 463     /**
 464      * Test of releaseKey method, of class RobotDriver.
 465      */
 466     @Test
 467     public void testReleaseKey() throws InterruptedException {
 468         System.out.println("releaseKey");
 469         KeyboardButton kbdButton = KeyboardButtons.B;
 470         Modifier modifiers[] = new Modifier[] {};
 471         keyReleased = false;
 472         instance.pressKey(kbdButton, modifiers);
 473         instance.releaseKey(kbdButton, modifiers);
 474 
 475         rb.waitForIdle();
 476         new Waiter(TIMEOUT, DELTA_TIMEOUT).ensureState(new State<Boolean>(){
 477 
 478             public Boolean reached() {
 479                 return keyReleased ? true: null;
 480             }
 481 
 482         });
 483         assertTrue(keyReleased);
 484     }
 485 
 486 }