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