205 lines
6.4 KiB
C++
205 lines
6.4 KiB
C++
|
|
// Copyright 2021 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/delayed_task_handle.h"
|
||
|
|
|
||
|
|
#include "base/memory/raw_ptr.h"
|
||
|
|
#include "base/test/gtest_util.h"
|
||
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
||
|
|
|
||
|
|
namespace base {
|
||
|
|
|
||
|
|
namespace {
|
||
|
|
|
||
|
|
// A non-working delegate that allows the testing of DelayedTaskHandle.
|
||
|
|
class TestDelegate : public DelayedTaskHandle::Delegate {
|
||
|
|
public:
|
||
|
|
explicit TestDelegate(bool* was_cancel_task_called = nullptr)
|
||
|
|
: was_cancel_task_called_(was_cancel_task_called) {
|
||
|
|
DCHECK(!was_cancel_task_called_ || !*was_cancel_task_called_);
|
||
|
|
}
|
||
|
|
~TestDelegate() override = default;
|
||
|
|
|
||
|
|
bool IsValid() const override { return is_valid_; }
|
||
|
|
void CancelTask() override {
|
||
|
|
is_valid_ = false;
|
||
|
|
|
||
|
|
if (was_cancel_task_called_)
|
||
|
|
*was_cancel_task_called_ = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private:
|
||
|
|
// Indicates if this delegate is currently valid.
|
||
|
|
bool is_valid_ = true;
|
||
|
|
|
||
|
|
// Indicates if CancelTask() was invoked, if not null. Must outlives |this|.
|
||
|
|
raw_ptr<bool> was_cancel_task_called_;
|
||
|
|
};
|
||
|
|
|
||
|
|
} // namespace
|
||
|
|
|
||
|
|
// Tests that a default-constructed handle is invalid.
|
||
|
|
TEST(DelayedTaskHandleTest, DefaultConstructor) {
|
||
|
|
DelayedTaskHandle delayed_task_handle;
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that creating a handle with an invalid delegate will DCHECK.
|
||
|
|
TEST(DelayedTaskHandleTest, RequiresValidDelegateOnConstruction) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
// Invalidate the delegate before creating the handle.
|
||
|
|
delegate->CancelTask();
|
||
|
|
EXPECT_FALSE(delegate->IsValid());
|
||
|
|
|
||
|
|
EXPECT_DCHECK_DEATH(
|
||
|
|
{ DelayedTaskHandle delayed_task_handle(std::move(delegate)); });
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that calling CancelTask() on the handle will call CancelTask() on the
|
||
|
|
// delegate and invalidate it.
|
||
|
|
TEST(DelayedTaskHandleTest, CancelTask) {
|
||
|
|
bool was_cancel_task_called = false;
|
||
|
|
auto delegate = std::make_unique<TestDelegate>(&was_cancel_task_called);
|
||
|
|
EXPECT_FALSE(was_cancel_task_called);
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_FALSE(was_cancel_task_called);
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
delayed_task_handle.CancelTask();
|
||
|
|
|
||
|
|
EXPECT_TRUE(was_cancel_task_called);
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that calling CancelTask() on a handle with no delegate will no-op.
|
||
|
|
TEST(DelayedTaskHandleTest, CancelTaskNoDelegate) {
|
||
|
|
DelayedTaskHandle delayed_task_handle;
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
delayed_task_handle.CancelTask();
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that calling CancelTask() on a handle with an invalid delegate doesn't
|
||
|
|
// crash and keeps the handle invalid.
|
||
|
|
TEST(DelayedTaskHandleTest, CancelTaskInvalidDelegate) {
|
||
|
|
bool was_cancel_task_called = false;
|
||
|
|
auto delegate = std::make_unique<TestDelegate>(&was_cancel_task_called);
|
||
|
|
EXPECT_FALSE(was_cancel_task_called);
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_FALSE(was_cancel_task_called);
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
delegate_ptr->CancelTask();
|
||
|
|
|
||
|
|
EXPECT_TRUE(was_cancel_task_called);
|
||
|
|
EXPECT_FALSE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
// Reset |was_cancel_task_called| to ensure Delegate::CancelTask() is still
|
||
|
|
// invoked on an invalid delegate.
|
||
|
|
was_cancel_task_called = false;
|
||
|
|
|
||
|
|
delayed_task_handle.CancelTask();
|
||
|
|
|
||
|
|
EXPECT_TRUE(was_cancel_task_called);
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that invalidating the delegate will also invalidate the handle.
|
||
|
|
TEST(DelayedTaskHandleTest, InvalidateDelegate) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
delegate_ptr->CancelTask();
|
||
|
|
|
||
|
|
EXPECT_FALSE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_FALSE(delayed_task_handle.IsValid());
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that destroying a valid handle will DCHECK.
|
||
|
|
TEST(DelayedTaskHandleTest, InvalidOnDestuction) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
EXPECT_DCHECK_DEATH({
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests the move-constructor.
|
||
|
|
TEST(DelayedTaskHandleTest, MoveConstructor) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
DelayedTaskHandle other_delayed_task_handle(std::move(delayed_task_handle));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(other_delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
// Clean-up.
|
||
|
|
other_delayed_task_handle.CancelTask();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests the move-assignment.
|
||
|
|
TEST(DelayedTaskHandleTest, MoveAssignment) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
DelayedTaskHandle other_delayed_task_handle;
|
||
|
|
EXPECT_FALSE(other_delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
other_delayed_task_handle = std::move(delayed_task_handle);
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(other_delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
// Clean-up.
|
||
|
|
other_delayed_task_handle.CancelTask();
|
||
|
|
}
|
||
|
|
|
||
|
|
// Tests that assigning to a valid handle will DCHECK.
|
||
|
|
TEST(DelayedTaskHandleTest, AssignToValidHandle) {
|
||
|
|
auto delegate = std::make_unique<TestDelegate>();
|
||
|
|
EXPECT_TRUE(delegate->IsValid());
|
||
|
|
|
||
|
|
auto* delegate_ptr = delegate.get();
|
||
|
|
DelayedTaskHandle delayed_task_handle(std::move(delegate));
|
||
|
|
EXPECT_TRUE(delegate_ptr->IsValid());
|
||
|
|
EXPECT_TRUE(delayed_task_handle.IsValid());
|
||
|
|
|
||
|
|
EXPECT_DCHECK_DEATH({ delayed_task_handle = DelayedTaskHandle(); });
|
||
|
|
|
||
|
|
// Clean-up.
|
||
|
|
delayed_task_handle.CancelTask();
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace base
|