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.  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 
  26 package test.robot.com.sun.glass.ui.monocle;
  27 
  28 import com.sun.glass.ui.monocle.TestLogShim;
  29 import test.robot.com.sun.glass.ui.monocle.TestApplication;
  30 import test.robot.com.sun.glass.ui.monocle.input.devices.TestTouchDevice;
  31 import test.robot.com.sun.glass.ui.monocle.input.devices.TestTouchDevices;
  32 import com.sun.javafx.PlatformUtil;
  33 import javafx.scene.input.GestureEvent;
  34 import org.junit.Assert;
  35 import org.junit.Assume;
  36 import org.junit.Before;
  37 import org.junit.Ignore;
  38 import org.junit.Test;
  39 import org.junit.runners.Parameterized;
  40 
  41 import java.util.ArrayList;
  42 import java.util.Collection;
  43 import java.util.List;
  44 import java.util.Timer;
  45 import java.util.TimerTask;
  46 import java.util.concurrent.CountDownLatch;
  47 import test.com.sun.glass.ui.monocle.TestRunnable;
  48 
  49 public class SwipeTest extends ParameterizedTestBase {
  50 
  51     static {
  52         System.setProperty("com.sun.javafx.isEmbedded", "true");
  53     }
  54 
  55     private static final SwipeTestCase[] TEST_CASES = {
  56         new SwipeTestCase(200.0, Math.PI * 0.5, 10l, 1000.0, 0.0, 200.0, "SWIPE_RIGHT"),
  57         new SwipeTestCase(200.0, Math.PI * 0.5, 50l, 1000.0, 0.0, 200.0, "SWIPE_RIGHT"),
  58 
  59         new SwipeTestCase(200.0, Math.PI * 0.4, 200l, 100.0, 0.0, 200.0, "SWIPE_RIGHT"),
  60         new SwipeTestCase(200.0, Math.PI * 0.5, 200l, 100.0, 0.0, 200.0, "SWIPE_RIGHT"),
  61         new SwipeTestCase(200.0, Math.PI * 0.6, 200l, 100.0, 0.0, 200.0, "SWIPE_RIGHT"),
  62         new SwipeTestCase(200.0, Math.PI * 0.4, 200l, 100.0, 30.0, 200.0, "SWIPE_RIGHT"),
  63         new SwipeTestCase(200.0, Math.PI * 0.5, 200l, 100.0, 30.0, 200.0, "SWIPE_RIGHT"),
  64         new SwipeTestCase(200.0, Math.PI * 0.6, 200l, 100.0, 30.0, 200.0, "SWIPE_RIGHT"),
  65 
  66         new SwipeTestCase(200.0, Math.PI * 1.4, 200l, 100.0, 0.0, 200.0, "SWIPE_LEFT"),
  67         new SwipeTestCase(200.0, Math.PI * 1.5, 200l, 100.0, 0.0, 200.0, "SWIPE_LEFT"),
  68         new SwipeTestCase(200.0, Math.PI * 1.6, 200l, 100.0, 0.0, 200.0, "SWIPE_LEFT"),
  69         new SwipeTestCase(200.0, Math.PI * 1.4, 200l, 100.0, 30.0, 200.0, "SWIPE_LEFT"),
  70         new SwipeTestCase(200.0, Math.PI * 1.5, 200l, 100.0, 30.0, 200.0, "SWIPE_LEFT"),
  71         new SwipeTestCase(200.0, Math.PI * 1.6, 200l, 100.0, 30.0, 200.0, "SWIPE_LEFT"),
  72 
  73         new SwipeTestCase(200.0, Math.PI * 1.9, 200l, 100.0, 0.0, 200.0, "SWIPE_UP"),
  74         new SwipeTestCase(200.0, Math.PI * 0.0, 200l, 100.0, 0.0, 200.0, "SWIPE_UP"),
  75         new SwipeTestCase(200.0, Math.PI * 0.1, 200l, 100.0, 0.0, 200.0, "SWIPE_UP"),
  76         new SwipeTestCase(200.0, Math.PI * 1.9, 200l, 100.0, 30.0, 200.0, "SWIPE_UP"),
  77         new SwipeTestCase(200.0, Math.PI * 0.0, 200l, 100.0, 30.0, 200.0, "SWIPE_UP"),
  78         new SwipeTestCase(200.0, Math.PI * 0.1, 200l, 100.0, 30.0, 200.0, "SWIPE_UP"),
  79 
  80         new SwipeTestCase(200.0, Math.PI * 0.9, 200l, 100.0, 0.0, 200.0, "SWIPE_DOWN"),
  81         new SwipeTestCase(200.0, Math.PI * 1.0, 200l, 100.0, 0.0, 200.0, "SWIPE_DOWN"),
  82         new SwipeTestCase(200.0, Math.PI * 1.1, 200l, 100.0, 0.0, 200.0, "SWIPE_DOWN"),
  83         new SwipeTestCase(200.0, Math.PI * 0.9, 200l, 100.0, 30.0, 200.0, "SWIPE_DOWN"),
  84         new SwipeTestCase(200.0, Math.PI * 1.0, 200l, 100.0, 30.0, 200.0, "SWIPE_DOWN"),
  85         new SwipeTestCase(200.0, Math.PI * 1.1, 200l, 100.0, 30.0, 200.0, "SWIPE_DOWN"),
  86     };
  87 
  88     private SwipeTestCase testCase;
  89 
  90     static class SwipeTestCase {
  91         double length;
  92         double theta;
  93         long time;
  94         double density;
  95         double amplitude;
  96         double wavelength;
  97         String expectedSwipe;
  98         SwipeTestCase(double length, double theta, long time, double density,
  99                       double amplitude, double wavelength, String expectedSwipe) {
 100             this.length = length;
 101             this.theta = theta;
 102             this.time = time;
 103             this.density = density;
 104             this.amplitude = amplitude;
 105             this.wavelength = wavelength;
 106             this.expectedSwipe = expectedSwipe;
 107         }
 108 
 109         public String toString() {
 110             return "SwipeTestCase["
 111                     + "length=" + length
 112                     + ",theta=" + theta
 113                     + ",time=" + time
 114                     + ",density=" + density
 115                     + ",amplitude=" + amplitude
 116                     + ",wavelength=" + wavelength
 117                     + ",expectedSwipe=" + expectedSwipe + "]";
 118         }
 119     }
 120 
 121     public SwipeTest(TestTouchDevice device, SwipeTestCase testCase) throws Exception {
 122         super(device);
 123         this.testCase = testCase;
 124         TestLogShim.format("Starting test with %s, %s", device, testCase);
 125         TestApplication.getStage();
 126         TestRunnable.invokeAndWait(() -> {
 127             Assume.assumeTrue(
 128                     TestApplication.isMonocle() || TestApplication.isLens());
 129             Assume.assumeTrue(PlatformUtil.isEmbedded());
 130         });
 131     }
 132 
 133     @Parameterized.Parameters
 134     public static Collection<Object[]> data() {
 135         List<Object[]> params = new ArrayList<>();
 136         List<TestTouchDevice> devices = TestTouchDevices.getTouchDevices();
 137         for (TestTouchDevice device : devices) {
 138             for (SwipeTestCase testCase : TEST_CASES) {
 139                 params.add(new Object[] { device, testCase });
 140             }
 141         }
 142         return params;
 143     }
 144 
 145     @Before
 146     public void addListener() throws Exception {
 147         TestApplication.getStage().getScene().addEventHandler(
 148                 GestureEvent.ANY,
 149                 e -> TestLogShim.format("%s at %.0f, %.0f",
 150                                     e.getEventType(),
 151                                     e.getScreenX(),
 152                                     e.getScreenY()));
 153     }
 154 
 155     /**
 156      * Sends a series of points as a sine wave
 157      *
 158      * @param p The point ID to move
 159      * @param x1 Starting X
 160      * @param y1 Starting Y
 161      * @param length length of the vector from the start point to the end point
 162      * @param theta Direction of the sine wave, measured in radians
 163      *              clockwise from the upwards Y axis
 164      * @param time Time to send all points, in milliseconds
 165      * @param density number of points to send per second
 166      * @param amplitude of the sine wave, in pixels
 167      * @param wavelength of the sine wave, in pixels
 168      */
 169     private CountDownLatch generatePoints(int p,
 170                                 int x1, int y1,
 171                                 double length,
 172                                 double theta,
 173                                 long time,
 174                                 double density,
 175                                 double amplitude,
 176                                 double wavelength) {
 177         long startTime = System.currentTimeMillis();
 178         double deltaX = length / (time * density / 1000.0);
 179         CountDownLatch latch = new CountDownLatch(1);
 180         TimerTask task = new TimerTask() {
 181             private double x = 0;
 182             @Override
 183             public void run() {
 184                 try {
 185                     double targetX =
 186                             (System.currentTimeMillis() - startTime) * length
 187                                     / time;
 188                     if (targetX > length) {
 189                         cancel();
 190                         latch.countDown();
 191                         return;
 192                     }
 193                     if (x > targetX) {
 194                         return;
 195                     }
 196                     do {
 197                         x += deltaX;
 198                         double y = amplitude * Math.sin(
 199                                 (x * Math.PI * 2.0) / wavelength);
 200                         double phi = Math.atan2(x, y);
 201                         double h = Math.sqrt(x * x + y * y);
 202                         double rotatedX = h * Math.cos(theta - phi);
 203                         double rotatedY = h * Math.sin(theta - phi);
 204                         device.setPoint(p, x1 + rotatedX, y1 + rotatedY);
 205                         device.sync();
 206                     } while (x < targetX);
 207                 } catch (Exception e) {
 208                     e.printStackTrace();
 209                 }
 210             }
 211         };
 212         new Timer("Touch point generator", true)
 213                 .scheduleAtFixedRate(task, 0, (int) Math.max(1, time / density));
 214         return latch;
 215     }
 216 
 217     @Test
 218     @Ignore("RT-37709")
 219     public void testSwipe() throws Exception {
 220         final int x = (int) Math.round(width * 0.5);
 221         final int y = (int) Math.round(height * 0.5);
 222         // tap
 223         int p = device.addPoint(x, y);
 224         device.sync();
 225         // swipe
 226         generatePoints(p, x, y,
 227                        testCase.length,
 228                        testCase.theta,
 229                        testCase.time,
 230                        testCase.density,
 231                        testCase.amplitude,
 232                        testCase.wavelength).await();
 233         // release
 234         device.removePoint(p);
 235         device.sync();
 236         TestLogShim.waitForLog("Mouse pressed: %d, %d", x, y);
 237         TestLogShim.waitForLogContaining("Mouse released");
 238         TestLogShim.waitForLogContaining("Mouse clicked");
 239         TestLogShim.waitForLogContaining("Touch pressed");
 240         TestLogShim.waitForLogContaining("Touch released");
 241         if (testCase.expectedSwipe == null) {
 242             Assert.assertEquals(0, TestLogShim.countLogContaining("SWIPE"));
 243         } else {
 244             TestLogShim.waitForLogContaining(testCase.expectedSwipe);
 245             Assert.assertEquals(1, TestLogShim.countLogContaining("SWIPE"));
 246         }
 247     }
 248 
 249 }