131 lines
4.9 KiB
C++
131 lines
4.9 KiB
C++
|
|
// Copyright 2020 The Chromium Authors
|
||
|
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
|
// found in the LICENSE file.
|
||
|
|
|
||
|
|
#include "base/task/thread_pool.h"
|
||
|
|
|
||
|
|
#include "base/functional/bind.h"
|
||
|
|
#include "base/location.h"
|
||
|
|
#include "base/run_loop.h"
|
||
|
|
#include "base/task/bind_post_task.h"
|
||
|
|
#include "base/task/single_thread_task_executor.h"
|
||
|
|
#include "base/task/thread_pool/thread_pool_instance.h"
|
||
|
|
#include "base/test/bind.h"
|
||
|
|
#include "base/test/task_environment.h"
|
||
|
|
#include "base/test/test_waitable_event.h"
|
||
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
|
|
||
|
|
namespace base {
|
||
|
|
|
||
|
|
TEST(ThreadPool, PostTaskAndReplyWithResultThreeArgs) {
|
||
|
|
base::test::TaskEnvironment env;
|
||
|
|
|
||
|
|
base::RunLoop run_loop;
|
||
|
|
base::ThreadPool::PostTaskAndReplyWithResult(
|
||
|
|
FROM_HERE, base::BindOnce([]() { return 3; }),
|
||
|
|
base::OnceCallback<void(int)>(
|
||
|
|
base::BindLambdaForTesting([&run_loop](int x) {
|
||
|
|
EXPECT_EQ(x, 3);
|
||
|
|
run_loop.Quit();
|
||
|
|
})));
|
||
|
|
run_loop.Run();
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(ThreadPool, PostTaskAndReplyWithResultFourArgs) {
|
||
|
|
base::test::TaskEnvironment env;
|
||
|
|
|
||
|
|
base::RunLoop run_loop;
|
||
|
|
base::ThreadPool::PostTaskAndReplyWithResult(
|
||
|
|
FROM_HERE, /*traits=*/{}, base::BindOnce([]() { return 3; }),
|
||
|
|
base::OnceCallback<void(int)>(
|
||
|
|
base::BindLambdaForTesting([&run_loop](int x) {
|
||
|
|
EXPECT_EQ(x, 3);
|
||
|
|
run_loop.Quit();
|
||
|
|
})));
|
||
|
|
run_loop.Run();
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(ThreadPool, BindPostTaskFizzlesOnShutdown) {
|
||
|
|
// Tests that a callback bound to a BLOCK_SHUTDOWN sequence doesn't trigger a
|
||
|
|
// DCHECK when it's deleted without running.
|
||
|
|
base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
|
||
|
|
"BindPostTaskFizzlesOnShutdownTest");
|
||
|
|
|
||
|
|
{
|
||
|
|
// Creating this callback and deleting it after the thread pool is shutdown
|
||
|
|
// used to trigger a DCHECK in task_tracker because the
|
||
|
|
// BindPostTaskTrampoline destructor has to delete its state on the sequence
|
||
|
|
// it's bound to. There is a DCHECK that ensures BLOCK_SHUTDOWN tasks aren't
|
||
|
|
// posted after shutdown, but BindPostTaskTrampoline uses
|
||
|
|
// base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks to avoid
|
||
|
|
// triggering it.
|
||
|
|
auto bound_callback =
|
||
|
|
base::BindPostTask(base::ThreadPool::CreateSequencedTaskRunner(
|
||
|
|
{TaskShutdownBehavior::BLOCK_SHUTDOWN}),
|
||
|
|
base::BindOnce([]() { ADD_FAILURE(); }));
|
||
|
|
base::ThreadPoolInstance::Get()->Shutdown();
|
||
|
|
}
|
||
|
|
|
||
|
|
ThreadPoolInstance::Get()->JoinForTesting();
|
||
|
|
ThreadPoolInstance::Set(nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST(ThreadPool, PostTaskAndReplyFizzlesOnShutdown) {
|
||
|
|
// Tests that a PostTaskAndReply from a BLOCK_SHUTDOWN sequence doesn't
|
||
|
|
// trigger a DCHECK when it's not run at shutdown.
|
||
|
|
base::ThreadPoolInstance::CreateAndStartWithDefaultParams(
|
||
|
|
"PostTaskAndReplyFizzlesOnShutdown");
|
||
|
|
|
||
|
|
{
|
||
|
|
base::SingleThreadTaskExecutor executor;
|
||
|
|
auto blocking_task_runner = base::ThreadPool::CreateSequencedTaskRunner(
|
||
|
|
{TaskShutdownBehavior::BLOCK_SHUTDOWN});
|
||
|
|
|
||
|
|
base::RunLoop run_loop;
|
||
|
|
|
||
|
|
// The setup that this test is exercising is as follows:
|
||
|
|
// - A task is posted using PostTaskAndReply from a BLOCK_SHUTDOWN sequence
|
||
|
|
// to the main thread
|
||
|
|
// - The task is not run on the main thread
|
||
|
|
// - Shutdown happens, the ThreadPool is shutdown
|
||
|
|
// - The main thread destroys its un-run tasks
|
||
|
|
// - ~PostTaskAndReplyRelay calls `DeleteSoon` to delete its reply's state
|
||
|
|
// on the sequence it's bound to
|
||
|
|
// - TaskTracker ensures that no BLOCK_SHUTDOWN tasks can be posted after
|
||
|
|
// shutdown. ~PostTaskAndReplyRelay avoids triggering this DCHECK by using a
|
||
|
|
// base::ThreadPoolInstance::ScopedFizzleBlockShutdownTasks
|
||
|
|
|
||
|
|
// Post a task to the BLOCK_SHUTDOWN thread pool sequence to setup the test.
|
||
|
|
base::TestWaitableEvent event;
|
||
|
|
blocking_task_runner->PostTask(
|
||
|
|
FROM_HERE, base::BindLambdaForTesting([&]() {
|
||
|
|
// Enqueue a task whose only purpose is to exit the run loop, ensuring
|
||
|
|
// the following task is never run.
|
||
|
|
executor.task_runner()->PostTask(FROM_HERE,
|
||
|
|
base::BindLambdaForTesting([&]() {
|
||
|
|
event.Wait();
|
||
|
|
run_loop.Quit();
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Post the task for which the reply will trigger the `DeleteSoon`
|
||
|
|
// from `~PostTaskAndReplyRelay`.
|
||
|
|
executor.task_runner()->PostTaskAndReply(
|
||
|
|
FROM_HERE, base::BindOnce([]() { ADD_FAILURE(); }),
|
||
|
|
base::BindOnce([]() { ADD_FAILURE(); }));
|
||
|
|
|
||
|
|
event.Signal();
|
||
|
|
}));
|
||
|
|
|
||
|
|
// Run until the first task posted to the SingleThreadTaskExecutor quits the
|
||
|
|
// run loop, resulting in the `PostTaskAndReply` being queued but not run.
|
||
|
|
run_loop.Run();
|
||
|
|
|
||
|
|
base::ThreadPoolInstance::Get()->Shutdown();
|
||
|
|
}
|
||
|
|
|
||
|
|
ThreadPoolInstance::Get()->JoinForTesting();
|
||
|
|
ThreadPoolInstance::Set(nullptr);
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace base
|