Commit 2d483376 authored by Alex Clarke's avatar Alex Clarke Committed by Commit Bot

Fix MockTimeDomain::MaybeFastForwardToNextTask with immeniate task

MockTimeDomain::MaybeFastForwardToNextTask incorrectly assumed the next task
was not immediate and if it was (e.g. due to a cross thread PostTask) it
would immediately dcheck.

This patch adds a check to deal with the case where the next task is
immediate.

Bug: 935651
Change-Id: I719616ab9f7346769189975d5af413ef65afcfe9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1503454
Commit-Queue: Gabriel Charette <gab@chromium.org>
Reviewed-by: default avatarGabriel Charette <gab@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638132}
parent 25b03fb9
...@@ -191,9 +191,12 @@ class ScopedTaskEnvironment::MockTimeDomain ...@@ -191,9 +191,12 @@ class ScopedTaskEnvironment::MockTimeDomain
// We don't need to call ReclaimMemory here because // We don't need to call ReclaimMemory here because
// DelayTillNextTask will have dealt with cancelled delayed tasks for us. // DelayTillNextTask will have dealt with cancelled delayed tasks for us.
Optional<TimeTicks> run_time = NextScheduledRunTime(); Optional<TimeTicks> run_time = NextScheduledRunTime();
if (!run_time) { if (!run_time || run_time == now_ticks_) {
// We've run out of tasks, but ScopedTaskEnvironment::FastForwardBy // We've run out of tasks (or an immediate task came in racily from
// requires the virtual time to be consumed. // another thread after reaching idle, ignore it, it will be processed in
// the next run as-if it arrived slightly later).
// ScopedTaskEnvironment::FastForwardBy requires the remaining virtual
// time to be consumed upon reaching idle.
if (now_ticks_ < allow_advance_until_ && !allow_advance_until_.is_max()) if (now_ticks_ < allow_advance_until_ && !allow_advance_until_.is_max())
SetTime(allow_advance_until_); SetTime(allow_advance_until_);
return false; return false;
...@@ -432,7 +435,6 @@ ScopedTaskEnvironment::~ScopedTaskEnvironment() { ...@@ -432,7 +435,6 @@ ScopedTaskEnvironment::~ScopedTaskEnvironment() {
} }
sequence_manager::TimeDomain* ScopedTaskEnvironment::GetTimeDomain() const { sequence_manager::TimeDomain* ScopedTaskEnvironment::GetTimeDomain() const {
DCHECK(subclass_creates_default_taskrunner_);
return mock_time_domain_ ? mock_time_domain_.get() return mock_time_domain_ ? mock_time_domain_.get()
: sequence_manager_->GetRealTimeDomain(); : sequence_manager_->GetRealTimeDomain();
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/synchronization/atomic_flag.h" #include "base/synchronization/atomic_flag.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "base/task/sequence_manager/time_domain.h"
#include "base/test/mock_callback.h" #include "base/test/mock_callback.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "base/threading/platform_thread.h" #include "base/threading/platform_thread.h"
...@@ -38,6 +39,19 @@ namespace test { ...@@ -38,6 +39,19 @@ namespace test {
namespace { namespace {
class ScopedTaskEnvironmentForTest : public ScopedTaskEnvironment {
public:
template <
class... ArgTypes,
class CheckArgumentsAreValid = std::enable_if_t<
base::trait_helpers::AreValidTraits<ScopedTaskEnvironment::ValidTrait,
ArgTypes...>::value>>
NOINLINE ScopedTaskEnvironmentForTest(const ArgTypes... args)
: ScopedTaskEnvironment(args...) {}
using ScopedTaskEnvironment::GetTimeDomain;
};
class ScopedTaskEnvironmentTest class ScopedTaskEnvironmentTest
: public testing::TestWithParam<ScopedTaskEnvironment::MainThreadType> {}; : public testing::TestWithParam<ScopedTaskEnvironment::MainThreadType> {};
...@@ -345,6 +359,46 @@ TEST_F(ScopedTaskEnvironmentTest, FastForwardAdvanceTimeTicks) { ...@@ -345,6 +359,46 @@ TEST_F(ScopedTaskEnvironmentTest, FastForwardAdvanceTimeTicks) {
EXPECT_EQ(start_time + kDelay, base::TimeTicks::Now()); EXPECT_EQ(start_time + kDelay, base::TimeTicks::Now());
} }
TEST_F(ScopedTaskEnvironmentTest, MockTimeDomain_MaybeFastForwardToNextTask) {
constexpr base::TimeDelta kDelay = TimeDelta::FromSeconds(42);
ScopedTaskEnvironmentForTest scoped_task_environment(
ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME);
const TimeTicks start_time = base::TimeTicks::Now();
EXPECT_FALSE(
scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask(
false));
EXPECT_EQ(start_time, base::TimeTicks::Now());
ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(),
kDelay);
EXPECT_TRUE(
scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask(
false));
EXPECT_EQ(start_time + kDelay, base::TimeTicks::Now());
}
TEST_F(ScopedTaskEnvironmentTest,
MockTimeDomain_MaybeFastForwardToNextTask_ImmediateTaskPending) {
constexpr base::TimeDelta kDelay = TimeDelta::FromSeconds(42);
ScopedTaskEnvironmentForTest scoped_task_environment(
ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME);
const TimeTicks start_time = base::TimeTicks::Now();
EXPECT_FALSE(
scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask(
false));
EXPECT_EQ(start_time, base::TimeTicks::Now());
ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(),
kDelay);
ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::DoNothing());
EXPECT_FALSE(
scoped_task_environment.GetTimeDomain()->MaybeFastForwardToNextTask(
false));
EXPECT_EQ(start_time, base::TimeTicks::Now());
}
#if defined(OS_WIN) #if defined(OS_WIN)
// Regression test to ensure that ScopedTaskEnvironment enables the MTA in the // Regression test to ensure that ScopedTaskEnvironment enables the MTA in the
// thread pool (so that the test environment matches that of the browser process // thread pool (so that the test environment matches that of the browser process
......
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