1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "remoting/client/ui/fling_animation.h"
6
7 #include <cmath>
8
9 #include "base/bind.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/test/simple_test_tick_clock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace remoting {
15
16 namespace {
17
18 const float kFlingTimeConstant = 325.f;
19
20 } // namespace
21
22 class FlingAnimationTest : public testing::Test {
23 public:
24 void SetUp() override;
25 void TearDown() override;
26
27 protected:
28 void TickAnimation(base::TimeDelta time_delta);
29
30 // Must be called after the animation ticks.
31 void AssertDeltaChanged();
32
33 FlingAnimation fling_animation_{
34 kFlingTimeConstant,
35 base::BindRepeating(&FlingAnimationTest::OnDeltaChanged,
36 base::Unretained(this))};
37
38 float received_dx_ = 0.f;
39 float received_dy_ = 0.f;
40
41 private:
42 void OnDeltaChanged(float dx, float dy);
43
44 bool change_received_ = false;
45
46 base::SimpleTestTickClock mock_clock_;
47 };
48
SetUp()49 void FlingAnimationTest::SetUp() {
50 fling_animation_.SetTickClockForTest(&mock_clock_);
51 }
52
TearDown()53 void FlingAnimationTest::TearDown() {
54 ASSERT_FALSE(change_received_);
55 }
56
TickAnimation(base::TimeDelta time_delta)57 void FlingAnimationTest::TickAnimation(base::TimeDelta time_delta) {
58 mock_clock_.Advance(time_delta);
59 fling_animation_.Tick();
60 }
61
AssertDeltaChanged()62 void FlingAnimationTest::AssertDeltaChanged() {
63 ASSERT_TRUE(change_received_);
64 change_received_ = false;
65 }
66
OnDeltaChanged(float dx,float dy)67 void FlingAnimationTest::OnDeltaChanged(float dx, float dy) {
68 received_dx_ = dx;
69 received_dy_ = dy;
70 change_received_ = true;
71 }
72
TEST_F(FlingAnimationTest,TestNoFling)73 TEST_F(FlingAnimationTest, TestNoFling) {
74 EXPECT_FALSE(fling_animation_.IsAnimationInProgress());
75
76 // This should not change the delta.
77 TickAnimation(base::TimeDelta::FromMilliseconds(100));
78 }
79
TEST_F(FlingAnimationTest,TestFlingWillEventuallyStop)80 TEST_F(FlingAnimationTest, TestFlingWillEventuallyStop) {
81 fling_animation_.SetVelocity(1500.f, 1200.f);
82
83 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
84
85 TickAnimation(base::TimeDelta::FromMinutes(1));
86
87 EXPECT_FALSE(fling_animation_.IsAnimationInProgress());
88 }
89
TEST_F(FlingAnimationTest,TestFlingDeltaIsDecreasing)90 TEST_F(FlingAnimationTest, TestFlingDeltaIsDecreasing) {
91 fling_animation_.SetVelocity(1500.f, 1200.f);
92
93 float previous_dx = std::numeric_limits<float>::infinity();
94 float previous_dy = std::numeric_limits<float>::infinity();
95
96 while (true) {
97 TickAnimation(base::TimeDelta::FromMilliseconds(16));
98 if (!fling_animation_.IsAnimationInProgress()) {
99 break;
100 }
101 AssertDeltaChanged();
102 float hyp =
103 std::sqrt(received_dx_ * received_dx_ + received_dy_ * received_dy_);
104 float prev_hyp =
105 std::sqrt(previous_dx * previous_dx + previous_dy * previous_dy);
106 EXPECT_LT(hyp, prev_hyp);
107 previous_dx = received_dx_;
108 previous_dy = received_dy_;
109 }
110 }
111
TEST_F(FlingAnimationTest,TestIgnoreLowVelocity)112 TEST_F(FlingAnimationTest, TestIgnoreLowVelocity) {
113 fling_animation_.SetVelocity(5.f, 5.f);
114
115 EXPECT_FALSE(fling_animation_.IsAnimationInProgress());
116
117 // This should not change the delta.
118 TickAnimation(base::TimeDelta::FromMilliseconds(5));
119 }
120
TEST_F(FlingAnimationTest,TestAbortAnimation)121 TEST_F(FlingAnimationTest, TestAbortAnimation) {
122 fling_animation_.SetVelocity(1500.f, 1200.f);
123
124 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
125
126 TickAnimation(base::TimeDelta::FromMilliseconds(16));
127 AssertDeltaChanged();
128 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
129
130 fling_animation_.Abort();
131 EXPECT_FALSE(fling_animation_.IsAnimationInProgress());
132 }
133
TEST_F(FlingAnimationTest,TestResetVelocity)134 TEST_F(FlingAnimationTest, TestResetVelocity) {
135 fling_animation_.SetVelocity(1000.f, -1000.f);
136 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
137 TickAnimation(base::TimeDelta::FromMilliseconds(16));
138 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
139 AssertDeltaChanged();
140 EXPECT_GT(received_dx_, 0);
141 EXPECT_LT(received_dy_, 0);
142
143 fling_animation_.SetVelocity(-1000.f, 1000.f);
144 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
145 TickAnimation(base::TimeDelta::FromMilliseconds(16));
146 EXPECT_TRUE(fling_animation_.IsAnimationInProgress());
147 AssertDeltaChanged();
148 EXPECT_LT(received_dx_, 0);
149 EXPECT_GT(received_dy_, 0);
150 }
151
152 } // namespace remoting
153