123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/webrtc/thread_wrapper.h"
- #include <stdint.h>
- #include "base/bind.h"
- #include "base/compiler_specific.h"
- #include "base/memory/raw_ptr.h"
- #include "base/run_loop.h"
- #include "base/synchronization/waitable_event.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/task/thread_pool.h"
- #include "base/test/task_environment.h"
- #include "base/threading/thread.h"
- #include "testing/gmock/include/gmock/gmock.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "third_party/webrtc_overrides/metronome_source.h"
- #include "third_party/webrtc_overrides/test/metronome_like_task_queue_test.h"
- using ::blink::MetronomeLikeTaskQueueTest;
- using ::testing::DoAll;
- using ::testing::InSequence;
- using ::testing::InvokeWithoutArgs;
- using ::testing::Mock;
- namespace webrtc {
- static const uint32_t kTestMessage1 = 1;
- static const uint32_t kTestMessage2 = 2;
- static const int kTestDelayMs1 = 10;
- static const int kTestDelayMs2 = 20;
- static const int kTestDelayMs3 = 30;
- static const int kTestDelayMs4 = 40;
- static const int kMaxTestDelay = 40;
- namespace {
- class MockMessageHandler : public rtc::MessageHandlerAutoCleanup {
- public:
- MOCK_METHOD1(OnMessage, void(rtc::Message* msg));
- };
- MATCHER_P3(MatchMessage, handler, message_id, data, "") {
- return arg->phandler == handler && arg->message_id == message_id &&
- arg->pdata == data;
- }
- ACTION(DeleteMessageData) {
- delete arg0->pdata;
- }
- // Helper class used in the Dispose test.
- class DeletableObject {
- public:
- DeletableObject(bool* deleted) : deleted_(deleted) { *deleted = false; }
- ~DeletableObject() { *deleted_ = true; }
- private:
- raw_ptr<bool> deleted_;
- };
- class ThreadWrapperTest : public testing::Test {
- public:
- // This method is used by the SendDuringSend test. It sends message to the
- // main thread synchronously using Send().
- void PingMainThread() {
- rtc::MessageData* data = new rtc::MessageData();
- MockMessageHandler handler;
- EXPECT_CALL(handler, OnMessage(MatchMessage(&handler, kTestMessage2, data)))
- .WillOnce(DeleteMessageData());
- thread_->Send(RTC_FROM_HERE, &handler, kTestMessage2, data);
- }
- protected:
- ThreadWrapperTest() : thread_(nullptr) {}
- void SetUp() override {
- ThreadWrapper::EnsureForCurrentMessageLoop();
- thread_ = rtc::Thread::Current();
- }
- // ThreadWrapper destroys itself when |message_loop_| is destroyed.
- base::test::SingleThreadTaskEnvironment task_environment_;
- raw_ptr<rtc::Thread> thread_;
- MockMessageHandler handler1_;
- MockMessageHandler handler2_;
- };
- TEST_F(ThreadWrapperTest, Post) {
- rtc::MessageData* data1 = new rtc::MessageData();
- rtc::MessageData* data2 = new rtc::MessageData();
- rtc::MessageData* data3 = new rtc::MessageData();
- rtc::MessageData* data4 = new rtc::MessageData();
- thread_->Post(RTC_FROM_HERE, &handler1_, kTestMessage1, data1);
- thread_->Post(RTC_FROM_HERE, &handler1_, kTestMessage2, data2);
- thread_->Post(RTC_FROM_HERE, &handler2_, kTestMessage1, data3);
- thread_->Post(RTC_FROM_HERE, &handler2_, kTestMessage1, data4);
- InSequence in_seq;
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, data1)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage2, data2)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, data3)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, data4)))
- .WillOnce(DeleteMessageData());
- base::RunLoop().RunUntilIdle();
- }
- TEST_F(ThreadWrapperTest, PostDelayed) {
- rtc::MessageData* data1 = new rtc::MessageData();
- rtc::MessageData* data2 = new rtc::MessageData();
- rtc::MessageData* data3 = new rtc::MessageData();
- rtc::MessageData* data4 = new rtc::MessageData();
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs1, &handler1_, kTestMessage1,
- data1);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs2, &handler1_, kTestMessage2,
- data2);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs3, &handler2_, kTestMessage1,
- data3);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs4, &handler2_, kTestMessage1,
- data4);
- InSequence in_seq;
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, data1)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage2, data2)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, data3)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, data4)))
- .WillOnce(DeleteMessageData());
- base::RunLoop run_loop;
- task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(kMaxTestDelay));
- run_loop.Run();
- }
- TEST_F(ThreadWrapperTest, Clear) {
- thread_->Post(RTC_FROM_HERE, &handler1_, kTestMessage1, NULL);
- thread_->Post(RTC_FROM_HERE, &handler1_, kTestMessage2, NULL);
- thread_->Post(RTC_FROM_HERE, &handler2_, kTestMessage1, NULL);
- thread_->Post(RTC_FROM_HERE, &handler2_, kTestMessage2, NULL);
- thread_->Clear(&handler1_, kTestMessage2);
- InSequence in_seq;
- rtc::MessageData* null_data = NULL;
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, null_data)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, null_data)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage2, null_data)))
- .WillOnce(DeleteMessageData());
- base::RunLoop().RunUntilIdle();
- }
- TEST_F(ThreadWrapperTest, ClearDelayed) {
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs1, &handler1_, kTestMessage1,
- NULL);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs2, &handler1_, kTestMessage2,
- NULL);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs3, &handler2_, kTestMessage1,
- NULL);
- thread_->PostDelayed(RTC_FROM_HERE, kTestDelayMs4, &handler2_, kTestMessage1,
- NULL);
- thread_->Clear(&handler1_, kTestMessage2);
- InSequence in_seq;
- rtc::MessageData* null_data = NULL;
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, null_data)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, null_data)))
- .WillOnce(DeleteMessageData());
- EXPECT_CALL(handler2_,
- OnMessage(MatchMessage(&handler2_, kTestMessage1, null_data)))
- .WillOnce(DeleteMessageData());
- base::RunLoop run_loop;
- task_environment_.GetMainThreadTaskRunner()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(kMaxTestDelay));
- run_loop.Run();
- }
- // Verify that the queue is cleared when a handler is destroyed.
- TEST_F(ThreadWrapperTest, ClearDestroyed) {
- MockMessageHandler* handler_ptr;
- {
- MockMessageHandler handler;
- handler_ptr = &handler;
- thread_->Post(RTC_FROM_HERE, &handler, kTestMessage1, NULL);
- }
- rtc::MessageList removed;
- thread_->Clear(handler_ptr, rtc::MQID_ANY, &removed);
- DCHECK_EQ(0U, removed.size());
- }
- // Verify that Send() calls handler synchronously when called on the
- // same thread.
- TEST_F(ThreadWrapperTest, SendSameThread) {
- rtc::MessageData* data = new rtc::MessageData();
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, data)))
- .WillOnce(DeleteMessageData());
- thread_->Send(RTC_FROM_HERE, &handler1_, kTestMessage1, data);
- }
- void InitializeWrapperForNewThread(rtc::Thread** thread,
- base::WaitableEvent* done_event) {
- ThreadWrapper::EnsureForCurrentMessageLoop();
- ThreadWrapper::current()->set_send_allowed(true);
- *thread = ThreadWrapper::current();
- done_event->Signal();
- }
- // Verify that Send() calls handler synchronously when called for a
- // different thread.
- TEST_F(ThreadWrapperTest, SendToOtherThread) {
- ThreadWrapper::current()->set_send_allowed(true);
- base::Thread second_thread("adWrapperTest");
- second_thread.Start();
- base::WaitableEvent initialized_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- rtc::Thread* target;
- second_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&InitializeWrapperForNewThread, &target,
- &initialized_event));
- initialized_event.Wait();
- ASSERT_TRUE(target != NULL);
- rtc::MessageData* data = new rtc::MessageData();
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, data)))
- .WillOnce(DeleteMessageData());
- target->Send(RTC_FROM_HERE, &handler1_, kTestMessage1, data);
- Mock::VerifyAndClearExpectations(&handler1_);
- }
- // Verify that thread handles Send() while another Send() is
- // pending. The test creates second thread and Send()s kTestMessage1
- // to that thread. kTestMessage1 handler calls PingMainThread() which
- // tries to Send() kTestMessage2 to the main thread.
- TEST_F(ThreadWrapperTest, SendDuringSend) {
- ThreadWrapper::current()->set_send_allowed(true);
- base::Thread second_thread("adWrapperTest");
- second_thread.Start();
- base::WaitableEvent initialized_event(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- rtc::Thread* target;
- second_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&InitializeWrapperForNewThread, &target,
- &initialized_event));
- initialized_event.Wait();
- ASSERT_TRUE(target != NULL);
- rtc::MessageData* data = new rtc::MessageData();
- EXPECT_CALL(handler1_,
- OnMessage(MatchMessage(&handler1_, kTestMessage1, data)))
- .WillOnce(
- DoAll(InvokeWithoutArgs(this, &ThreadWrapperTest::PingMainThread),
- DeleteMessageData()));
- target->Send(RTC_FROM_HERE, &handler1_, kTestMessage1, data);
- Mock::VerifyAndClearExpectations(&handler1_);
- }
- TEST_F(ThreadWrapperTest, Dispose) {
- bool deleted_ = false;
- thread_->Dispose(new DeletableObject(&deleted_));
- EXPECT_FALSE(deleted_);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(deleted_);
- }
- // Provider needed for the MetronomeLikeTaskQueueTest suite.
- class ThreadWrapperProvider : public blink::MetronomeLikeTaskQueueProvider {
- public:
- void Initialize() override {
- ThreadWrapper::EnsureForCurrentMessageLoop();
- thread_ = rtc::Thread::Current();
- }
- base::TimeDelta DeltaToNextTick() const override {
- base::TimeTicks now = base::TimeTicks::Now();
- return blink::MetronomeSource::TimeSnappedToNextTick(now) - now;
- }
- base::TimeDelta MetronomeTick() const override {
- return blink::MetronomeSource::Tick();
- }
- webrtc::TaskQueueBase* TaskQueue() const override { return thread_; }
- private:
- // ThreadWrapper destroys itself when |message_loop_| is destroyed.
- raw_ptr<rtc::Thread> thread_;
- };
- // Instantiate suite to run all tests defined in
- // third_party/webrtc_overrides/test/metronome_like_task_queue_test.h
- INSTANTIATE_TEST_SUITE_P(
- ThreadWrapper,
- MetronomeLikeTaskQueueTest,
- ::testing::Values(std::make_unique<ThreadWrapperProvider>));
- } // namespace
- } // namespace webrtc
|