OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2016 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 // Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc. | |
12 | |
13 #include <memory> | |
14 | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 #include "webrtc/base/checks.h" | |
17 #include "webrtc/base/constructormagic.h" | |
18 #include "webrtc/base/sequenced_task_checker.h" | |
19 #include "webrtc/base/task_queue.h" | |
20 #include "webrtc/base/thread.h" | |
21 | |
22 namespace rtc { | |
23 | |
24 namespace { | |
25 // Calls SequencedCheckerClass::PlatformThread on another thread. | |
26 class CallDoStuffOnThread : public PlatformThread { | |
tommi
2016/07/12 13:08:56
instead of inheriting from PlatformThread, add a m
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
27 public: | |
28 explicit CallDoStuffOnThread(bool expect_true, | |
tommi
2016/07/12 13:08:56
no need for explicit (2 args)
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
29 SequencedTaskChecker* sequenced_task_checker) | |
30 : PlatformThread(Run, this, "call_do_stuff_on_thread"), | |
tommi
2016/07/12 13:08:56
&Run
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
31 expect_true_(expect_true), | |
32 sequenced_task_checker_(sequenced_task_checker) {} | |
33 | |
34 static bool Run(void* obj) { | |
tommi
2016/07/12 13:08:56
make private
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
35 CallDoStuffOnThread* call_stuff_on_thread = | |
36 static_cast<CallDoStuffOnThread*>(obj); | |
37 if (call_stuff_on_thread->expect_true_) | |
tommi
2016/07/12 13:08:56
{}
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
38 EXPECT_TRUE( | |
tommi
2016/07/12 13:08:56
could also do:
EXPECT_EQ(call_stuff_on_thread->ex
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
39 call_stuff_on_thread->sequenced_task_checker_->CalledSequentially()); | |
40 else | |
41 EXPECT_FALSE( | |
42 call_stuff_on_thread->sequenced_task_checker_->CalledSequentially()); | |
43 return false; | |
44 } | |
45 | |
46 private: | |
47 const bool expect_true_; | |
48 SequencedTaskChecker* const sequenced_task_checker_; | |
49 | |
50 RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread); | |
51 }; | |
52 | |
53 // Deletes SequencedTaskChecker on a different thread. | |
54 class DeleteThreadCheckerOnThread : public PlatformThread { | |
tommi
2016/07/12 13:08:56
Favor object composition over class inheritance.
(
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
55 public: | |
56 explicit DeleteThreadCheckerOnThread( | |
57 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker) | |
58 : PlatformThread(Run, this, "delete_sequenced_task_checker_on_thread"), | |
tommi
2016/07/12 13:08:56
&Run
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
59 sequenced_task_checker_(std::move(sequenced_task_checker)) {} | |
60 | |
61 static bool Run(void* obj) { | |
tommi
2016/07/12 13:08:56
private (etc)
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
62 static_cast<DeleteThreadCheckerOnThread*>(obj) | |
63 ->sequenced_task_checker_.reset(); | |
64 return false; | |
65 } | |
66 | |
67 private: | |
68 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker_; | |
69 | |
70 RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerOnThread); | |
71 }; | |
72 | |
73 void RunMethodOnDifferentThread(bool expect_true) { | |
74 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
75 new SequencedTaskChecker()); | |
76 | |
77 CallDoStuffOnThread call_on_thread(expect_true, sequenced_task_checker.get()); | |
78 | |
79 call_on_thread.Start(); | |
tommi
2016/07/12 13:08:56
Start/Stop could occur implicitly in the ctor/dtor
perkj_webrtc
2016/07/12 15:22:00
Done.
| |
80 call_on_thread.Stop(); | |
81 } | |
82 | |
83 void RunMethodOnDifferentTaskQueue(bool expect_true) { | |
84 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
85 new SequencedTaskChecker()); | |
86 | |
87 static const char kQueueName[] = "MethodNotAllowedOnDifferentTq"; | |
88 TaskQueue queue(kQueueName); | |
89 Event done_event(false, false); | |
90 queue.PostTask([&sequenced_task_checker, &done_event, expect_true] { | |
91 if (expect_true) | |
92 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
93 else | |
94 EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); | |
95 done_event.Set(); | |
96 }); | |
97 EXPECT_TRUE(done_event.Wait(1000)); | |
98 } | |
99 | |
100 void DetachThenCallFromDifferentTaskQueue(bool expect_true) { | |
101 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
102 new SequencedTaskChecker()); | |
103 | |
104 sequenced_task_checker->Detach(); | |
105 | |
106 Event done_event(false, false); | |
107 TaskQueue queue1("DetachThenCallFromDifferentTaskQueueImpl1"); | |
108 queue1.PostTask([&sequenced_task_checker, &done_event] { | |
109 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
110 done_event.Set(); | |
111 }); | |
112 EXPECT_TRUE(done_event.Wait(1000)); | |
113 | |
114 // CalledSequentially should return false in debug builds after moving to | |
115 // another task queue. | |
116 TaskQueue queue2("DetachThenCallFromDifferentTaskQueueImpl2"); | |
117 queue2.PostTask([&sequenced_task_checker, &done_event, expect_true] { | |
118 if (expect_true) | |
119 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
120 else | |
121 EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); | |
122 done_event.Set(); | |
123 }); | |
124 done_event.Wait(1000); | |
125 } | |
126 } // namespace | |
127 | |
128 TEST(SequencedTaskCheckerTest, CallsAllowedOnSameThread) { | |
129 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
130 new SequencedTaskChecker()); | |
131 | |
132 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
133 | |
134 // Verify that the destructor doesn't assert. | |
135 sequenced_task_checker.reset(); | |
136 } | |
137 | |
138 TEST(SequencedTaskCheckerTest, DestructorAllowedOnDifferentThread) { | |
139 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
140 new SequencedTaskChecker()); | |
141 | |
142 // Verify that the destructor doesn't assert when called on a different | |
143 // thread. | |
144 DeleteThreadCheckerOnThread delete_on_thread( | |
145 std::move(sequenced_task_checker)); | |
146 | |
147 delete_on_thread.Start(); | |
148 delete_on_thread.Stop(); | |
149 } | |
150 | |
151 TEST(SequencedTaskCheckerTest, DetachFromThread) { | |
152 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
153 new SequencedTaskChecker()); | |
154 | |
155 sequenced_task_checker->Detach(); | |
156 CallDoStuffOnThread call_on_thread(true, sequenced_task_checker.get()); | |
157 | |
158 call_on_thread.Start(); | |
159 call_on_thread.Stop(); | |
160 } | |
161 | |
162 TEST(SequencedTaskCheckerTest, DetachFromThreadAndUseOnTaskQueue) { | |
163 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
164 new SequencedTaskChecker()); | |
165 | |
166 sequenced_task_checker->Detach(); | |
167 static const char kQueueName[] = "DetachFromThreadAndUseOnTaskQueue"; | |
168 TaskQueue queue(kQueueName); | |
169 Event done_event(false, false); | |
170 queue.PostTask([&sequenced_task_checker, &done_event] { | |
171 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
172 done_event.Set(); | |
173 }); | |
174 EXPECT_TRUE(done_event.Wait(1000)); | |
175 } | |
176 | |
177 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueAndUseOnThread) { | |
178 TaskQueue queue("DetachFromTaskQueueAndUseOnThread"); | |
179 Event done_event(false, false); | |
180 queue.PostTask([&done_event] { | |
181 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
182 new SequencedTaskChecker()); | |
183 | |
184 sequenced_task_checker->Detach(); | |
185 CallDoStuffOnThread call_on_thread(true, sequenced_task_checker.get()); | |
186 | |
187 call_on_thread.Start(); | |
188 call_on_thread.Stop(); | |
189 | |
190 done_event.Set(); | |
191 }); | |
192 EXPECT_TRUE(done_event.Wait(1000)); | |
193 } | |
194 | |
195 #if !NDEBUG || DCHECK_ALWAYS_ON | |
196 TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) { | |
197 RunMethodOnDifferentThread(false); | |
198 } | |
199 #else | |
200 TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentThreadInRelease) { | |
201 RunMethodOnDifferentThread(true); | |
202 } | |
203 #endif | |
204 | |
205 #if !NDEBUG || DCHECK_ALWAYS_ON | |
206 TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) { | |
207 RunMethodOnDifferentTaskQueue(false); | |
208 } | |
209 #else | |
210 TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentTaskQueueInDebug) { | |
211 RunMethodOnDifferentTaskQueue(true); | |
212 } | |
213 #endif | |
214 | |
215 #if !NDEBUG || DCHECK_ALWAYS_ON | |
216 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInDebug) { | |
217 DetachThenCallFromDifferentTaskQueue(false); | |
218 } | |
219 #else | |
220 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInRelease) { | |
221 DetachThenCallFromDifferentTaskQueue(true); | |
222 } | |
223 #endif | |
224 } // namespace rtc | |
OLD | NEW |