1/* 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 11#include <utility> 12 13#include "testing/gmock/include/gmock/gmock.h" 14#include "testing/gtest/include/gtest/gtest.h" 15#include "webrtc/modules/include/module.h" 16#include "webrtc/modules/utility/source/process_thread_impl.h" 17#include "webrtc/system_wrappers/include/tick_util.h" 18 19namespace webrtc { 20 21using ::testing::_; 22using ::testing::DoAll; 23using ::testing::InSequence; 24using ::testing::Invoke; 25using ::testing::Return; 26using ::testing::SetArgPointee; 27 28class MockModule : public Module { 29 public: 30 MOCK_METHOD0(TimeUntilNextProcess, int64_t()); 31 MOCK_METHOD0(Process, int32_t()); 32 MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*)); 33}; 34 35class RaiseEventTask : public ProcessTask { 36 public: 37 RaiseEventTask(EventWrapper* event) : event_(event) {} 38 void Run() override { event_->Set(); } 39 40 private: 41 EventWrapper* event_; 42}; 43 44ACTION_P(SetEvent, event) { 45 event->Set(); 46} 47 48ACTION_P(Increment, counter) { 49 ++(*counter); 50} 51 52ACTION_P(SetTimestamp, ptr) { 53 *ptr = TickTime::MillisecondTimestamp(); 54} 55 56TEST(ProcessThreadImpl, StartStop) { 57 ProcessThreadImpl thread("ProcessThread"); 58 thread.Start(); 59 thread.Stop(); 60} 61 62TEST(ProcessThreadImpl, MultipleStartStop) { 63 ProcessThreadImpl thread("ProcessThread"); 64 for (int i = 0; i < 5; ++i) { 65 thread.Start(); 66 thread.Stop(); 67 } 68} 69 70// Verifies that we get at least call back to Process() on the worker thread. 71TEST(ProcessThreadImpl, ProcessCall) { 72 ProcessThreadImpl thread("ProcessThread"); 73 thread.Start(); 74 75 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create()); 76 77 MockModule module; 78 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0)); 79 EXPECT_CALL(module, Process()) 80 .WillOnce(DoAll(SetEvent(event.get()), Return(0))) 81 .WillRepeatedly(Return(0)); 82 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 83 84 thread.RegisterModule(&module); 85 EXPECT_EQ(kEventSignaled, event->Wait(100)); 86 87 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 88 thread.Stop(); 89} 90 91// Same as ProcessCall except the module is registered before the 92// call to Start(). 93TEST(ProcessThreadImpl, ProcessCall2) { 94 ProcessThreadImpl thread("ProcessThread"); 95 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create()); 96 97 MockModule module; 98 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0)); 99 EXPECT_CALL(module, Process()) 100 .WillOnce(DoAll(SetEvent(event.get()), Return(0))) 101 .WillRepeatedly(Return(0)); 102 103 thread.RegisterModule(&module); 104 105 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 106 thread.Start(); 107 EXPECT_EQ(kEventSignaled, event->Wait(100)); 108 109 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 110 thread.Stop(); 111} 112 113// Tests setting up a module for callbacks and then unregister that module. 114// After unregistration, we should not receive any further callbacks. 115TEST(ProcessThreadImpl, Deregister) { 116 ProcessThreadImpl thread("ProcessThread"); 117 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create()); 118 119 int process_count = 0; 120 MockModule module; 121 EXPECT_CALL(module, TimeUntilNextProcess()).WillRepeatedly(Return(0)); 122 EXPECT_CALL(module, Process()) 123 .WillOnce(DoAll(SetEvent(event.get()), 124 Increment(&process_count), 125 Return(0))) 126 .WillRepeatedly(DoAll(Increment(&process_count), Return(0))); 127 128 thread.RegisterModule(&module); 129 130 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 131 thread.Start(); 132 133 EXPECT_EQ(kEventSignaled, event->Wait(100)); 134 135 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 136 thread.DeRegisterModule(&module); 137 138 EXPECT_GE(process_count, 1); 139 int count_after_deregister = process_count; 140 141 // We shouldn't get any more callbacks. 142 EXPECT_EQ(kEventTimeout, event->Wait(20)); 143 EXPECT_EQ(count_after_deregister, process_count); 144 thread.Stop(); 145} 146 147// Helper function for testing receiving a callback after a certain amount of 148// time. There's some variance of timing built into it to reduce chance of 149// flakiness on bots. 150void ProcessCallAfterAFewMs(int64_t milliseconds) { 151 ProcessThreadImpl thread("ProcessThread"); 152 thread.Start(); 153 154 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create()); 155 156 MockModule module; 157 int64_t start_time = 0; 158 int64_t called_time = 0; 159 EXPECT_CALL(module, TimeUntilNextProcess()) 160 .WillOnce(DoAll(SetTimestamp(&start_time), 161 Return(milliseconds))) 162 .WillRepeatedly(Return(milliseconds)); 163 EXPECT_CALL(module, Process()) 164 .WillOnce(DoAll(SetTimestamp(&called_time), 165 SetEvent(event.get()), 166 Return(0))) 167 .WillRepeatedly(Return(0)); 168 169 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 170 thread.RegisterModule(&module); 171 172 // Add a buffer of 50ms due to slowness of some trybots 173 // (e.g. win_drmemory_light) 174 EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50)); 175 176 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 177 thread.Stop(); 178 179 ASSERT_GT(start_time, 0); 180 ASSERT_GT(called_time, 0); 181 // Use >= instead of > since due to rounding and timer accuracy (or lack 182 // thereof), can make the test run in "0"ms time. 183 EXPECT_GE(called_time, start_time); 184 // Check for an acceptable range. 185 uint32_t diff = called_time - start_time; 186 EXPECT_GE(diff, milliseconds - 15); 187 EXPECT_LT(diff, milliseconds + 15); 188} 189 190// DISABLED for now since the virtual build bots are too slow :( 191// TODO(tommi): Fix. 192TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) { 193 ProcessCallAfterAFewMs(5); 194} 195 196// DISABLED for now since the virtual build bots are too slow :( 197// TODO(tommi): Fix. 198TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) { 199 ProcessCallAfterAFewMs(50); 200} 201 202// DISABLED for now since the virtual build bots are too slow :( 203// TODO(tommi): Fix. 204TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) { 205 ProcessCallAfterAFewMs(200); 206} 207 208// Runs callbacks with the goal of getting up to 50 callbacks within a second 209// (on average 1 callback every 20ms). On real hardware, we're usually pretty 210// close to that, but the test bots that run on virtual machines, will 211// typically be in the range 30-40 callbacks. 212// DISABLED for now since this can take up to 2 seconds to run on the slowest 213// build bots. 214// TODO(tommi): Fix. 215TEST(ProcessThreadImpl, DISABLED_Process50Times) { 216 ProcessThreadImpl thread("ProcessThread"); 217 thread.Start(); 218 219 rtc::scoped_ptr<EventWrapper> event(EventWrapper::Create()); 220 221 MockModule module; 222 int callback_count = 0; 223 // Ask for a callback after 20ms. 224 EXPECT_CALL(module, TimeUntilNextProcess()) 225 .WillRepeatedly(Return(20)); 226 EXPECT_CALL(module, Process()) 227 .WillRepeatedly(DoAll(Increment(&callback_count), 228 Return(0))); 229 230 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 231 thread.RegisterModule(&module); 232 233 EXPECT_EQ(kEventTimeout, event->Wait(1000)); 234 235 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 236 thread.Stop(); 237 238 printf("Callback count: %i\n", callback_count); 239 // Check that we got called back up to 50 times. 240 // Some of the try bots run on slow virtual machines, so the lower bound 241 // is much more relaxed to avoid flakiness. 242 EXPECT_GE(callback_count, 25); 243 EXPECT_LE(callback_count, 50); 244} 245 246// Tests that we can wake up the worker thread to give us a callback right 247// away when we know the thread is sleeping. 248TEST(ProcessThreadImpl, WakeUp) { 249 ProcessThreadImpl thread("ProcessThread"); 250 thread.Start(); 251 252 rtc::scoped_ptr<EventWrapper> started(EventWrapper::Create()); 253 rtc::scoped_ptr<EventWrapper> called(EventWrapper::Create()); 254 255 MockModule module; 256 int64_t start_time; 257 int64_t called_time; 258 259 // Ask for a callback after 1000ms. 260 // TimeUntilNextProcess will be called twice. 261 // The first time we use it to get the thread into a waiting state. 262 // Then we wake the thread and there should not be another call made to 263 // TimeUntilNextProcess before Process() is called. 264 // The second time TimeUntilNextProcess is then called, is after Process 265 // has been called and we don't expect any more calls. 266 EXPECT_CALL(module, TimeUntilNextProcess()) 267 .WillOnce(DoAll(SetTimestamp(&start_time), 268 SetEvent(started.get()), 269 Return(1000))) 270 .WillOnce(Return(1000)); 271 EXPECT_CALL(module, Process()) 272 .WillOnce(DoAll(SetTimestamp(&called_time), 273 SetEvent(called.get()), 274 Return(0))) 275 .WillRepeatedly(Return(0)); 276 277 EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1); 278 thread.RegisterModule(&module); 279 280 EXPECT_EQ(kEventSignaled, started->Wait(100)); 281 thread.WakeUp(&module); 282 EXPECT_EQ(kEventSignaled, called->Wait(100)); 283 284 EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1); 285 thread.Stop(); 286 287 EXPECT_GE(called_time, start_time); 288 uint32_t diff = called_time - start_time; 289 // We should have been called back much quicker than 1sec. 290 EXPECT_LE(diff, 100u); 291} 292 293// Tests that we can post a task that gets run straight away on the worker 294// thread. 295TEST(ProcessThreadImpl, PostTask) { 296 ProcessThreadImpl thread("ProcessThread"); 297 rtc::scoped_ptr<EventWrapper> task_ran(EventWrapper::Create()); 298 rtc::scoped_ptr<RaiseEventTask> task(new RaiseEventTask(task_ran.get())); 299 thread.Start(); 300 thread.PostTask(std::move(task)); 301 EXPECT_EQ(kEventSignaled, task_ran->Wait(100)); 302 thread.Stop(); 303} 304 305} // namespace webrtc 306