blob: 013ef523b9056e8f5da59b6bf1b2ce164abbbb56 [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"
Steve Anton10542f22019-01-11 09:11:00 -080018#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#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:
Niels Möller2c16cc62018-10-29 09:47:51 +010045 RaiseEventTask(rtc::Event* 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:
Niels Möller2c16cc62018-10-29 09:47:51 +010052 rtc::Event* event_;
tommi@webrtc.org03054482015-03-05 13:13:42 +000053};
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
Niels Möllerc572ff32018-11-07 08:43:50 +010086 rtc::Event event;
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())
Niels Möller2c16cc62018-10-29 09:47:51 +010093 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -080094 .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);
Niels Möller2c16cc62018-10-29 09:47:51 +010098 EXPECT_TRUE(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");
Niels Möllerc572ff32018-11-07 08:43:50 +0100108 rtc::Event event;
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())
Niels Möller2c16cc62018-10-29 09:47:51 +0100115 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -0800116 .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();
Niels Möller2c16cc62018-10-29 09:47:51 +0100122 EXPECT_TRUE(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");
Niels Möllerc572ff32018-11-07 08:43:50 +0100132 rtc::Event event;
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())
Niels Möller2c16cc62018-10-29 09:47:51 +0100140 .WillOnce(DoAll(SetEvent(&event), Increment(&process_count), Return()))
pbosa26ac922016-02-25 04:50:01 -0800141 .WillRepeatedly(DoAll(Increment(&process_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000142
tommidea489f2017-03-03 03:20:24 -0800143 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000144
145 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
146 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000147
Niels Möller2c16cc62018-10-29 09:47:51 +0100148 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000149
150 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
151 thread.DeRegisterModule(&module);
152
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000153 EXPECT_GE(process_count, 1);
154 int count_after_deregister = process_count;
155
156 // We shouldn't get any more callbacks.
Niels Möller2c16cc62018-10-29 09:47:51 +0100157 EXPECT_FALSE(event.Wait(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000158 EXPECT_EQ(count_after_deregister, process_count);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000159 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000160}
161
162// Helper function for testing receiving a callback after a certain amount of
163// time. There's some variance of timing built into it to reduce chance of
164// flakiness on bots.
165void ProcessCallAfterAFewMs(int64_t milliseconds) {
stefan847855b2015-09-11 09:52:15 -0700166 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000167 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000168
Niels Möllerc572ff32018-11-07 08:43:50 +0100169 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000170
171 MockModule module;
172 int64_t start_time = 0;
173 int64_t called_time = 0;
174 EXPECT_CALL(module, TimeUntilNextProcess())
Yves Gerey665174f2018-06-19 15:03:05 +0200175 .WillOnce(DoAll(SetTimestamp(&start_time), Return(milliseconds)))
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000176 .WillRepeatedly(Return(milliseconds));
177 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100178 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -0800179 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000180
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000181 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800182 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000183
184 // Add a buffer of 50ms due to slowness of some trybots
185 // (e.g. win_drmemory_light)
Niels Möller2c16cc62018-10-29 09:47:51 +0100186 EXPECT_TRUE(event.Wait(milliseconds + 50));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000187
188 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
189 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000190
191 ASSERT_GT(start_time, 0);
192 ASSERT_GT(called_time, 0);
193 // Use >= instead of > since due to rounding and timer accuracy (or lack
194 // thereof), can make the test run in "0"ms time.
195 EXPECT_GE(called_time, start_time);
196 // Check for an acceptable range.
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000197 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000198 EXPECT_GE(diff, milliseconds - 15);
199 EXPECT_LT(diff, milliseconds + 15);
200}
201
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000202// DISABLED for now since the virtual build bots are too slow :(
203// TODO(tommi): Fix.
204TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000205 ProcessCallAfterAFewMs(5);
206}
207
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000208// DISABLED for now since the virtual build bots are too slow :(
209// TODO(tommi): Fix.
210TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000211 ProcessCallAfterAFewMs(50);
212}
213
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000214// DISABLED for now since the virtual build bots are too slow :(
215// TODO(tommi): Fix.
216TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000217 ProcessCallAfterAFewMs(200);
218}
219
220// Runs callbacks with the goal of getting up to 50 callbacks within a second
221// (on average 1 callback every 20ms). On real hardware, we're usually pretty
222// close to that, but the test bots that run on virtual machines, will
223// typically be in the range 30-40 callbacks.
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000224// DISABLED for now since this can take up to 2 seconds to run on the slowest
225// build bots.
226// TODO(tommi): Fix.
227TEST(ProcessThreadImpl, DISABLED_Process50Times) {
stefan847855b2015-09-11 09:52:15 -0700228 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000229 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000230
Niels Möllerc572ff32018-11-07 08:43:50 +0100231 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000232
233 MockModule module;
234 int callback_count = 0;
235 // Ask for a callback after 20ms.
Yves Gerey665174f2018-06-19 15:03:05 +0200236 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000237 EXPECT_CALL(module, Process())
Yves Gerey665174f2018-06-19 15:03:05 +0200238 .WillRepeatedly(DoAll(Increment(&callback_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000239
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000240 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800241 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000242
Niels Möller2c16cc62018-10-29 09:47:51 +0100243 EXPECT_TRUE(event.Wait(1000));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000244
245 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
246 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000247
248 printf("Callback count: %i\n", callback_count);
249 // Check that we got called back up to 50 times.
250 // Some of the try bots run on slow virtual machines, so the lower bound
251 // is much more relaxed to avoid flakiness.
252 EXPECT_GE(callback_count, 25);
253 EXPECT_LE(callback_count, 50);
254}
255
256// Tests that we can wake up the worker thread to give us a callback right
257// away when we know the thread is sleeping.
258TEST(ProcessThreadImpl, WakeUp) {
stefan847855b2015-09-11 09:52:15 -0700259 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000260 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000261
Niels Möllerc572ff32018-11-07 08:43:50 +0100262 rtc::Event started;
263 rtc::Event called;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000264
265 MockModule module;
thaloun2935e012015-11-17 15:02:44 -0800266 int64_t start_time;
267 int64_t called_time;
268
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000269 // Ask for a callback after 1000ms.
270 // TimeUntilNextProcess will be called twice.
271 // The first time we use it to get the thread into a waiting state.
272 // Then we wake the thread and there should not be another call made to
273 // TimeUntilNextProcess before Process() is called.
274 // The second time TimeUntilNextProcess is then called, is after Process
275 // has been called and we don't expect any more calls.
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000276 EXPECT_CALL(module, TimeUntilNextProcess())
Niels Möller2c16cc62018-10-29 09:47:51 +0100277 .WillOnce(
278 DoAll(SetTimestamp(&start_time), SetEvent(&started), Return(1000)))
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000279 .WillOnce(Return(1000));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000280 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100281 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&called), Return()))
pbosa26ac922016-02-25 04:50:01 -0800282 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000283
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000284 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800285 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000286
Niels Möller2c16cc62018-10-29 09:47:51 +0100287 EXPECT_TRUE(started.Wait(kEventWaitTimeout));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000288 thread.WakeUp(&module);
Niels Möller2c16cc62018-10-29 09:47:51 +0100289 EXPECT_TRUE(called.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000290
291 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
292 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000293
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000294 EXPECT_GE(called_time, start_time);
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000295 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000296 // We should have been called back much quicker than 1sec.
297 EXPECT_LE(diff, 100u);
298}
299
tommi@webrtc.org03054482015-03-05 13:13:42 +0000300// Tests that we can post a task that gets run straight away on the worker
301// thread.
302TEST(ProcessThreadImpl, PostTask) {
stefan847855b2015-09-11 09:52:15 -0700303 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100304 rtc::Event task_ran;
Niels Möller2c16cc62018-10-29 09:47:51 +0100305 std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(&task_ran));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000306 thread.Start();
kwiberg1c7fdd82016-04-26 08:18:04 -0700307 thread.PostTask(std::move(task));
Niels Möller2c16cc62018-10-29 09:47:51 +0100308 EXPECT_TRUE(task_ran.Wait(kEventWaitTimeout));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000309 thread.Stop();
310}
311
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000312} // namespace webrtc