mirror of https://github.com/NekoX-Dev/NekoX.git
192 lines
7.2 KiB
C++
192 lines
7.2 KiB
C++
// Copyright 2019 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#ifndef BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
|
|
#define BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
|
|
|
|
#include "base/synchronization/atomic_flag.h"
|
|
#include "base/task/thread_pool/task_tracker.h"
|
|
#include "base/task/thread_pool/test_utils.h"
|
|
#include "base/task_runner.h"
|
|
#include "base/test/bind_test_util.h"
|
|
#include "base/test/test_timeouts.h"
|
|
#include "base/test/test_waitable_event.h"
|
|
#include "base/threading/platform_thread.h"
|
|
#include "build/build_config.h"
|
|
|
|
namespace base {
|
|
namespace internal {
|
|
namespace test {
|
|
|
|
// Verify that tasks only run when allowed by the CanRunPolicy. |target| is the
|
|
// object on which DidUpdateCanRunPolicy() must be called after updating the
|
|
// CanRunPolicy in |task_tracker|. |create_task_runner| is a function that
|
|
// receives a TaskPriority and returns a TaskRunner. |task_tracker| is the
|
|
// TaskTracker.
|
|
template <typename Target, typename CreateTaskRunner>
|
|
void TestCanRunPolicyBasic(Target* target,
|
|
CreateTaskRunner create_task_runner,
|
|
TaskTracker* task_tracker) {
|
|
AtomicFlag foreground_can_run;
|
|
TestWaitableEvent foreground_did_run;
|
|
AtomicFlag best_effort_can_run;
|
|
TestWaitableEvent best_effort_did_run;
|
|
|
|
task_tracker->SetCanRunPolicy(CanRunPolicy::kNone);
|
|
target->DidUpdateCanRunPolicy();
|
|
|
|
const auto user_visible_task_runner =
|
|
create_task_runner(TaskPriority::USER_VISIBLE);
|
|
user_visible_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
|
|
EXPECT_TRUE(foreground_can_run.IsSet());
|
|
foreground_did_run.Signal();
|
|
}));
|
|
const auto best_effort_task_runner =
|
|
create_task_runner(TaskPriority::BEST_EFFORT);
|
|
best_effort_task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
|
|
EXPECT_TRUE(best_effort_can_run.IsSet());
|
|
best_effort_did_run.Signal();
|
|
}));
|
|
|
|
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
|
|
|
|
foreground_can_run.Set();
|
|
task_tracker->SetCanRunPolicy(CanRunPolicy::kForegroundOnly);
|
|
target->DidUpdateCanRunPolicy();
|
|
foreground_did_run.Wait();
|
|
|
|
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
|
|
|
|
best_effort_can_run.Set();
|
|
task_tracker->SetCanRunPolicy(CanRunPolicy::kAll);
|
|
target->DidUpdateCanRunPolicy();
|
|
best_effort_did_run.Wait();
|
|
}
|
|
|
|
// Verify that if a task was allowed to run by the CanRunPolicy when it was
|
|
// posted, but the CanRunPolicy is updated to disallow it from running before it
|
|
// starts running, it doesn't run. |target| is the object on which
|
|
// DidUpdateCanRunPolicy() must be called after updating the CanRunPolicy in
|
|
// |task_tracker|. |create_task_runner| is a function that receives a
|
|
// TaskPriority and returns a *Sequenced*TaskRunner. |task_tracker| is the
|
|
// TaskTracker.
|
|
template <typename Target, typename CreateTaskRunner>
|
|
void TestCanRunPolicyChangedBeforeRun(Target* target,
|
|
CreateTaskRunner create_task_runner,
|
|
TaskTracker* task_tracker) {
|
|
constexpr struct {
|
|
// Descriptor for the test case.
|
|
const char* descriptor;
|
|
// Task priority being tested.
|
|
TaskPriority priority;
|
|
// Policy that disallows running tasks with |priority|.
|
|
CanRunPolicy disallow_policy;
|
|
// Policy that allows running tasks with |priority|.
|
|
CanRunPolicy allow_policy;
|
|
} kTestCases[] = {
|
|
{"BestEffort/kNone/kAll", TaskPriority::BEST_EFFORT, CanRunPolicy::kNone,
|
|
CanRunPolicy::kAll},
|
|
{"BestEffort/kForegroundOnly/kAll", TaskPriority::BEST_EFFORT,
|
|
CanRunPolicy::kForegroundOnly, CanRunPolicy::kAll},
|
|
{"UserVisible/kNone/kForegroundOnly", TaskPriority::USER_VISIBLE,
|
|
CanRunPolicy::kNone, CanRunPolicy::kForegroundOnly},
|
|
{"UserVisible/kNone/kAll", TaskPriority::USER_VISIBLE,
|
|
CanRunPolicy::kNone, CanRunPolicy::kAll}};
|
|
|
|
for (auto& test_case : kTestCases) {
|
|
SCOPED_TRACE(test_case.descriptor);
|
|
|
|
TestWaitableEvent first_task_started;
|
|
TestWaitableEvent first_task_blocked;
|
|
AtomicFlag second_task_can_run;
|
|
|
|
task_tracker->SetCanRunPolicy(test_case.allow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
|
|
const auto task_runner = create_task_runner(test_case.priority);
|
|
task_runner->PostTask(
|
|
FROM_HERE, BindLambdaForTesting([&]() {
|
|
first_task_started.Signal();
|
|
first_task_blocked.Wait();
|
|
}));
|
|
task_runner->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
|
|
EXPECT_TRUE(second_task_can_run.IsSet());
|
|
}));
|
|
|
|
first_task_started.Wait();
|
|
task_tracker->SetCanRunPolicy(test_case.disallow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
first_task_blocked.Signal();
|
|
|
|
PlatformThread::Sleep(TestTimeouts::tiny_timeout());
|
|
|
|
second_task_can_run.Set();
|
|
task_tracker->SetCanRunPolicy(test_case.allow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
task_tracker->FlushForTesting();
|
|
}
|
|
}
|
|
|
|
// Regression test for https://crbug.com/950383
|
|
template <typename Target, typename CreateTaskRunner>
|
|
void TestCanRunPolicyLoad(Target* target,
|
|
CreateTaskRunner create_task_runner,
|
|
TaskTracker* task_tracker) {
|
|
constexpr struct {
|
|
// Descriptor for the test case.
|
|
const char* descriptor;
|
|
// Task priority being tested.
|
|
TaskPriority priority;
|
|
// Policy that allows running tasks with |priority|.
|
|
CanRunPolicy allow_policy;
|
|
// Policy that disallows running tasks with |priority|.
|
|
CanRunPolicy disallow_policy;
|
|
} kTestCases[] = {
|
|
{"BestEffort/kAll/kNone", TaskPriority::BEST_EFFORT, CanRunPolicy::kAll,
|
|
CanRunPolicy::kNone},
|
|
{"BestEffort/kAll/kForegroundOnly", TaskPriority::BEST_EFFORT,
|
|
CanRunPolicy::kAll, CanRunPolicy::kForegroundOnly},
|
|
{"UserVisible/kForegroundOnly/kNone", TaskPriority::USER_VISIBLE,
|
|
CanRunPolicy::kForegroundOnly, CanRunPolicy::kNone},
|
|
{"UserVisible/kAll/kNone", TaskPriority::USER_VISIBLE, CanRunPolicy::kAll,
|
|
CanRunPolicy::kNone}};
|
|
|
|
for (auto& test_case : kTestCases) {
|
|
SCOPED_TRACE(test_case.descriptor);
|
|
|
|
task_tracker->SetCanRunPolicy(test_case.allow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
|
|
const auto task_runner = create_task_runner(test_case.priority);
|
|
|
|
// Post less tasks on iOS to avoid timeouts.
|
|
const size_t kLargeNumber =
|
|
#if defined(OS_IOS)
|
|
16;
|
|
#else
|
|
256;
|
|
#endif
|
|
for (size_t i = 0; i < kLargeNumber; ++i)
|
|
task_runner->PostTask(FROM_HERE, DoNothing());
|
|
|
|
// Change the CanRunPolicy concurrently with running tasks.
|
|
// This should not cause crashes.
|
|
for (size_t i = 0; i < kLargeNumber; ++i) {
|
|
task_tracker->SetCanRunPolicy(test_case.disallow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
|
|
task_tracker->SetCanRunPolicy(test_case.allow_policy);
|
|
target->DidUpdateCanRunPolicy();
|
|
}
|
|
|
|
task_tracker->FlushForTesting();
|
|
}
|
|
}
|
|
|
|
} // namespace test
|
|
} // namespace internal
|
|
} // namespace base
|
|
|
|
#endif // BASE_TASK_THREAD_POOL_CAN_RUN_POLICY_TEST_H_
|