1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
|
// Copyright 2016 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.
#include "third_party/blink/renderer/platform/web_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h"
namespace blink {
namespace {
void Increment(int* x) {
++*x;
}
void GetIsActive(bool* is_active, TaskHandle* handle) {
*is_active = handle->IsActive();
}
class CancellationTestHelper {
public:
CancellationTestHelper() : weak_ptr_factory_(this) {}
base::WeakPtr<CancellationTestHelper> GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
void RevokeWeakPtrs() { weak_ptr_factory_.InvalidateWeakPtrs(); }
void IncrementCounter() { ++counter_; }
int Counter() const { return counter_; }
private:
int counter_ = 0;
base::WeakPtrFactory<CancellationTestHelper> weak_ptr_factory_;
};
} // namespace
TEST(WebTaskRunnerTest, PostCancellableTaskTest) {
scoped_refptr<scheduler::FakeTaskRunner> task_runner =
base::MakeRefCounted<scheduler::FakeTaskRunner>();
// Run without cancellation.
int count = 0;
TaskHandle handle = PostCancellableTask(
*task_runner, FROM_HERE, WTF::Bind(&Increment, WTF::Unretained(&count)));
EXPECT_EQ(0, count);
EXPECT_TRUE(handle.IsActive());
task_runner->RunUntilIdle();
EXPECT_EQ(1, count);
EXPECT_FALSE(handle.IsActive());
count = 0;
handle = PostDelayedCancellableTask(
*task_runner, FROM_HERE, WTF::Bind(&Increment, WTF::Unretained(&count)),
TimeDelta::FromMilliseconds(1));
EXPECT_EQ(0, count);
EXPECT_TRUE(handle.IsActive());
task_runner->RunUntilIdle();
EXPECT_EQ(1, count);
EXPECT_FALSE(handle.IsActive());
// Cancel a task.
count = 0;
handle = PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&Increment, WTF::Unretained(&count)));
handle.Cancel();
EXPECT_EQ(0, count);
EXPECT_FALSE(handle.IsActive());
task_runner->RunUntilIdle();
EXPECT_EQ(0, count);
// The task should be cancelled when the handle is dropped.
{
count = 0;
TaskHandle handle2 =
PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&Increment, WTF::Unretained(&count)));
EXPECT_TRUE(handle2.IsActive());
}
EXPECT_EQ(0, count);
task_runner->RunUntilIdle();
EXPECT_EQ(0, count);
// The task should be cancelled when another TaskHandle is assigned on it.
count = 0;
handle = PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&Increment, WTF::Unretained(&count)));
handle = PostCancellableTask(*task_runner, FROM_HERE, WTF::Bind([] {}));
EXPECT_EQ(0, count);
task_runner->RunUntilIdle();
EXPECT_EQ(0, count);
// Self assign should be nop.
count = 0;
handle = PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&Increment, WTF::Unretained(&count)));
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wself-move"
handle = std::move(handle);
#pragma GCC diagnostic pop
#else
handle = std::move(handle);
#endif // defined(__clang__)
EXPECT_EQ(0, count);
task_runner->RunUntilIdle();
EXPECT_EQ(1, count);
// handle->isActive() should switch to false before the task starts running.
bool is_active = false;
handle =
PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&GetIsActive, WTF::Unretained(&is_active),
WTF::Unretained(&handle)));
EXPECT_TRUE(handle.IsActive());
task_runner->RunUntilIdle();
EXPECT_FALSE(is_active);
EXPECT_FALSE(handle.IsActive());
}
TEST(WebTaskRunnerTest, CancellationCheckerTest) {
scoped_refptr<scheduler::FakeTaskRunner> task_runner =
base::MakeRefCounted<scheduler::FakeTaskRunner>();
int count = 0;
TaskHandle handle = PostCancellableTask(
*task_runner, FROM_HERE, WTF::Bind(&Increment, WTF::Unretained(&count)));
EXPECT_EQ(0, count);
// TaskHandle::isActive should detect the deletion of posted task.
auto queue = task_runner->TakePendingTasksForTesting();
ASSERT_EQ(1u, queue.size());
EXPECT_FALSE(queue[0].first.IsCancelled());
EXPECT_TRUE(handle.IsActive());
queue.clear();
EXPECT_FALSE(handle.IsActive());
EXPECT_EQ(0, count);
count = 0;
CancellationTestHelper helper;
handle =
PostCancellableTask(*task_runner, FROM_HERE,
WTF::Bind(&CancellationTestHelper::IncrementCounter,
helper.GetWeakPtr()));
EXPECT_EQ(0, helper.Counter());
// The cancellation of the posted task should be propagated to TaskHandle.
queue = task_runner->TakePendingTasksForTesting();
ASSERT_EQ(1u, queue.size());
EXPECT_FALSE(queue[0].first.IsCancelled());
EXPECT_TRUE(handle.IsActive());
helper.RevokeWeakPtrs();
EXPECT_TRUE(queue[0].first.IsCancelled());
EXPECT_FALSE(handle.IsActive());
}
} // namespace blink
|