NRWT lies about the number of tests that it's skipping when used with --repeat-each
[WebKit-https.git] / Source / WebKit / chromium / tests / WebCompositorInputHandlerImplTest.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #include "WebCompositorInputHandlerImpl.h"
29
30 #include "CCActiveGestureAnimation.h"
31 #include "CCInputHandler.h"
32 #include "CCSingleThreadProxy.h"
33 #include "WebCompositorInputHandlerClient.h"
34 #include "WebInputEvent.h"
35 #include <public/WebCompositor.h>
36 #include <public/WebFloatPoint.h>
37 #include <public/WebPoint.h>
38
39 #include <gmock/gmock.h>
40 #include <gtest/gtest.h>
41 #include <wtf/OwnPtr.h>
42
43 using namespace WebKit;
44
45 namespace {
46
47 class MockCCInputHandlerClient : public WebCore::CCInputHandlerClient {
48     WTF_MAKE_NONCOPYABLE(MockCCInputHandlerClient);
49 public:
50     MockCCInputHandlerClient()
51     {
52     }
53     virtual ~MockCCInputHandlerClient() { }
54
55
56     MOCK_METHOD0(pinchGestureBegin, void());
57     MOCK_METHOD2(pinchGestureUpdate, void(float magnifyDelta, const WebCore::IntPoint& anchor));
58     MOCK_METHOD0(pinchGestureEnd, void());
59
60     MOCK_METHOD0(scheduleAnimation, void());
61
62     MOCK_METHOD2(scrollBegin, ScrollStatus(const WebCore::IntPoint&, WebCore::CCInputHandlerClient::ScrollInputType));
63     MOCK_METHOD2(scrollBy, void(const WebCore::IntPoint&, const WebCore::IntSize&));
64     MOCK_METHOD0(scrollEnd, void());
65
66 private:
67     virtual void startPageScaleAnimation(const WebCore::IntSize& targetPosition,
68                                          bool anchorPoint,
69                                          float pageScale,
70                                          double startTimeMs,
71                                          double durationMs) OVERRIDE { }
72
73     virtual WebCore::CCActiveGestureAnimation* activeGestureAnimation() OVERRIDE { return 0; }
74     virtual void setActiveGestureAnimation(PassOwnPtr<WebCore::CCActiveGestureAnimation>) OVERRIDE { }
75 };
76
77 class MockWebCompositorInputHandlerClient : public WebCompositorInputHandlerClient {
78     WTF_MAKE_NONCOPYABLE(MockWebCompositorInputHandlerClient);
79 public:
80     MockWebCompositorInputHandlerClient()
81         : WebCompositorInputHandlerClient()
82     {
83     }
84     virtual ~MockWebCompositorInputHandlerClient() { }
85
86     MOCK_METHOD0(willShutdown, void());
87     MOCK_METHOD0(didHandleInputEvent, void());
88     MOCK_METHOD1(didNotHandleInputEvent, void(bool sendToWidget));
89
90     MOCK_METHOD1(transferActiveWheelFlingAnimation, void(const WebActiveWheelFlingParameters&));
91
92 };
93
94 TEST(WebCompositorInputHandlerImpl, fromIdentifier)
95 {
96     WebCompositor::initialize(0);
97     WebCore::DebugScopedSetImplThread alwaysImplThread;
98
99     // Before creating any WebCompositorInputHandlers, lookups for any value should fail and not crash.
100     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(2));
101     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(0));
102     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(-1));
103
104     int compositorIdentifier = -1;
105     {
106         OwnPtr<WebCompositorInputHandlerImpl> inputHandler = WebCompositorInputHandlerImpl::create(0);
107         compositorIdentifier = inputHandler->identifier();
108         // The compositor we just created should be locatable.
109         EXPECT_EQ(inputHandler.get(), WebCompositorInputHandler::fromIdentifier(compositorIdentifier));
110
111         // But nothing else.
112         EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(inputHandler->identifier() + 10));
113     }
114
115     // After the compositor is destroyed, its entry should be removed from the map.
116     EXPECT_EQ(0, WebCompositorInputHandler::fromIdentifier(compositorIdentifier));
117     WebCompositor::shutdown();
118 }
119
120 class WebCompositorInitializer {
121 public:
122     WebCompositorInitializer()
123     {
124         WebCompositor::initialize(0);
125     }
126
127     ~WebCompositorInitializer()
128     {
129         WebCompositor::shutdown();
130     }
131 };
132
133 class WebCompositorInputHandlerImplTest : public testing::Test {
134 public:
135     WebCompositorInputHandlerImplTest()
136         : m_expectedDisposition(DidHandle)
137     {
138         m_inputHandler = WebCompositorInputHandlerImpl::create(&m_mockCCInputHandlerClient);
139         m_inputHandler->setClient(&m_mockClient);
140     }
141
142     ~WebCompositorInputHandlerImplTest()
143     {
144         m_inputHandler->setClient(0);
145         m_inputHandler.clear();
146     }
147
148     // This is defined as a macro because when an expectation is not satisfied the only output you get
149     // out of gmock is the line number that set the expectation.
150 #define VERIFY_AND_RESET_MOCKS() do                                                                                      \
151     {                                                                                                                    \
152         testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);                                          \
153         testing::Mock::VerifyAndClearExpectations(&m_mockClient);                                                        \
154         switch (m_expectedDisposition) {                                                                                 \
155         case DidHandle:                                                                                                  \
156             /* If we expect to handle events, we shouldn't get any didNotHandleInputEvent() calls with any parameter. */ \
157             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(::testing::_)).Times(0);                                    \
158             EXPECT_CALL(m_mockClient, didHandleInputEvent());                                                            \
159             break;                                                                                                       \
160         case DidNotHandle:                                                                                               \
161             /* If we aren't expecting to handle events, we shouldn't call didHandleInputEvent(). */                      \
162             EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0);                                                   \
163             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false)).Times(0);                                           \
164             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));                                                     \
165             break;                                                                                                       \
166         case DropEvent:                                                                                                  \
167             /* If we're expecting to drop, we shouldn't get any didHandle..() or didNotHandleInputEvent(true) calls. */  \
168             EXPECT_CALL(m_mockClient, didHandleInputEvent()).Times(0);                                                   \
169             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true)).Times(0);                                            \
170             EXPECT_CALL(m_mockClient, didNotHandleInputEvent(false));                                                    \
171             break;                                                                                                       \
172         }                                                                                                                                                       \
173     } while (0)
174
175 protected:
176     MockCCInputHandlerClient m_mockCCInputHandlerClient;
177     OwnPtr<WebCompositorInputHandlerImpl> m_inputHandler;
178     MockWebCompositorInputHandlerClient m_mockClient;
179     WebGestureEvent gesture;
180     WebCore::DebugScopedSetImplThread alwaysImplThread;
181     WebCompositorInitializer initializer;
182
183     enum ExpectedDisposition { DidHandle, DidNotHandle, DropEvent };
184     ExpectedDisposition m_expectedDisposition;
185 };
186
187
188 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollStarted)
189 {
190     // We shouldn't send any events to the widget for this gesture.
191     m_expectedDisposition = DidHandle;
192     VERIFY_AND_RESET_MOCKS();
193
194     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
195         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
196
197     gesture.type = WebInputEvent::GestureScrollBegin;
198     m_inputHandler->handleInputEvent(gesture);
199
200     VERIFY_AND_RESET_MOCKS();
201
202     gesture.type = WebInputEvent::GestureScrollUpdate;
203     gesture.deltaY = -40; // -Y means scroll down - i.e. in the +Y direction.
204     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
205     m_inputHandler->handleInputEvent(gesture);
206
207     VERIFY_AND_RESET_MOCKS();
208
209     gesture.type = WebInputEvent::GestureScrollEnd;
210     gesture.deltaY = 0;
211     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
212     m_inputHandler->handleInputEvent(gesture);
213 }
214
215 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollOnMainThread)
216 {
217     // We should send all events to the widget for this gesture.
218     m_expectedDisposition = DidNotHandle;
219     VERIFY_AND_RESET_MOCKS();
220
221     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(::testing::_, ::testing::_))
222         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
223
224     gesture.type = WebInputEvent::GestureScrollBegin;
225     m_inputHandler->handleInputEvent(gesture);
226
227     VERIFY_AND_RESET_MOCKS();
228
229     gesture.type = WebInputEvent::GestureScrollUpdate;
230     gesture.deltaY = 40;
231     m_inputHandler->handleInputEvent(gesture);
232
233     VERIFY_AND_RESET_MOCKS();
234
235     gesture.type = WebInputEvent::GestureScrollEnd;
236     gesture.deltaY = 0;
237     m_inputHandler->handleInputEvent(gesture);
238 }
239
240 TEST_F(WebCompositorInputHandlerImplTest, gestureScrollIgnored)
241 {
242     // We shouldn't handle the GestureScrollBegin.
243     // Instead, we should get one didNotHandleInputEvent(false) call per handleInputEvent(),
244     // indicating that we could determine that there's nothing that could scroll or otherwise
245     // react to this gesture sequence and thus we should drop the whole gesture sequence on the floor.
246     m_expectedDisposition = DropEvent;
247     VERIFY_AND_RESET_MOCKS();
248
249     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
250         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
251
252     gesture.type = WebInputEvent::GestureScrollBegin;
253     m_inputHandler->handleInputEvent(gesture);
254 }
255
256 TEST_F(WebCompositorInputHandlerImplTest, gesturePinch)
257 {
258     // We shouldn't send any events to the widget for this gesture.
259     m_expectedDisposition = DidHandle;
260     VERIFY_AND_RESET_MOCKS();
261
262     gesture.type = WebInputEvent::GesturePinchBegin;
263     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureBegin());
264     m_inputHandler->handleInputEvent(gesture);
265
266     VERIFY_AND_RESET_MOCKS();
267
268     gesture.type = WebInputEvent::GesturePinchUpdate;
269     gesture.deltaX = 1.5;
270     gesture.x = 7;
271     gesture.y = 13;
272     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(1.5, WebCore::IntPoint(7, 13)));
273     m_inputHandler->handleInputEvent(gesture);
274
275     VERIFY_AND_RESET_MOCKS();
276
277     gesture.type = WebInputEvent::GesturePinchUpdate;
278     gesture.deltaX = 0.5;
279     gesture.x = 9;
280     gesture.y = 6;
281     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureUpdate(.5, WebCore::IntPoint(9, 6)));
282     m_inputHandler->handleInputEvent(gesture);
283
284     VERIFY_AND_RESET_MOCKS();
285
286     gesture.type = WebInputEvent::GesturePinchEnd;
287     EXPECT_CALL(m_mockCCInputHandlerClient, pinchGestureEnd());
288     m_inputHandler->handleInputEvent(gesture);
289 }
290
291 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingStarted)
292 {
293     // We shouldn't send any events to the widget for this gesture.
294     m_expectedDisposition = DidHandle;
295     VERIFY_AND_RESET_MOCKS();
296
297     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
298         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
299
300     gesture.type = WebInputEvent::GestureFlingStart;
301     gesture.deltaX = 10;
302     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
303     m_inputHandler->handleInputEvent(gesture);
304
305     VERIFY_AND_RESET_MOCKS();
306
307     // Verify that a GestureFlingCancel during an animation cancels it.
308     gesture.type = WebInputEvent::GestureFlingCancel;
309     m_inputHandler->handleInputEvent(gesture);
310 }
311
312 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingFailed)
313 {
314     // We should send all events to the widget for this gesture.
315     m_expectedDisposition = DidNotHandle;
316     VERIFY_AND_RESET_MOCKS();
317
318     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
319         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
320
321     gesture.type = WebInputEvent::GestureFlingStart;
322     m_inputHandler->handleInputEvent(gesture);
323
324     VERIFY_AND_RESET_MOCKS();
325
326     // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
327     gesture.type = WebInputEvent::GestureFlingCancel;
328     m_inputHandler->handleInputEvent(gesture);
329 }
330
331 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingIgnored)
332 {
333     m_expectedDisposition = DidNotHandle;
334     VERIFY_AND_RESET_MOCKS();
335
336     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
337         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollIgnored));
338
339     gesture.type = WebInputEvent::GestureFlingStart;
340     m_inputHandler->handleInputEvent(gesture);
341
342     VERIFY_AND_RESET_MOCKS();
343
344     // Even if we didn't start a fling ourselves, we still need to send the cancel event to the widget.
345     gesture.type = WebInputEvent::GestureFlingCancel;
346     m_inputHandler->handleInputEvent(gesture);
347 }
348
349 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingAnimates)
350 {
351     // We shouldn't send any events to the widget for this gesture.
352     m_expectedDisposition = DidHandle;
353     VERIFY_AND_RESET_MOCKS();
354
355     // On the fling start, we should schedule an animation but not actually start
356     // scrolling.
357     gesture.type = WebInputEvent::GestureFlingStart;
358     WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
359     WebPoint flingPoint = WebPoint(7, 13);
360     WebPoint flingGlobalPoint = WebPoint(17, 23);
361     int modifiers = 7;
362     gesture.deltaX = flingDelta.x;
363     gesture.deltaY = flingDelta.y;
364     gesture.x = flingPoint.x;
365     gesture.y = flingPoint.y;
366     gesture.globalX = flingGlobalPoint.x;
367     gesture.globalY = flingGlobalPoint.y;
368     gesture.modifiers = modifiers;
369     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
370     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
371         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
372     m_inputHandler->handleInputEvent(gesture);
373
374     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
375     // The first animate call should let us pick up an animation start time, but we
376     // shouldn't actually move anywhere just yet. The first frame after the fling start
377     // will typically include the last scroll from the gesture that lead to the scroll
378     // (either wheel or gesture scroll), so there should be no visible hitch.
379     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
380     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
381     m_inputHandler->animate(10);
382
383     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
384
385     // The second call should start scrolling in the -X direction.
386     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
387     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
388         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
389     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
390     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
391     m_inputHandler->animate(10.1);
392
393     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
394
395     // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
396     // We also should pass the current fling parameters out to the client so the rest of the fling can be
397     // transferred to the main thread.
398     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
399     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
400         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
401     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::_)).Times(0);
402     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
403
404     // Expected wheel fling animation parameters:
405     // *) flingDelta and flingPoint should match the original GestureFlingStart event
406     // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
407     // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
408     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
409         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
410         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
411         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
412         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
413         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
414         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
415             testing::Field(&WebSize::width, testing::Gt(0))))));
416     m_inputHandler->animate(10.2);
417
418     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
419     testing::Mock::VerifyAndClearExpectations(&m_mockClient);
420
421     // Since we've aborted the fling, the next animation should be a no-op and should not result in another
422     // frame being requested.
423     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
424     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
425     m_inputHandler->animate(10.3);
426
427     // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
428     // thread as well.
429     EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
430     gesture.type = WebInputEvent::GestureFlingCancel;
431     m_inputHandler->handleInputEvent(gesture);
432 }
433
434 TEST_F(WebCompositorInputHandlerImplTest, gestureFlingTransferResets)
435 {
436     // We shouldn't send any events to the widget for this gesture.
437     m_expectedDisposition = DidHandle;
438     VERIFY_AND_RESET_MOCKS();
439
440     // Start a gesture fling in the -X direction with zero Y movement.
441     gesture.type = WebInputEvent::GestureFlingStart;
442     WebFloatPoint flingDelta = WebFloatPoint(1000, 0);
443     WebPoint flingPoint = WebPoint(7, 13);
444     WebPoint flingGlobalPoint = WebPoint(17, 23);
445     int modifiers = 1;
446     gesture.deltaX = flingDelta.x;
447     gesture.deltaY = flingDelta.y;
448     gesture.x = flingPoint.x;
449     gesture.y = flingPoint.y;
450     gesture.globalX = flingGlobalPoint.x;
451     gesture.globalY = flingGlobalPoint.y;
452     gesture.modifiers = modifiers;
453     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
454     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
455         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
456     m_inputHandler->handleInputEvent(gesture);
457
458     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
459
460     // Start the fling animation at time 10. This shouldn't actually scroll, just establish a start time.
461     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
462     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
463     m_inputHandler->animate(10);
464
465     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
466
467     // The second call should start scrolling in the -X direction.
468     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
469     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
470         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
471     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::Property(&WebCore::IntSize::width, testing::Lt(0))));
472     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
473     m_inputHandler->animate(10.1);
474
475     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
476
477     // Let's say on the third call we hit a non-scrollable region. We should abort the fling and not scroll.
478     // We also should pass the current fling parameters out to the client so the rest of the fling can be
479     // transferred to the main thread.
480     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
481     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
482         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
483     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::_)).Times(0);
484     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
485
486     // Expected wheel fling animation parameters:
487     // *) flingDelta and flingPoint should match the original GestureFlingStart event
488     // *) startTime should be 10 to match the time parameter of the first animate() call after the GestureFlingStart
489     // *) cumulativeScroll depends on the curve, but since we've animated in the -X direction the X value should be < 0
490     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
491         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
492         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
493         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
494         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
495         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(10)),
496         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
497             testing::Field(&WebSize::width, testing::Gt(0))))));
498     m_inputHandler->animate(10.2);
499
500     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
501     testing::Mock::VerifyAndClearExpectations(&m_mockClient);
502
503     // Since we've aborted the fling, the next animation should be a no-op and should not result in another
504     // frame being requested.
505     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation()).Times(0);
506     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
507     m_inputHandler->animate(10.3);
508
509     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
510
511     // Since we've transferred the fling to the main thread, we need to pass the next GestureFlingCancel to the main
512     // thread as well.
513     EXPECT_CALL(m_mockClient, didNotHandleInputEvent(true));
514     gesture.type = WebInputEvent::GestureFlingCancel;
515     m_inputHandler->handleInputEvent(gesture);
516
517     VERIFY_AND_RESET_MOCKS();
518
519     // Start a second gesture fling, this time in the +Y direction with no X.
520     gesture.type = WebInputEvent::GestureFlingStart;
521     flingDelta = WebFloatPoint(0, -1000);
522     flingPoint = WebPoint(95, 87);
523     flingGlobalPoint = WebPoint(32, 71);
524     modifiers = 2;
525     gesture.deltaX = flingDelta.x;
526     gesture.deltaY = flingDelta.y;
527     gesture.x = flingPoint.x;
528     gesture.y = flingPoint.y;
529     gesture.globalX = flingGlobalPoint.x;
530     gesture.globalY = flingGlobalPoint.y;
531     gesture.modifiers = modifiers;
532     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
533     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
534         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
535     m_inputHandler->handleInputEvent(gesture);
536
537     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
538
539     // Start the second fling animation at time 30.
540     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
541     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_)).Times(0);
542     m_inputHandler->animate(30);
543
544     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
545
546     // Tick the second fling once normally.
547     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
548     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
549         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollStarted));
550     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::Property(&WebCore::IntSize::height, testing::Gt(0))));
551     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd());
552     m_inputHandler->animate(30.1);
553
554     testing::Mock::VerifyAndClearExpectations(&m_mockCCInputHandlerClient);
555
556     // Then abort the second fling.
557     EXPECT_CALL(m_mockCCInputHandlerClient, scheduleAnimation());
558     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBegin(testing::_, testing::_))
559         .WillOnce(testing::Return(WebCore::CCInputHandlerClient::ScrollOnMainThread));
560     EXPECT_CALL(m_mockCCInputHandlerClient, scrollBy(testing::_, testing::_)).Times(0);
561     EXPECT_CALL(m_mockCCInputHandlerClient, scrollEnd()).Times(0);
562
563     // We should get parameters from the second fling, nothing from the first fling should "leak".
564     EXPECT_CALL(m_mockClient, transferActiveWheelFlingAnimation(testing::AllOf(
565         testing::Field(&WebActiveWheelFlingParameters::delta, testing::Eq(flingDelta)),
566         testing::Field(&WebActiveWheelFlingParameters::point, testing::Eq(flingPoint)),
567         testing::Field(&WebActiveWheelFlingParameters::globalPoint, testing::Eq(flingGlobalPoint)),
568         testing::Field(&WebActiveWheelFlingParameters::modifiers, testing::Eq(modifiers)),
569         testing::Field(&WebActiveWheelFlingParameters::startTime, testing::Eq(30)),
570         testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
571             testing::Field(&WebSize::height, testing::Lt(0))))));
572     m_inputHandler->animate(30.2);
573 }
574
575 }