blob: d27896410edffcef4e73ded68f0f065533b5906b [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())
140 .WillOnce(DoAll(SetEvent(event.get()),
141 Increment(&process_count),
pbosa26ac922016-02-25 04:50:01 -0800142 Return()))
143 .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
skvladb460fd82016-09-06 14:34:32 -0700150 EXPECT_EQ(kEventSignaled, 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.
159 EXPECT_EQ(kEventTimeout, event->Wait(20));
160 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
kwiberg22feaa32016-03-17 09:17:43 -0700171 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
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())
177 .WillOnce(DoAll(SetTimestamp(&start_time),
178 Return(milliseconds)))
179 .WillRepeatedly(Return(milliseconds));
180 EXPECT_CALL(module, Process())
181 .WillOnce(DoAll(SetTimestamp(&called_time),
182 SetEvent(event.get()),
pbosa26ac922016-02-25 04:50:01 -0800183 Return()))
184 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000185
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000186 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800187 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000188
189 // Add a buffer of 50ms due to slowness of some trybots
190 // (e.g. win_drmemory_light)
191 EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000192
193 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
194 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000195
196 ASSERT_GT(start_time, 0);
197 ASSERT_GT(called_time, 0);
198 // Use >= instead of > since due to rounding and timer accuracy (or lack
199 // thereof), can make the test run in "0"ms time.
200 EXPECT_GE(called_time, start_time);
201 // Check for an acceptable range.
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000202 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000203 EXPECT_GE(diff, milliseconds - 15);
204 EXPECT_LT(diff, milliseconds + 15);
205}
206
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000207// DISABLED for now since the virtual build bots are too slow :(
208// TODO(tommi): Fix.
209TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000210 ProcessCallAfterAFewMs(5);
211}
212
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000213// DISABLED for now since the virtual build bots are too slow :(
214// TODO(tommi): Fix.
215TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000216 ProcessCallAfterAFewMs(50);
217}
218
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000219// DISABLED for now since the virtual build bots are too slow :(
220// TODO(tommi): Fix.
221TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000222 ProcessCallAfterAFewMs(200);
223}
224
225// Runs callbacks with the goal of getting up to 50 callbacks within a second
226// (on average 1 callback every 20ms). On real hardware, we're usually pretty
227// close to that, but the test bots that run on virtual machines, will
228// typically be in the range 30-40 callbacks.
tommi@webrtc.org1d4830a2015-02-07 08:44:28 +0000229// DISABLED for now since this can take up to 2 seconds to run on the slowest
230// build bots.
231// TODO(tommi): Fix.
232TEST(ProcessThreadImpl, DISABLED_Process50Times) {
stefan847855b2015-09-11 09:52:15 -0700233 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000234 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000235
kwiberg22feaa32016-03-17 09:17:43 -0700236 std::unique_ptr<EventWrapper> event(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000237
238 MockModule module;
239 int callback_count = 0;
240 // Ask for a callback after 20ms.
241 EXPECT_CALL(module, TimeUntilNextProcess())
242 .WillRepeatedly(Return(20));
243 EXPECT_CALL(module, Process())
244 .WillRepeatedly(DoAll(Increment(&callback_count),
pbosa26ac922016-02-25 04:50:01 -0800245 Return()));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000246
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000247 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800248 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000249
250 EXPECT_EQ(kEventTimeout, event->Wait(1000));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000251
252 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
253 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000254
255 printf("Callback count: %i\n", callback_count);
256 // Check that we got called back up to 50 times.
257 // Some of the try bots run on slow virtual machines, so the lower bound
258 // is much more relaxed to avoid flakiness.
259 EXPECT_GE(callback_count, 25);
260 EXPECT_LE(callback_count, 50);
261}
262
263// Tests that we can wake up the worker thread to give us a callback right
264// away when we know the thread is sleeping.
265TEST(ProcessThreadImpl, WakeUp) {
stefan847855b2015-09-11 09:52:15 -0700266 ProcessThreadImpl thread("ProcessThread");
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000267 thread.Start();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000268
kwiberg22feaa32016-03-17 09:17:43 -0700269 std::unique_ptr<EventWrapper> started(EventWrapper::Create());
270 std::unique_ptr<EventWrapper> called(EventWrapper::Create());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000271
272 MockModule module;
thaloun2935e012015-11-17 15:02:44 -0800273 int64_t start_time;
274 int64_t called_time;
275
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000276 // Ask for a callback after 1000ms.
277 // TimeUntilNextProcess will be called twice.
278 // The first time we use it to get the thread into a waiting state.
279 // Then we wake the thread and there should not be another call made to
280 // TimeUntilNextProcess before Process() is called.
281 // The second time TimeUntilNextProcess is then called, is after Process
282 // has been called and we don't expect any more calls.
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000283 EXPECT_CALL(module, TimeUntilNextProcess())
284 .WillOnce(DoAll(SetTimestamp(&start_time),
285 SetEvent(started.get()),
286 Return(1000)))
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000287 .WillOnce(Return(1000));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000288 EXPECT_CALL(module, Process())
pbosa26ac922016-02-25 04:50:01 -0800289 .WillOnce(
290 DoAll(SetTimestamp(&called_time), SetEvent(called.get()), Return()))
291 .WillRepeatedly(Return());
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000292
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000293 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
tommidea489f2017-03-03 03:20:24 -0800294 thread.RegisterModule(&module, RTC_FROM_HERE);
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000295
skvladb460fd82016-09-06 14:34:32 -0700296 EXPECT_EQ(kEventSignaled, started->Wait(kEventWaitTimeout));
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000297 thread.WakeUp(&module);
skvladb460fd82016-09-06 14:34:32 -0700298 EXPECT_EQ(kEventSignaled, called->Wait(kEventWaitTimeout));
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000299
300 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
301 thread.Stop();
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000302
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000303 EXPECT_GE(called_time, start_time);
kwiberg@webrtc.org11426dc2015-02-11 14:30:34 +0000304 uint32_t diff = called_time - start_time;
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000305 // We should have been called back much quicker than 1sec.
306 EXPECT_LE(diff, 100u);
307}
308
tommi@webrtc.org03054482015-03-05 13:13:42 +0000309// Tests that we can post a task that gets run straight away on the worker
310// thread.
311TEST(ProcessThreadImpl, PostTask) {
stefan847855b2015-09-11 09:52:15 -0700312 ProcessThreadImpl thread("ProcessThread");
kwiberg22feaa32016-03-17 09:17:43 -0700313 std::unique_ptr<EventWrapper> task_ran(EventWrapper::Create());
314 std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(task_ran.get()));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000315 thread.Start();
kwiberg1c7fdd82016-04-26 08:18:04 -0700316 thread.PostTask(std::move(task));
skvladb460fd82016-09-06 14:34:32 -0700317 EXPECT_EQ(kEventSignaled, task_ran->Wait(kEventWaitTimeout));
tommi@webrtc.org03054482015-03-05 13:13:42 +0000318 thread.Stop();
319}
320
tommi@webrtc.org0c3e12b2015-02-06 09:44:12 +0000321} // namespace webrtc