blob: bc893cf2a1f6eafba0605773c1ad78591d7a1d17 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/utility/source/process_thread_impl.h"
12
kwiberg22feaa32016-03-17 09:17:43 -070013#include <memory>
kwiberg0eb15ed2015-12-17 03:04:15 -080014#include <utility>
15
Danil Chapovalov471783f2019-03-11 14:26:02 +010016#include "api/task_queue/queued_task.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/include/module.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/location.h"
Steve Anton10542f22019-01-11 09:11:00 -080019#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "test/gmock.h"
21#include "test/gtest.h"
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000022
23namespace webrtc {
24
25using ::testing::_;
26using ::testing::DoAll;
27using ::testing::InSequence;
28using ::testing::Invoke;
29using ::testing::Return;
30using ::testing::SetArgPointee;
31
skvladb460fd82016-09-06 14:34:32 -070032// The length of time, in milliseconds, to wait for an event to become signaled.
33// Set to a fairly large value as there is quite a bit of variation on some
34// Windows bots.
35static const int kEventWaitTimeout = 500;
36
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000037class MockModule : public Module {
38 public:
39 MOCK_METHOD0(TimeUntilNextProcess, int64_t());
pbosa26ac922016-02-25 04:50:01 -080040 MOCK_METHOD0(Process, void());
tommi@webrtc.org3985f012015-02-27 13:36:34 +000041 MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000042};
43
Danil Chapovalov471783f2019-03-11 14:26:02 +010044class RaiseEventTask : public QueuedTask {
tommi@webrtc.org03054482015-03-05 13:13:42 +000045 public:
Niels Möller2c16cc62018-10-29 09:47:51 +010046 RaiseEventTask(rtc::Event* event) : event_(event) {}
tommi435f98b2016-05-28 14:57:15 -070047 bool Run() override {
48 event_->Set();
49 return true;
50 }
tommi@webrtc.org03054482015-03-05 13:13:42 +000051
52 private:
Niels Möller2c16cc62018-10-29 09:47:51 +010053 rtc::Event* event_;
tommi@webrtc.org03054482015-03-05 13:13:42 +000054};
55
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000056ACTION_P(SetEvent, event) {
57 event->Set();
58}
59
60ACTION_P(Increment, counter) {
61 ++(*counter);
62}
63
64ACTION_P(SetTimestamp, ptr) {
Niels Möllerd28db7f2016-05-10 16:31:47 +020065 *ptr = rtc::TimeMillis();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000066}
67
68TEST(ProcessThreadImpl, StartStop) {
stefan847855b2015-09-11 09:52:15 -070069 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000070 thread.Start();
71 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000072}
73
74TEST(ProcessThreadImpl, MultipleStartStop) {
stefan847855b2015-09-11 09:52:15 -070075 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000076 for (int i = 0; i < 5; ++i) {
tommi@webrtc.org3985f012015-02-27 13:36:34 +000077 thread.Start();
78 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000079 }
80}
81
82// Verifies that we get at least call back to Process() on the worker thread.
83TEST(ProcessThreadImpl, ProcessCall) {
stefan847855b2015-09-11 09:52:15 -070084 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000085 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000086
Niels Möllerc572ff32018-11-07 08:43:50 +010087 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000088
89 MockModule module;
tommi82ead602017-02-19 16:09:55 -080090 EXPECT_CALL(module, TimeUntilNextProcess())
91 .WillOnce(Return(0))
92 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000093 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +010094 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -080095 .WillRepeatedly(Return());
tommi@webrtc.org3985f012015-02-27 13:36:34 +000096 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000097
tommidea489f2017-03-03 03:20:24 -080098 thread.RegisterModule(&module, RTC_FROM_HERE);
Niels Möller2c16cc62018-10-29 09:47:51 +010099 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000100
101 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
102 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000103}
104
105// Same as ProcessCall except the module is registered before the
106// call to Start().
107TEST(ProcessThreadImpl, ProcessCall2) {
stefan847855b2015-09-11 09:52:15 -0700108 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100109 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000110
111 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800112 EXPECT_CALL(module, TimeUntilNextProcess())
113 .WillOnce(Return(0))
114 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000115 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100116 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -0800117 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000118
tommidea489f2017-03-03 03:20:24 -0800119 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000120
121 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
122 thread.Start();
Niels Möller2c16cc62018-10-29 09:47:51 +0100123 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000124
125 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
126 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000127}
128
129// Tests setting up a module for callbacks and then unregister that module.
130// After unregistration, we should not receive any further callbacks.
131TEST(ProcessThreadImpl, Deregister) {
stefan847855b2015-09-11 09:52:15 -0700132 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100133 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000134
135 int process_count = 0;
136 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800137 EXPECT_CALL(module, TimeUntilNextProcess())
138 .WillOnce(Return(0))
139 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000140 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100141 .WillOnce(DoAll(SetEvent(&event), 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
Niels Möller2c16cc62018-10-29 09:47:51 +0100149 EXPECT_TRUE(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.
Niels Möller2c16cc62018-10-29 09:47:51 +0100158 EXPECT_FALSE(event.Wait(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000159 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
Niels Möllerc572ff32018-11-07 08:43:50 +0100170 rtc::Event event;
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())
Niels Möller2c16cc62018-10-29 09:47:51 +0100179 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -0800180 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000181
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000182 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800183 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000184
185 // Add a buffer of 50ms due to slowness of some trybots
186 // (e.g. win_drmemory_light)
Niels Möller2c16cc62018-10-29 09:47:51 +0100187 EXPECT_TRUE(event.Wait(milliseconds + 50));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000188
189 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
190 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000191
192 ASSERT_GT(start_time, 0);
193 ASSERT_GT(called_time, 0);
194 // Use >= instead of > since due to rounding and timer accuracy (or lack
195 // thereof), can make the test run in "0"ms time.
196 EXPECT_GE(called_time, start_time);
197 // Check for an acceptable range.
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000198 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000199 EXPECT_GE(diff, milliseconds - 15);
200 EXPECT_LT(diff, milliseconds + 15);
201}
202
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000203// DISABLED for now since the virtual build bots are too slow :(
204// TODO(tommi): Fix.
205TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000206 ProcessCallAfterAFewMs(5);
207}
208
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000209// DISABLED for now since the virtual build bots are too slow :(
210// TODO(tommi): Fix.
211TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000212 ProcessCallAfterAFewMs(50);
213}
214
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000215// DISABLED for now since the virtual build bots are too slow :(
216// TODO(tommi): Fix.
217TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000218 ProcessCallAfterAFewMs(200);
219}
220
221// Runs callbacks with the goal of getting up to 50 callbacks within a second
222// (on average 1 callback every 20ms). On real hardware, we're usually pretty
223// close to that, but the test bots that run on virtual machines, will
224// typically be in the range 30-40 callbacks.
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000225// DISABLED for now since this can take up to 2 seconds to run on the slowest
226// build bots.
227// TODO(tommi): Fix.
228TEST(ProcessThreadImpl, DISABLED_Process50Times) {
stefan847855b2015-09-11 09:52:15 -0700229 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000230 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000231
Niels Möllerc572ff32018-11-07 08:43:50 +0100232 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000233
234 MockModule module;
235 int callback_count = 0;
236 // Ask for a callback after 20ms.
Yves Gerey665174f2018-06-19 15:03:05 +0200237 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000238 EXPECT_CALL(module, Process())
Yves Gerey665174f2018-06-19 15:03:05 +0200239 .WillRepeatedly(DoAll(Increment(&callback_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000240
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000241 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800242 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000243
Niels Möller2c16cc62018-10-29 09:47:51 +0100244 EXPECT_TRUE(event.Wait(1000));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000245
246 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
247 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000248
249 printf("Callback count: %i\n", callback_count);
250 // Check that we got called back up to 50 times.
251 // Some of the try bots run on slow virtual machines, so the lower bound
252 // is much more relaxed to avoid flakiness.
253 EXPECT_GE(callback_count, 25);
254 EXPECT_LE(callback_count, 50);
255}
256
257// Tests that we can wake up the worker thread to give us a callback right
258// away when we know the thread is sleeping.
259TEST(ProcessThreadImpl, WakeUp) {
stefan847855b2015-09-11 09:52:15 -0700260 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000261 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000262
Niels Möllerc572ff32018-11-07 08:43:50 +0100263 rtc::Event started;
264 rtc::Event called;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000265
266 MockModule module;
thaloun2935e012015-11-17 15:02:44 -0800267 int64_t start_time;
268 int64_t called_time;
269
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000270 // Ask for a callback after 1000ms.
271 // TimeUntilNextProcess will be called twice.
272 // The first time we use it to get the thread into a waiting state.
273 // Then we wake the thread and there should not be another call made to
274 // TimeUntilNextProcess before Process() is called.
275 // The second time TimeUntilNextProcess is then called, is after Process
276 // has been called and we don't expect any more calls.
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000277 EXPECT_CALL(module, TimeUntilNextProcess())
Niels Möller2c16cc62018-10-29 09:47:51 +0100278 .WillOnce(
279 DoAll(SetTimestamp(&start_time), SetEvent(&started), Return(1000)))
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000280 .WillOnce(Return(1000));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000281 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100282 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&called), Return()))
pbosa26ac922016-02-25 04:50:01 -0800283 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000284
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000285 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800286 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000287
Niels Möller2c16cc62018-10-29 09:47:51 +0100288 EXPECT_TRUE(started.Wait(kEventWaitTimeout));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000289 thread.WakeUp(&module);
Niels Möller2c16cc62018-10-29 09:47:51 +0100290 EXPECT_TRUE(called.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000291
292 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
293 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000294
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000295 EXPECT_GE(called_time, start_time);
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000296 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000297 // We should have been called back much quicker than 1sec.
298 EXPECT_LE(diff, 100u);
299}
300
tommi@webrtc.org03054482015-03-05 13:13:42 +0000301// Tests that we can post a task that gets run straight away on the worker
302// thread.
303TEST(ProcessThreadImpl, PostTask) {
stefan847855b2015-09-11 09:52:15 -0700304 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100305 rtc::Event task_ran;
Niels Möller2c16cc62018-10-29 09:47:51 +0100306 std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(&task_ran));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000307 thread.Start();
kwiberg1c7fdd82016-04-26 08:18:04 -0700308 thread.PostTask(std::move(task));
Niels Möller2c16cc62018-10-29 09:47:51 +0100309 EXPECT_TRUE(task_ran.Wait(kEventWaitTimeout));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000310 thread.Stop();
311}
312
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000313} // namespace webrtc