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
19namespace webrtc {
20
21using ::testing::_;
22using ::testing::DoAll;
23using ::testing::InSequence;
24using ::testing::Invoke;
25using ::testing::Return;
26using ::testing::SetArgPointee;
27
28class 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
35class RaiseEventTask : public ProcessTask {
36 public:
37  RaiseEventTask(EventWrapper* event) : event_(event) {}
38  void Run() override { event_->Set(); }
39
40 private:
41  EventWrapper* event_;
42};
43
44ACTION_P(SetEvent, event) {
45  event->Set();
46}
47
48ACTION_P(Increment, counter) {
49  ++(*counter);
50}
51
52ACTION_P(SetTimestamp, ptr) {
53  *ptr = TickTime::MillisecondTimestamp();
54}
55
56TEST(ProcessThreadImpl, StartStop) {
57  ProcessThreadImpl thread("ProcessThread");
58  thread.Start();
59  thread.Stop();
60}
61
62TEST(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.
71TEST(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().
93TEST(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.
115TEST(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.
150void 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.
192TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
193  ProcessCallAfterAFewMs(5);
194}
195
196// DISABLED for now since the virtual build bots are too slow :(
197// TODO(tommi): Fix.
198TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
199  ProcessCallAfterAFewMs(50);
200}
201
202// DISABLED for now since the virtual build bots are too slow :(
203// TODO(tommi): Fix.
204TEST(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.
215TEST(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.
248TEST(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.
295TEST(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