1 /*
2 * Copyright (c) 2012 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 <utility>
12
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/modules/include/module.h"
16 #include "webrtc/modules/utility/source/process_thread_impl.h"
17 #include "webrtc/system_wrappers/include/tick_util.h"
18
19 namespace webrtc {
20
21 using ::testing::_;
22 using ::testing::DoAll;
23 using ::testing::InSequence;
24 using ::testing::Invoke;
25 using ::testing::Return;
26 using ::testing::SetArgPointee;
27
28 class MockModule : public Module {
29 public:
30 MOCK_METHOD0(TimeUntilNextProcess, int64_t());
31 MOCK_METHOD0(Process, int32_t());
32 MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*));
33 };
34
35 class RaiseEventTask : public ProcessTask {
36 public:
RaiseEventTask(EventWrapper * event)37 RaiseEventTask(EventWrapper* event) : event_(event) {}
Run()38 void Run() override { event_->Set(); }
39
40 private:
41 EventWrapper* event_;
42 };
43
ACTION_P(SetEvent,event)44 ACTION_P(SetEvent, event) {
45 event->Set();
46 }
47
ACTION_P(Increment,counter)48 ACTION_P(Increment, counter) {
49 ++(*counter);
50 }
51
ACTION_P(SetTimestamp,ptr)52 ACTION_P(SetTimestamp, ptr) {
53 *ptr = TickTime::MillisecondTimestamp();
54 }
55
TEST(ProcessThreadImpl,StartStop)56 TEST(ProcessThreadImpl, StartStop) {
57 ProcessThreadImpl thread("ProcessThread");
58 thread.Start();
59 thread.Stop();
60 }
61
TEST(ProcessThreadImpl,MultipleStartStop)62 TEST(ProcessThreadImpl, MultipleStartStop) {
63 ProcessThreadImpl thread("ProcessThread");
64 for (int i = 0; i < 5; ++i) {
65 thread.Start();
66 thread.Stop();
67 }
68 }
69
70 // Verifies that we get at least call back to Process() on the worker thread.
TEST(ProcessThreadImpl,ProcessCall)71 TEST(ProcessThreadImpl, ProcessCall) {
72 ProcessThreadImpl thread("ProcessThread");
73 thread.Start();
74
75 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
76
77 MockModule module;
78 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
79 EXPECT_CALL(module, Process())
80 .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
81 .WillRepeatedly(Return(0));
82 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
83
84 thread.RegisterModule(&module);
85 EXPECT_EQ(kEventSignaled, event->Wait(100));
86
87 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
88 thread.Stop();
89 }
90
91 // Same as ProcessCall except the module is registered before the
92 // call to Start().
TEST(ProcessThreadImpl,ProcessCall2)93 TEST(ProcessThreadImpl, ProcessCall2) {
94 ProcessThreadImpl thread("ProcessThread");
95 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
96
97 MockModule module;
98 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
99 EXPECT_CALL(module, Process())
100 .WillOnce(DoAll(SetEvent(event.get()), Return(0)))
101 .WillRepeatedly(Return(0));
102
103 thread.RegisterModule(&module);
104
105 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
106 thread.Start();
107 EXPECT_EQ(kEventSignaled, event->Wait(100));
108
109 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
110 thread.Stop();
111 }
112
113 // Tests setting up a module for callbacks and then unregister that module.
114 // After unregistration, we should not receive any further callbacks.
TEST(ProcessThreadImpl,Deregister)115 TEST(ProcessThreadImpl, Deregister) {
116 ProcessThreadImpl thread("ProcessThread");
117 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
118
119 int process_count = 0;
120 MockModule module;
121 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0));
122 EXPECT_CALL(module, Process())
123 .WillOnce(DoAll(SetEvent(event.get()),
124 Increment(&process_count),
125 Return(0)))
126 .WillRepeatedly(DoAll(Increment(&process_count), Return(0)));
127
128 thread.RegisterModule(&module);
129
130 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
131 thread.Start();
132
133 EXPECT_EQ(kEventSignaled, event->Wait(100));
134
135 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
136 thread.DeRegisterModule(&module);
137
138 EXPECT_GE(process_count, 1);
139 int count_after_deregister = process_count;
140
141 // We shouldn't get any more callbacks.
142 EXPECT_EQ(kEventTimeout, event->Wait(20));
143 EXPECT_EQ(count_after_deregister, process_count);
144 thread.Stop();
145 }
146
147 // Helper function for testing receiving a callback after a certain amount of
148 // time. There's some variance of timing built into it to reduce chance of
149 // flakiness on bots.
ProcessCallAfterAFewMs(int64_t milliseconds)150 void ProcessCallAfterAFewMs(int64_t milliseconds) {
151 ProcessThreadImpl thread("ProcessThread");
152 thread.Start();
153
154 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
155
156 MockModule module;
157 int64_t start_time = 0;
158 int64_t called_time = 0;
159 EXPECT_CALL(module, TimeUntilNextProcess())
160 .WillOnce(DoAll(SetTimestamp(&start_time),
161 Return(milliseconds)))
162 .WillRepeatedly(Return(milliseconds));
163 EXPECT_CALL(module, Process())
164 .WillOnce(DoAll(SetTimestamp(&called_time),
165 SetEvent(event.get()),
166 Return(0)))
167 .WillRepeatedly(Return(0));
168
169 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
170 thread.RegisterModule(&module);
171
172 // Add a buffer of 50ms due to slowness of some trybots
173 // (e.g. win_drmemory_light)
174 EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
175
176 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
177 thread.Stop();
178
179 ASSERT_GT(start_time, 0);
180 ASSERT_GT(called_time, 0);
181 // Use >= instead of > since due to rounding and timer accuracy (or lack
182 // thereof), can make the test run in "0"ms time.
183 EXPECT_GE(called_time, start_time);
184 // Check for an acceptable range.
185 uint32_t diff = called_time - start_time;
186 EXPECT_GE(diff, milliseconds - 15);
187 EXPECT_LT(diff, milliseconds + 15);
188 }
189
190 // DISABLED for now since the virtual build bots are too slow :(
191 // TODO(tommi): Fix.
TEST(ProcessThreadImpl,DISABLED_ProcessCallAfter5ms)192 TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
193 ProcessCallAfterAFewMs(5);
194 }
195
196 // DISABLED for now since the virtual build bots are too slow :(
197 // TODO(tommi): Fix.
TEST(ProcessThreadImpl,DISABLED_ProcessCallAfter50ms)198 TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
199 ProcessCallAfterAFewMs(50);
200 }
201
202 // DISABLED for now since the virtual build bots are too slow :(
203 // TODO(tommi): Fix.
TEST(ProcessThreadImpl,DISABLED_ProcessCallAfter200ms)204 TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
205 ProcessCallAfterAFewMs(200);
206 }
207
208 // Runs callbacks with the goal of getting up to 50 callbacks within a second
209 // (on average 1 callback every 20ms). On real hardware, we're usually pretty
210 // close to that, but the test bots that run on virtual machines, will
211 // typically be in the range 30-40 callbacks.
212 // DISABLED for now since this can take up to 2 seconds to run on the slowest
213 // build bots.
214 // TODO(tommi): Fix.
TEST(ProcessThreadImpl,DISABLED_Process50Times)215 TEST(ProcessThreadImpl, DISABLED_Process50Times) {
216 ProcessThreadImpl thread("ProcessThread");
217 thread.Start();
218
219 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create());
220
221 MockModule module;
222 int callback_count = 0;
223 // Ask for a callback after 20ms.
224 EXPECT_CALL(module, TimeUntilNextProcess())
225 .WillRepeatedly(Return(20));
226 EXPECT_CALL(module, Process())
227 .WillRepeatedly(DoAll(Increment(&callback_count),
228 Return(0)));
229
230 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
231 thread.RegisterModule(&module);
232
233 EXPECT_EQ(kEventTimeout, event->Wait(1000));
234
235 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
236 thread.Stop();
237
238 printf("Callback count: %i\n", callback_count);
239 // Check that we got called back up to 50 times.
240 // Some of the try bots run on slow virtual machines, so the lower bound
241 // is much more relaxed to avoid flakiness.
242 EXPECT_GE(callback_count, 25);
243 EXPECT_LE(callback_count, 50);
244 }
245
246 // Tests that we can wake up the worker thread to give us a callback right
247 // away when we know the thread is sleeping.
TEST(ProcessThreadImpl,WakeUp)248 TEST(ProcessThreadImpl, WakeUp) {
249 ProcessThreadImpl thread("ProcessThread");
250 thread.Start();
251
252 rtc::scoped_ptr<EventWrapper> started(EventWrapper::Create());
253 rtc::scoped_ptr<EventWrapper> called(EventWrapper::Create());
254
255 MockModule module;
256 int64_t start_time;
257 int64_t called_time;
258
259 // Ask for a callback after 1000ms.
260 // TimeUntilNextProcess will be called twice.
261 // The first time we use it to get the thread into a waiting state.
262 // Then we wake the thread and there should not be another call made to
263 // TimeUntilNextProcess before Process() is called.
264 // The second time TimeUntilNextProcess is then called, is after Process
265 // has been called and we don't expect any more calls.
266 EXPECT_CALL(module, TimeUntilNextProcess())
267 .WillOnce(DoAll(SetTimestamp(&start_time),
268 SetEvent(started.get()),
269 Return(1000)))
270 .WillOnce(Return(1000));
271 EXPECT_CALL(module, Process())
272 .WillOnce(DoAll(SetTimestamp(&called_time),
273 SetEvent(called.get()),
274 Return(0)))
275 .WillRepeatedly(Return(0));
276
277 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
278 thread.RegisterModule(&module);
279
280 EXPECT_EQ(kEventSignaled, started->Wait(100));
281 thread.WakeUp(&module);
282 EXPECT_EQ(kEventSignaled, called->Wait(100));
283
284 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
285 thread.Stop();
286
287 EXPECT_GE(called_time, start_time);
288 uint32_t diff = called_time - start_time;
289 // We should have been called back much quicker than 1sec.
290 EXPECT_LE(diff, 100u);
291 }
292
293 // Tests that we can post a task that gets run straight away on the worker
294 // thread.
TEST(ProcessThreadImpl,PostTask)295 TEST(ProcessThreadImpl, PostTask) {
296 ProcessThreadImpl thread("ProcessThread");
297 rtc::scoped_ptr<EventWrapper> task_ran(EventWrapper::Create());
298 rtc::scoped_ptr<RaiseEventTask> task(new RaiseEventTask(task_ran.get()));
299 thread.Start();
300 thread.PostTask(std::move(task));
301 EXPECT_EQ(kEventSignaled, task_ran->Wait(100));
302 thread.Stop();
303 }
304
305 } // namespace webrtc
306