Commit bcad4fec authored by Etienne Bergeron's avatar Etienne Bergeron Committed by Commit Bot

[3/4] Add tests for setting High Resolution timer

This CL is adding unittests from a recent commit:
  https://chromium-review.googlesource.com/c/chromium/src/+/2169069

The new tests ensure Time::ActivateHighResolutionTimer(...) is not
called when power is suspended.


Bug: 1074332, 1074028
Change-Id: I07de5932a0007163bedbd623ae276df0f2ea1af4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2200042
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771625}
parent 08ba61fb
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h"
#include <algorithm>
#include <utility>
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/message_loop/message_pump.h" #include "base/message_loop/message_pump.h"
......
...@@ -95,17 +95,6 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl ...@@ -95,17 +95,6 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl
void Quit() override; void Quit() override;
void EnsureWorkScheduled() override; void EnsureWorkScheduled() override;
private:
friend class DoWorkScope;
friend class RunScope;
// Returns the delay till the next task. If there's no delay TimeDelta::Max()
// will be returned.
TimeDelta DoWorkImpl(LazyNow* continuation_lazy_now);
void InitializeThreadTaskRunnerHandle()
EXCLUSIVE_LOCKS_REQUIRED(task_runner_lock_);
struct MainThreadOnly { struct MainThreadOnly {
MainThreadOnly(); MainThreadOnly();
~MainThreadOnly(); ~MainThreadOnly();
...@@ -135,6 +124,25 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl ...@@ -135,6 +124,25 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl
bool task_execution_allowed = true; bool task_execution_allowed = true;
}; };
const MainThreadOnly& MainThreadOnlyForTesting() const {
return main_thread_only_;
}
ThreadControllerPowerMonitor* ThreadControllerPowerMonitorForTesting() {
return &power_monitor_;
}
private:
friend class DoWorkScope;
friend class RunScope;
// Returns the delay till the next task. If there's no delay TimeDelta::Max()
// will be returned.
TimeDelta DoWorkImpl(LazyNow* continuation_lazy_now);
void InitializeThreadTaskRunnerHandle()
EXCLUSIVE_LOCKS_REQUIRED(task_runner_lock_);
MainThreadOnly& main_thread_only() { MainThreadOnly& main_thread_only() {
DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker); DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
return main_thread_only_; return main_thread_only_;
......
...@@ -4,19 +4,25 @@ ...@@ -4,19 +4,25 @@
#include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h" #include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h"
#include <queue>
#include <string>
#include <utility>
#include <vector>
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "base/power_monitor/power_monitor.h"
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/task/sequence_manager/thread_controller_power_monitor.h"
#include "base/test/bind_test_util.h" #include "base/test/bind_test_util.h"
#include "base/test/mock_callback.h" #include "base/test/mock_callback.h"
#include "base/test/simple_test_tick_clock.h" #include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include <queue>
using testing::_; using testing::_;
using testing::Invoke; using testing::Invoke;
using testing::ElementsAre; using testing::ElementsAre;
...@@ -30,7 +36,7 @@ class ThreadControllerForTest ...@@ -30,7 +36,7 @@ class ThreadControllerForTest
: public internal::ThreadControllerWithMessagePumpImpl { : public internal::ThreadControllerWithMessagePumpImpl {
public: public:
ThreadControllerForTest(std::unique_ptr<MessagePump> pump, ThreadControllerForTest(std::unique_ptr<MessagePump> pump,
SequenceManager::Settings& settings) const SequenceManager::Settings& settings)
: ThreadControllerWithMessagePumpImpl(std::move(pump), settings) {} : ThreadControllerWithMessagePumpImpl(std::move(pump), settings) {}
using ThreadControllerWithMessagePumpImpl::DoIdleWork; using ThreadControllerWithMessagePumpImpl::DoIdleWork;
...@@ -38,6 +44,10 @@ class ThreadControllerForTest ...@@ -38,6 +44,10 @@ class ThreadControllerForTest
using ThreadControllerWithMessagePumpImpl::EnsureWorkScheduled; using ThreadControllerWithMessagePumpImpl::EnsureWorkScheduled;
using ThreadControllerWithMessagePumpImpl::Quit; using ThreadControllerWithMessagePumpImpl::Quit;
using ThreadControllerWithMessagePumpImpl::Run; using ThreadControllerWithMessagePumpImpl::Run;
using ThreadControllerWithMessagePumpImpl::MainThreadOnlyForTesting;
using ThreadControllerWithMessagePumpImpl::
ThreadControllerPowerMonitorForTesting;
}; };
class MockMessagePump : public MessagePump { class MockMessagePump : public MessagePump {
...@@ -110,7 +120,13 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource { ...@@ -110,7 +120,13 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource {
delayed_run_time, EnqueueOrder::FromIntForTesting(13))); delayed_run_time, EnqueueOrder::FromIntForTesting(13)));
} }
bool HasPendingHighResolutionTasks() override { return false; } bool HasPendingHighResolutionTasks() override {
return has_pending_high_resolution_tasks;
}
void SetHasPendingHighResolutionTasks(bool state) {
has_pending_high_resolution_tasks = state;
}
bool OnSystemIdle() override { return false; } bool OnSystemIdle() override { return false; }
...@@ -118,6 +134,7 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource { ...@@ -118,6 +134,7 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource {
TickClock* clock_; TickClock* clock_;
std::queue<Task> tasks_; std::queue<Task> tasks_;
std::vector<Task> running_stack_; std::vector<Task> running_stack_;
bool has_pending_high_resolution_tasks = false;
}; };
TimeTicks Seconds(int seconds) { TimeTicks Seconds(int seconds) {
...@@ -578,5 +595,84 @@ TEST_F(ThreadControllerWithMessagePumpTest, RunWithTimeout) { ...@@ -578,5 +595,84 @@ TEST_F(ThreadControllerWithMessagePumpTest, RunWithTimeout) {
thread_controller_.Run(true, TimeDelta::FromSeconds(15)); thread_controller_.Run(true, TimeDelta::FromSeconds(15));
} }
#if defined(OS_WIN)
TEST_F(ThreadControllerWithMessagePumpTest, SetHighResolutionTimer) {
MockCallback<OnceClosure> task;
task_source_.AddTask(FROM_HERE, task.Get(), Seconds(5));
ThreadTaskRunnerHandle handle(MakeRefCounted<FakeTaskRunner>());
EXPECT_CALL(*message_pump_, Run(_))
.WillOnce(Invoke([&](MessagePump::Delegate* delegate) {
// Should initially not be in high resolution.
EXPECT_FALSE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
// Ensures timer resolution is set to high resolution.
task_source_.SetHasPendingHighResolutionTasks(true);
EXPECT_FALSE(delegate->DoIdleWork());
EXPECT_TRUE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
// Ensures time resolution is set back to low resolution.
task_source_.SetHasPendingHighResolutionTasks(false);
EXPECT_FALSE(delegate->DoIdleWork());
EXPECT_FALSE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
EXPECT_CALL(*message_pump_, Quit());
thread_controller_.Quit();
}));
RunLoop run_loop;
run_loop.Run();
}
#endif // OS_WIN
#if defined(OS_WIN)
TEST_F(ThreadControllerWithMessagePumpTest,
SetHighResolutionTimerWithPowerSuspend) {
MockCallback<OnceClosure> task;
task_source_.AddTask(FROM_HERE, task.Get(), Seconds(5));
ThreadTaskRunnerHandle handle(MakeRefCounted<FakeTaskRunner>());
internal::ThreadControllerPowerMonitor::OverrideUsePowerMonitorForTesting(
true);
EXPECT_CALL(*message_pump_, Run(_))
.WillOnce(Invoke([&](MessagePump::Delegate* delegate) {
// Should initially not be in high resolution.
EXPECT_FALSE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
// The power suspend notification is sent.
thread_controller_.ThreadControllerPowerMonitorForTesting()
->OnSuspend();
// The timer resolution should NOT be updated during power suspend.
task_source_.SetHasPendingHighResolutionTasks(true);
EXPECT_FALSE(delegate->DoIdleWork());
EXPECT_FALSE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
// The power resume notification is sent.
thread_controller_.ThreadControllerPowerMonitorForTesting()->OnResume();
// Ensures timer resolution is set to high resolution.
EXPECT_FALSE(delegate->DoIdleWork());
EXPECT_TRUE(
thread_controller_.MainThreadOnlyForTesting().in_high_res_mode);
EXPECT_CALL(*message_pump_, Quit());
thread_controller_.Quit();
}));
RunLoop run_loop;
run_loop.Run();
internal::ThreadControllerPowerMonitor::ResetForTesting();
}
#endif // OS_WIN
} // namespace sequence_manager } // namespace sequence_manager
} // namespace base } // namespace base
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment