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 #include "testing/gtest/include/gtest/gtest.h" | |
11 #include "webrtc/base/checks.h" | |
12 #include "webrtc/base/constructormagic.h" | |
13 #include "webrtc/base/platform_thread.h" | |
14 #include "webrtc/base/sequenced_task_checker.h" | |
15 #include "webrtc/base/task_queue.h" | |
16 | |
17 namespace rtc { | |
18 | |
19 namespace { | |
20 // Calls SequencedCheckerClass::PlatformThread on another thread. | |
21 class CallCalledSequentiallyOnThread { | |
22 public: | |
23 CallCalledSequentiallyOnThread(bool expect_true, | |
24 SequencedTaskChecker* sequenced_task_checker) | |
25 : expect_true_(expect_true), | |
26 thread_(&Run, this, "call_do_stuff_on_thread"), | |
27 sequenced_task_checker_(sequenced_task_checker) { | |
28 thread_.Start(); | |
29 thread_.Stop(); | |
tommi
2016/07/12 17:19:23
call Stop() in the dtor? (same below)
How do you g
perkj_webrtc
2016/07/12 20:50:57
Done but why would calling stop in the dtor be any
tommi
2016/07/12 21:11:06
Ah, that's great. If that's the contract, then it
| |
30 } | |
31 | |
32 private: | |
33 static bool Run(void* obj) { | |
34 CallCalledSequentiallyOnThread* call_stuff_on_thread = | |
35 static_cast<CallCalledSequentiallyOnThread*>(obj); | |
36 EXPECT_EQ( | |
37 call_stuff_on_thread->sequenced_task_checker_->CalledSequentially(), | |
38 call_stuff_on_thread->expect_true_); | |
tommi
2016/07/12 17:19:23
nit: expectation first
perkj_webrtc
2016/07/12 20:50:57
Done.
| |
39 return false; | |
40 } | |
41 | |
42 const bool expect_true_; | |
43 PlatformThread thread_; | |
44 SequencedTaskChecker* const sequenced_task_checker_; | |
45 | |
46 RTC_DISALLOW_COPY_AND_ASSIGN(CallCalledSequentiallyOnThread); | |
47 }; | |
48 | |
49 // Deletes SequencedTaskChecker on a different thread. | |
50 class DeleteThreadCheckerOnThread { | |
51 public: | |
52 explicit DeleteThreadCheckerOnThread( | |
53 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker) | |
54 : thread_(&Run, this, "delete_sequenced_task_checker_on_thread"), | |
55 sequenced_task_checker_(std::move(sequenced_task_checker)) { | |
56 thread_.Start(); | |
57 thread_.Stop(); | |
58 } | |
59 | |
60 private: | |
61 static bool Run(void* obj) { | |
62 static_cast<DeleteThreadCheckerOnThread*>(obj) | |
63 ->sequenced_task_checker_.reset(); | |
64 return false; | |
65 } | |
66 | |
67 private: | |
68 PlatformThread thread_; | |
69 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker_; | |
70 | |
71 RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerOnThread); | |
72 }; | |
73 | |
74 void RunMethodOnDifferentThread(bool expect_true) { | |
75 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
76 new SequencedTaskChecker()); | |
77 | |
78 CallCalledSequentiallyOnThread call_on_thread(expect_true, | |
79 sequenced_task_checker.get()); | |
80 } | |
81 | |
82 void RunMethodOnDifferentTaskQueue(bool expect_true) { | |
83 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
84 new SequencedTaskChecker()); | |
85 | |
86 static const char kQueueName[] = "MethodNotAllowedOnDifferentTq"; | |
87 TaskQueue queue(kQueueName); | |
88 Event done_event(false, false); | |
89 queue.PostTask([&sequenced_task_checker, &done_event, expect_true] { | |
90 if (expect_true) | |
91 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
92 else | |
93 EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); | |
94 done_event.Set(); | |
95 }); | |
96 EXPECT_TRUE(done_event.Wait(1000)); | |
97 } | |
98 | |
99 void DetachThenCallFromDifferentTaskQueue(bool expect_true) { | |
100 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
101 new SequencedTaskChecker()); | |
102 | |
103 sequenced_task_checker->Detach(); | |
104 | |
105 Event done_event(false, false); | |
106 TaskQueue queue1("DetachThenCallFromDifferentTaskQueueImpl1"); | |
107 queue1.PostTask([&sequenced_task_checker, &done_event] { | |
108 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
109 done_event.Set(); | |
110 }); | |
111 EXPECT_TRUE(done_event.Wait(1000)); | |
112 | |
113 // CalledSequentially should return false in debug builds after moving to | |
114 // another task queue. | |
115 TaskQueue queue2("DetachThenCallFromDifferentTaskQueueImpl2"); | |
116 queue2.PostTask([&sequenced_task_checker, &done_event, expect_true] { | |
117 if (expect_true) | |
118 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
119 else | |
120 EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); | |
121 done_event.Set(); | |
122 }); | |
123 done_event.Wait(1000); | |
124 } | |
125 } // namespace | |
126 | |
127 TEST(SequencedTaskCheckerTest, CallsAllowedOnSameThread) { | |
128 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
129 new SequencedTaskChecker()); | |
130 | |
131 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
132 | |
133 // Verify that the destructor doesn't assert. | |
134 sequenced_task_checker.reset(); | |
135 } | |
136 | |
137 TEST(SequencedTaskCheckerTest, DestructorAllowedOnDifferentThread) { | |
138 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
139 new SequencedTaskChecker()); | |
140 | |
141 // Verify that the destructor doesn't assert when called on a different | |
142 // thread. | |
143 DeleteThreadCheckerOnThread delete_on_thread( | |
144 std::move(sequenced_task_checker)); | |
145 } | |
146 | |
147 TEST(SequencedTaskCheckerTest, DetachFromThread) { | |
148 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
149 new SequencedTaskChecker()); | |
150 | |
151 sequenced_task_checker->Detach(); | |
152 CallCalledSequentiallyOnThread call_on_thread(true, | |
153 sequenced_task_checker.get()); | |
154 } | |
155 | |
156 TEST(SequencedTaskCheckerTest, DetachFromThreadAndUseOnTaskQueue) { | |
157 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
158 new SequencedTaskChecker()); | |
159 | |
160 sequenced_task_checker->Detach(); | |
161 static const char kQueueName[] = "DetachFromThreadAndUseOnTaskQueue"; | |
162 TaskQueue queue(kQueueName); | |
163 Event done_event(false, false); | |
164 queue.PostTask([&sequenced_task_checker, &done_event] { | |
165 EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); | |
166 done_event.Set(); | |
167 }); | |
168 EXPECT_TRUE(done_event.Wait(1000)); | |
169 } | |
170 | |
171 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueAndUseOnThread) { | |
172 TaskQueue queue("DetachFromTaskQueueAndUseOnThread"); | |
173 Event done_event(false, false); | |
174 queue.PostTask([&done_event] { | |
175 std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( | |
176 new SequencedTaskChecker()); | |
177 | |
178 sequenced_task_checker->Detach(); | |
179 CallCalledSequentiallyOnThread call_on_thread(true, | |
180 sequenced_task_checker.get()); | |
181 done_event.Set(); | |
182 }); | |
183 EXPECT_TRUE(done_event.Wait(1000)); | |
184 } | |
185 | |
186 #if !NDEBUG || DCHECK_ALWAYS_ON | |
187 TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) { | |
188 RunMethodOnDifferentThread(false); | |
189 } | |
190 #else | |
191 TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentThreadInRelease) { | |
192 RunMethodOnDifferentThread(true); | |
193 } | |
194 #endif | |
195 | |
196 #if !NDEBUG || DCHECK_ALWAYS_ON | |
197 TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) { | |
198 RunMethodOnDifferentTaskQueue(false); | |
199 } | |
200 #else | |
201 TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentTaskQueueInRelease) { | |
202 RunMethodOnDifferentTaskQueue(true); | |
203 } | |
204 #endif | |
205 | |
206 #if !NDEBUG || DCHECK_ALWAYS_ON | |
207 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInDebug) { | |
208 DetachThenCallFromDifferentTaskQueue(false); | |
209 } | |
210 #else | |
211 TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInRelease) { | |
212 DetachThenCallFromDifferentTaskQueue(true); | |
213 } | |
214 #endif | |
215 | |
216 class TestAnnotations { | |
217 public: | |
218 TestAnnotations() : test_var_(false) {} | |
219 | |
220 void ModifyTestVar() { | |
221 RTC_DCHECK_CALLED_SEQUENTIALLY(&checker_); | |
222 test_var_ = true; | |
223 } | |
224 | |
225 private: | |
226 bool test_var_ GUARDED_BY(&checker_); | |
227 SequencedTaskChecker checker_; | |
228 }; | |
229 | |
230 TEST(SequencedTaskCheckerTest, TestAnnotations) { | |
231 TestAnnotations annotations; | |
232 annotations.ModifyTestVar(); | |
233 } | |
234 | |
235 #if GTEST_HAS_DEATH_TEST | |
tommi
2016/07/12 17:19:22
check the source code for where we use this. There
perkj_webrtc
2016/07/12 20:50:57
do not run on android it looks like.
| |
236 | |
237 void TestAnnotationsOnWrongQueue() { | |
238 TestAnnotations annotations; | |
239 static const char kQueueName[] = "TestAnnotationsOnWrongQueueDebug"; | |
240 TaskQueue queue(kQueueName); | |
241 Event done_event(false, false); | |
242 queue.PostTask([&annotations, &done_event] { | |
243 annotations.ModifyTestVar(); | |
244 done_event.Set(); | |
245 }); | |
246 EXPECT_TRUE(done_event.Wait(1000)); | |
247 } | |
248 | |
249 #if !NDEBUG || DCHECK_ALWAYS_ON | |
250 TEST(SequencedTaskCheckerTest, TestAnnotationsOnWrongQueueDebug) { | |
251 ASSERT_DEATH({ TestAnnotationsOnWrongQueue(); }, ""); | |
252 } | |
253 #else | |
254 TEST(SequencedTaskCheckerTest, TestAnnotationsOnWrongQueueRelease) { | |
255 TestAnnotationsOnWrongQueue(); | |
256 } | |
257 #endif | |
258 #endif // GTEST_HAS_DEATH_TEST | |
259 } // namespace rtc | |
OLD | NEW |