mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-15 14:50:39 +01:00

In https://webrtc-review.googlesource.com/c/src/+/1560 we moved WebRTC from src/webrtc to src/ (in order to preserve an healthy git history). This CL takes care of fixing header guards, #include paths, etc... NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true TBR=tommi@webrtc.org Bug: chromium:611808 Change-Id: Iea91618212bee0af16aa3f05071eab8f93706578 Reviewed-on: https://webrtc-review.googlesource.com/1561 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Henrik Kjellander <kjellander@webrtc.org> Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org> Cr-Commit-Position: refs/heads/master@{#19846}
321 lines
10 KiB
C++
321 lines
10 KiB
C++
/*
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "modules/include/module.h"
|
|
#include "modules/utility/source/process_thread_impl.h"
|
|
#include "rtc_base/location.h"
|
|
#include "rtc_base/task_queue.h"
|
|
#include "rtc_base/timeutils.h"
|
|
#include "test/gmock.h"
|
|
#include "test/gtest.h"
|
|
|
|
namespace webrtc {
|
|
|
|
using ::testing::_;
|
|
using ::testing::DoAll;
|
|
using ::testing::InSequence;
|
|
using ::testing::Invoke;
|
|
using ::testing::Return;
|
|
using ::testing::SetArgPointee;
|
|
|
|
// The length of time, in milliseconds, to wait for an event to become signaled.
|
|
// Set to a fairly large value as there is quite a bit of variation on some
|
|
// Windows bots.
|
|
static const int kEventWaitTimeout = 500;
|
|
|
|
class MockModule : public Module {
|
|
public:
|
|
MOCK_METHOD0(TimeUntilNextProcess, int64_t());
|
|
MOCK_METHOD0(Process, void());
|
|
MOCK_METHOD1(ProcessThreadAttached, void(ProcessThread*));
|
|
};
|
|
|
|
class RaiseEventTask : public rtc::QueuedTask {
|
|
public:
|
|
RaiseEventTask(EventWrapper* event) : event_(event) {}
|
|
bool Run() override {
|
|
event_->Set();
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
EventWrapper* event_;
|
|
};
|
|
|
|
ACTION_P(SetEvent, event) {
|
|
event->Set();
|
|
}
|
|
|
|
ACTION_P(Increment, counter) {
|
|
++(*counter);
|
|
}
|
|
|
|
ACTION_P(SetTimestamp, ptr) {
|
|
*ptr = rtc::TimeMillis();
|
|
}
|
|
|
|
TEST(ProcessThreadImpl, StartStop) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
thread.Start();
|
|
thread.Stop();
|
|
}
|
|
|
|
TEST(ProcessThreadImpl, MultipleStartStop) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
for (int i = 0; i < 5; ++i) {
|
|
thread.Start();
|
|
thread.Stop();
|
|
}
|
|
}
|
|
|
|
// Verifies that we get at least call back to Process() on the worker thread.
|
|
TEST(ProcessThreadImpl, ProcessCall) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
thread.Start();
|
|
|
|
std::unique_ptr<EventWrapper> event(EventWrapper::Create());
|
|
|
|
MockModule module;
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillOnce(Return(0))
|
|
.WillRepeatedly(Return(1));
|
|
EXPECT_CALL(module, Process())
|
|
.WillOnce(DoAll(SetEvent(event.get()), Return()))
|
|
.WillRepeatedly(Return());
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.Stop();
|
|
}
|
|
|
|
// Same as ProcessCall except the module is registered before the
|
|
// call to Start().
|
|
TEST(ProcessThreadImpl, ProcessCall2) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
std::unique_ptr<EventWrapper> event(EventWrapper::Create());
|
|
|
|
MockModule module;
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillOnce(Return(0))
|
|
.WillRepeatedly(Return(1));
|
|
EXPECT_CALL(module, Process())
|
|
.WillOnce(DoAll(SetEvent(event.get()), Return()))
|
|
.WillRepeatedly(Return());
|
|
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
thread.Start();
|
|
EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.Stop();
|
|
}
|
|
|
|
// Tests setting up a module for callbacks and then unregister that module.
|
|
// After unregistration, we should not receive any further callbacks.
|
|
TEST(ProcessThreadImpl, Deregister) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
std::unique_ptr<EventWrapper> event(EventWrapper::Create());
|
|
|
|
int process_count = 0;
|
|
MockModule module;
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillOnce(Return(0))
|
|
.WillRepeatedly(Return(1));
|
|
EXPECT_CALL(module, Process())
|
|
.WillOnce(DoAll(SetEvent(event.get()),
|
|
Increment(&process_count),
|
|
Return()))
|
|
.WillRepeatedly(DoAll(Increment(&process_count), Return()));
|
|
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
thread.Start();
|
|
|
|
EXPECT_EQ(kEventSignaled, event->Wait(kEventWaitTimeout));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.DeRegisterModule(&module);
|
|
|
|
EXPECT_GE(process_count, 1);
|
|
int count_after_deregister = process_count;
|
|
|
|
// We shouldn't get any more callbacks.
|
|
EXPECT_EQ(kEventTimeout, event->Wait(20));
|
|
EXPECT_EQ(count_after_deregister, process_count);
|
|
thread.Stop();
|
|
}
|
|
|
|
// Helper function for testing receiving a callback after a certain amount of
|
|
// time. There's some variance of timing built into it to reduce chance of
|
|
// flakiness on bots.
|
|
void ProcessCallAfterAFewMs(int64_t milliseconds) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
thread.Start();
|
|
|
|
std::unique_ptr<EventWrapper> event(EventWrapper::Create());
|
|
|
|
MockModule module;
|
|
int64_t start_time = 0;
|
|
int64_t called_time = 0;
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillOnce(DoAll(SetTimestamp(&start_time),
|
|
Return(milliseconds)))
|
|
.WillRepeatedly(Return(milliseconds));
|
|
EXPECT_CALL(module, Process())
|
|
.WillOnce(DoAll(SetTimestamp(&called_time),
|
|
SetEvent(event.get()),
|
|
Return()))
|
|
.WillRepeatedly(Return());
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
|
|
// Add a buffer of 50ms due to slowness of some trybots
|
|
// (e.g. win_drmemory_light)
|
|
EXPECT_EQ(kEventSignaled, event->Wait(milliseconds + 50));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.Stop();
|
|
|
|
ASSERT_GT(start_time, 0);
|
|
ASSERT_GT(called_time, 0);
|
|
// Use >= instead of > since due to rounding and timer accuracy (or lack
|
|
// thereof), can make the test run in "0"ms time.
|
|
EXPECT_GE(called_time, start_time);
|
|
// Check for an acceptable range.
|
|
uint32_t diff = called_time - start_time;
|
|
EXPECT_GE(diff, milliseconds - 15);
|
|
EXPECT_LT(diff, milliseconds + 15);
|
|
}
|
|
|
|
// DISABLED for now since the virtual build bots are too slow :(
|
|
// TODO(tommi): Fix.
|
|
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter5ms) {
|
|
ProcessCallAfterAFewMs(5);
|
|
}
|
|
|
|
// DISABLED for now since the virtual build bots are too slow :(
|
|
// TODO(tommi): Fix.
|
|
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter50ms) {
|
|
ProcessCallAfterAFewMs(50);
|
|
}
|
|
|
|
// DISABLED for now since the virtual build bots are too slow :(
|
|
// TODO(tommi): Fix.
|
|
TEST(ProcessThreadImpl, DISABLED_ProcessCallAfter200ms) {
|
|
ProcessCallAfterAFewMs(200);
|
|
}
|
|
|
|
// Runs callbacks with the goal of getting up to 50 callbacks within a second
|
|
// (on average 1 callback every 20ms). On real hardware, we're usually pretty
|
|
// close to that, but the test bots that run on virtual machines, will
|
|
// typically be in the range 30-40 callbacks.
|
|
// DISABLED for now since this can take up to 2 seconds to run on the slowest
|
|
// build bots.
|
|
// TODO(tommi): Fix.
|
|
TEST(ProcessThreadImpl, DISABLED_Process50Times) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
thread.Start();
|
|
|
|
std::unique_ptr<EventWrapper> event(EventWrapper::Create());
|
|
|
|
MockModule module;
|
|
int callback_count = 0;
|
|
// Ask for a callback after 20ms.
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillRepeatedly(Return(20));
|
|
EXPECT_CALL(module, Process())
|
|
.WillRepeatedly(DoAll(Increment(&callback_count),
|
|
Return()));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
|
|
EXPECT_EQ(kEventTimeout, event->Wait(1000));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.Stop();
|
|
|
|
printf("Callback count: %i\n", callback_count);
|
|
// Check that we got called back up to 50 times.
|
|
// Some of the try bots run on slow virtual machines, so the lower bound
|
|
// is much more relaxed to avoid flakiness.
|
|
EXPECT_GE(callback_count, 25);
|
|
EXPECT_LE(callback_count, 50);
|
|
}
|
|
|
|
// Tests that we can wake up the worker thread to give us a callback right
|
|
// away when we know the thread is sleeping.
|
|
TEST(ProcessThreadImpl, WakeUp) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
thread.Start();
|
|
|
|
std::unique_ptr<EventWrapper> started(EventWrapper::Create());
|
|
std::unique_ptr<EventWrapper> called(EventWrapper::Create());
|
|
|
|
MockModule module;
|
|
int64_t start_time;
|
|
int64_t called_time;
|
|
|
|
// Ask for a callback after 1000ms.
|
|
// TimeUntilNextProcess will be called twice.
|
|
// The first time we use it to get the thread into a waiting state.
|
|
// Then we wake the thread and there should not be another call made to
|
|
// TimeUntilNextProcess before Process() is called.
|
|
// The second time TimeUntilNextProcess is then called, is after Process
|
|
// has been called and we don't expect any more calls.
|
|
EXPECT_CALL(module, TimeUntilNextProcess())
|
|
.WillOnce(DoAll(SetTimestamp(&start_time),
|
|
SetEvent(started.get()),
|
|
Return(1000)))
|
|
.WillOnce(Return(1000));
|
|
EXPECT_CALL(module, Process())
|
|
.WillOnce(
|
|
DoAll(SetTimestamp(&called_time), SetEvent(called.get()), Return()))
|
|
.WillRepeatedly(Return());
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(&thread)).Times(1);
|
|
thread.RegisterModule(&module, RTC_FROM_HERE);
|
|
|
|
EXPECT_EQ(kEventSignaled, started->Wait(kEventWaitTimeout));
|
|
thread.WakeUp(&module);
|
|
EXPECT_EQ(kEventSignaled, called->Wait(kEventWaitTimeout));
|
|
|
|
EXPECT_CALL(module, ProcessThreadAttached(nullptr)).Times(1);
|
|
thread.Stop();
|
|
|
|
EXPECT_GE(called_time, start_time);
|
|
uint32_t diff = called_time - start_time;
|
|
// We should have been called back much quicker than 1sec.
|
|
EXPECT_LE(diff, 100u);
|
|
}
|
|
|
|
// Tests that we can post a task that gets run straight away on the worker
|
|
// thread.
|
|
TEST(ProcessThreadImpl, PostTask) {
|
|
ProcessThreadImpl thread("ProcessThread");
|
|
std::unique_ptr<EventWrapper> task_ran(EventWrapper::Create());
|
|
std::unique_ptr<RaiseEventTask> task(new RaiseEventTask(task_ran.get()));
|
|
thread.Start();
|
|
thread.PostTask(std::move(task));
|
|
EXPECT_EQ(kEventSignaled, task_ran->Wait(kEventWaitTimeout));
|
|
thread.Stop();
|
|
}
|
|
|
|
} // namespace webrtc
|