#include "base/message_loop/message_pump.h"
#include <type_traits>
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/message_loop/message_pump_for_io.h"
#include "base/message_loop/message_pump_for_ui.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/task/single_thread_task_executor.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/input_hint_checker.h"
#include "base/test/test_support_android.h"
#endif
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#endif
_;
AnyNumber;
AtMost;
Invoke;
Return;
namespace base {
namespace {
constexpr bool ChromeControlsNativeEventProcessing(MessagePumpType pump_type) { … }
class MockMessagePumpDelegate : public MessagePump::Delegate { … };
class MessagePumpTest : public ::testing::TestWithParam<MessagePumpType> { … };
}
TEST_P(MessagePumpTest, QuitStopsWork) { … }
#if BUILDFLAG(IS_ANDROID)
class MockInputHintChecker : public android::InputHintChecker {
public:
MOCK_METHOD(bool, HasInputImplWithThrottling, (), (override));
};
TEST_P(MessagePumpTest, DetectingHasInputYieldsOnUi) {
testing::InSequence sequence;
MessagePumpType pump_type = GetParam();
testing::StrictMock<MockMessagePumpDelegate> delegate(pump_type);
testing::StrictMock<MockInputHintChecker> hint_checker_mock;
android::InputHintChecker::ScopedOverrideInstance scoped_override_hint(
&hint_checker_mock);
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(android::kYieldWithInputHint);
android::InputHintChecker::InitializeFeatures();
uint32_t initial_work_enters = GetAndroidNonDelayedWorkEnterCount();
EXPECT_CALL(delegate, DoWork).WillOnce(Invoke([] {
auto work_info =
MessagePump::Delegate::NextWorkInfo{.delayed_run_time = TimeTicks()};
CHECK(work_info.is_immediate());
return work_info;
}));
if (pump_type == MessagePumpType::UI) {
EXPECT_CALL(hint_checker_mock, HasInputImplWithThrottling())
.WillOnce(Invoke([] { return true; }));
}
EXPECT_CALL(delegate, DoWork).WillOnce(Invoke([this] {
message_pump_->Quit();
return MessagePump::Delegate::NextWorkInfo{.delayed_run_time =
TimeTicks::Max()};
}));
EXPECT_CALL(delegate, DoIdleWork()).Times(0);
message_pump_->Run(&delegate);
uint32_t work_loop_entered = (pump_type == MessagePumpType::UI) ? 2 : 0;
EXPECT_EQ(initial_work_enters + work_loop_entered,
GetAndroidNonDelayedWorkEnterCount());
}
#endif
TEST_P(MessagePumpTest, QuitStopsWorkWithNestedRunLoop) { … }
TEST_P(MessagePumpTest, YieldToNativeRequestedSmokeTest) { … }
TEST_P(MessagePumpTest, LeewaySmokeTest) { … }
TEST_P(MessagePumpTest, RunWithoutScheduleWorkInvokesDoWork) { … }
TEST_P(MessagePumpTest, NestedRunWithoutScheduleWorkInvokesDoWork) { … }
INSTANTIATE_TEST_SUITE_P(…);
}