thread_wrapper_unittest.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/compiler_specific.h" 7#include "base/message_loop.h" 8#include "base/threading/thread.h" 9#include "jingle/glue/thread_wrapper.h" 10#include "testing/gmock/include/gmock/gmock.h" 11#include "testing/gtest/include/gtest/gtest.h" 12 13using ::testing::DoAll; 14using ::testing::InSequence; 15using ::testing::InvokeWithoutArgs; 16using ::testing::Mock; 17 18namespace jingle_glue { 19 20static const uint32 kTestMessage1 = 1; 21static const uint32 kTestMessage2 = 2; 22 23static const int kTestDelayMs1 = 10; 24static const int kTestDelayMs2 = 20; 25static const int kTestDelayMs3 = 30; 26static const int kTestDelayMs4 = 40; 27static const int kMaxTestDelay = 40; 28 29namespace { 30 31class MockMessageHandler : public talk_base::MessageHandler { 32 public: 33 MOCK_METHOD1(OnMessage, void(talk_base::Message* msg)); 34}; 35 36MATCHER_P3(MatchMessage, handler, message_id, data, "") { 37 return arg->phandler == handler && 38 arg->message_id == message_id && 39 arg->pdata == data; 40} 41 42ACTION(DeleteMessageData) { 43 delete arg0->pdata; 44} 45 46// Helper class used in the Dispose test. 47class DeletableObject { 48 public: 49 DeletableObject(bool* deleted) 50 : deleted_(deleted) { 51 *deleted = false; 52 } 53 54 ~DeletableObject() { 55 *deleted_ = true; 56 } 57 58 private: 59 bool* deleted_; 60}; 61 62} // namespace 63 64class ThreadWrapperTest : public testing::Test { 65 public: 66 // This method is used by the SendDuringSend test. It sends message to the 67 // main thread synchronously using Send(). 68 void PingMainThread() { 69 talk_base::MessageData* data = new talk_base::MessageData(); 70 MockMessageHandler handler; 71 72 EXPECT_CALL(handler, OnMessage( 73 MatchMessage(&handler, kTestMessage2, data))) 74 .WillOnce(DeleteMessageData()); 75 thread_->Send(&handler, kTestMessage2, data); 76 } 77 78 protected: 79 ThreadWrapperTest() 80 : thread_(NULL) { 81 } 82 83 virtual void SetUp() OVERRIDE { 84 JingleThreadWrapper::EnsureForCurrentMessageLoop(); 85 thread_ = talk_base::Thread::Current(); 86 } 87 88 // ThreadWrapper destroyes itself when |message_loop_| is destroyed. 89 MessageLoop message_loop_; 90 talk_base::Thread* thread_; 91 MockMessageHandler handler1_; 92 MockMessageHandler handler2_; 93}; 94 95TEST_F(ThreadWrapperTest, Post) { 96 talk_base::MessageData* data1 = new talk_base::MessageData(); 97 talk_base::MessageData* data2 = new talk_base::MessageData(); 98 talk_base::MessageData* data3 = new talk_base::MessageData(); 99 talk_base::MessageData* data4 = new talk_base::MessageData(); 100 101 thread_->Post(&handler1_, kTestMessage1, data1); 102 thread_->Post(&handler1_, kTestMessage2, data2); 103 thread_->Post(&handler2_, kTestMessage1, data3); 104 thread_->Post(&handler2_, kTestMessage1, data4); 105 106 InSequence in_seq; 107 108 EXPECT_CALL(handler1_, OnMessage( 109 MatchMessage(&handler1_, kTestMessage1, data1))) 110 .WillOnce(DeleteMessageData()); 111 EXPECT_CALL(handler1_, OnMessage( 112 MatchMessage(&handler1_, kTestMessage2, data2))) 113 .WillOnce(DeleteMessageData()); 114 EXPECT_CALL(handler2_, OnMessage( 115 MatchMessage(&handler2_, kTestMessage1, data3))) 116 .WillOnce(DeleteMessageData()); 117 EXPECT_CALL(handler2_, OnMessage( 118 MatchMessage(&handler2_, kTestMessage1, data4))) 119 .WillOnce(DeleteMessageData()); 120 121 message_loop_.RunAllPending(); 122} 123 124TEST_F(ThreadWrapperTest, PostDelayed) { 125 talk_base::MessageData* data1 = new talk_base::MessageData(); 126 talk_base::MessageData* data2 = new talk_base::MessageData(); 127 talk_base::MessageData* data3 = new talk_base::MessageData(); 128 talk_base::MessageData* data4 = new talk_base::MessageData(); 129 130 thread_->PostDelayed(kTestDelayMs1, &handler1_, kTestMessage1, data1); 131 thread_->PostDelayed(kTestDelayMs2, &handler1_, kTestMessage2, data2); 132 thread_->PostDelayed(kTestDelayMs3, &handler2_, kTestMessage1, data3); 133 thread_->PostDelayed(kTestDelayMs4, &handler2_, kTestMessage1, data4); 134 135 InSequence in_seq; 136 137 EXPECT_CALL(handler1_, OnMessage( 138 MatchMessage(&handler1_, kTestMessage1, data1))) 139 .WillOnce(DeleteMessageData()); 140 EXPECT_CALL(handler1_, OnMessage( 141 MatchMessage(&handler1_, kTestMessage2, data2))) 142 .WillOnce(DeleteMessageData()); 143 EXPECT_CALL(handler2_, OnMessage( 144 MatchMessage(&handler2_, kTestMessage1, data3))) 145 .WillOnce(DeleteMessageData()); 146 EXPECT_CALL(handler2_, OnMessage( 147 MatchMessage(&handler2_, kTestMessage1, data4))) 148 .WillOnce(DeleteMessageData()); 149 150 message_loop_.PostDelayedTask( 151 FROM_HERE, MessageLoop::QuitClosure(), 152 base::TimeDelta::FromMilliseconds(kMaxTestDelay)); 153 message_loop_.Run(); 154} 155 156TEST_F(ThreadWrapperTest, Clear) { 157 thread_->Post(&handler1_, kTestMessage1, NULL); 158 thread_->Post(&handler1_, kTestMessage2, NULL); 159 thread_->Post(&handler2_, kTestMessage1, NULL); 160 thread_->Post(&handler2_, kTestMessage2, NULL); 161 162 thread_->Clear(&handler1_, kTestMessage2); 163 164 InSequence in_seq; 165 166 talk_base::MessageData* null_data = NULL; 167 EXPECT_CALL(handler1_, OnMessage( 168 MatchMessage(&handler1_, kTestMessage1, null_data))) 169 .WillOnce(DeleteMessageData()); 170 EXPECT_CALL(handler2_, OnMessage( 171 MatchMessage(&handler2_, kTestMessage1, null_data))) 172 .WillOnce(DeleteMessageData()); 173 EXPECT_CALL(handler2_, OnMessage( 174 MatchMessage(&handler2_, kTestMessage2, null_data))) 175 .WillOnce(DeleteMessageData()); 176 177 message_loop_.RunAllPending(); 178} 179 180TEST_F(ThreadWrapperTest, ClearDelayed) { 181 thread_->PostDelayed(kTestDelayMs1, &handler1_, kTestMessage1, NULL); 182 thread_->PostDelayed(kTestDelayMs2, &handler1_, kTestMessage2, NULL); 183 thread_->PostDelayed(kTestDelayMs3, &handler2_, kTestMessage1, NULL); 184 thread_->PostDelayed(kTestDelayMs4, &handler2_, kTestMessage1, NULL); 185 186 thread_->Clear(&handler1_, kTestMessage2); 187 188 InSequence in_seq; 189 190 talk_base::MessageData* null_data = NULL; 191 EXPECT_CALL(handler1_, OnMessage( 192 MatchMessage(&handler1_, kTestMessage1, null_data))) 193 .WillOnce(DeleteMessageData()); 194 EXPECT_CALL(handler2_, OnMessage( 195 MatchMessage(&handler2_, kTestMessage1, null_data))) 196 .WillOnce(DeleteMessageData()); 197 EXPECT_CALL(handler2_, OnMessage( 198 MatchMessage(&handler2_, kTestMessage1, null_data))) 199 .WillOnce(DeleteMessageData()); 200 201 message_loop_.PostDelayedTask( 202 FROM_HERE, MessageLoop::QuitClosure(), 203 base::TimeDelta::FromMilliseconds(kMaxTestDelay)); 204 message_loop_.Run(); 205} 206 207// Verify that the queue is cleared when a handler is destroyed. 208TEST_F(ThreadWrapperTest, ClearDestoroyed) { 209 MockMessageHandler* handler_ptr; 210 { 211 MockMessageHandler handler; 212 handler_ptr = &handler; 213 thread_->Post(&handler, kTestMessage1, NULL); 214 } 215 talk_base::MessageList removed; 216 thread_->Clear(handler_ptr, talk_base::MQID_ANY, &removed); 217 DCHECK_EQ(0U, removed.size()); 218} 219 220// Verify that Send() calls handler synchronously when called on the 221// same thread. 222TEST_F(ThreadWrapperTest, SendSameThread) { 223 talk_base::MessageData* data = new talk_base::MessageData(); 224 225 EXPECT_CALL(handler1_, OnMessage( 226 MatchMessage(&handler1_, kTestMessage1, data))) 227 .WillOnce(DeleteMessageData()); 228 thread_->Send(&handler1_, kTestMessage1, data); 229} 230 231void InitializeWrapperForNewThread(talk_base::Thread** thread, 232 base::WaitableEvent* done_event) { 233 JingleThreadWrapper::EnsureForCurrentMessageLoop(); 234 JingleThreadWrapper::current()->set_send_allowed(true); 235 *thread = JingleThreadWrapper::current(); 236 done_event->Signal(); 237} 238 239// Verify that Send() calls handler synchronously when called for a 240// different thread. 241TEST_F(ThreadWrapperTest, SendToOtherThread) { 242 JingleThreadWrapper::current()->set_send_allowed(true); 243 244 base::Thread second_thread("JingleThreadWrapperTest"); 245 second_thread.Start(); 246 247 base::WaitableEvent initialized_event(true, false); 248 talk_base::Thread* target; 249 second_thread.message_loop()->PostTask( 250 FROM_HERE, base::Bind(&InitializeWrapperForNewThread, 251 &target, &initialized_event)); 252 initialized_event.Wait(); 253 254 ASSERT_TRUE(target != NULL); 255 256 talk_base::MessageData* data = new talk_base::MessageData(); 257 258 EXPECT_CALL(handler1_, OnMessage( 259 MatchMessage(&handler1_, kTestMessage1, data))) 260 .WillOnce(DeleteMessageData()); 261 target->Send(&handler1_, kTestMessage1, data); 262 263 Mock::VerifyAndClearExpectations(&handler1_); 264} 265 266// Verify that thread handles Send() while another Send() is 267// pending. The test creates second thread and Send()s kTestMessage1 268// to that thread. kTestMessage1 handler calls PingMainThread() which 269// tries to Send() kTestMessage2 to the main thread. 270TEST_F(ThreadWrapperTest, SendDuringSend) { 271 JingleThreadWrapper::current()->set_send_allowed(true); 272 273 base::Thread second_thread("JingleThreadWrapperTest"); 274 second_thread.Start(); 275 276 base::WaitableEvent initialized_event(true, false); 277 talk_base::Thread* target; 278 second_thread.message_loop()->PostTask( 279 FROM_HERE, base::Bind(&InitializeWrapperForNewThread, 280 &target, &initialized_event)); 281 initialized_event.Wait(); 282 283 ASSERT_TRUE(target != NULL); 284 285 talk_base::MessageData* data = new talk_base::MessageData(); 286 287 EXPECT_CALL(handler1_, OnMessage( 288 MatchMessage(&handler1_, kTestMessage1, data))) 289 .WillOnce(DoAll( 290 InvokeWithoutArgs( 291 this, &ThreadWrapperTest::PingMainThread), 292 DeleteMessageData())); 293 target->Send(&handler1_, kTestMessage1, data); 294 295 Mock::VerifyAndClearExpectations(&handler1_); 296} 297 298TEST_F(ThreadWrapperTest, Dispose) { 299 bool deleted_; 300 thread_->Dispose(new DeletableObject(&deleted_)); 301 EXPECT_FALSE(deleted_); 302 message_loop_.RunAllPending(); 303 EXPECT_TRUE(deleted_); 304} 305 306} // namespace jingle_glue 307