blob: 778eec043421ad08be1e1410bab9afc3d1354ef4 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stddef.h>
#include <new>
#include <utility>
#include <vector>
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/test/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_simple_task_runner.h"
#include "build/build_config.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/renderer/input/main_thread_event_queue.h"
#include "content/renderer/render_thread_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/scheduler/test/mock_renderer_scheduler.h"
using blink::WebInputEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
using blink::WebTouchEvent;
namespace blink {
bool operator==(const WebMouseWheelEvent& lhs, const WebMouseWheelEvent& rhs) {
return memcmp(&lhs, &rhs, lhs.size) == 0;
}
bool operator==(const WebTouchEvent& lhs, const WebTouchEvent& rhs) {
return memcmp(&lhs, &rhs, lhs.size) == 0;
}
} // namespace blink
namespace content {
namespace {
const unsigned kRafAlignedEnabledTouch = 1;
const unsigned kRafAlignedEnabledMouse = 1 << 1;
const int kTestRoutingID = 13;
const char* kCoalescedCountHistogram =
"Event.MainThreadEventQueue.CoalescedCount";
} // namespace
class MainThreadEventQueueTest : public testing::TestWithParam<unsigned>,
public MainThreadEventQueueClient {
public:
MainThreadEventQueueTest()
: main_task_runner_(new base::TestSimpleTaskRunner()),
raf_aligned_input_setting_(GetParam()),
needs_main_frame_(false) {
std::vector<std::string> features;
if (raf_aligned_input_setting_ & kRafAlignedEnabledTouch)
features.push_back(features::kRafAlignedTouchInputEvents.name);
if (raf_aligned_input_setting_ & kRafAlignedEnabledMouse)
features.push_back(features::kRafAlignedMouseInputEvents.name);
feature_list_.InitFromCommandLine(base::JoinString(features, ","),
std::string());
}
void SetUp() override {
queue_ = new MainThreadEventQueue(kTestRoutingID, this, main_task_runner_,
&renderer_scheduler_);
}
void HandleEventOnMainThread(int routing_id,
const blink::WebInputEvent* event,
const ui::LatencyInfo& latency,
InputEventDispatchType type) override {
EXPECT_EQ(kTestRoutingID, routing_id);
handled_events_.push_back(ui::WebInputEventTraits::Clone(*event));
queue_->EventHandled(event->type, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
void SendInputEventAck(int routing_id,
blink::WebInputEvent::Type type,
InputEventAckState ack_result,
uint32_t touch_event_id) override {
additional_acked_events_.push_back(touch_event_id);
}
void HandleEvent(WebInputEvent& event, InputEventAckState ack_result) {
queue_->HandleEvent(ui::WebInputEventTraits::Clone(event),
ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING, ack_result);
}
void NeedsMainFrame(int routing_id) override { needs_main_frame_ = true; }
WebInputEventQueue<EventWithDispatchType>& event_queue() {
return queue_->shared_state_.events_;
}
bool last_touch_start_forced_nonblocking_due_to_fling() {
return queue_->last_touch_start_forced_nonblocking_due_to_fling_;
}
void set_enable_fling_passive_listener_flag(bool enable_flag) {
queue_->enable_fling_passive_listener_flag_ = enable_flag;
}
void RunPendingTasksWithSimulatedRaf() {
while (needs_main_frame_ || main_task_runner_->HasPendingTask()) {
main_task_runner_->RunUntilIdle();
needs_main_frame_ = false;
queue_->DispatchRafAlignedInput();
}
}
void RunSimulatedRafOnce() {
if (needs_main_frame_) {
needs_main_frame_ = false;
queue_->DispatchRafAlignedInput();
}
}
protected:
base::test::ScopedFeatureList feature_list_;
scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
blink::scheduler::MockRendererScheduler renderer_scheduler_;
scoped_refptr<MainThreadEventQueue> queue_;
std::vector<ui::ScopedWebInputEvent> handled_events_;
std::vector<uint32_t> additional_acked_events_;
int raf_aligned_input_setting_;
bool needs_main_frame_;
};
TEST_P(MainThreadEventQueueTest, NonBlockingWheel) {
base::HistogramTester histogram_tester;
WebMouseWheelEvent kEvents[4] = {
SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 0, false),
SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
};
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
for (WebMouseWheelEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
EXPECT_EQ((raf_aligned_input_setting_ & kRafAlignedEnabledMouse) == 0,
main_task_runner_->HasPendingTask());
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(2u, handled_events_.size());
{
EXPECT_EQ(kEvents[0].size, handled_events_.at(0)->size);
EXPECT_EQ(kEvents[0].type, handled_events_.at(0)->type);
const WebMouseWheelEvent* last_wheel_event =
static_cast<const WebMouseWheelEvent*>(handled_events_.at(0).get());
EXPECT_EQ(WebInputEvent::DispatchType::ListenersNonBlockingPassive,
last_wheel_event->dispatchType);
WebMouseWheelEvent coalesced_event = kEvents[0];
ui::Coalesce(kEvents[1], &coalesced_event);
coalesced_event.dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(coalesced_event, *last_wheel_event);
}
{
const WebMouseWheelEvent* last_wheel_event =
static_cast<const WebMouseWheelEvent*>(handled_events_.at(1).get());
WebMouseWheelEvent coalesced_event = kEvents[2];
ui::Coalesce(kEvents[3], &coalesced_event);
coalesced_event.dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(coalesced_event, *last_wheel_event);
}
histogram_tester.ExpectUniqueSample(kCoalescedCountHistogram, 1, 2);
}
TEST_P(MainThreadEventQueueTest, NonBlockingTouch) {
base::HistogramTester histogram_tester;
SyntheticWebTouchEvent kEvents[4];
kEvents[0].PressPoint(10, 10);
kEvents[1].PressPoint(10, 10);
kEvents[1].modifiers = 1;
kEvents[1].MovePoint(0, 20, 20);
kEvents[2].PressPoint(10, 10);
kEvents[2].MovePoint(0, 30, 30);
kEvents[3].PressPoint(10, 10);
kEvents[3].MovePoint(0, 35, 35);
for (SyntheticWebTouchEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(3u, event_queue().size());
EXPECT_TRUE(main_task_runner_->HasPendingTask());
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(3u, handled_events_.size());
EXPECT_EQ(kEvents[0].size, handled_events_.at(0)->size);
EXPECT_EQ(kEvents[0].type, handled_events_.at(0)->type);
const WebTouchEvent* last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(0).get());
kEvents[0].dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(kEvents[0], *last_touch_event);
EXPECT_EQ(kEvents[1].size, handled_events_.at(1)->size);
EXPECT_EQ(kEvents[1].type, handled_events_.at(1)->type);
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(1).get());
kEvents[1].dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(kEvents[1], *last_touch_event);
EXPECT_EQ(kEvents[2].size, handled_events_.at(1)->size);
EXPECT_EQ(kEvents[2].type, handled_events_.at(2)->type);
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(2).get());
WebTouchEvent coalesced_event = kEvents[2];
ui::Coalesce(kEvents[3], &coalesced_event);
coalesced_event.dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(coalesced_event, *last_touch_event);
histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 0, 1);
histogram_tester.ExpectBucketCount(kCoalescedCountHistogram, 1, 1);
}
TEST_P(MainThreadEventQueueTest, BlockingTouch) {
base::HistogramTester histogram_tester;
SyntheticWebTouchEvent kEvents[4];
kEvents[0].PressPoint(10, 10);
kEvents[1].PressPoint(10, 10);
kEvents[1].MovePoint(0, 20, 20);
kEvents[2].PressPoint(10, 10);
kEvents[2].MovePoint(0, 30, 30);
kEvents[3].PressPoint(10, 10);
kEvents[3].MovePoint(0, 35, 35);
EXPECT_CALL(renderer_scheduler_, DidHandleInputEventOnMainThread(testing::_))
.Times(2);
// Ensure that coalescing takes place.
HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
HandleEvent(kEvents[2], INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
HandleEvent(kEvents[3], INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(2u, event_queue().size());
EXPECT_TRUE(main_task_runner_->HasPendingTask());
RunPendingTasksWithSimulatedRaf();
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(2u, additional_acked_events_.size());
EXPECT_EQ(kEvents[2].uniqueTouchEventId, additional_acked_events_.at(0));
EXPECT_EQ(kEvents[3].uniqueTouchEventId, additional_acked_events_.at(1));
HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kEvents[2], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kEvents[3], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(1u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
histogram_tester.ExpectUniqueSample(kCoalescedCountHistogram, 2, 1);
}
TEST_P(MainThreadEventQueueTest, InterleavedEvents) {
WebMouseWheelEvent kWheelEvents[2] = {
SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 0, false),
SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
};
SyntheticWebTouchEvent kTouchEvents[2];
kTouchEvents[0].PressPoint(10, 10);
kTouchEvents[0].MovePoint(0, 20, 20);
kTouchEvents[1].PressPoint(10, 10);
kTouchEvents[1].MovePoint(0, 30, 30);
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
HandleEvent(kWheelEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kTouchEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kWheelEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kTouchEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
EXPECT_EQ(raf_aligned_input_setting_ !=
(kRafAlignedEnabledMouse | kRafAlignedEnabledTouch),
main_task_runner_->HasPendingTask());
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(2u, handled_events_.size());
{
EXPECT_EQ(kWheelEvents[0].size, handled_events_.at(0)->size);
EXPECT_EQ(kWheelEvents[0].type, handled_events_.at(0)->type);
const WebMouseWheelEvent* last_wheel_event =
static_cast<const WebMouseWheelEvent*>(handled_events_.at(0).get());
EXPECT_EQ(WebInputEvent::DispatchType::ListenersNonBlockingPassive,
last_wheel_event->dispatchType);
WebMouseWheelEvent coalesced_event = kWheelEvents[0];
ui::Coalesce(kWheelEvents[1], &coalesced_event);
coalesced_event.dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(coalesced_event, *last_wheel_event);
}
{
EXPECT_EQ(kTouchEvents[0].size, handled_events_.at(1)->size);
EXPECT_EQ(kTouchEvents[0].type, handled_events_.at(1)->type);
const WebTouchEvent* last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(1).get());
WebTouchEvent coalesced_event = kTouchEvents[0];
ui::Coalesce(kTouchEvents[1], &coalesced_event);
coalesced_event.dispatchType =
WebInputEvent::DispatchType::ListenersNonBlockingPassive;
EXPECT_EQ(coalesced_event, *last_touch_event);
}
}
TEST_P(MainThreadEventQueueTest, RafAlignedMouseInput) {
// Don't run the test when we aren't supporting rAF aligned input.
if ((raf_aligned_input_setting_ & kRafAlignedEnabledMouse) == 0)
return;
WebMouseEvent mouseDown =
SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseDown, 10, 10, 0);
WebMouseEvent mouseMove =
SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseMove, 10, 10, 0);
WebMouseEvent mouseUp =
SyntheticWebMouseEventBuilder::Build(WebInputEvent::MouseUp, 10, 10, 0);
WebMouseWheelEvent wheelEvents[2] = {
SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 0, false),
SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
};
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
// Simulate enqueing a discrete event, followed by continuous events and
// then a discrete event. The last discrete event should flush the
// continuous events so the aren't aligned to rAF and are processed
// immediately.
HandleEvent(mouseDown, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(mouseMove, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(wheelEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(wheelEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(mouseUp, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(4u, event_queue().size());
EXPECT_TRUE(main_task_runner_->HasPendingTask());
EXPECT_TRUE(needs_main_frame_);
main_task_runner_->RunUntilIdle();
EXPECT_EQ(0u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
// Simulate the rAF running before the PostTask occurs. The first rAF
// shouldn't do anything.
HandleEvent(mouseDown, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(wheelEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
EXPECT_TRUE(needs_main_frame_);
RunSimulatedRafOnce();
EXPECT_FALSE(needs_main_frame_);
EXPECT_EQ(2u, event_queue().size());
main_task_runner_->RunUntilIdle();
EXPECT_TRUE(needs_main_frame_);
EXPECT_EQ(1u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
EXPECT_EQ(0u, event_queue().size());
}
TEST_P(MainThreadEventQueueTest, RafAlignedTouchInput) {
// Don't run the test when we aren't supporting rAF aligned input.
if ((raf_aligned_input_setting_ & kRafAlignedEnabledTouch) == 0)
return;
SyntheticWebTouchEvent kEvents[3];
kEvents[0].PressPoint(10, 10);
kEvents[1].PressPoint(10, 10);
kEvents[1].MovePoint(0, 50, 50);
kEvents[2].PressPoint(10, 10);
kEvents[2].ReleasePoint(0);
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
// Simulate enqueing a discrete event, followed by continuous events and
// then a discrete event. The last discrete event should flush the
// continuous events so the aren't aligned to rAF and are processed
// immediately.
for (SyntheticWebTouchEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(3u, event_queue().size());
EXPECT_TRUE(main_task_runner_->HasPendingTask());
EXPECT_TRUE(needs_main_frame_);
main_task_runner_->RunUntilIdle();
EXPECT_EQ(0u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
// Simulate the rAF running before the PostTask occurs. The first rAF
// shouldn't do anything.
HandleEvent(kEvents[0], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
HandleEvent(kEvents[1], INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
EXPECT_EQ(2u, event_queue().size());
EXPECT_TRUE(needs_main_frame_);
RunSimulatedRafOnce();
EXPECT_FALSE(needs_main_frame_);
EXPECT_EQ(2u, event_queue().size());
RunPendingTasksWithSimulatedRaf();
EXPECT_EQ(0u, event_queue().size());
// Simulate the touch move being discrete
kEvents[0].touchStartOrFirstTouchMove = true;
kEvents[1].touchStartOrFirstTouchMove = true;
for (SyntheticWebTouchEvent& event : kEvents)
HandleEvent(event, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_EQ(3u, event_queue().size());
EXPECT_TRUE(main_task_runner_->HasPendingTask());
EXPECT_FALSE(needs_main_frame_);
main_task_runner_->RunUntilIdle();
}
TEST_P(MainThreadEventQueueTest, BlockingTouchesDuringFling) {
SyntheticWebTouchEvent kEvents;
kEvents.PressPoint(10, 10);
kEvents.touchStartOrFirstTouchMove = true;
set_enable_fling_passive_listener_flag(true);
EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(1u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(0)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(0)->type);
EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
const WebTouchEvent* last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(0).get());
kEvents.dispatchType = WebInputEvent::ListenersForcedNonBlockingDueToFling;
EXPECT_EQ(kEvents, *last_touch_event);
kEvents.MovePoint(0, 30, 30);
EXPECT_FALSE(main_task_runner_->HasPendingTask());
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING);
EXPECT_EQ((raf_aligned_input_setting_ & kRafAlignedEnabledTouch) == 0,
main_task_runner_->HasPendingTask());
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(2u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(1)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(1)->type);
EXPECT_TRUE(last_touch_start_forced_nonblocking_due_to_fling());
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(1).get());
kEvents.dispatchType = WebInputEvent::ListenersForcedNonBlockingDueToFling;
EXPECT_EQ(kEvents, *last_touch_event);
kEvents.MovePoint(0, 50, 50);
kEvents.touchStartOrFirstTouchMove = false;
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(3u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(2)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(2)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(2).get());
EXPECT_EQ(kEvents, *last_touch_event);
kEvents.ReleasePoint(0);
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING_DUE_TO_FLING);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(4u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(3)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(3)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(3).get());
EXPECT_EQ(kEvents, *last_touch_event);
}
TEST_P(MainThreadEventQueueTest, BlockingTouchesOutsideFling) {
SyntheticWebTouchEvent kEvents;
kEvents.PressPoint(10, 10);
kEvents.touchStartOrFirstTouchMove = true;
set_enable_fling_passive_listener_flag(false);
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(1u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(0)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(0)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
const WebTouchEvent* last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(0).get());
EXPECT_EQ(kEvents, *last_touch_event);
set_enable_fling_passive_listener_flag(false);
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(2u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(1)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(1)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(1).get());
EXPECT_EQ(kEvents, *last_touch_event);
set_enable_fling_passive_listener_flag(true);
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(3u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(2)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(2)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(2).get());
EXPECT_EQ(kEvents, *last_touch_event);
kEvents.MovePoint(0, 30, 30);
HandleEvent(kEvents, INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
RunPendingTasksWithSimulatedRaf();
EXPECT_FALSE(main_task_runner_->HasPendingTask());
EXPECT_EQ(0u, event_queue().size());
EXPECT_EQ(4u, handled_events_.size());
EXPECT_EQ(kEvents.size, handled_events_.at(3)->size);
EXPECT_EQ(kEvents.type, handled_events_.at(3)->type);
EXPECT_EQ(kEvents.dispatchType, WebInputEvent::Blocking);
EXPECT_FALSE(last_touch_start_forced_nonblocking_due_to_fling());
last_touch_event =
static_cast<const WebTouchEvent*>(handled_events_.at(3).get());
EXPECT_EQ(kEvents, *last_touch_event);
}
// The boolean parameterized test varies whether rAF aligned input
// is enabled or not.
INSTANTIATE_TEST_CASE_P(
MainThreadEventQueueTests,
MainThreadEventQueueTest,
testing::Range(0u,
(kRafAlignedEnabledTouch | kRafAlignedEnabledMouse) + 1));
} // namespace content