| /* | |
| * Copyright 2019 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "rtc_base/task_utils/to_queued_task.h" | |
| #include <memory> | |
| #include "absl/memory/memory.h" | |
| #include "api/task_queue/queued_task.h" | |
| #include "test/gmock.h" | |
| #include "test/gtest.h" | |
| namespace webrtc { | |
| namespace { | |
| using ::testing::InSequence; | |
| using ::testing::MockFunction; | |
| void RunTask(std::unique_ptr<QueuedTask> task) { | |
| // Simulate how task queue suppose to run tasks. | |
| QueuedTask* raw = task.release(); | |
| if (raw->Run()) | |
| delete raw; | |
| } | |
| TEST(ToQueuedTaskTest, AcceptsLambda) { | |
| bool run = false; | |
| std::unique_ptr<QueuedTask> task = ToQueuedTask([&run] { run = true; }); | |
| EXPECT_FALSE(run); | |
| RunTask(std::move(task)); | |
| EXPECT_TRUE(run); | |
| } | |
| TEST(ToQueuedTaskTest, AcceptsCopyableClosure) { | |
| struct CopyableClosure { | |
| CopyableClosure(int* num_copies, int* num_moves, int* num_runs) | |
| : num_copies(num_copies), num_moves(num_moves), num_runs(num_runs) {} | |
| CopyableClosure(const CopyableClosure& other) | |
| : num_copies(other.num_copies), | |
| num_moves(other.num_moves), | |
| num_runs(other.num_runs) { | |
| ++*num_copies; | |
| } | |
| CopyableClosure(CopyableClosure&& other) | |
| : num_copies(other.num_copies), | |
| num_moves(other.num_moves), | |
| num_runs(other.num_runs) { | |
| ++*num_moves; | |
| } | |
| void operator()() { ++*num_runs; } | |
| int* num_copies; | |
| int* num_moves; | |
| int* num_runs; | |
| }; | |
| int num_copies = 0; | |
| int num_moves = 0; | |
| int num_runs = 0; | |
| std::unique_ptr<QueuedTask> task; | |
| { | |
| CopyableClosure closure(&num_copies, &num_moves, &num_runs); | |
| task = ToQueuedTask(closure); | |
| // Destroy closure to check with msan task has own copy. | |
| } | |
| EXPECT_EQ(num_copies, 1); | |
| EXPECT_EQ(num_runs, 0); | |
| RunTask(std::move(task)); | |
| EXPECT_EQ(num_copies, 1); | |
| EXPECT_EQ(num_moves, 0); | |
| EXPECT_EQ(num_runs, 1); | |
| } | |
| TEST(ToQueuedTaskTest, AcceptsMoveOnlyClosure) { | |
| struct MoveOnlyClosure { | |
| MoveOnlyClosure(int* num_moves, std::function<void()> trigger) | |
| : num_moves(num_moves), trigger(std::move(trigger)) {} | |
| MoveOnlyClosure(const MoveOnlyClosure&) = delete; | |
| MoveOnlyClosure(MoveOnlyClosure&& other) | |
| : num_moves(other.num_moves), trigger(std::move(other.trigger)) { | |
| ++*num_moves; | |
| } | |
| void operator()() { trigger(); } | |
| int* num_moves; | |
| std::function<void()> trigger; | |
| }; | |
| int num_moves = 0; | |
| MockFunction<void()> run; | |
| auto task = ToQueuedTask(MoveOnlyClosure(&num_moves, run.AsStdFunction())); | |
| EXPECT_EQ(num_moves, 1); | |
| EXPECT_CALL(run, Call); | |
| RunTask(std::move(task)); | |
| EXPECT_EQ(num_moves, 1); | |
| } | |
| TEST(ToQueuedTaskTest, AcceptsMoveOnlyCleanup) { | |
| struct MoveOnlyClosure { | |
| MoveOnlyClosure(const MoveOnlyClosure&) = delete; | |
| MoveOnlyClosure(MoveOnlyClosure&&) = default; | |
| void operator()() { trigger(); } | |
| std::function<void()> trigger; | |
| }; | |
| MockFunction<void()> run; | |
| MockFunction<void()> cleanup; | |
| auto task = ToQueuedTask(MoveOnlyClosure{run.AsStdFunction()}, | |
| MoveOnlyClosure{cleanup.AsStdFunction()}); | |
| // Expect run closure to complete before cleanup closure. | |
| InSequence in_sequence; | |
| EXPECT_CALL(run, Call); | |
| EXPECT_CALL(cleanup, Call); | |
| RunTask(std::move(task)); | |
| } | |
| TEST(ToQueuedTaskTest, PendingTaskSafetyFlag) { | |
| rtc::scoped_refptr<PendingTaskSafetyFlag> flag = | |
| PendingTaskSafetyFlag::Create(); | |
| int count = 0; | |
| // Create two identical tasks that increment the `count`. | |
| auto task1 = ToQueuedTask(flag, [&count]() { ++count; }); | |
| auto task2 = ToQueuedTask(flag, [&count]() { ++count; }); | |
| EXPECT_EQ(0, count); | |
| RunTask(std::move(task1)); | |
| EXPECT_EQ(1, count); | |
| flag->SetNotAlive(); | |
| // Now task2 should actually not run. | |
| RunTask(std::move(task2)); | |
| EXPECT_EQ(1, count); | |
| } | |
| } // namespace | |
| } // namespace webrtc |