Commit 00074543 authored by Jesse McKenna's avatar Jesse McKenna Committed by Commit Bot

TaskScheduler: Add unit tests for TaskSchedulerImpl::UpdatePriority()

Bug: 889029
Change-Id: I87d82881660aaec994fab40543463bf6e61963ee
Reviewed-on: https://chromium-review.googlesource.com/c/1354322
Commit-Queue: Jesse McKenna <jessemckenna@google.com>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#612517}
parent 0a3e48db
......@@ -46,7 +46,6 @@
#include "base/threading/thread.h"
#include "base/threading/thread_checker_impl.h"
#include "base/threading/thread_local_storage.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
......@@ -69,14 +68,6 @@ constexpr size_t kNumTasksPostedPerThread = 150;
constexpr TimeDelta kReclaimTimeForCleanupTests =
TimeDelta::FromMilliseconds(500);
// Waits on |event| in a scope where the blocking observer is null, to avoid
// affecting the max tasks.
void WaitWithoutBlockingObserver(WaitableEvent* event) {
internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
event->Wait();
}
class TaskSchedulerWorkerPoolImplTestBase
: public SchedulerWorkerPool::Delegate {
protected:
......@@ -252,7 +243,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, PostTasksWithOneAvailableWorker) {
GetParam()));
EXPECT_TRUE(blocked_task_factories.back()->PostTask(
PostNestedTask::NO,
BindOnce(&WaitWithoutBlockingObserver, Unretained(&event))));
BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&event))));
blocked_task_factories.back()->WaitForAllTasksToRun();
}
......@@ -288,7 +279,7 @@ TEST_P(TaskSchedulerWorkerPoolImplTestParam, Saturate) {
GetParam()));
EXPECT_TRUE(factories.back()->PostTask(
PostNestedTask::NO,
BindOnce(&WaitWithoutBlockingObserver, Unretained(&event))));
BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&event))));
factories.back()->WaitForAllTasksToRun();
}
......@@ -404,7 +395,7 @@ void TaskPostedBeforeStart(PlatformThreadRef* platform_thread_ref,
WaitableEvent* barrier) {
*platform_thread_ref = PlatformThread::CurrentRef();
task_running->Signal();
WaitWithoutBlockingObserver(barrier);
test::WaitWithoutBlockingObserver(barrier);
}
} // namespace
......@@ -483,7 +474,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse
public:
void SetTlsValueAndWait() {
slot_.Set(reinterpret_cast<void*>(kMagicTlsValue));
WaitWithoutBlockingObserver(&waiter_);
test::WaitWithoutBlockingObserver(&waiter_);
}
void CountZeroTlsValuesAndWait(WaitableEvent* count_waiter) {
......@@ -491,7 +482,7 @@ class TaskSchedulerWorkerPoolCheckTlsReuse
subtle::NoBarrier_AtomicIncrement(&zero_tls_values_, 1);
count_waiter->Signal();
WaitWithoutBlockingObserver(&waiter_);
test::WaitWithoutBlockingObserver(&waiter_);
}
protected:
......@@ -596,7 +587,7 @@ class TaskSchedulerWorkerPoolHistogramTest
BindOnce(
[](OnceClosure on_running, WaitableEvent* continue_event) {
std::move(on_running).Run();
WaitWithoutBlockingObserver(continue_event);
test::WaitWithoutBlockingObserver(continue_event);
},
all_workers_running_barrier, continue_event));
}
......@@ -619,8 +610,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBetweenWaits) {
{WithBaseSyncPrimitives()}, &mock_scheduler_task_runner_delegate_);
// Post a task.
task_runner->PostTask(
FROM_HERE, BindOnce(&WaitWithoutBlockingObserver, Unretained(&event)));
task_runner->PostTask(FROM_HERE, BindOnce(&test::WaitWithoutBlockingObserver,
Unretained(&event)));
// Post 2 more tasks while the first task hasn't completed its execution. It
// is guaranteed that these tasks will run immediately after the first task,
......@@ -733,7 +724,7 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
ASSERT_FALSE(thread_ref->is_null());
EXPECT_EQ(*thread_ref, PlatformThread::CurrentRef());
cleanup_thread_running->Signal();
WaitWithoutBlockingObserver(cleanup_thread_continue);
test::WaitWithoutBlockingObserver(cleanup_thread_continue);
},
Unretained(&thread_ref), Unretained(&cleanup_thread_running),
Unretained(&cleanup_thread_continue)));
......@@ -778,7 +769,8 @@ TEST_F(TaskSchedulerWorkerPoolHistogramTest, NumTasksBeforeCleanup) {
<< "Worker reused. Worker will not cleanup and the "
"histogram value will be wrong.";
top_idle_thread_running->Signal();
WaitWithoutBlockingObserver(top_idle_thread_continue);
test::WaitWithoutBlockingObserver(
top_idle_thread_continue);
},
thread_ref, Unretained(&top_idle_thread_running),
Unretained(&top_idle_thread_continue)));
......@@ -842,7 +834,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, VerifyStandbyThread) {
RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
thread_running.Signal();
WaitWithoutBlockingObserver(&threads_continue);
test::WaitWithoutBlockingObserver(&threads_continue);
});
// There should be one idle thread until we reach capacity
......@@ -932,7 +924,7 @@ TEST_F(TaskSchedulerWorkerPoolStandbyPolicyTest, OnlyKeepActiveStandbyThreads) {
RepeatingClosure thread_blocker = BindLambdaForTesting([&]() {
thread_running.Signal();
WaitWithoutBlockingObserver(&threads_continue);
test::WaitWithoutBlockingObserver(&threads_continue);
});
for (size_t i = 0; i < kMaxTasks; ++i) {
......@@ -1054,7 +1046,7 @@ class TaskSchedulerWorkerPoolBlockingTest
NestedScopedBlockingCall nested_scoped_blocking_call(
nested_blocking_type);
blocking_threads_running_closure->Run();
WaitWithoutBlockingObserver(blocking_threads_continue_);
test::WaitWithoutBlockingObserver(blocking_threads_continue_);
},
Unretained(&blocking_threads_running_closure),
Unretained(&blocking_threads_continue_), nested_blocking_type));
......@@ -1130,11 +1122,11 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
WaitableEvent* thread_running, WaitableEvent* thread_can_block,
WaitableEvent* threads_continue) {
thread_running->Signal();
WaitWithoutBlockingObserver(thread_can_block);
test::WaitWithoutBlockingObserver(thread_can_block);
NestedScopedBlockingCall nested_scoped_blocking_call(
nested_blocking_type);
WaitWithoutBlockingObserver(threads_continue);
test::WaitWithoutBlockingObserver(threads_continue);
},
GetParam(), Unretained(&thread_running),
Unretained(&thread_can_block), Unretained(&threads_continue)));
......@@ -1157,7 +1149,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, PostBeforeBlocking) {
[](Closure* extra_threads_running_barrier,
WaitableEvent* extra_threads_continue) {
extra_threads_running_barrier->Run();
WaitWithoutBlockingObserver(extra_threads_continue);
test::WaitWithoutBlockingObserver(
extra_threads_continue);
},
Unretained(&extra_threads_running_barrier),
Unretained(&extra_threads_continue)));
......@@ -1202,7 +1195,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingTest, WorkersIdleWhenOverCapacity) {
auto callback = BindOnce(
[](Closure* threads_running_barrier, WaitableEvent* threads_continue) {
threads_running_barrier->Run();
WaitWithoutBlockingObserver(threads_continue);
test::WaitWithoutBlockingObserver(threads_continue);
},
Unretained(&threads_running_barrier), Unretained(&threads_continue));
task_runner_->PostTask(FROM_HERE, std::move(callback));
......@@ -1302,8 +1295,9 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest,
// Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment
// the max tasks.
for (size_t i = 0; i < kMaxTasks - 1; ++i) {
task_runner->PostTask(FROM_HERE, BindOnce(&WaitWithoutBlockingObserver,
Unretained(&can_return)));
task_runner->PostTask(
FROM_HERE,
BindOnce(&test::WaitWithoutBlockingObserver, Unretained(&can_return)));
}
WaitableEvent can_instantiate_will_block;
......@@ -1317,10 +1311,10 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest,
WaitableEvent* did_instantiate_will_block,
WaitableEvent* can_return) {
ScopedBlockingCall may_block(BlockingType::MAY_BLOCK);
WaitWithoutBlockingObserver(can_instantiate_will_block);
test::WaitWithoutBlockingObserver(can_instantiate_will_block);
ScopedBlockingCall will_block(BlockingType::WILL_BLOCK);
did_instantiate_will_block->Signal();
WaitWithoutBlockingObserver(can_return);
test::WaitWithoutBlockingObserver(can_return);
},
Unretained(&can_instantiate_will_block),
Unretained(&did_instantiate_will_block), Unretained(&can_return)));
......@@ -1391,9 +1385,9 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) {
threads_running_barrier->Run();
{
ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
WaitWithoutBlockingObserver(blocked_call_continue);
test::WaitWithoutBlockingObserver(blocked_call_continue);
}
WaitWithoutBlockingObserver(threads_continue);
test::WaitWithoutBlockingObserver(threads_continue);
},
Unretained(&threads_running_barrier), Unretained(&threads_continue),
Unretained(&blocked_call_continue));
......@@ -1416,7 +1410,8 @@ TEST_F(TaskSchedulerWorkerPoolOverCapacityTest, VerifyCleanup) {
[](Closure* extra_threads_running_barrier,
WaitableEvent* extra_threads_continue) {
extra_threads_running_barrier->Run();
WaitWithoutBlockingObserver(extra_threads_continue);
test::WaitWithoutBlockingObserver(
extra_threads_continue);
},
Unretained(&extra_threads_running_barrier),
Unretained(&extra_threads_continue)));
......@@ -1475,7 +1470,8 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
ScopedBlockingCall scoped_blocking_call(
BlockingType::WILL_BLOCK);
early_threads_barrier_closure->Run();
WaitWithoutBlockingObserver(early_release_threads_continue);
test::WaitWithoutBlockingObserver(
early_release_threads_continue);
}
early_threads_finished->Run();
},
......@@ -1506,7 +1502,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
WaitableEvent* late_release_thread_contine) {
ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
late_threads_barrier_closure->Run();
WaitWithoutBlockingObserver(late_release_thread_contine);
test::WaitWithoutBlockingObserver(late_release_thread_contine);
},
Unretained(&late_threads_barrier_closure),
Unretained(&late_release_thread_contine)));
......@@ -1533,7 +1529,7 @@ TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
BindOnce(
[](Closure* closure, WaitableEvent* final_tasks_continue) {
closure->Run();
WaitWithoutBlockingObserver(final_tasks_continue);
test::WaitWithoutBlockingObserver(final_tasks_continue);
},
Unretained(&final_tasks_running_barrier),
Unretained(&final_tasks_continue)));
......@@ -1572,7 +1568,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, MaxBestEffortTasks) {
background_runner->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
best_effort_tasks_running_barrier.Run();
WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
test::WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
}));
}
best_effort_tasks_running.Wait();
......@@ -1651,7 +1647,8 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
FROM_HERE, base::BindLambdaForTesting([&]() {
blocking_best_effort_tasks_running_barrier.Run();
ScopedBlockingCall scoped_blocking_call(GetParam());
WaitWithoutBlockingObserver(&unblock_blocking_best_effort_tasks);
test::WaitWithoutBlockingObserver(
&unblock_blocking_best_effort_tasks);
}));
}
blocking_best_effort_tasks_running.Wait();
......@@ -1671,7 +1668,7 @@ TEST_P(TaskSchedulerWorkerPoolBlockingCallAndMaxBestEffortTasksTest,
background_runner->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
best_effort_tasks_running_barrier.Run();
WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
test::WaitWithoutBlockingObserver(&unblock_best_effort_tasks);
}));
}
best_effort_tasks_running.Wait();
......@@ -1724,7 +1721,7 @@ TEST_F(TaskSchedulerWorkerPoolImplStartInBodyTest, RacyCleanup) {
BindOnce(
[](OnceClosure on_running, WaitableEvent* unblock_threads) {
std::move(on_running).Run();
WaitWithoutBlockingObserver(unblock_threads);
test::WaitWithoutBlockingObserver(unblock_threads);
},
threads_running_barrier, Unretained(&unblock_threads)));
}
......
......@@ -256,6 +256,13 @@ TaskSchedulerImpl::CreateCOMSTATaskRunnerWithTraits(
}
#endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner>
TaskSchedulerImpl::CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
const TaskTraits& traits) {
const TaskTraits new_traits = SetUserBlockingPriorityIfNeeded(traits);
return MakeRefCounted<SchedulerSequencedTaskRunner>(new_traits, this);
}
std::vector<const HistogramBase*> TaskSchedulerImpl::GetHistograms() const {
std::vector<const HistogramBase*> histograms;
for (const auto& worker_pool : worker_pools_)
......
......@@ -25,6 +25,7 @@
#include "base/task/task_scheduler/task_scheduler.h"
#include "base/task/task_scheduler/task_tracker.h"
#include "base/task/task_traits.h"
#include "base/updateable_sequenced_task_runner.h"
#include "build/build_config.h"
#if defined(OS_POSIX) && !defined(OS_NACL_SFI)
......@@ -93,6 +94,9 @@ class BASE_EXPORT TaskSchedulerImpl : public TaskScheduler,
const TaskTraits& traits,
SingleThreadTaskRunnerThreadMode thread_mode) override;
#endif // defined(OS_WIN)
scoped_refptr<UpdateableSequencedTaskRunner>
CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
const TaskTraits& traits);
private:
// Returns the worker pool that runs Tasks with |traits|.
......
......@@ -6,6 +6,7 @@
#include <stddef.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
......@@ -26,6 +27,7 @@
#include "base/task/task_scheduler/test_task_factory.h"
#include "base/task/task_scheduler/test_utils.h"
#include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_timeouts.h"
......@@ -35,6 +37,7 @@
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/updateable_sequenced_task_runner.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -159,6 +162,18 @@ void VerifyTimeAndTaskEnvironmentAndSignalEvent(const TaskTraits& traits,
event->Signal();
}
void VerifyOrderAndTaskEnvironmentAndSignalEvent(
const TaskTraits& traits,
SchedulerState state,
WaitableEvent* expected_previous_event,
WaitableEvent* event) {
DCHECK(event);
if (expected_previous_event)
EXPECT_TRUE(expected_previous_event->IsSignaled());
VerifyTaskEnvironment(traits, state);
event->Signal();
}
scoped_refptr<TaskRunner> CreateTaskRunnerWithTraitsAndExecutionMode(
TaskScheduler* scheduler,
const TaskTraits& traits,
......@@ -906,5 +921,199 @@ TEST_P(TaskSchedulerImplTest, SchedulerWorkerObserver) {
TearDown();
}
class TaskSchedulerPriorityUpdateTest : public testing::Test {
protected:
struct PoolBlockingEvents {
PoolBlockingEvents(const TaskTraits& pool_traits)
: pool_traits(pool_traits) {}
const TaskTraits pool_traits;
WaitableEvent scheduled;
WaitableEvent blocked;
};
struct TaskRunnerAndEvents {
TaskRunnerAndEvents(
scoped_refptr<UpdateableSequencedTaskRunner> task_runner,
const TaskPriority updated_priority,
WaitableEvent* expected_previous_event)
: task_runner(std::move(task_runner)),
updated_priority(updated_priority),
expected_previous_event(expected_previous_event) {}
scoped_refptr<UpdateableSequencedTaskRunner> task_runner;
const TaskPriority updated_priority;
WaitableEvent scheduled;
WaitableEvent blocked;
WaitableEvent task_ran;
WaitableEvent* expected_previous_event;
};
TaskSchedulerPriorityUpdateTest() : scheduler_("Test") {}
void StartTaskSchedulerWithNumThreadsPerPool(int threads_per_pool) {
constexpr TimeDelta kSuggestedReclaimTime = TimeDelta::FromSeconds(30);
scheduler_.Start({{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime},
{threads_per_pool, kSuggestedReclaimTime}},
nullptr);
}
// Create a series of sample task runners that will post tasks at various
// initial priorities, then update priority.
void CreateTaskRunnersAndEvents() {
// Task runner that will start as USER_VISIBLE and update to USER_BLOCKING.
// Its task is expected to run first.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::USER_VISIBLE})),
TaskPriority::USER_BLOCKING, nullptr));
// Task runner that will start as BEST_EFFORT and update to USER_VISIBLE.
// Its task is expected to run after the USER_BLOCKING task runner's task.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::BEST_EFFORT})),
TaskPriority::USER_VISIBLE,
&task_runners_and_events_.back()->task_ran));
// Task runner that will start as USER_BLOCKING and update to BEST_EFFORT.
// Its task is expected to run asynchronously with the other two task
// task runners' tasks if background pools exist, or after the USER_VISIBLE
// task runner's task if not.
task_runners_and_events_.push_back(std::make_unique<TaskRunnerAndEvents>(
scheduler_.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
TaskTraits({TaskPriority::USER_BLOCKING})),
TaskPriority::BEST_EFFORT,
CanUseBackgroundPriorityForSchedulerWorker()
? nullptr
: &task_runners_and_events_.back()->task_ran));
}
void TearDown() override {
scheduler_.FlushForTesting();
scheduler_.JoinForTesting();
}
TaskSchedulerImpl scheduler_;
std::vector<std::unique_ptr<TaskRunnerAndEvents>> task_runners_and_events_;
DISALLOW_COPY_AND_ASSIGN(TaskSchedulerPriorityUpdateTest);
};
// Update the priority of a sequence when it is not scheduled.
TEST_F(TaskSchedulerPriorityUpdateTest, UpdatePrioritySequenceNotScheduled) {
StartTaskSchedulerWithNumThreadsPerPool(1);
// Schedule blocking tasks on all threads to prevent tasks from being
// scheduled later in the test.
std::vector<std::unique_ptr<PoolBlockingEvents>> pool_blocking_events;
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::USER_BLOCKING})));
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::USER_BLOCKING, MayBlock()})));
if (CanUseBackgroundPriorityForSchedulerWorker()) {
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::BEST_EFFORT})));
pool_blocking_events.push_back(std::make_unique<PoolBlockingEvents>(
TaskTraits({TaskPriority::BEST_EFFORT, MayBlock()})));
}
// When all blocking tasks signal |scheduled|, there is a task blocked in
// each pool.
for (auto& pool_blocking_event : pool_blocking_events) {
scheduler_
.CreateUpdateableSequencedTaskRunnerWithTraitsForTesting(
pool_blocking_event->pool_traits)
->PostTask(
FROM_HERE, BindLambdaForTesting([&]() {
pool_blocking_event->scheduled.Signal();
test::WaitWithoutBlockingObserver(&pool_blocking_event->blocked);
}));
test::WaitWithoutBlockingObserver(&pool_blocking_event->scheduled);
}
CreateTaskRunnersAndEvents();
// Post tasks to multiple task runners while they are at initial priority.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE,
BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent,
task_runner_and_events->updated_priority,
SchedulerState::kAfterSchedulerStart,
Unretained(task_runner_and_events->expected_previous_event),
Unretained(&task_runner_and_events->task_ran)));
}
// Update the priorities of the task runners that posted the tasks.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->UpdatePriority(
task_runner_and_events->updated_priority);
}
// Unblock the task blocking each pool, allowing the posted tasks to run.
// Each posted task will verify that it has been posted with updated priority
// when it runs.
for (auto& pool_blocking_event : pool_blocking_events) {
pool_blocking_event->blocked.Signal();
}
for (auto& task_runner_and_events : task_runners_and_events_) {
test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran);
}
}
// Update the priority of a sequence when it is scheduled, i.e. not currently
// in a priority queue.
TEST_F(TaskSchedulerPriorityUpdateTest, UpdatePrioritySequenceScheduled) {
StartTaskSchedulerWithNumThreadsPerPool(5);
CreateTaskRunnersAndEvents();
// Post blocking tasks to all task runners to prevent tasks from being
// scheduled later in the test.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE, BindLambdaForTesting([&]() {
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
task_runner_and_events->scheduled.Signal();
test::WaitWithoutBlockingObserver(&task_runner_and_events->blocked);
}));
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
test::WaitWithoutBlockingObserver(&task_runner_and_events->scheduled);
}
// Update the priorities of the task runners while they are scheduled and
// blocked.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->UpdatePriority(
task_runner_and_events->updated_priority);
}
// Post an additional task to each task runner.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->task_runner->PostTask(
FROM_HERE,
BindOnce(&VerifyOrderAndTaskEnvironmentAndSignalEvent,
TaskTraits(task_runner_and_events->updated_priority),
SchedulerState::kAfterSchedulerStart,
Unretained(task_runner_and_events->expected_previous_event),
Unretained(&task_runner_and_events->task_ran)));
}
// Unblock the task blocking each task runner, allowing the additional posted
// tasks to run. Each posted task will verify that it has been posted with
// updated priority when it runs.
for (auto& task_runner_and_events : task_runners_and_events_) {
task_runner_and_events->blocked.Signal();
test::WaitWithoutBlockingObserver(&task_runner_and_events->task_ran);
}
}
} // namespace internal
} // namespace base
......@@ -9,6 +9,8 @@
#include "base/bind.h"
#include "base/task/task_scheduler/scheduler_parallel_task_runner.h"
#include "base/task/task_scheduler/scheduler_sequenced_task_runner.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_restrictions.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
......@@ -59,6 +61,14 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
traits, mock_scheduler_task_runner_delegate);
}
// Waits on |event| in a scope where the blocking observer is null, to avoid
// affecting the max tasks in a worker pool.
void WaitWithoutBlockingObserver(WaitableEvent* event) {
internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
event->Wait();
}
MockSchedulerTaskRunnerDelegate::MockSchedulerTaskRunnerDelegate(
TrackedRef<TaskTracker> task_tracker,
DelayedTaskManager* delayed_task_manager)
......
......@@ -80,6 +80,8 @@ scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunnerWithTraits(
const TaskTraits& traits,
MockSchedulerTaskRunnerDelegate* mock_scheduler_task_runner_delegate);
void WaitWithoutBlockingObserver(WaitableEvent* event);
} // namespace test
} // namespace internal
} // 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