tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestFlingAcceleration.cpp (10199B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <initializer_list>
      8 #include "APZCTreeManagerTester.h"
      9 #include "APZTestCommon.h"
     10 #include "InputUtils.h"
     11 
     12 class APZCFlingAccelerationTester : public APZCTreeManagerTester {
     13 protected:
     14  void SetUp() {
     15    APZCTreeManagerTester::SetUp();
     16    const char* treeShape = "x";
     17    LayerIntRect layerVisibleRect[] = {
     18        LayerIntRect(0, 0, 800, 1000),
     19    };
     20    CreateScrollData(treeShape, layerVisibleRect);
     21    SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
     22                              CSSRect(0, 0, 800, 50000));
     23    // Scroll somewhere into the middle of the scroll range, so that we have
     24    // lots of space to scroll in both directions.
     25    ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) {
     26      aMetrics.SetVisualScrollUpdateType(
     27          FrameMetrics::ScrollOffsetUpdateType::eMainThread);
     28      aMetrics.SetVisualDestination(CSSPoint(0, 25000));
     29    });
     30 
     31    registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
     32    UpdateHitTestingTree();
     33 
     34    apzc = ApzcOf(root);
     35  }
     36 
     37  void ExecutePanGesture100Hz(const ScreenIntPoint& aStartPoint,
     38                              std::initializer_list<int32_t> aYDeltas) {
     39    APZEventResult result = TouchDown(apzc, aStartPoint, mcc->Time());
     40 
     41    // Allowed touch behaviours must be set after sending touch-start.
     42    if (result.GetStatus() != nsEventStatus_eConsumeNoDefault) {
     43      SetDefaultAllowedTouchBehavior(apzc, result.mInputBlockId);
     44    }
     45 
     46    const TimeDuration kTouchTimeDelta100Hz =
     47        TimeDuration::FromMilliseconds(10);
     48 
     49    ScreenIntPoint currentLocation = aStartPoint;
     50    for (int32_t delta : aYDeltas) {
     51      mcc->AdvanceBy(kTouchTimeDelta100Hz);
     52      if (delta != 0) {
     53        currentLocation.y += delta;
     54        (void)TouchMove(apzc, currentLocation, mcc->Time());
     55      }
     56    }
     57 
     58    (void)TouchUp(apzc, currentLocation, mcc->Time());
     59  }
     60 
     61  void ExecuteWait(const TimeDuration& aDuration) {
     62    TimeDuration remaining = aDuration;
     63    const TimeDuration TIME_BETWEEN_FRAMES =
     64        TimeDuration::FromSeconds(1) / int64_t(60);
     65    while (remaining.ToMilliseconds() > 0) {
     66      mcc->AdvanceBy(TIME_BETWEEN_FRAMES);
     67      apzc->AdvanceAnimations(mcc->GetSampleTime());
     68      remaining -= TIME_BETWEEN_FRAMES;
     69    }
     70  }
     71 
     72  RefPtr<TestAsyncPanZoomController> apzc;
     73  UniquePtr<ScopedLayerTreeRegistration> registration;
     74 };
     75 
     76 enum class UpOrDown : uint8_t { Up, Down };
     77 
     78 // This is a macro so that the assertions print useful line numbers.
     79 #define CHECK_VELOCITY(aUpOrDown, aLowerBound, aUpperBound) \
     80  do {                                                      \
     81    auto vel = apzc->GetVelocityVector();                   \
     82    if (UpOrDown::aUpOrDown == UpOrDown::Up) {              \
     83      EXPECT_LT(vel.y, 0.0);                                \
     84    } else {                                                \
     85      EXPECT_GT(vel.y, 0.0);                                \
     86    }                                                       \
     87    EXPECT_GE(vel.Length(), aLowerBound);                   \
     88    EXPECT_LE(vel.Length(), aUpperBound);                   \
     89  } while (0)
     90 
     91 // These tests have the following pattern: Two flings are executed, with a bit
     92 // of wait time in between. The deltas in each pan gesture have been captured
     93 // from a real phone, from touch events triggered by real fingers.
     94 // We check the velocity at the end to detect whether the fling was accelerated
     95 // or not. As an additional safety precaution, we also check the velocities for
     96 // the first fling, so that changes in behavior are easier to analyze.
     97 // One added challenge of this test is the fact that it has to work with on
     98 // multiple platforms, and we use different velocity estimation strategies and
     99 // different fling physics depending on the platform.
    100 // The upper and lower bounds for the velocities were chosen in such a way that
    101 // the test passes on all platforms. At the time of writing, we usually end up
    102 // with higher velocities on Android than on Desktop, so the observed velocities
    103 // on Android became the upper bounds and the observed velocities on Desktop
    104 // becaume the lower bounds, each rounded out to a multiple of 0.1.
    105 
    106 TEST_F(APZCFlingAccelerationTester, TwoNormalFlingsShouldAccelerate) {
    107  ExecutePanGesture100Hz(ScreenIntPoint{665, 1244},
    108                         {0, 0, -21, -44, -52, -55, -53, -49, -46, -47});
    109  CHECK_VELOCITY(Down, 4.5, 6.8);
    110 
    111  ExecuteWait(TimeDuration::FromMilliseconds(375));
    112  CHECK_VELOCITY(Down, 2.2, 5.1);
    113 
    114  ExecutePanGesture100Hz(ScreenIntPoint{623, 1211},
    115                         {-6, -51, -55, 0, -53, -57, -60, -60, -56});
    116  CHECK_VELOCITY(Down, 9.0, 14.0);
    117 }
    118 
    119 TEST_F(APZCFlingAccelerationTester, TwoFastFlingsShouldAccelerate) {
    120  ExecutePanGesture100Hz(ScreenIntPoint{764, 714},
    121                         {9, 30, 49, 60, 64, 64, 62, 59, 51});
    122  CHECK_VELOCITY(Up, 5.0, 7.5);
    123 
    124  ExecuteWait(TimeDuration::FromMilliseconds(447));
    125  CHECK_VELOCITY(Up, 2.3, 5.2);
    126 
    127  ExecutePanGesture100Hz(ScreenIntPoint{743, 739},
    128                         {7, 0, 38, 66, 75, 146, 0, 119});
    129  CHECK_VELOCITY(Up, 13.0, 20.0);
    130 }
    131 
    132 TEST_F(APZCFlingAccelerationTester,
    133       FlingsInOppositeDirectionShouldNotAccelerate) {
    134  ExecutePanGesture100Hz(ScreenIntPoint{728, 1381},
    135                         {0, 0, 0, -12, -24, -32, -43, -46, 0});
    136  CHECK_VELOCITY(Down, 2.9, 5.3);
    137 
    138  ExecuteWait(TimeDuration::FromMilliseconds(153));
    139  CHECK_VELOCITY(Down, 2.1, 4.8);
    140 
    141  ExecutePanGesture100Hz(ScreenIntPoint{698, 1059},
    142                         {0, 0, 14, 61, 41, 0, 45, 35});
    143  CHECK_VELOCITY(Up, 3.2, 4.3);
    144 }
    145 
    146 TEST_F(APZCFlingAccelerationTester,
    147       ShouldNotAccelerateWhenPreviousFlingHasSlowedDown) {
    148  ExecutePanGesture100Hz(ScreenIntPoint{748, 1046},
    149                         {0, 9, 15, 23, 31, 30, 0, 34, 31, 29, 28, 24, 24, 11});
    150  CHECK_VELOCITY(Up, 2.2, 3.0);
    151  ExecuteWait(TimeDuration::FromMilliseconds(498));
    152  CHECK_VELOCITY(Up, 0.5, 1.0);
    153  ExecutePanGesture100Hz(ScreenIntPoint{745, 1056},
    154                         {0, 10, 17, 29, 29, 33, 33, 0, 31, 27, 13});
    155  CHECK_VELOCITY(Up, 1.8, 2.7);
    156 }
    157 
    158 TEST_F(APZCFlingAccelerationTester, ShouldNotAccelerateWhenPausedAtStartOfPan) {
    159  ExecutePanGesture100Hz(
    160      ScreenIntPoint{711, 1468},
    161      {0, 0, 0, 0, -8, 0, -18, -32, -50, -57, -66, -68, -63, -60});
    162  CHECK_VELOCITY(Down, 6.2, 8.6);
    163 
    164  ExecuteWait(TimeDuration::FromMilliseconds(285));
    165  CHECK_VELOCITY(Down, 3.4, 7.4);
    166 
    167  ExecutePanGesture100Hz(
    168      ScreenIntPoint{658, 1352},
    169      {0, 0, 0, 0, 0, 0,  0,   0,   0,   0,   0,   0,   0,
    170       0, 0, 0, 0, 0, -8, -18, -34, -53, -70, -75, -75, -64});
    171  CHECK_VELOCITY(Down, 6.7, 9.1);
    172 }
    173 
    174 TEST_F(APZCFlingAccelerationTester, ShouldNotAccelerateWhenPausedDuringPan) {
    175  ExecutePanGesture100Hz(
    176      ScreenIntPoint{732, 1423},
    177      {0, 0, 0, -5, 0, -15, -41, -71, -90, -93, -85, -64, -44});
    178  CHECK_VELOCITY(Down, 7.5, 10.1);
    179 
    180  ExecuteWait(TimeDuration::FromMilliseconds(204));
    181  CHECK_VELOCITY(Down, 4.8, 9.4);
    182 
    183  ExecutePanGesture100Hz(
    184      ScreenIntPoint{651, 1372},
    185      {0,   0,   0,  -6, 0,  -16, -26, -41, -49, -65, -66, -61, -50, -35, -24,
    186       -17, -11, -8, -6, -5, -4,  -3,  -2,  -2,  -2,  -2,  -2,  -2,  -2,  -2,
    187       -3,  -4,  -5, -7, -9, -10, -10, -12, -18, -25, -23, -28, -30, -24});
    188  CHECK_VELOCITY(Down, 2.5, 3.4);
    189 }
    190 
    191 TEST_F(APZCFlingAccelerationTester,
    192       ShouldNotAccelerateWhenOppositeDirectionDuringPan) {
    193  ExecutePanGesture100Hz(ScreenIntPoint{663, 1371},
    194                         {0, 0, 0, -5, -18, -31, -49, -56, -61, -54, -55});
    195  CHECK_VELOCITY(Down, 5.4, 7.1);
    196 
    197  ExecuteWait(TimeDuration::FromMilliseconds(255));
    198  CHECK_VELOCITY(Down, 3.1, 6.0);
    199 
    200  ExecutePanGesture100Hz(
    201      ScreenIntPoint{726, 930},
    202      {0,  0,   0,   0,   30,  0,   19,  24,  32,  30, 37, 33,
    203       33, 32,  25,  23,  23,  18,  13,  9,   5,   3,  1,  0,
    204       -7, -19, -38, -53, -68, -79, -85, -73, -64, -54});
    205  CHECK_VELOCITY(Down, 7.0, 10.0);
    206 }
    207 
    208 TEST_F(APZCFlingAccelerationTester,
    209       ShouldAccelerateAfterLongWaitIfVelocityStillHigh) {
    210  // Reduce friction with the "Desktop" fling physics a little, so that it
    211  // behaves more similarly to the Android fling physics, and has enough
    212  // velocity after the wait time to allow for acceleration.
    213  SCOPED_GFX_PREF_FLOAT("apz.fling_friction", 0.0012);
    214 
    215  ExecutePanGesture100Hz(ScreenIntPoint{739, 1424},
    216                         {0, 0, -5, -10, -20, 0, -110, -86, 0, -102, -105});
    217  CHECK_VELOCITY(Down, 6.3, 9.4);
    218 
    219  ExecuteWait(TimeDuration::FromMilliseconds(1117));
    220  CHECK_VELOCITY(Down, 1.6, 3.3);
    221 
    222  ExecutePanGesture100Hz(ScreenIntPoint{726, 1380},
    223                         {0, -8, 0, -30, -60, -87, -104, -111});
    224  CHECK_VELOCITY(Down, 13.0, 23.0);
    225 }
    226 
    227 TEST_F(APZCFlingAccelerationTester, ShouldNotAccelerateAfterCanceledWithTap) {
    228  // First, build up a lot of speed.
    229  ExecutePanGesture100Hz(ScreenIntPoint{569, 710},
    230                         {11, 2, 107, 18, 148, 57, 133, 159, 21});
    231  ExecuteWait(TimeDuration::FromMilliseconds(154));
    232  ExecutePanGesture100Hz(ScreenIntPoint{581, 650},
    233                         {12, 68, 0, 162, 78, 140, 167});
    234  ExecuteWait(TimeDuration::FromMilliseconds(123));
    235  ExecutePanGesture100Hz(ScreenIntPoint{568, 723}, {11, 0, 79, 91, 131, 171});
    236  ExecuteWait(TimeDuration::FromMilliseconds(123));
    237  ExecutePanGesture100Hz(ScreenIntPoint{598, 678},
    238                         {8, 55, 22, 87, 117, 220, 54});
    239  ExecuteWait(TimeDuration::FromMilliseconds(134));
    240  ExecutePanGesture100Hz(ScreenIntPoint{585, 854}, {45, 137, 107, 102, 79});
    241  ExecuteWait(TimeDuration::FromMilliseconds(246));
    242 
    243  // Then, interrupt with a tap.
    244  ExecutePanGesture100Hz(ScreenIntPoint{566, 812}, {0, 0, 0, 0});
    245  ExecuteWait(TimeDuration::FromMilliseconds(869));
    246 
    247  // Then do a regular fling.
    248  ExecutePanGesture100Hz(ScreenIntPoint{599, 819},
    249                         {0, 0, 8, 35, 8, 38, 29, 37});
    250 
    251  CHECK_VELOCITY(Up, 2.8, 4.2);
    252 }