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 @@
#include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h"
#include <algorithm>
#include <utility>
#include "base/auto_reset.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_pump.h"
......
......@@ -95,17 +95,6 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl
void Quit() 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 {
MainThreadOnly();
~MainThreadOnly();
......@@ -135,6 +124,25 @@ class BASE_EXPORT ThreadControllerWithMessagePumpImpl
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() {
DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
return main_thread_only_;
......
......@@ -4,19 +4,25 @@
#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_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/power_monitor/power_monitor.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/mock_callback.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include <queue>
using testing::_;
using testing::Invoke;
using testing::ElementsAre;
......@@ -30,7 +36,7 @@ class ThreadControllerForTest
: public internal::ThreadControllerWithMessagePumpImpl {
public:
ThreadControllerForTest(std::unique_ptr<MessagePump> pump,
SequenceManager::Settings& settings)
const SequenceManager::Settings& settings)
: ThreadControllerWithMessagePumpImpl(std::move(pump), settings) {}
using ThreadControllerWithMessagePumpImpl::DoIdleWork;
......@@ -38,6 +44,10 @@ class ThreadControllerForTest
using ThreadControllerWithMessagePumpImpl::EnsureWorkScheduled;
using ThreadControllerWithMessagePumpImpl::Quit;
using ThreadControllerWithMessagePumpImpl::Run;
using ThreadControllerWithMessagePumpImpl::MainThreadOnlyForTesting;
using ThreadControllerWithMessagePumpImpl::
ThreadControllerPowerMonitorForTesting;
};
class MockMessagePump : public MessagePump {
......@@ -110,7 +120,13 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource {
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; }
......@@ -118,6 +134,7 @@ class FakeSequencedTaskSource : public internal::SequencedTaskSource {
TickClock* clock_;
std::queue<Task> tasks_;
std::vector<Task> running_stack_;
bool has_pending_high_resolution_tasks = false;
};
TimeTicks Seconds(int seconds) {
......@@ -578,5 +595,84 @@ TEST_F(ThreadControllerWithMessagePumpTest, RunWithTimeout) {
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 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