Introduce TaskQueueForTest.
This class adds a convenience method that allows *sending* a task to the queue (as opposed to posting). Sending is essentially Post+Wait, a pattern that we don't want to encourage use of in production code, but is convenient to have from a testing perspective and there are already several places in the source code where we use it. Change-Id: I6efd1b2257e6c641294bb6e4eb53b0021d9553ca Bug: webrtc:8848 Reviewed-on: https://webrtc-review.googlesource.com/50441 Reviewed-by: Magnus Jedvert <magjed@webrtc.org> Commit-Queue: Tommi <tommi@webrtc.org> Cr-Commit-Position: refs/heads/master@{#22022}
This commit is contained in:
parent
db6145f055
commit
685615678a
@ -491,6 +491,7 @@ if (rtc_include_tests) {
|
||||
"../rtc_base:rtc_base",
|
||||
"../rtc_base:rtc_base_approved",
|
||||
"../rtc_base:rtc_base_tests_utils",
|
||||
"../rtc_base:rtc_task_queue_for_test",
|
||||
"../test:test_support",
|
||||
"//testing/gtest",
|
||||
]
|
||||
|
||||
@ -137,15 +137,19 @@ FakeVideoCapturerWithTaskQueue::FakeVideoCapturerWithTaskQueue(
|
||||
FakeVideoCapturerWithTaskQueue::FakeVideoCapturerWithTaskQueue() {}
|
||||
|
||||
bool FakeVideoCapturerWithTaskQueue::CaptureFrame() {
|
||||
if (task_queue_.IsCurrent())
|
||||
return FakeVideoCapturer::CaptureFrame();
|
||||
bool ret = false;
|
||||
RunSynchronouslyOnTaskQueue(
|
||||
task_queue_.SendTask(
|
||||
[this, &ret]() { ret = FakeVideoCapturer::CaptureFrame(); });
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FakeVideoCapturerWithTaskQueue::CaptureCustomFrame(int width, int height) {
|
||||
if (task_queue_.IsCurrent())
|
||||
return FakeVideoCapturer::CaptureCustomFrame(width, height);
|
||||
bool ret = false;
|
||||
RunSynchronouslyOnTaskQueue([this, &ret, width, height]() {
|
||||
task_queue_.SendTask([this, &ret, width, height]() {
|
||||
ret = FakeVideoCapturer::CaptureCustomFrame(width, height);
|
||||
});
|
||||
return ret;
|
||||
|
||||
@ -21,8 +21,7 @@
|
||||
#include "media/base/fakeframesource.h"
|
||||
#include "media/base/videocapturer.h"
|
||||
#include "media/base/videocommon.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
|
||||
namespace cricket {
|
||||
@ -73,21 +72,7 @@ class FakeVideoCapturerWithTaskQueue : public FakeVideoCapturer {
|
||||
bool CaptureCustomFrame(int width, int height) override;
|
||||
|
||||
protected:
|
||||
template <class Closure>
|
||||
void RunSynchronouslyOnTaskQueue(Closure&& closure) {
|
||||
if (task_queue_.IsCurrent()) {
|
||||
closure();
|
||||
return;
|
||||
}
|
||||
rtc::Event event(false, false);
|
||||
task_queue_.PostTask([&closure, &event]() {
|
||||
closure();
|
||||
event.Set();
|
||||
});
|
||||
event.Wait(rtc::Event::kForever);
|
||||
}
|
||||
|
||||
rtc::TaskQueue task_queue_{"FakeVideoCapturerWithTaskQueue"};
|
||||
rtc::test::TaskQueueForTest task_queue_{"FakeVideoCapturerWithTaskQueue"};
|
||||
};
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include "api/video/i420_buffer.h"
|
||||
#include "media/base/testutils.h"
|
||||
#include "media/engine/webrtcvideocapturer.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
|
||||
class FakeWebRtcVcmFactory;
|
||||
|
||||
@ -60,17 +61,18 @@ class FakeWebRtcVideoCaptureModule : public webrtc::VideoCaptureModule {
|
||||
return true; // Rotation compensation is turned on.
|
||||
}
|
||||
void SendFrame(int w, int h) {
|
||||
if (!running_) return;
|
||||
if (!running_ || !callback_)
|
||||
return;
|
||||
|
||||
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
|
||||
webrtc::I420Buffer::Create(w, h);
|
||||
// Initialize memory to satisfy DrMemory tests. See
|
||||
// https://bugs.chromium.org/p/libyuv/issues/detail?id=377
|
||||
buffer->InitializeData();
|
||||
if (callback_) {
|
||||
task_queue_.SendTask([this, w, h]() {
|
||||
rtc::scoped_refptr<webrtc::I420Buffer> buffer =
|
||||
webrtc::I420Buffer::Create(w, h);
|
||||
// Initialize memory to satisfy DrMemory tests. See
|
||||
// https://bugs.chromium.org/p/libyuv/issues/detail?id=377
|
||||
buffer->InitializeData();
|
||||
callback_->OnFrame(
|
||||
webrtc::VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const webrtc::VideoCaptureCapability& cap() const {
|
||||
@ -78,6 +80,7 @@ class FakeWebRtcVideoCaptureModule : public webrtc::VideoCaptureModule {
|
||||
}
|
||||
|
||||
private:
|
||||
rtc::test::TaskQueueForTest task_queue_{"FakeWebRtcVideoCaptureModule"};
|
||||
FakeWebRtcVcmFactory* factory_;
|
||||
rtc::VideoSinkInterface<webrtc::VideoFrame>* callback_;
|
||||
bool running_;
|
||||
|
||||
@ -88,7 +88,7 @@ if (rtc_include_tests) {
|
||||
"../../audio/utility:audio_frame_operations",
|
||||
"../../rtc_base:checks",
|
||||
"../../rtc_base:rtc_base_approved",
|
||||
"../../rtc_base:rtc_task_queue",
|
||||
"../../rtc_base:rtc_task_queue_for_test",
|
||||
"../../test:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
@ -21,8 +21,7 @@
|
||||
#include "modules/audio_mixer/default_output_rate_calculator.h"
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
#include "test/gmock.h"
|
||||
|
||||
using testing::_;
|
||||
@ -372,14 +371,9 @@ TEST(AudioMixer, RampedOutSourcesShouldNotBeMarkedMixed) {
|
||||
// This test checks that the initialization and participant addition
|
||||
// can be done on a different thread.
|
||||
TEST(AudioMixer, ConstructFromOtherThread) {
|
||||
rtc::TaskQueue init_queue("init");
|
||||
rtc::test::TaskQueueForTest init_queue("init");
|
||||
rtc::scoped_refptr<AudioMixer> mixer;
|
||||
rtc::Event event(false, false);
|
||||
init_queue.PostTask([&mixer, &event]() {
|
||||
mixer = AudioMixerImpl::Create();
|
||||
event.Set();
|
||||
});
|
||||
event.Wait(rtc::Event::kForever);
|
||||
init_queue.SendTask([&mixer]() { mixer = AudioMixerImpl::Create(); });
|
||||
|
||||
MockMixerAudioSource participant;
|
||||
EXPECT_CALL(participant, PreferredSampleRate())
|
||||
@ -387,12 +381,9 @@ TEST(AudioMixer, ConstructFromOtherThread) {
|
||||
|
||||
ResetFrame(participant.fake_frame());
|
||||
|
||||
rtc::TaskQueue participant_queue("participant");
|
||||
participant_queue.PostTask([&mixer, &event, &participant]() {
|
||||
mixer->AddSource(&participant);
|
||||
event.Set();
|
||||
});
|
||||
event.Wait(rtc::Event::kForever);
|
||||
rtc::test::TaskQueueForTest participant_queue("participant");
|
||||
participant_queue.SendTask(
|
||||
[&mixer, &participant]() { mixer->AddSource(&participant); });
|
||||
|
||||
EXPECT_CALL(participant, GetAudioFrameWithInfo(kDefaultSampleRateHz, _))
|
||||
.Times(Exactly(1));
|
||||
|
||||
@ -52,7 +52,7 @@ class FakePeriodicVideoCapturer
|
||||
// So, in order to allow tests to stop frame delivery directly from the
|
||||
// test thread, we expose this method publicly.
|
||||
void StopFrameDelivery() {
|
||||
RunSynchronouslyOnTaskQueue([this]() {
|
||||
task_queue_.SendTask([this]() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
deliver_frames_ = false;
|
||||
});
|
||||
|
||||
@ -996,6 +996,21 @@ if (rtc_include_tests) {
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("rtc_task_queue_for_test") {
|
||||
visibility = [ "*" ]
|
||||
testonly = true
|
||||
|
||||
sources = [
|
||||
"task_queue_for_test.cc",
|
||||
"task_queue_for_test.h",
|
||||
]
|
||||
deps = [
|
||||
":checks",
|
||||
":rtc_base_approved",
|
||||
":rtc_task_queue",
|
||||
]
|
||||
}
|
||||
|
||||
rtc_source_set("rtc_task_queue_unittests") {
|
||||
visibility = [ "*" ]
|
||||
testonly = true
|
||||
@ -1008,6 +1023,7 @@ if (rtc_include_tests) {
|
||||
":rtc_base_tests_main",
|
||||
":rtc_base_tests_utils",
|
||||
":rtc_task_queue",
|
||||
":rtc_task_queue_for_test",
|
||||
"../test:test_support",
|
||||
]
|
||||
}
|
||||
|
||||
19
rtc_base/task_queue_for_test.cc
Normal file
19
rtc_base/task_queue_for_test.cc
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2018 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 "rtc_base/task_queue_for_test.h"
|
||||
|
||||
namespace rtc {
|
||||
namespace test {
|
||||
TaskQueueForTest::TaskQueueForTest(const char* queue_name, Priority priority)
|
||||
: TaskQueue(queue_name, priority) {}
|
||||
TaskQueueForTest::~TaskQueueForTest() {}
|
||||
} // namespace test
|
||||
} // namespace rtc
|
||||
61
rtc_base/task_queue_for_test.h
Normal file
61
rtc_base/task_queue_for_test.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef RTC_BASE_TASK_QUEUE_FOR_TEST_H_
|
||||
#define RTC_BASE_TASK_QUEUE_FOR_TEST_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
|
||||
namespace rtc {
|
||||
namespace test {
|
||||
class RTC_LOCKABLE TaskQueueForTest : public TaskQueue {
|
||||
public:
|
||||
explicit TaskQueueForTest(const char* queue_name,
|
||||
Priority priority = Priority::NORMAL);
|
||||
~TaskQueueForTest();
|
||||
|
||||
// A convenience, test-only method that blocks the current thread while
|
||||
// a task executes on the task queue.
|
||||
// This variant is specifically for posting custom QueuedTask derived
|
||||
// implementations that tests do not want to pass ownership of over to the
|
||||
// task queue (i.e. the Run() method always returns |false|.).
|
||||
template <class Closure>
|
||||
void SendTask(Closure* task) {
|
||||
RTC_DCHECK(!IsCurrent());
|
||||
rtc::Event event(false, false);
|
||||
PostTask(rtc::NewClosure(
|
||||
[&task]() {
|
||||
RTC_CHECK_EQ(false, static_cast<QueuedTask*>(task)->Run());
|
||||
},
|
||||
[&event]() { event.Set(); }));
|
||||
event.Wait(rtc::Event::kForever);
|
||||
}
|
||||
|
||||
// A convenience, test-only method that blocks the current thread while
|
||||
// a task executes on the task queue.
|
||||
template <class Closure>
|
||||
void SendTask(Closure&& task) {
|
||||
RTC_DCHECK(!IsCurrent());
|
||||
rtc::Event event(false, false);
|
||||
PostTask(rtc::NewClosure(std::move(task), [&event]() { event.Set(); }));
|
||||
event.Wait(rtc::Event::kForever);
|
||||
}
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(TaskQueueForTest);
|
||||
};
|
||||
} // namespace test
|
||||
} // namespace rtc
|
||||
|
||||
#endif // RTC_BASE_TASK_QUEUE_FOR_TEST_H_
|
||||
@ -21,10 +21,13 @@
|
||||
#include "rtc_base/bind.h"
|
||||
#include "rtc_base/event.h"
|
||||
#include "rtc_base/gunit.h"
|
||||
#include "rtc_base/task_queue.h"
|
||||
#include "rtc_base/task_queue_for_test.h"
|
||||
#include "rtc_base/timeutils.h"
|
||||
|
||||
using rtc::test::TaskQueueForTest;
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace {
|
||||
// Noop on all platforms except Windows, where it turns on high precision
|
||||
// multimedia timers which increases the precision of TimeMillis() while in
|
||||
@ -44,9 +47,7 @@ class EnableHighResTimers {
|
||||
const bool enabled_;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
void CheckCurrent(Event* signal, TaskQueue* queue) {
|
||||
EXPECT_TRUE(queue->IsCurrent());
|
||||
if (signal)
|
||||
@ -76,34 +77,31 @@ TEST(TaskQueueTest, PostAndCheckCurrent) {
|
||||
|
||||
TEST(TaskQueueTest, PostCustomTask) {
|
||||
static const char kQueueName[] = "PostCustomImplementation";
|
||||
Event event(false, false);
|
||||
TaskQueue queue(kQueueName);
|
||||
TaskQueueForTest queue(kQueueName);
|
||||
|
||||
class CustomTask : public QueuedTask {
|
||||
public:
|
||||
explicit CustomTask(Event* event) : event_(event) {}
|
||||
CustomTask() {}
|
||||
bool ran() const { return ran_; }
|
||||
|
||||
private:
|
||||
bool Run() override {
|
||||
event_->Set();
|
||||
return false; // Never allows the task to be deleted by the queue.
|
||||
ran_ = true;
|
||||
return false; // Never allow the task to be deleted by the queue.
|
||||
}
|
||||
|
||||
Event* const event_;
|
||||
} my_task(&event);
|
||||
bool ran_ = false;
|
||||
} my_task;
|
||||
|
||||
// Please don't do this in production code! :)
|
||||
queue.PostTask(std::unique_ptr<QueuedTask>(&my_task));
|
||||
EXPECT_TRUE(event.Wait(1000));
|
||||
queue.SendTask(&my_task);
|
||||
EXPECT_TRUE(my_task.ran());
|
||||
}
|
||||
|
||||
TEST(TaskQueueTest, PostLambda) {
|
||||
static const char kQueueName[] = "PostLambda";
|
||||
Event event(false, false);
|
||||
TaskQueue queue(kQueueName);
|
||||
|
||||
queue.PostTask([&event]() { event.Set(); });
|
||||
EXPECT_TRUE(event.Wait(1000));
|
||||
TaskQueueForTest queue("PostLambda");
|
||||
bool ran = false;
|
||||
queue.SendTask([&ran]() { ran = true; });
|
||||
EXPECT_TRUE(ran);
|
||||
}
|
||||
|
||||
TEST(TaskQueueTest, PostDelayedZero) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user