1 /*
2 * Copyright 2019 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/task_utils/to_queued_task.h"
12
13 #include <memory>
14
15 #include "absl/memory/memory.h"
16 #include "api/task_queue/queued_task.h"
17 #include "test/gmock.h"
18 #include "test/gtest.h"
19
20 namespace webrtc {
21 namespace {
22
23 using ::testing::InSequence;
24 using ::testing::MockFunction;
25
RunTask(std::unique_ptr<QueuedTask> task)26 void RunTask(std::unique_ptr<QueuedTask> task) {
27 // Simulate how task queue suppose to run tasks.
28 QueuedTask* raw = task.release();
29 if (raw->Run())
30 delete raw;
31 }
32
TEST(ToQueuedTaskTest,AcceptsLambda)33 TEST(ToQueuedTaskTest, AcceptsLambda) {
34 bool run = false;
35 std::unique_ptr<QueuedTask> task = ToQueuedTask([&run] { run = true; });
36 EXPECT_FALSE(run);
37 RunTask(std::move(task));
38 EXPECT_TRUE(run);
39 }
40
TEST(ToQueuedTaskTest,AcceptsCopyableClosure)41 TEST(ToQueuedTaskTest, AcceptsCopyableClosure) {
42 struct CopyableClosure {
43 CopyableClosure(int* num_copies, int* num_moves, int* num_runs)
44 : num_copies(num_copies), num_moves(num_moves), num_runs(num_runs) {}
45 CopyableClosure(const CopyableClosure& other)
46 : num_copies(other.num_copies),
47 num_moves(other.num_moves),
48 num_runs(other.num_runs) {
49 ++*num_copies;
50 }
51 CopyableClosure(CopyableClosure&& other)
52 : num_copies(other.num_copies),
53 num_moves(other.num_moves),
54 num_runs(other.num_runs) {
55 ++*num_moves;
56 }
57 void operator()() { ++*num_runs; }
58
59 int* num_copies;
60 int* num_moves;
61 int* num_runs;
62 };
63
64 int num_copies = 0;
65 int num_moves = 0;
66 int num_runs = 0;
67
68 std::unique_ptr<QueuedTask> task;
69 {
70 CopyableClosure closure(&num_copies, &num_moves, &num_runs);
71 task = ToQueuedTask(closure);
72 // Destroy closure to check with msan task has own copy.
73 }
74 EXPECT_EQ(num_copies, 1);
75 EXPECT_EQ(num_runs, 0);
76 RunTask(std::move(task));
77 EXPECT_EQ(num_copies, 1);
78 EXPECT_EQ(num_moves, 0);
79 EXPECT_EQ(num_runs, 1);
80 }
81
TEST(ToQueuedTaskTest,AcceptsMoveOnlyClosure)82 TEST(ToQueuedTaskTest, AcceptsMoveOnlyClosure) {
83 struct MoveOnlyClosure {
84 MoveOnlyClosure(int* num_moves, std::function<void()> trigger)
85 : num_moves(num_moves), trigger(std::move(trigger)) {}
86 MoveOnlyClosure(const MoveOnlyClosure&) = delete;
87 MoveOnlyClosure(MoveOnlyClosure&& other)
88 : num_moves(other.num_moves), trigger(std::move(other.trigger)) {
89 ++*num_moves;
90 }
91 void operator()() { trigger(); }
92
93 int* num_moves;
94 std::function<void()> trigger;
95 };
96
97 int num_moves = 0;
98 MockFunction<void()> run;
99
100 auto task = ToQueuedTask(MoveOnlyClosure(&num_moves, run.AsStdFunction()));
101 EXPECT_EQ(num_moves, 1);
102 EXPECT_CALL(run, Call);
103 RunTask(std::move(task));
104 EXPECT_EQ(num_moves, 1);
105 }
106
TEST(ToQueuedTaskTest,AcceptsMoveOnlyCleanup)107 TEST(ToQueuedTaskTest, AcceptsMoveOnlyCleanup) {
108 struct MoveOnlyClosure {
109 MoveOnlyClosure(const MoveOnlyClosure&) = delete;
110 MoveOnlyClosure(MoveOnlyClosure&&) = default;
111 void operator()() { trigger(); }
112
113 std::function<void()> trigger;
114 };
115
116 MockFunction<void()> run;
117 MockFunction<void()> cleanup;
118
119 auto task = ToQueuedTask(MoveOnlyClosure{run.AsStdFunction()},
120 MoveOnlyClosure{cleanup.AsStdFunction()});
121
122 // Expect run closure to complete before cleanup closure.
123 InSequence in_sequence;
124 EXPECT_CALL(run, Call);
125 EXPECT_CALL(cleanup, Call);
126 RunTask(std::move(task));
127 }
128
TEST(ToQueuedTaskTest,PendingTaskSafetyFlag)129 TEST(ToQueuedTaskTest, PendingTaskSafetyFlag) {
130 rtc::scoped_refptr<PendingTaskSafetyFlag> flag =
131 PendingTaskSafetyFlag::Create();
132
133 int count = 0;
134 // Create two identical tasks that increment the |count|.
135 auto task1 = ToQueuedTask(flag, [&count]() { ++count; });
136 auto task2 = ToQueuedTask(flag, [&count]() { ++count; });
137
138 EXPECT_EQ(0, count);
139 RunTask(std::move(task1));
140 EXPECT_EQ(1, count);
141 flag->SetNotAlive();
142 // Now task2 should actually not run.
143 RunTask(std::move(task2));
144 EXPECT_EQ(1, count);
145 }
146
147 } // namespace
148 } // namespace webrtc
149