blob: d5926b26c3e2ca4b07722663cac6bb0c46e15c70 [file] [log] [blame]
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +00001/*
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
kwiberg22feaa32016-03-17 09:17:43 -070011#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080012#include <utility>
13
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020014#include "modules/include/module.h"
15#include "modules/utility/source/process_thread_impl.h"
16#include "rtc_base/location.h"
17#include "rtc_base/task_queue.h"
18#include "rtc_base/timeutils.h"
19#include "test/gmock.h"
20#include "test/gtest.h"
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000021
22namespace webrtc {
23
24using ::testing::_;
25using ::testing::DoAll;
26using ::testing::InSequence;
27using ::testing::Invoke;
28using ::testing::Return;
29using ::testing::SetArgPointee;
30
skvladb460fd82016-09-06 14:34:32 -070031// The length of time, in milliseconds, to wait for an event to become signaled.
32// Set to a fairly large value as there is quite a bit of variation on some
33// Windows bots.
34static const int kEventWaitTimeout = 500;
35
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000036class MockModule : public Module {
37 public:
38 MOCK_METHOD0(TimeUntilNextProcess, int64_t());
pbosa26ac922016-02-25 04:50:01 -080039 MOCK_METHOD0(Process, void());
tommi@webrtc.org3985f012015-02-27 13:36:34 +000040 MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000041};
42
tommi435f98b2016-05-28 14:57:15 -070043class RaiseEventTask : public rtc::QueuedTask {
tommi@webrtc.org03054482015-03-05 13:13:42 +000044 public:
45 RaiseEventTask(EventWrapper* event) : event_(event) {}
tommi435f98b2016-05-28 14:57:15 -070046 bool Run() override {
47 event_->Set();
48 return true;
49 }
tommi@webrtc.org03054482015-03-05 13:13:42 +000050
51 private:
52 EventWrapper* event_;
53};
54
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000055ACTION_P(SetEvent, event) {
56 event->Set();
57}
58
59ACTION_P(Increment, counter) {
60 ++(*counter);
61}
62
63ACTION_P(SetTimestamp, ptr) {
Niels Möllerd28db7f2016-05-10 16:31:47 +020064 *ptr = rtc::TimeMillis();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000065}
66
67TEST(ProcessThreadImpl, StartStop) {
stefan847855b2015-09-11 09:52:15 -070068 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000069 thread.Start();
70 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000071}
72
73TEST(ProcessThreadImpl, MultipleStartStop) {
stefan847855b2015-09-11 09:52:15 -070074 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000075 for (int i = 0; i < 5; ++i) {
tommi@webrtc.org3985f012015-02-27 13:36:34 +000076 thread.Start();
77 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000078 }
79}
80
81// Verifies that we get at least call back to Process() on the worker thread.
82TEST(ProcessThreadImpl, ProcessCall) {
stefan847855b2015-09-11 09:52:15 -070083 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000084 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000085
kwiberg22feaa32016-03-17 09:17:43 -070086 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000087
88 MockModule module;
tommi82ead602017-02-19 16:09:55 -080089 EXPECT_CALL(module, TimeUntilNextProcess())
90 .WillOnce(Return(0))
91 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000092 EXPECT_CALL(module, Process())
pbosa26ac922016-02-25 04:50:01 -080093 .WillOnce(DoAll(SetEvent(event.get()), Return()))
94 .WillRepeatedly(Return());
tommi@webrtc.org3985f012015-02-27 13:36:34 +000095 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000096
tommidea489f2017-03-03 03:20:24 -080097 thread.RegisterModule(&module, RTC_FROM_HERE);
skvladb460fd82016-09-06 14:34:32 -070098 EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +000099
100 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
101 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000102}
103
104// Same as ProcessCall except the module is registered before the
105// call to Start().
106TEST(ProcessThreadImpl, ProcessCall2) {
stefan847855b2015-09-11 09:52:15 -0700107 ProcessThreadImpl thread("ProcessThread");
kwiberg22feaa32016-03-17 09:17:43 -0700108 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000109
110 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800111 EXPECT_CALL(module, TimeUntilNextProcess())
112 .WillOnce(Return(0))
113 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000114 EXPECT_CALL(module, Process())
pbosa26ac922016-02-25 04:50:01 -0800115 .WillOnce(DoAll(SetEvent(event.get()), Return()))
116 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000117
tommidea489f2017-03-03 03:20:24 -0800118 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000119
120 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
121 thread.Start();
skvladb460fd82016-09-06 14:34:32 -0700122 EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000123
124 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
125 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000126}
127
128// Tests setting up a module for callbacks and then unregister that module.
129// After unregistration, we should not receive any further callbacks.
130TEST(ProcessThreadImpl, Deregister) {
stefan847855b2015-09-11 09:52:15 -0700131 ProcessThreadImpl thread("ProcessThread");
kwiberg22feaa32016-03-17 09:17:43 -0700132 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000133
134 int process_count = 0;
135 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800136 EXPECT_CALL(module, TimeUntilNextProcess())
137 .WillOnce(Return(0))
138 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000139 EXPECT_CALL(module, Process())
Yves Gerey665174f2018-06-19 15:03:05 +0200140 .WillOnce(
141 DoAll(SetEvent(event.get()), Increment(&process_count), Return()))
pbosa26ac922016-02-25 04:50:01 -0800142 .WillRepeatedly(DoAll(Increment(&process_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000143
tommidea489f2017-03-03 03:20:24 -0800144 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000145
146 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
147 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000148
skvladb460fd82016-09-06 14:34:32 -0700149 EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000150
151 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
152 thread.DeRegisterModule(&module);
153
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000154 EXPECT_GE(process_count, 1);
155 int count_after_deregister = process_count;
156
157 // We shouldn't get any more callbacks.
158 EXPECT_EQ(kEventTimeout, event->Wait(20));
159 EXPECT_EQ(count_after_deregister, process_count);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000160 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000161}
162
163// Helper function for testing receiving a callback after a certain amount of
164// time. There's some variance of timing built into it to reduce chance of
165// flakiness on bots.
166void ProcessCallAfterAFewMs(int64_t milliseconds) {
stefan847855b2015-09-11 09:52:15 -0700167 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000168 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000169
kwiberg22feaa32016-03-17 09:17:43 -0700170 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000171
172 MockModule module;
173 int64_t start_time = 0;
174 int64_t called_time = 0;
175 EXPECT_CALL(module, TimeUntilNextProcess())
Yves Gerey665174f2018-06-19 15:03:05 +0200176 .WillOnce(DoAll(SetTimestamp(&start_time), Return(milliseconds)))
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000177 .WillRepeatedly(Return(milliseconds));
178 EXPECT_CALL(module, Process())
Yves Gerey665174f2018-06-19 15:03:05 +0200179 .WillOnce(
180 DoAll(SetTimestamp(&called_time), SetEvent(event.get()), Return()))
pbosa26ac922016-02-25 04:50:01 -0800181 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000182
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000183 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800184 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000185
186 // Add a buffer of 50ms due to slowness of some trybots
187 // (e.g. win_drmemory_light)
188 EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000189
190 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
191 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000192
193 ASSERT_GT(start_time, 0);
194 ASSERT_GT(called_time, 0);
195 // Use >= instead of > since due to rounding and timer accuracy (or lack
196 // thereof), can make the test run in "0"ms time.
197 EXPECT_GE(called_time, start_time);
198 // Check for an acceptable range.
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000199 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000200 EXPECT_GE(diff, milliseconds - 15);
201 EXPECT_LT(diff, milliseconds + 15);
202}
203
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000204// DISABLED for now since the virtual build bots are too slow :(
205// TODO(tommi): Fix.
206TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000207 ProcessCallAfterAFewMs(5);
208}
209
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000210// DISABLED for now since the virtual build bots are too slow :(
211// TODO(tommi): Fix.
212TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000213 ProcessCallAfterAFewMs(50);
214}
215
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000216// DISABLED for now since the virtual build bots are too slow :(
217// TODO(tommi): Fix.
218TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000219 ProcessCallAfterAFewMs(200);
220}
221
222// Runs callbacks with the goal of getting up to 50 callbacks within a second
223// (on average 1 callback every 20ms). On real hardware, we're usually pretty
224// close to that, but the test bots that run on virtual machines, will
225// typically be in the range 30-40 callbacks.
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000226// DISABLED for now since this can take up to 2 seconds to run on the slowest
227// build bots.
228// TODO(tommi): Fix.
229TEST(ProcessThreadImpl, DISABLED_Process50Times) {
stefan847855b2015-09-11 09:52:15 -0700230 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000231 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000232
kwiberg22feaa32016-03-17 09:17:43 -0700233 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000234
235 MockModule module;
236 int callback_count = 0;
237 // Ask for a callback after 20ms.
Yves Gerey665174f2018-06-19 15:03:05 +0200238 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000239 EXPECT_CALL(module, Process())
Yves Gerey665174f2018-06-19 15:03:05 +0200240 .WillRepeatedly(DoAll(Increment(&callback_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000241
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000242 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800243 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000244
245 EXPECT_EQ(kEventTimeout, event->Wait(1000));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000246
247 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
248 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000249
250 printf("Callback count: %i\n", callback_count);
251 // Check that we got called back up to 50 times.
252 // Some of the try bots run on slow virtual machines, so the lower bound
253 // is much more relaxed to avoid flakiness.
254 EXPECT_GE(callback_count, 25);
255 EXPECT_LE(callback_count, 50);
256}
257
258// Tests that we can wake up the worker thread to give us a callback right
259// away when we know the thread is sleeping.
260TEST(ProcessThreadImpl, WakeUp) {
stefan847855b2015-09-11 09:52:15 -0700261 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000262 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000263
kwiberg22feaa32016-03-17 09:17:43 -0700264 std::unique_ptr<EventWrapper> started(EventWrapper::Create());
265 std::unique_ptr<EventWrapper> called(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000266
267 MockModule module;
thaloun2935e012015-11-17 15:02:44 -0800268 int64_t start_time;
269 int64_t called_time;
270
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000271 // Ask for a callback after 1000ms.
272 // TimeUntilNextProcess will be called twice.
273 // The first time we use it to get the thread into a waiting state.
274 // Then we wake the thread and there should not be another call made to
275 // TimeUntilNextProcess before Process() is called.
276 // The second time TimeUntilNextProcess is then called, is after Process
277 // has been called and we don't expect any more calls.
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000278 EXPECT_CALL(module, TimeUntilNextProcess())
Yves Gerey665174f2018-06-19 15:03:05 +0200279 .WillOnce(DoAll(SetTimestamp(&start_time), SetEvent(started.get()),
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000280 Return(1000)))
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000281 .WillOnce(Return(1000));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000282 EXPECT_CALL(module, Process())
pbosa26ac922016-02-25 04:50:01 -0800283 .WillOnce(
284 DoAll(SetTimestamp(&called_time), SetEvent(called.get()), Return()))
285 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000286
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000287 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800288 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000289
skvladb460fd82016-09-06 14:34:32 -0700290 EXPECT_EQ(kEventSignaled, started->Wait(kEventWaitTimeout));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000291 thread.WakeUp(&module);
skvladb460fd82016-09-06 14:34:32 -0700292 EXPECT_EQ(kEventSignaled, called->Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000293
294 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
295 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000296
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000297 EXPECT_GE(called_time, start_time);
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000298 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000299 // We should have been called back much quicker than 1sec.
300 EXPECT_LE(diff, 100u);
301}
302
tommi@webrtc.org03054482015-03-05 13:13:42 +0000303// Tests that we can post a task that gets run straight away on the worker
304// thread.
305TEST(ProcessThreadImpl, PostTask) {
stefan847855b2015-09-11 09:52:15 -0700306 ProcessThreadImpl thread("ProcessThread");
kwiberg22feaa32016-03-17 09:17:43 -0700307 std::unique_ptr<EventWrapper> task_ran(EventWrapper::Create());
308 std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(task_ran.get()));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000309 thread.Start();
kwiberg1c7fdd82016-04-26 08:18:04 -0700310 thread.PostTask(std::move(task));
skvladb460fd82016-09-06 14:34:32 -0700311 EXPECT_EQ(kEventSignaled, task_ran->Wait(kEventWaitTimeout));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000312 thread.Stop();
313}
314
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000315} // namespace webrtc