Publish task queue test suite.
The set of tests is a copy of rtc_base/task_queue_unittests excluding tests that verify rtc::NewClosure rather than task queue implementation itself. Bug: webrtc:10191 Change-Id: I94e962ad63ff6510c43a97ef0cd4da7d08f25538 Reviewed-on: https://webrtc-review.googlesource.com/c/118445 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26369}
This commit is contained in:
committed by
Commit Bot
parent
b0397d69a9
commit
33b716f7dd
@ -39,6 +39,25 @@ rtc_source_set("task_queue_factory") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("task_queue_test") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
testonly = true
|
||||||
|
sources = [
|
||||||
|
"task_queue_test.cc",
|
||||||
|
"task_queue_test.h",
|
||||||
|
]
|
||||||
|
deps = [
|
||||||
|
":task_queue",
|
||||||
|
":task_queue_factory",
|
||||||
|
"../../rtc_base:rtc_event",
|
||||||
|
"../../rtc_base:rtc_task_queue_api",
|
||||||
|
"../../rtc_base:timeutils",
|
||||||
|
"../../test:test_support",
|
||||||
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
|
"//third_party/abseil-cpp/absl/strings",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
rtc_source_set("default_task_queue_factory") {
|
rtc_source_set("default_task_queue_factory") {
|
||||||
# TODO(bugs.webrtc.org/10191): Make public when implemented for all
|
# TODO(bugs.webrtc.org/10191): Make public when implemented for all
|
||||||
# supported platforms.
|
# supported platforms.
|
||||||
|
|||||||
@ -4,4 +4,7 @@ specific_include_rules = {
|
|||||||
"task_queue_impl\.h": [
|
"task_queue_impl\.h": [
|
||||||
"+rtc_base/task_queue.h",
|
"+rtc_base/task_queue.h",
|
||||||
],
|
],
|
||||||
|
"task_queue_test\.h": [
|
||||||
|
"+test/gtest.h",
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
212
api/task_queue/task_queue_test.cc
Normal file
212
api/task_queue/task_queue_test.cc
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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 "api/task_queue/task_queue_test.h"
|
||||||
|
|
||||||
|
#include "absl/memory/memory.h"
|
||||||
|
#include "absl/strings/string_view.h"
|
||||||
|
#include "rtc_base/event.h"
|
||||||
|
#include "rtc_base/task_queue.h"
|
||||||
|
#include "rtc_base/timeutils.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::unique_ptr<TaskQueueBase, TaskQueueDeleter> CreateTaskQueue(
|
||||||
|
TaskQueueFactory* factory,
|
||||||
|
absl::string_view task_queue_name,
|
||||||
|
TaskQueueFactory::Priority priority = TaskQueueFactory::Priority::NORMAL) {
|
||||||
|
return factory->CreateTaskQueue(task_queue_name, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, Construct) {
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "Construct");
|
||||||
|
EXPECT_FALSE(queue->IsCurrent());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostAndCheckCurrent) {
|
||||||
|
rtc::Event event;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostAndCheckCurrent");
|
||||||
|
|
||||||
|
// We're not running a task, so there shouldn't be a current queue.
|
||||||
|
EXPECT_FALSE(queue->IsCurrent());
|
||||||
|
EXPECT_FALSE(TaskQueueBase::Current());
|
||||||
|
|
||||||
|
queue->PostTask(rtc::NewClosure([&event, &queue] {
|
||||||
|
EXPECT_TRUE(queue->IsCurrent());
|
||||||
|
event.Set();
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostCustomTask) {
|
||||||
|
rtc::Event ran;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostCustomImplementation");
|
||||||
|
|
||||||
|
class CustomTask : public QueuedTask {
|
||||||
|
public:
|
||||||
|
explicit CustomTask(rtc::Event* ran) : ran_(ran) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Run() override {
|
||||||
|
ran_->Set();
|
||||||
|
return false; // Do not allow the task to be deleted by the queue.
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::Event* const ran_;
|
||||||
|
} my_task(&ran);
|
||||||
|
|
||||||
|
queue->PostTask(absl::WrapUnique(&my_task));
|
||||||
|
EXPECT_TRUE(ran.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostDelayedZero) {
|
||||||
|
rtc::Event event;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostDelayedZero");
|
||||||
|
|
||||||
|
queue->PostDelayedTask(rtc::NewClosure([&event] { event.Set(); }), 0);
|
||||||
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostFromQueue) {
|
||||||
|
rtc::Event event;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostFromQueue");
|
||||||
|
|
||||||
|
queue->PostTask(rtc::NewClosure([&event, &queue] {
|
||||||
|
queue->PostTask(rtc::NewClosure([&event] { event.Set(); }));
|
||||||
|
}));
|
||||||
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostDelayed) {
|
||||||
|
rtc::Event event;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostDelayed",
|
||||||
|
TaskQueueFactory::Priority::HIGH);
|
||||||
|
|
||||||
|
int64_t start = rtc::TimeMillis();
|
||||||
|
queue->PostDelayedTask(rtc::NewClosure([&event, &queue] {
|
||||||
|
EXPECT_TRUE(queue->IsCurrent());
|
||||||
|
event.Set();
|
||||||
|
}),
|
||||||
|
100);
|
||||||
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
|
int64_t end = rtc::TimeMillis();
|
||||||
|
// These tests are a little relaxed due to how "powerful" our test bots can
|
||||||
|
// be. Most recently we've seen windows bots fire the callback after 94-99ms,
|
||||||
|
// which is why we have a little bit of leeway backwards as well.
|
||||||
|
EXPECT_GE(end - start, 90u);
|
||||||
|
EXPECT_NEAR(end - start, 190u, 100u); // Accept 90-290.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostMultipleDelayed) {
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostMultipleDelayed");
|
||||||
|
|
||||||
|
std::vector<rtc::Event> events(100);
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
rtc::Event* event = &events[i];
|
||||||
|
queue->PostDelayedTask(rtc::NewClosure([event, &queue] {
|
||||||
|
EXPECT_TRUE(queue->IsCurrent());
|
||||||
|
event->Set();
|
||||||
|
}),
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (rtc::Event& e : events)
|
||||||
|
EXPECT_TRUE(e.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostDelayedAfterDestruct) {
|
||||||
|
rtc::Event run;
|
||||||
|
rtc::Event deleted;
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostDelayedAfterDestruct");
|
||||||
|
queue->PostDelayedTask(
|
||||||
|
rtc::NewClosure([&run] { run.Set(); }, [&deleted] { deleted.Set(); }),
|
||||||
|
100);
|
||||||
|
// Destroy the queue.
|
||||||
|
queue = nullptr;
|
||||||
|
// Task might outlive the TaskQueue, but still should be deleted.
|
||||||
|
EXPECT_TRUE(deleted.Wait(200));
|
||||||
|
EXPECT_FALSE(run.Wait(0)); // and should not run.
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(TaskQueueTest, PostAndReuse) {
|
||||||
|
rtc::Event event;
|
||||||
|
auto post_queue = CreateTaskQueue(GetParam(), "PostQueue");
|
||||||
|
auto reply_queue = CreateTaskQueue(GetParam(), "ReplyQueue");
|
||||||
|
|
||||||
|
int call_count = 0;
|
||||||
|
|
||||||
|
class ReusedTask : public QueuedTask {
|
||||||
|
public:
|
||||||
|
ReusedTask(int* counter, TaskQueueBase* reply_queue, rtc::Event* event)
|
||||||
|
: counter_(*counter), reply_queue_(reply_queue), event_(*event) {
|
||||||
|
EXPECT_EQ(counter_, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Run() override {
|
||||||
|
if (++counter_ == 1) {
|
||||||
|
reply_queue_->PostTask(absl::WrapUnique(this));
|
||||||
|
// At this point, the object is owned by reply_queue_ and it's
|
||||||
|
// theoratically possible that the object has been deleted (e.g. if
|
||||||
|
// posting wasn't possible). So, don't touch any member variables here.
|
||||||
|
|
||||||
|
// Indicate to the current queue that ownership has been transferred.
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(counter_, 2);
|
||||||
|
EXPECT_TRUE(reply_queue_->IsCurrent());
|
||||||
|
event_.Set();
|
||||||
|
return true; // Indicate that the object should be deleted.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int& counter_;
|
||||||
|
TaskQueueBase* const reply_queue_;
|
||||||
|
rtc::Event& event_;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto task =
|
||||||
|
absl::make_unique<ReusedTask>(&call_count, reply_queue.get(), &event);
|
||||||
|
post_queue->PostTask(std::move(task));
|
||||||
|
EXPECT_TRUE(event.Wait(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tests posting more messages than a queue can queue up.
|
||||||
|
// In situations like that, tasks will get dropped.
|
||||||
|
TEST_P(TaskQueueTest, PostALot) {
|
||||||
|
// To destruct the event after the queue has gone out of scope.
|
||||||
|
rtc::Event event;
|
||||||
|
|
||||||
|
int tasks_executed = 0;
|
||||||
|
int tasks_cleaned_up = 0;
|
||||||
|
static const int kTaskCount = 0xffff;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto queue = CreateTaskQueue(GetParam(), "PostALot");
|
||||||
|
|
||||||
|
// On linux, the limit of pending bytes in the pipe buffer is 0xffff.
|
||||||
|
// So here we post a total of 0xffff+1 messages, which triggers a failure
|
||||||
|
// case inside of the libevent queue implementation.
|
||||||
|
|
||||||
|
queue->PostTask(
|
||||||
|
rtc::NewClosure([&event] { event.Wait(rtc::Event::kForever); }));
|
||||||
|
for (int i = 0; i < kTaskCount; ++i)
|
||||||
|
queue->PostTask(
|
||||||
|
rtc::NewClosure([&tasks_executed] { ++tasks_executed; },
|
||||||
|
[&tasks_cleaned_up] { ++tasks_cleaned_up; }));
|
||||||
|
event.Set(); // Unblock the first task.
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_GE(tasks_cleaned_up, tasks_executed);
|
||||||
|
EXPECT_EQ(tasks_cleaned_up, kTaskCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace webrtc
|
||||||
32
api/task_queue/task_queue_test.h
Normal file
32
api/task_queue/task_queue_test.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 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 API_TASK_QUEUE_TASK_QUEUE_TEST_H_
|
||||||
|
#define API_TASK_QUEUE_TASK_QUEUE_TEST_H_
|
||||||
|
|
||||||
|
#include "api/task_queue/task_queue_factory.h"
|
||||||
|
#include "test/gtest.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// Suite of tests to verify TaskQueue implementation with.
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// namespace {
|
||||||
|
//
|
||||||
|
// using ::webrtc::TaskQueueTest;
|
||||||
|
// webrtc::TaskQueueFactory* MyFactory();
|
||||||
|
// INSTANTIATE_TEST_SUITE_P(My, TaskQueueTest, ::testing::Values(MyFactory()));
|
||||||
|
//
|
||||||
|
// } // namespace
|
||||||
|
class TaskQueueTest : public ::testing::TestWithParam<TaskQueueFactory*> {};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // API_TASK_QUEUE_TASK_QUEUE_TEST_H_
|
||||||
Reference in New Issue
Block a user