Index: webrtc/base/sequenced_task_checker_unittest.cc |
diff --git a/webrtc/base/sequenced_task_checker_unittest.cc b/webrtc/base/sequenced_task_checker_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ad51603615eba2a81dab705c0f02eacbc9382990 |
--- /dev/null |
+++ b/webrtc/base/sequenced_task_checker_unittest.cc |
@@ -0,0 +1,224 @@ |
+/* |
+ * Copyright (c) 2016 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. |
+ */ |
+ |
+// Borrowed from Chromium's src/base/threading/thread_checker_unittest.cc. |
+ |
+#include <memory> |
+ |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "webrtc/base/checks.h" |
+#include "webrtc/base/constructormagic.h" |
+#include "webrtc/base/sequenced_task_checker.h" |
+#include "webrtc/base/task_queue.h" |
+#include "webrtc/base/thread.h" |
+ |
+namespace rtc { |
+ |
+namespace { |
+// Calls SequencedCheckerClass::PlatformThread on another thread. |
+class CallDoStuffOnThread : public PlatformThread { |
tommi
2016/07/12 13:08:56
instead of inheriting from PlatformThread, add a m
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ public: |
+ explicit CallDoStuffOnThread(bool expect_true, |
tommi
2016/07/12 13:08:56
no need for explicit (2 args)
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ SequencedTaskChecker* sequenced_task_checker) |
+ : PlatformThread(Run, this, "call_do_stuff_on_thread"), |
tommi
2016/07/12 13:08:56
&Run
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ expect_true_(expect_true), |
+ sequenced_task_checker_(sequenced_task_checker) {} |
+ |
+ static bool Run(void* obj) { |
tommi
2016/07/12 13:08:56
make private
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ CallDoStuffOnThread* call_stuff_on_thread = |
+ static_cast<CallDoStuffOnThread*>(obj); |
+ if (call_stuff_on_thread->expect_true_) |
tommi
2016/07/12 13:08:56
{}
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ EXPECT_TRUE( |
tommi
2016/07/12 13:08:56
could also do:
EXPECT_EQ(call_stuff_on_thread->ex
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ call_stuff_on_thread->sequenced_task_checker_->CalledSequentially()); |
+ else |
+ EXPECT_FALSE( |
+ call_stuff_on_thread->sequenced_task_checker_->CalledSequentially()); |
+ return false; |
+ } |
+ |
+ private: |
+ const bool expect_true_; |
+ SequencedTaskChecker* const sequenced_task_checker_; |
+ |
+ RTC_DISALLOW_COPY_AND_ASSIGN(CallDoStuffOnThread); |
+}; |
+ |
+// Deletes SequencedTaskChecker on a different thread. |
+class DeleteThreadCheckerOnThread : public PlatformThread { |
tommi
2016/07/12 13:08:56
Favor object composition over class inheritance.
(
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ public: |
+ explicit DeleteThreadCheckerOnThread( |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker) |
+ : PlatformThread(Run, this, "delete_sequenced_task_checker_on_thread"), |
tommi
2016/07/12 13:08:56
&Run
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ sequenced_task_checker_(std::move(sequenced_task_checker)) {} |
+ |
+ static bool Run(void* obj) { |
tommi
2016/07/12 13:08:56
private (etc)
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ static_cast<DeleteThreadCheckerOnThread*>(obj) |
+ ->sequenced_task_checker_.reset(); |
+ return false; |
+ } |
+ |
+ private: |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker_; |
+ |
+ RTC_DISALLOW_COPY_AND_ASSIGN(DeleteThreadCheckerOnThread); |
+}; |
+ |
+void RunMethodOnDifferentThread(bool expect_true) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ CallDoStuffOnThread call_on_thread(expect_true, sequenced_task_checker.get()); |
+ |
+ call_on_thread.Start(); |
tommi
2016/07/12 13:08:56
Start/Stop could occur implicitly in the ctor/dtor
perkj_webrtc
2016/07/12 15:22:00
Done.
|
+ call_on_thread.Stop(); |
+} |
+ |
+void RunMethodOnDifferentTaskQueue(bool expect_true) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ static const char kQueueName[] = "MethodNotAllowedOnDifferentTq"; |
+ TaskQueue queue(kQueueName); |
+ Event done_event(false, false); |
+ queue.PostTask([&sequenced_task_checker, &done_event, expect_true] { |
+ if (expect_true) |
+ EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); |
+ else |
+ EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); |
+ done_event.Set(); |
+ }); |
+ EXPECT_TRUE(done_event.Wait(1000)); |
+} |
+ |
+void DetachThenCallFromDifferentTaskQueue(bool expect_true) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ sequenced_task_checker->Detach(); |
+ |
+ Event done_event(false, false); |
+ TaskQueue queue1("DetachThenCallFromDifferentTaskQueueImpl1"); |
+ queue1.PostTask([&sequenced_task_checker, &done_event] { |
+ EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); |
+ done_event.Set(); |
+ }); |
+ EXPECT_TRUE(done_event.Wait(1000)); |
+ |
+ // CalledSequentially should return false in debug builds after moving to |
+ // another task queue. |
+ TaskQueue queue2("DetachThenCallFromDifferentTaskQueueImpl2"); |
+ queue2.PostTask([&sequenced_task_checker, &done_event, expect_true] { |
+ if (expect_true) |
+ EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); |
+ else |
+ EXPECT_FALSE(sequenced_task_checker->CalledSequentially()); |
+ done_event.Set(); |
+ }); |
+ done_event.Wait(1000); |
+} |
+} // namespace |
+ |
+TEST(SequencedTaskCheckerTest, CallsAllowedOnSameThread) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); |
+ |
+ // Verify that the destructor doesn't assert. |
+ sequenced_task_checker.reset(); |
+} |
+ |
+TEST(SequencedTaskCheckerTest, DestructorAllowedOnDifferentThread) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ // Verify that the destructor doesn't assert when called on a different |
+ // thread. |
+ DeleteThreadCheckerOnThread delete_on_thread( |
+ std::move(sequenced_task_checker)); |
+ |
+ delete_on_thread.Start(); |
+ delete_on_thread.Stop(); |
+} |
+ |
+TEST(SequencedTaskCheckerTest, DetachFromThread) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ sequenced_task_checker->Detach(); |
+ CallDoStuffOnThread call_on_thread(true, sequenced_task_checker.get()); |
+ |
+ call_on_thread.Start(); |
+ call_on_thread.Stop(); |
+} |
+ |
+TEST(SequencedTaskCheckerTest, DetachFromThreadAndUseOnTaskQueue) { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ sequenced_task_checker->Detach(); |
+ static const char kQueueName[] = "DetachFromThreadAndUseOnTaskQueue"; |
+ TaskQueue queue(kQueueName); |
+ Event done_event(false, false); |
+ queue.PostTask([&sequenced_task_checker, &done_event] { |
+ EXPECT_TRUE(sequenced_task_checker->CalledSequentially()); |
+ done_event.Set(); |
+ }); |
+ EXPECT_TRUE(done_event.Wait(1000)); |
+} |
+ |
+TEST(SequencedTaskCheckerTest, DetachFromTaskQueueAndUseOnThread) { |
+ TaskQueue queue("DetachFromTaskQueueAndUseOnThread"); |
+ Event done_event(false, false); |
+ queue.PostTask([&done_event] { |
+ std::unique_ptr<SequencedTaskChecker> sequenced_task_checker( |
+ new SequencedTaskChecker()); |
+ |
+ sequenced_task_checker->Detach(); |
+ CallDoStuffOnThread call_on_thread(true, sequenced_task_checker.get()); |
+ |
+ call_on_thread.Start(); |
+ call_on_thread.Stop(); |
+ |
+ done_event.Set(); |
+ }); |
+ EXPECT_TRUE(done_event.Wait(1000)); |
+} |
+ |
+#if !NDEBUG || DCHECK_ALWAYS_ON |
+TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentThreadInDebug) { |
+ RunMethodOnDifferentThread(false); |
+} |
+#else |
+TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentThreadInRelease) { |
+ RunMethodOnDifferentThread(true); |
+} |
+#endif |
+ |
+#if !NDEBUG || DCHECK_ALWAYS_ON |
+TEST(SequencedTaskCheckerTest, MethodNotAllowedOnDifferentTaskQueueInDebug) { |
+ RunMethodOnDifferentTaskQueue(false); |
+} |
+#else |
+TEST(SequencedTaskCheckerTest, MethodAllowedOnDifferentTaskQueueInDebug) { |
+ RunMethodOnDifferentTaskQueue(true); |
+} |
+#endif |
+ |
+#if !NDEBUG || DCHECK_ALWAYS_ON |
+TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInDebug) { |
+ DetachThenCallFromDifferentTaskQueue(false); |
+} |
+#else |
+TEST(SequencedTaskCheckerTest, DetachFromTaskQueueInRelease) { |
+ DetachThenCallFromDifferentTaskQueue(true); |
+} |
+#endif |
+} // namespace rtc |