blob: 1fef0b674017491ca3a0b2d951afa306c000ec77 [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"
Danil Chapovalov14273de2020-02-27 13:37:43 +010017#include "api/task_queue/task_queue_test.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/include/module.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/location.h"
Steve Anton10542f22019-01-11 09:11:00 -080020#include "rtc_base/time_utils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gmock.h"
22#include "test/gtest.h"
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000023
24namespace webrtc {
25
26using ::testing::_;
27using ::testing::DoAll;
28using ::testing::InSequence;
29using ::testing::Invoke;
30using ::testing::Return;
31using ::testing::SetArgPointee;
32
skvladb460fd82016-09-06 14:34:32 -070033// The length of time, in milliseconds, to wait for an event to become signaled.
34// Set to a fairly large value as there is quite a bit of variation on some
35// Windows bots.
36static const int kEventWaitTimeout = 500;
37
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000038class MockModule : public Module {
39 public:
Danil Chapovaloved5d5942020-05-27 13:41:34 +020040 MOCK_METHOD(int64_t, TimeUntilNextProcess, (), (override));
41 MOCK_METHOD(void, Process, (), (override));
42 MOCK_METHOD(void, ProcessThreadAttached, (ProcessThread*), (override));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000043};
44
Danil Chapovalov471783f2019-03-11 14:26:02 +010045class RaiseEventTask : public QueuedTask {
tommi@webrtc.org03054482015-03-05 13:13:42 +000046 public:
Niels Möller2c16cc62018-10-29 09:47:51 +010047 RaiseEventTask(rtc::Event* event) : event_(event) {}
tommi435f98b2016-05-28 14:57:15 -070048 bool Run() override {
49 event_->Set();
50 return true;
51 }
tommi@webrtc.org03054482015-03-05 13:13:42 +000052
53 private:
Niels Möller2c16cc62018-10-29 09:47:51 +010054 rtc::Event* event_;
tommi@webrtc.org03054482015-03-05 13:13:42 +000055};
56
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000057ACTION_P(SetEvent, event) {
58 event->Set();
59}
60
61ACTION_P(Increment, counter) {
62 ++(*counter);
63}
64
65ACTION_P(SetTimestamp, ptr) {
Niels Möllerd28db7f2016-05-10 16:31:47 +020066 *ptr = rtc::TimeMillis();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000067}
68
69TEST(ProcessThreadImpl, StartStop) {
stefan847855b2015-09-11 09:52:15 -070070 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000071 thread.Start();
72 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000073}
74
75TEST(ProcessThreadImpl, MultipleStartStop) {
stefan847855b2015-09-11 09:52:15 -070076 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000077 for (int i = 0; i < 5; ++i) {
tommi@webrtc.org3985f012015-02-27 13:36:34 +000078 thread.Start();
79 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000080 }
81}
82
83// Verifies that we get at least call back to Process() on the worker thread.
84TEST(ProcessThreadImpl, ProcessCall) {
stefan847855b2015-09-11 09:52:15 -070085 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +000086 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000087
Niels Möllerc572ff32018-11-07 08:43:50 +010088 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000089
90 MockModule module;
tommi82ead602017-02-19 16:09:55 -080091 EXPECT_CALL(module, TimeUntilNextProcess())
92 .WillOnce(Return(0))
93 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000094 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +010095 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -080096 .WillRepeatedly(Return());
tommi@webrtc.org3985f012015-02-27 13:36:34 +000097 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +000098
tommidea489f2017-03-03 03:20:24 -080099 thread.RegisterModule(&module, RTC_FROM_HERE);
Niels Möller2c16cc62018-10-29 09:47:51 +0100100 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000101
102 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
103 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000104}
105
106// Same as ProcessCall except the module is registered before the
107// call to Start().
108TEST(ProcessThreadImpl, ProcessCall2) {
stefan847855b2015-09-11 09:52:15 -0700109 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100110 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000111
112 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800113 EXPECT_CALL(module, TimeUntilNextProcess())
114 .WillOnce(Return(0))
115 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000116 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100117 .WillOnce(DoAll(SetEvent(&event), Return()))
pbosa26ac922016-02-25 04:50:01 -0800118 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000119
tommidea489f2017-03-03 03:20:24 -0800120 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000121
122 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
123 thread.Start();
Niels Möller2c16cc62018-10-29 09:47:51 +0100124 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000125
126 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
127 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000128}
129
130// Tests setting up a module for callbacks and then unregister that module.
131// After unregistration, we should not receive any further callbacks.
132TEST(ProcessThreadImpl, Deregister) {
stefan847855b2015-09-11 09:52:15 -0700133 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100134 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000135
136 int process_count = 0;
137 MockModule module;
tommi82ead602017-02-19 16:09:55 -0800138 EXPECT_CALL(module, TimeUntilNextProcess())
139 .WillOnce(Return(0))
140 .WillRepeatedly(Return(1));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000141 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100142 .WillOnce(DoAll(SetEvent(&event), Increment(&process_count), Return()))
pbosa26ac922016-02-25 04:50:01 -0800143 .WillRepeatedly(DoAll(Increment(&process_count), Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000144
tommidea489f2017-03-03 03:20:24 -0800145 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000146
147 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
148 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000149
Niels Möller2c16cc62018-10-29 09:47:51 +0100150 EXPECT_TRUE(event.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000151
152 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
153 thread.DeRegisterModule(&module);
154
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000155 EXPECT_GE(process_count, 1);
156 int count_after_deregister = process_count;
157
158 // We shouldn't get any more callbacks.
Niels Möller2c16cc62018-10-29 09:47:51 +0100159 EXPECT_FALSE(event.Wait(20));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000160 EXPECT_EQ(count_after_deregister, process_count);
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000161 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000162}
163
164// Helper function for testing receiving a callback after a certain amount of
165// time. There's some variance of timing built into it to reduce chance of
166// flakiness on bots.
167void ProcessCallAfterAFewMs(int64_t milliseconds) {
stefan847855b2015-09-11 09:52:15 -0700168 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000169 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000170
Niels Möllerc572ff32018-11-07 08:43:50 +0100171 rtc::Event event;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000172
173 MockModule module;
174 int64_t start_time = 0;
175 int64_t called_time = 0;
176 EXPECT_CALL(module, TimeUntilNextProcess())
Yves Gerey665174f2018-06-19 15:03:05 +0200177 .WillOnce(DoAll(SetTimestamp(&start_time), Return(milliseconds)))
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000178 .WillRepeatedly(Return(milliseconds));
179 EXPECT_CALL(module, Process())
Niels Möller2c16cc62018-10-29 09:47:51 +0100180 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&event), 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)
Niels Möller2c16cc62018-10-29 09:47:51 +0100188 EXPECT_TRUE(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
Niels Möllerc572ff32018-11-07 08:43:50 +0100233 rtc::Event event;
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
Niels Möller2c16cc62018-10-29 09:47:51 +0100245 EXPECT_TRUE(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
Niels Möllerc572ff32018-11-07 08:43:50 +0100264 rtc::Event started;
265 rtc::Event called;
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())
Niels Möller2c16cc62018-10-29 09:47:51 +0100279 .WillOnce(
280 DoAll(SetTimestamp(&start_time), SetEvent(&started), 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())
Niels Möller2c16cc62018-10-29 09:47:51 +0100283 .WillOnce(DoAll(SetTimestamp(&called_time), SetEvent(&called), Return()))
pbosa26ac922016-02-25 04:50:01 -0800284 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000285
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000286 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800287 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000288
Niels Möller2c16cc62018-10-29 09:47:51 +0100289 EXPECT_TRUE(started.Wait(kEventWaitTimeout));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000290 thread.WakeUp(&module);
Niels Möller2c16cc62018-10-29 09:47:51 +0100291 EXPECT_TRUE(called.Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000292
293 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
294 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000295
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000296 EXPECT_GE(called_time, start_time);
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000297 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000298 // We should have been called back much quicker than 1sec.
299 EXPECT_LE(diff, 100u);
300}
301
tommi@webrtc.org03054482015-03-05 13:13:42 +0000302// Tests that we can post a task that gets run straight away on the worker
303// thread.
304TEST(ProcessThreadImpl, PostTask) {
stefan847855b2015-09-11 09:52:15 -0700305 ProcessThreadImpl thread("ProcessThread");
Niels Möllerc572ff32018-11-07 08:43:50 +0100306 rtc::Event task_ran;
Niels Möller2c16cc62018-10-29 09:47:51 +0100307 std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(&task_ran));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000308 thread.Start();
kwiberg1c7fdd82016-04-26 08:18:04 -0700309 thread.PostTask(std::move(task));
Niels Möller2c16cc62018-10-29 09:47:51 +0100310 EXPECT_TRUE(task_ran.Wait(kEventWaitTimeout));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000311 thread.Stop();
312}
313
Danil Chapovalov14273de2020-02-27 13:37:43 +0100314class ProcessThreadFactory : public TaskQueueFactory {
315 public:
316 ~ProcessThreadFactory() override = default;
317 std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
318 absl::string_view name,
319 Priority priority) const override {
320 ProcessThreadImpl* process_thread = new ProcessThreadImpl("thread");
321 process_thread->Start();
322 return std::unique_ptr<TaskQueueBase, TaskQueueDeleter>(process_thread);
323 }
324};
325
326INSTANTIATE_TEST_SUITE_P(
327 ProcessThread,
328 TaskQueueTest,
329 testing::Values(std::make_unique<ProcessThreadFactory>));
330
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000331} // namespace webrtc