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 |