chromium/base/task/thread_pool/thread_group_unittest.cc

// Copyright 2017 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/thread_group.h"

#include <memory>
#include <tuple>
#include <utility>

#include "base/barrier_closure.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/task/task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool/can_run_policy_test.h"
#include "base/task/thread_pool/delayed_task_manager.h"
#include "base/task/thread_pool/pooled_sequenced_task_runner.h"
#include "base/task/thread_pool/task_tracker.h"
#include "base/task/thread_pool/test_task_factory.h"
#include "base/task/thread_pool/test_utils.h"
#include "base/task/thread_pool/thread_group_impl.h"
#include "base/test/bind.h"
#include "base/test/test_timeouts.h"
#include "base/test/test_waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/scoped_blocking_call_internal.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_WIN)
#include "base/win/com_init_check_hook.h"
#include "base/win/com_init_util.h"
#endif

namespace base {
namespace internal {

namespace {

constexpr size_t kMaxTasks =;
constexpr size_t kTooManyTasks =;
// By default, tests allow half of the thread group to be used by best-effort
// tasks.
constexpr size_t kMaxBestEffortTasks =;
constexpr size_t kNumThreadsPostingTasks =;
constexpr size_t kNumTasksPostedPerThread =;

PostNestedTask;

class ThreadPostingTasks : public SimpleThread {};

class ThreadGroupTestBase : public testing::Test, public ThreadGroup::Delegate {};

ThreadGroupTest;

// TODO(etiennep): Audit tests that don't need TaskSourceExecutionMode
// parameter.
class ThreadGroupTestAllExecutionModes
    : public ThreadGroupTestBase,
      public testing::WithParamInterface<TaskSourceExecutionMode> {};

void ShouldNotRun() {}

}  // namespace

TEST_P(ThreadGroupTestAllExecutionModes, PostTasks) {}

TEST_P(ThreadGroupTestAllExecutionModes, NestedPostTasks) {}

// Verify that a Task can't be posted after shutdown.
TEST_P(ThreadGroupTestAllExecutionModes, PostTaskAfterShutdown) {}

// Verify that a Task runs shortly after its delay expires.
TEST_P(ThreadGroupTestAllExecutionModes, PostDelayedTask) {}

// Verify that the RunsTasksInCurrentSequence() method of a SEQUENCED TaskRunner
// returns false when called from a task that isn't part of the sequence. Note:
// Tests that use TestTaskFactory already verify that
// RunsTasksInCurrentSequence() returns true when appropriate so this method
// complements it to get full coverage of that method.
TEST_P(ThreadGroupTestAllExecutionModes, SequencedRunsTasksInCurrentSequence) {}

// Verify that tasks posted before Start run after Start.
TEST_P(ThreadGroupTestAllExecutionModes, PostBeforeStart) {}

// Verify that tasks only run when allowed by the CanRunPolicy.
TEST_P(ThreadGroupTestAllExecutionModes, CanRunPolicyBasic) {}

TEST_F(ThreadGroupTest, CanRunPolicyUpdatedBeforeRun) {}

TEST_P(ThreadGroupTestAllExecutionModes, CanRunPolicyLoad) {}

// Verifies that ShouldYield() returns true for a priority that is not allowed
// to run by the CanRunPolicy.
TEST_F(ThreadGroupTest, CanRunPolicyShouldYield) {}

TEST_F(ThreadGroupTest, SetMaxTasks) {}

// Verify that the maximum number of BEST_EFFORT tasks that can run concurrently
// in a thread group does not affect Sequences with a priority that was
// increased from BEST_EFFORT to USER_BLOCKING.
TEST_F(ThreadGroupTest, UpdatePriorityBestEffortToUserBlocking) {}

// Regression test for crbug.com/955953.
TEST_P(ThreadGroupTestAllExecutionModes, ScopedBlockingCallTwice) {}

#if BUILDFLAG(IS_WIN)
TEST_P(ThreadGroupTestAllExecutionModes, COMMTAWorkerEnvironment) {
  StartThreadGroup(ThreadGroup::WorkerEnvironment::COM_MTA);
  auto task_runner = test::CreatePooledTaskRunnerWithExecutionMode(
      execution_mode(), &mock_pooled_task_runner_delegate_);

  TestWaitableEvent task_ran;
  task_runner->PostTask(
      FROM_HERE, BindOnce(
                     [](TestWaitableEvent* task_ran) {
                       win::AssertComApartmentType(win::ComApartmentType::MTA);
                       task_ran->Signal();
                     },
                     Unretained(&task_ran)));
  task_ran.Wait();
}

TEST_P(ThreadGroupTestAllExecutionModes, NoWorkerEnvironment) {
  StartThreadGroup(ThreadGroup::WorkerEnvironment::NONE);
  auto task_runner = test::CreatePooledTaskRunnerWithExecutionMode(
      execution_mode(), &mock_pooled_task_runner_delegate_);

  TestWaitableEvent task_ran;
  task_runner->PostTask(
      FROM_HERE, BindOnce(
                     [](TestWaitableEvent* task_ran) {
                       win::AssertComApartmentType(win::ComApartmentType::NONE);
                       task_ran->Signal();
                     },
                     Unretained(&task_ran)));
  task_ran.Wait();
}
#endif

// Verifies that ShouldYield() returns false when there is no pending task.
TEST_F(ThreadGroupTest, ShouldYieldSingleTask) {}

// Verify that tasks from a JobTaskSource run at the intended concurrency.
TEST_F(ThreadGroupTest, ScheduleJobTaskSource) {}

// Verify that tasks from a JobTaskSource run at the intended concurrency.
TEST_F(ThreadGroupTest, ScheduleJobTaskSourceMultipleTime) {}

// Verify that Cancel() on a job stops running the worker task and causes
// current workers to yield.
TEST_F(ThreadGroupTest, CancelJobTaskSource) {}

// Verify that calling JobTaskSource::NotifyConcurrencyIncrease() (re-)schedule
// tasks with the intended concurrency.
TEST_F(ThreadGroupTest, JobTaskSourceConcurrencyIncrease) {}

// Verify that a JobTaskSource that becomes empty while in the queue eventually
// gets discarded.
TEST_F(ThreadGroupTest, ScheduleEmptyJobTaskSource) {}

// Verify that Join() on a job contributes to max concurrency and waits for all
// workers to return.
TEST_F(ThreadGroupTest, JoinJobTaskSource) {}

// Verify that finishing work outside of a job unblocks workers with a stale
// max concurrency.
TEST_F(ThreadGroupTest, JoinJobTaskSourceStaleConcurrency) {}

// Verify that cancelling a job unblocks workers with a stale max concurrency.
TEST_F(ThreadGroupTest, CancelJobTaskSourceWithStaleConcurrency) {}

// Verify that the maximum number of BEST_EFFORT tasks that can run concurrently
// in a thread group does not affect JobTaskSource with a priority that was
// increased from BEST_EFFORT to USER_BLOCKING.
TEST_F(ThreadGroupTest, JobTaskSourceUpdatePriority) {}

INSTANTIATE_TEST_SUITE_P();
INSTANTIATE_TEST_SUITE_P();
INSTANTIATE_TEST_SUITE_P();

}  // namespace internal
}  // namespace base