diff --git a/api/BUILD.gn b/api/BUILD.gn index ed3c708df1..32f4c8e079 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -681,6 +681,7 @@ if (rtc_include_tests) { "../rtc_base:gunit_helpers", "../rtc_base:rtc_base_approved", "../test:test_support", + "task_queue:task_queue_default_factory_unittests", "units:units_unittests", ] } diff --git a/api/task_queue/BUILD.gn b/api/task_queue/BUILD.gn index 578a212465..e7e3aec32f 100644 --- a/api/task_queue/BUILD.gn +++ b/api/task_queue/BUILD.gn @@ -60,9 +60,7 @@ rtc_source_set("task_queue_test") { } rtc_source_set("default_task_queue_factory") { - # TODO(bugs.webrtc.org/10191): Make public when implemented for all - # supported platforms. - visibility = [ ":global_task_queue_factory" ] + visibility = [ "*" ] sources = [ "default_task_queue_factory.h", ] @@ -112,6 +110,20 @@ rtc_source_set("default_task_queue_factory_impl") { } } +if (rtc_include_tests) { + rtc_source_set("task_queue_default_factory_unittests") { + testonly = true + sources = [ + "default_task_queue_factory_unittest.cc", + ] + deps = [ + ":default_task_queue_factory", + ":task_queue_test", + "../../test:test_support", + ] + } +} + # Linking with global_task_queue_factory adds link-time implementation of the # rtc::TaskQueue that allows run-time injection of the TaskQueue implementaion. rtc_source_set("global_task_queue_factory") { diff --git a/api/task_queue/default_task_queue_factory_unittest.cc b/api/task_queue/default_task_queue_factory_unittest.cc new file mode 100644 index 0000000000..92c17d8444 --- /dev/null +++ b/api/task_queue/default_task_queue_factory_unittest.cc @@ -0,0 +1,24 @@ +/* + * 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/default_task_queue_factory.h" + +#include "api/task_queue/task_queue_test.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { + +INSTANTIATE_TEST_SUITE_P(Default, + TaskQueueTest, + ::testing::Values(CreateDefaultTaskQueueFactory)); + +} // namespace +} // namespace webrtc diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 63b4f3f165..0c66af898c 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -1321,7 +1321,6 @@ if (rtc_include_tests) { ":rtc_base_tests_main", ":rtc_base_tests_utils", ":rtc_task_queue", - ":rtc_task_queue_for_test", "../test:test_support", "//third_party/abseil-cpp/absl/memory", ] diff --git a/rtc_base/task_queue_unittest.cc b/rtc_base/task_queue_unittest.cc index 9086206214..04861f348e 100644 --- a/rtc_base/task_queue_unittest.cc +++ b/rtc_base/task_queue_unittest.cc @@ -24,12 +24,9 @@ #include "rtc_base/bind.h" #include "rtc_base/event.h" #include "rtc_base/task_queue.h" -#include "rtc_base/task_queue_for_test.h" #include "rtc_base/time_utils.h" #include "test/gtest.h" -using rtc::test::TaskQueueForTest; - namespace rtc { namespace { @@ -60,89 +57,6 @@ void CheckCurrent(Event* signal, TaskQueue* queue) { } // namespace -TEST(TaskQueueTest, Construct) { - static const char kQueueName[] = "Construct"; - TaskQueue queue(kQueueName); - EXPECT_FALSE(queue.IsCurrent()); -} - -TEST(TaskQueueTest, PostAndCheckCurrent) { - static const char kQueueName[] = "PostAndCheckCurrent"; - Event event; - TaskQueue queue(kQueueName); - - // We're not running a task, so there shouldn't be a current queue. - EXPECT_FALSE(queue.IsCurrent()); - EXPECT_FALSE(TaskQueue::Current()); - - queue.PostTask(Bind(&CheckCurrent, &event, &queue)); - EXPECT_TRUE(event.Wait(1000)); -} - -TEST(TaskQueueTest, PostCustomTask) { - static const char kQueueName[] = "PostCustomImplementation"; - TaskQueueForTest queue(kQueueName); - - class CustomTask : public QueuedTask { - public: - CustomTask() {} - bool ran() const { return ran_; } - - private: - bool Run() override { - ran_ = true; - return false; // Never allow the task to be deleted by the queue. - } - - bool ran_ = false; - } my_task; - - queue.SendTask(&my_task); - EXPECT_TRUE(my_task.ran()); -} - -TEST(TaskQueueTest, PostLambda) { - TaskQueueForTest queue("PostLambda"); - bool ran = false; - queue.SendTask([&ran]() { ran = true; }); - EXPECT_TRUE(ran); -} - -TEST(TaskQueueTest, PostDelayedZero) { - static const char kQueueName[] = "PostDelayedZero"; - Event event; - TaskQueue queue(kQueueName); - - queue.PostDelayedTask([&event]() { event.Set(); }, 0); - EXPECT_TRUE(event.Wait(1000)); -} - -TEST(TaskQueueTest, PostFromQueue) { - static const char kQueueName[] = "PostFromQueue"; - Event event; - TaskQueue queue(kQueueName); - - queue.PostTask( - [&event, &queue]() { queue.PostTask([&event]() { event.Set(); }); }); - EXPECT_TRUE(event.Wait(1000)); -} - -TEST(TaskQueueTest, PostDelayed) { - static const char kQueueName[] = "PostDelayed"; - Event event; - TaskQueue queue(kQueueName, TaskQueue::Priority::HIGH); - - uint32_t start = Time(); - queue.PostDelayedTask(Bind(&CheckCurrent, &event, &queue), 100); - EXPECT_TRUE(event.Wait(1000)); - uint32_t end = Time(); - // 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. -} - // This task needs to be run manually due to the slowness of some of our bots. // TODO(tommi): Can we run this on the perf bots? TEST(TaskQueueTest, DISABLED_PostDelayedHighRes) { @@ -163,80 +77,13 @@ TEST(TaskQueueTest, DISABLED_PostDelayedHighRes) { EXPECT_NEAR(end - start, 3, 3u); } -TEST(TaskQueueTest, PostMultipleDelayed) { - static const char kQueueName[] = "PostMultipleDelayed"; - TaskQueue queue(kQueueName); - - std::vector> events; - for (int i = 0; i < 100; ++i) { - events.push_back(absl::make_unique()); - queue.PostDelayedTask(Bind(&CheckCurrent, events.back().get(), &queue), i); - } - - for (const auto& e : events) - EXPECT_TRUE(e->Wait(1000)); -} - -TEST(TaskQueueTest, PostDelayedAfterDestruct) { - static const char kQueueName[] = "PostDelayedAfterDestruct"; - Event run; - Event deleted; - { - TaskQueue queue(kQueueName); - queue.PostDelayedTask( - rtc::NewClosure([&run] { run.Set(); }, [&deleted] { deleted.Set(); }), - 100); - } - // 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(TaskQueueTest, PostAndReuse) { - static const char kPostQueue[] = "PostQueue"; - static const char kReplyQueue[] = "ReplyQueue"; - Event event; - TaskQueue post_queue(kPostQueue); - TaskQueue reply_queue(kReplyQueue); - - int call_count = 0; - - class ReusedTask : public QueuedTask { - public: - ReusedTask(int* counter, TaskQueue* reply_queue, Event* event) - : counter_(counter), reply_queue_(reply_queue), event_(event) { - EXPECT_EQ(0, *counter_); - } - - private: - bool Run() override { - if (++(*counter_) == 1) { - std::unique_ptr myself(this); - reply_queue_->PostTask(std::move(myself)); - // 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(2, *counter_); - EXPECT_TRUE(reply_queue_->IsCurrent()); - event_->Set(); - return true; // Indicate that the object should be deleted. - } - } - - int* const counter_; - TaskQueue* const reply_queue_; - Event* const event_; - }; - - std::unique_ptr task( - new ReusedTask(&call_count, &reply_queue, &event)); - - post_queue.PostTask(std::move(task)); - EXPECT_TRUE(event.Wait(1000)); +// TODO(danilchap): Reshape and rename tests below to show they are verifying +// rtc::NewClosure helper rather than TaskQueue implementation. +TEST(TaskQueueTest, PostLambda) { + TaskQueue queue("PostLambda"); + Event ran; + queue.PostTask([&ran] { ran.Set(); }); + EXPECT_TRUE(ran.Wait(1000)); } TEST(TaskQueueTest, PostCopyableClosure) { @@ -338,66 +185,4 @@ TEST(TaskQueueTest, PostMoveOnlyCleanup) { EXPECT_TRUE(event_run.Wait(0)); } -// Tests posting more messages than a queue can queue up. -// In situations like that, tasks will get dropped. -TEST(TaskQueueTest, PostALot) { - // To destruct the event after the queue has gone out of scope. - Event event; - - int tasks_executed = 0; - int tasks_cleaned_up = 0; - static const int kTaskCount = 0xffff; - - { - static const char kQueueName[] = "PostALot"; - TaskQueue queue(kQueueName); - - // 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([&event]() { event.Wait(Event::kForever); }); - for (int i = 0; i < kTaskCount; ++i) - queue.PostTask(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(kTaskCount, tasks_cleaned_up); -} - -// Test posting two tasks that have shared state not protected by a -// lock. The TaskQueue should guarantee memory read-write order and -// FIFO task execution order, so the second task should always see the -// changes that were made by the first task. -// -// If the TaskQueue doesn't properly synchronize the execution of -// tasks, there will be a data race, which is undefined behavior. The -// EXPECT calls may randomly catch this, but to make the most of this -// unit test, run it under TSan or some other tool that is able to -// directly detect data races. -TEST(TaskQueueTest, PostTwoWithSharedUnprotectedState) { - static const char kQueueName[] = "PostTwoWithSharedUnprotectedState"; - struct SharedState { - // First task will set this value to 1 and second will assert it. - int state = 0; - } state; - - TaskQueue queue(kQueueName); - rtc::Event done; - queue.PostTask([&state, &queue, &done] { - // Post tasks from queue to guarantee, that 1st task won't be - // executed before the second one will be posted. - queue.PostTask([&state] { state.state = 1; }); - queue.PostTask([&state, &done] { - EXPECT_EQ(state.state, 1); - done.Set(); - }); - // Check, that state changing tasks didn't start yet. - EXPECT_EQ(state.state, 0); - }); - EXPECT_TRUE(done.Wait(1000)); -} - } // namespace rtc