• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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