Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: webrtc/base/sequenced_task_checker_unittest.cc

Issue 2125113003: Implement SequencedTaskChecker. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 // Duplicated from base/threading/sequenced_thread_checker.h so that we can be
23 // good citizens there and undef the macro.
24 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
25 #define ENABLE_SEQUENCED_TASK_CHECKER 1
tommi 2016/07/08 13:15:15 this doesn't look like the right place to change t
perkj_webrtc 2016/07/11 08:38:01 Ok- These tests were a copy of the threadcheker un
26 #else
27 #define ENABLE_SEQUENCED_TASK_CHECKER 0
28 #endif
29
30 namespace rtc {
31
32 namespace {
33
34 // Simple class to exercise the basics of SequencedTaskChecker.
35 class SequencedCheckerClass : public SequencedTaskChecker {
36 public:
37 SequencedCheckerClass() {}
38
39 // Verifies that it was called on the same thread as the constructor.
40 void DoStuff() { RTC_DCHECK(IsCurrent()); }
tommi 2016/07/08 13:15:15 since this is a test, it's probably better to do E
perkj_webrtc 2016/07/11 08:38:01 Done. - No longer using death tests.
41
42 void DetachFromSequence() { SequencedTaskChecker::Detach(); }
tommi 2016/07/08 13:15:16 Is this method needed or can the caller just call
perkj_webrtc 2016/07/11 08:38:01 Done.
43
44 static void MethodOnDifferentThreadImpl();
45 static void MethodOnDifferentTaskQueueImpl();
46 static void DetachThenCallFromDifferentThreadImpl();
47 static void DetachThenCallFromDifferentTaskQueueImpl();
48
49 private:
50 RTC_DISALLOW_COPY_AND_ASSIGN(SequencedCheckerClass);
51 };
52
53 // Calls SequencedCheckerClass::DoStuff on another thread.
54 class CallDoStuffOnThread : public Thread {
tommi 2016/07/08 13:15:15 instead of using rtc::Thread (which we're using le
perkj_webrtc 2016/07/11 08:38:01 Done.
55 public:
56 explicit CallDoStuffOnThread(SequencedCheckerClass* sequence_checker_class)
57 : Thread(), sequence_checker_class_(sequence_checker_class) {
58 SetName("call_do_stuff_on_thread", NULL);
59 }
60
61 void Run() override { sequence_checker_class_->DoStuff(); }
62
63 // New method. Needed since Thread::Join is protected, and it is called by
64 // the TEST.
65 void Join() { Thread::Join(); }
tommi 2016/07/08 13:15:15 I think you can also do: using Thread::Join;
perkj_webrtc 2016/07/11 08:38:01 Acknowledged.
66
67 private:
68 SequencedCheckerClass* sequence_checker_class_;
69
70 RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread);
71 };
72
73 // Deletes SequencedCheckerClass on a different thread.
74 class DeleteThreadCheckerClassOnThread : public Thread {
75 public:
76 explicit DeleteThreadCheckerClassOnThread(
77 SequencedCheckerClass* sequence_checker_class)
78 : Thread(), sequenced_checker_class_(sequence_checker_class) {
79 SetName("delete_sequence_checker_class_on_thread", NULL);
80 }
81
82 void Run() override { sequenced_checker_class_.reset(); }
83
84 // New method. Needed since Thread::Join is protected, and it is called by
85 // the TEST.
86 void Join() { Thread::Join(); }
87
88 private:
89 std::unique_ptr<SequencedCheckerClass> sequenced_checker_class_;
90
91 RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerClassOnThread);
92 };
93
94 } // namespace
95
96 TEST(SequencedTaskCheckerTest, CallsAllowedOnSameThread) {
97 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
98 new SequencedCheckerClass);
tommi 2016/07/08 13:15:15 new SequencedCheckerClass()
perkj_webrtc 2016/07/11 08:38:01 Done.
99
100 // Verify that DoStuff doesn't assert.
101 sequence_checker_class->DoStuff();
102
103 // Verify that the destructor doesn't assert.
104 sequence_checker_class.reset();
105 }
106
107 TEST(SequencedTaskCheckerTest, DestructorAllowedOnDifferentThread) {
108 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
109 new SequencedCheckerClass);
110
111 // Verify that the destructor doesn't assert
112 // when called on a different thread.
113 DeleteThreadCheckerClassOnThread delete_on_thread(
114 sequence_checker_class.release());
115
116 delete_on_thread.Start();
117 delete_on_thread.Join();
118 }
119
120 TEST(SequencedTaskCheckerTest, DetachFromThread) {
121 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
122 new SequencedCheckerClass);
123
124 // Verify that DoStuff doesn't assert when called on a different thread after
125 // a call to DetachFromSequence.
126 sequence_checker_class->DetachFromSequence();
127 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
128
129 call_on_thread.Start();
130 call_on_thread.Join();
131 }
132
133 TEST(SequencedTaskCheckerTest, DetachFromThreadAndUseOnTaskQueue) {
134 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
135 new SequencedCheckerClass);
136
137 // Verify that DoStuff doesn't assert when called on a different tq after
138 // a call to DetachFromSequence.
139 sequence_checker_class->DetachFromSequence();
140 static const char kQueueName[] = "DetachFromThreadAndUseOnTaskQueue";
141 TaskQueue queue(kQueueName);
142 Event done_event(false, false);
143 queue.PostTask([&sequence_checker_class, &done_event] {
144 sequence_checker_class->DoStuff();
145 done_event.Set();
146 });
147 EXPECT_TRUE(done_event.Wait(1000));
148 }
149
150 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueAndUseOnThread) {
151 TaskQueue queue("DetachFromTaskQueueAndUseOnThread");
152 Event done_event(false, false);
153 queue.PostTask([&done_event] {
154 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
155 new SequencedCheckerClass);
156
157 // Verify that DoStuff doesn't assert when called on a different thread
158 // after a call to DetachFromSequence.
159 sequence_checker_class->DetachFromSequence();
160 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
161
162 call_on_thread.Start();
163 call_on_thread.Join();
164
165 done_event.Set();
166 });
167 EXPECT_TRUE(done_event.Wait(1000));
168 }
169
170 #if GTEST_HAS_DEATH_TEST || !ENABLE_SEQUENCED_TASK_CHECKER
tommi 2016/07/08 13:15:15 I'm having problems groking this check... can you
perkj_webrtc 2016/07/11 08:38:01 Refactored to no longer use death tests.
171
172 void SequencedCheckerClass::MethodOnDifferentThreadImpl() {
173 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
174 new SequencedCheckerClass);
175
176 // DoStuff should assert in debug builds only when called on a
177 // different thread.
178 CallDoStuffOnThread call_on_thread(sequence_checker_class.get());
179
180 call_on_thread.Start();
181 call_on_thread.Join();
182 }
183
184 #if ENABLE_SEQUENCED_TASK_CHECKER
185 TEST(SequencedTaskCheckerDeathTest, MethodNotAllowedOnDifferentThreadInDebug) {
186 ASSERT_DEATH({ SequencedCheckerClass::MethodOnDifferentThreadImpl(); }, "");
187 }
188 #else
189 TEST(SequencedTaskCheckerDeathTest, MethodAllowedOnDifferentThreadInRelease) {
190 SequencedCheckerClass::MethodOnDifferentThreadImpl();
191 }
192 #endif // ENABLE_SEQUENCED_TASK_CHECKER
193
194 void SequencedCheckerClass::MethodOnDifferentTaskQueueImpl() {
195 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
196 new SequencedCheckerClass);
197
198 // Verify that DoStuff assert when called on a tq.
199 static const char kQueueName[] = "MethodNotAllowedOnDifferentTq";
200 TaskQueue queue(kQueueName);
201 Event done_event(false, false);
202 queue.PostTask([&sequence_checker_class, &done_event] {
203 sequence_checker_class->DoStuff();
204 done_event.Set();
205 });
206 EXPECT_TRUE(done_event.Wait(1000));
207 }
208
209 #if ENABLE_SEQUENCED_TASK_CHECKER
210 TEST(SequencedTaskCheckerDeathTest, MethodNotAllowedOnDifferentTqInDebug) {
211 ASSERT_DEATH({ SequencedCheckerClass::MethodOnDifferentTaskQueueImpl(); },
212 "");
213 }
214 #else
215 TEST(SequencedTaskCheckerDeathTest, MethodAllowedOnDifferentTqInRelease) {
216 SequencedCheckerClass::MethodOnDifferentTaskQueueImpl();
217 }
218 #endif // ENABLE_SEQUENCED_TASK_CHECKER
219
220 void SequencedCheckerClass::DetachThenCallFromDifferentTaskQueueImpl() {
221 std::unique_ptr<SequencedCheckerClass> sequence_checker_class(
222 new SequencedCheckerClass);
223
224 // DoStuff doesn't assert when called on a different task queue
225 // after a call to DetachFromSequence.
226 sequence_checker_class->DetachFromSequence();
227
228 Event done_event(false, false);
229 TaskQueue queue1("DetachThenCallFromDifferentTaskQueueImpl1");
230 queue1.PostTask([&sequence_checker_class, &done_event] {
231 sequence_checker_class->DoStuff();
232 done_event.Set();
233 });
234 EXPECT_TRUE(done_event.Wait(1000));
235
236 // DoStuff should assert in debug builds only after moving to
237 // another task queue.
238 TaskQueue queue2("DetachThenCallFromDifferentTaskQueueImpl2");
239 queue2.PostTask([&sequence_checker_class, &done_event] {
240 sequence_checker_class->DoStuff();
241 done_event.Set();
242 });
243 done_event.Wait(1000);
244 }
245
246 #if ENABLE_SEQUENCED_TASK_CHECKER
247 TEST(SequencedTaskCheckerDeathTest, DetachFromTaskQueueInDebug) {
248 ASSERT_DEATH(
249 { SequencedCheckerClass::DetachThenCallFromDifferentTaskQueueImpl(); },
250 "");
251 }
252 #else
253 TEST(SequencedTaskCheckerDeathTest, DetachFromThreadInRelease) {
254 SequencedCheckerClass::DetachThenCallFromDifferentTaskQueueImpl();
255 }
256 #endif // ENABLE_THREAD_CHECKER
257
258 #endif // GTEST_HAS_DEATH_TEST || !ENABLE_THREAD_CHECKER
259
260 class SequencedTaskCheckerAnnotateTest {
261 public:
262 // Next two function should create warnings when compile (e.g. if used with
263 // specific T).
264 // TODO(danilchap): Find a way to test they do not compile when thread
265 // annotation checks enabled.
266 template <typename T>
267 void access_var_no_annotate() {
tommi 2016/07/08 13:15:15 AccessVarNoAnnotate (since this isn't a getter)
perkj_webrtc 2016/07/11 08:38:01 removed all for now.
268 var_checker_ = 42;
269 }
270
271 template <typename T>
272 void access_fun_no_annotate() {
tommi 2016/07/08 13:15:15 AccessFunctionNoAnnotate etc
perkj_webrtc 2016/07/11 08:38:01 dito
273 function();
274 }
275
276 // Function below should be able to compile.
277 void access_var_annotate_checker() {
278 RTC_DCHECK_RUN_ON(&checker_);
279 var_checker_ = 44;
280 }
281
282 void access_fun_annotate() {
283 RTC_DCHECK_RUN_ON(&checker_);
284 function();
285 }
286
287 private:
288 void function() RUN_ON(checker_) {}
289
290 rtc::SequencedTaskChecker checker_;
291
292 int var_checker_ GUARDED_BY(checker_);
293 };
294
295 TEST(SequencedTaskCheckerAnnotateTest, test) {
296 SequencedTaskCheckerAnnotateTest tester;
297 tester.access_var_annotate_checker();
298 }
299
300 // Just in case we ever get lumped together with other compilation units.
301 #undef ENABLE_SEQUENCED_TASK_CHECKER
tommi 2016/07/08 13:15:15 this could only happen if another file #includes s
perkj_webrtc 2016/07/11 08:38:01 Acknowledged.
302
303 } // namespace rtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698