| Index: ui/events/gesture_detection/velocity_tracker_unittest.cc
|
| diff --git a/ui/events/gesture_detection/velocity_tracker_unittest.cc b/ui/events/gesture_detection/velocity_tracker_unittest.cc
|
| index c5cf15c567040061782b21475c4ae65d5edb0652..564bcd95a28355793789b5a4d30dcde31af12372 100644
|
| --- a/ui/events/gesture_detection/velocity_tracker_unittest.cc
|
| +++ b/ui/events/gesture_detection/velocity_tracker_unittest.cc
|
| @@ -8,7 +8,7 @@
|
| #include "base/time/time.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "ui/events/gesture_detection/velocity_tracker_state.h"
|
| -#include "ui/events/test/mock_motion_event.h"
|
| +#include "ui/events/test/motion_event_test_utils.h"
|
| #include "ui/gfx/geometry/point_f.h"
|
| #include "ui/gfx/geometry/vector2d_f.h"
|
|
|
| @@ -27,13 +27,14 @@ const char* GetStrategyName(VelocityTracker::Strategy strategy) {
|
| switch (strategy) {
|
| case VelocityTracker::LSQ1: return "LSQ1";
|
| case VelocityTracker::LSQ2: return "LSQ2";
|
| + case VelocityTracker::LSQ2_RESTRICTED: return "LSQ2_RESTRICTED";
|
| case VelocityTracker::LSQ3: return "LSQ3";
|
| case VelocityTracker::WLSQ2_DELTA: return "WLSQ2_DELTA";
|
| case VelocityTracker::WLSQ2_CENTRAL: return "WLSQ2_CENTRAL";
|
| case VelocityTracker::WLSQ2_RECENT: return "WLSQ2_RECENT";
|
| case VelocityTracker::INT1: return "INT1";
|
| case VelocityTracker::INT2: return "INT2";
|
| - };
|
| + }
|
| NOTREACHED() << "Invalid strategy";
|
| return "";
|
| }
|
| @@ -47,21 +48,21 @@ class VelocityTrackerTest : public testing::Test {
|
|
|
| protected:
|
| static MockMotionEvent Sample(MotionEvent::Action action,
|
| - gfx::PointF p0,
|
| + const gfx::PointF& p0,
|
| TimeTicks t0,
|
| - gfx::Vector2dF v,
|
| + const gfx::Vector2dF& v,
|
| TimeDelta dt) {
|
| const gfx::PointF p = p0 + ScaleVector2d(v, dt.InSecondsF());
|
| return MockMotionEvent(action, t0 + dt, p.x(), p.y());
|
| }
|
|
|
| static void ApplyMovementSequence(VelocityTrackerState* state,
|
| - gfx::PointF p0,
|
| - gfx::Vector2dF v,
|
| + const gfx::PointF& p0,
|
| + const gfx::Vector2dF& v,
|
| TimeTicks t0,
|
| TimeDelta t,
|
| size_t samples) {
|
| - EXPECT_TRUE(!!samples);
|
| + EXPECT_TRUE(samples);
|
| if (!samples)
|
| return;
|
| const base::TimeDelta dt = t / samples;
|
| @@ -71,12 +72,12 @@ class VelocityTrackerTest : public testing::Test {
|
| }
|
|
|
| static void ApplyMovement(VelocityTrackerState* state,
|
| - gfx::PointF p0,
|
| - gfx::Vector2dF v,
|
| + const gfx::PointF& p0,
|
| + const gfx::Vector2dF& v,
|
| TimeTicks t0,
|
| TimeDelta t,
|
| size_t samples) {
|
| - EXPECT_TRUE(!!samples);
|
| + EXPECT_TRUE(samples);
|
| if (!samples)
|
| return;
|
| const base::TimeDelta dt = t / samples;
|
| @@ -127,7 +128,7 @@ TEST_F(VelocityTrackerTest, MaxVelocity) {
|
| const size_t samples = 3;
|
| const base::TimeDelta dt = kTenMillis * 2;
|
|
|
| - VelocityTrackerState state;
|
| + VelocityTrackerState state(VelocityTracker::Strategy::LSQ2);
|
| ApplyMovementSequence(&state, p0, v, TimeTicks::Now(), dt, samples);
|
|
|
| // The computed velocity should be restricted to the provided maximum.
|
| @@ -197,7 +198,7 @@ TEST_F(VelocityTrackerTest, DelayedActionUp) {
|
| const base::TimeTicks t0 = base::TimeTicks::Now();
|
| const base::TimeDelta dt = kTenMillis * 2;
|
|
|
| - VelocityTrackerState state;
|
| + VelocityTrackerState state(VelocityTracker::Strategy::LSQ2);
|
| state.AddMovement(
|
| Sample(MotionEvent::ACTION_DOWN, p0, t0, v, base::TimeDelta()));
|
|
|
| @@ -219,4 +220,43 @@ TEST_F(VelocityTrackerTest, DelayedActionUp) {
|
| EXPECT_EQ(0.f, state.GetYVelocity(0));
|
| }
|
|
|
| +// Tests that a rapid deceleration won't result in a velocity going in the
|
| +// opposite direction to the pointers primary movement, with the LSQ_RESTRICTED
|
| +// strategy. See crbug.com/417855.
|
| +TEST_F(VelocityTrackerTest, NoDirectionReversal) {
|
| + VelocityTrackerState state_unrestricted(VelocityTracker::LSQ2);
|
| + VelocityTrackerState state_restricted(VelocityTracker::LSQ2_RESTRICTED);
|
| + const base::TimeTicks t0 = base::TimeTicks::Now();
|
| + const base::TimeDelta dt = base::TimeDelta::FromMilliseconds(1);
|
| + const size_t samples = 60;
|
| +
|
| + gfx::PointF p(0, 0);
|
| +
|
| + MockMotionEvent m1(MotionEvent::ACTION_DOWN, t0, p.x(), p.y());
|
| + state_unrestricted.AddMovement(m1);
|
| + state_restricted.AddMovement(m1);
|
| +
|
| + for (size_t i = 0; i < samples; ++i) {
|
| + if (i < 50)
|
| + p.set_y(p.y() + 10);
|
| + MockMotionEvent mi(MotionEvent::ACTION_MOVE, t0 + dt * i, p.x(), p.y());
|
| + state_unrestricted.AddMovement(mi);
|
| + state_restricted.AddMovement(mi);
|
| + }
|
| +
|
| + // The computed velocity be zero, as we stopped at the end of the gesture. In
|
| + // particular, it should not be negative, as all movement was in the positive
|
| + // direction.
|
| + state_restricted.ComputeCurrentVelocity(1000, 20000);
|
| + EXPECT_EQ(0, state_restricted.GetXVelocity(0));
|
| + EXPECT_EQ(0, state_restricted.GetYVelocity(0));
|
| +
|
| + // This does not hold for the unrestricted LSQ2 strategy.
|
| + state_unrestricted.ComputeCurrentVelocity(1000, 20000);
|
| + EXPECT_EQ(0, state_unrestricted.GetXVelocity(0));
|
| + // Y velocity is negative, despite the fact that the finger only moved in the
|
| + // positive y direction.
|
| + EXPECT_GT(0, state_unrestricted.GetYVelocity(0));
|
| +}
|
| +
|
| } // namespace ui
|
|
|