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/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 base::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_.RunUntilIdle(); 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, 152 base::MessageLoop::QuitClosure(), 153 base::TimeDelta::FromMilliseconds(kMaxTestDelay)); 154 message_loop_.Run(); 155} 156 157TEST_F(ThreadWrapperTest, Clear) { 158 thread_->Post(&handler1_, kTestMessage1, NULL); 159 thread_->Post(&handler1_, kTestMessage2, NULL); 160 thread_->Post(&handler2_, kTestMessage1, NULL); 161 thread_->Post(&handler2_, kTestMessage2, NULL); 162 163 thread_->Clear(&handler1_, kTestMessage2); 164 165 InSequence in_seq; 166 167 talk_base::MessageData* null_data = NULL; 168 EXPECT_CALL(handler1_, OnMessage( 169 MatchMessage(&handler1_, kTestMessage1, null_data))) 170 .WillOnce(DeleteMessageData()); 171 EXPECT_CALL(handler2_, OnMessage( 172 MatchMessage(&handler2_, kTestMessage1, null_data))) 173 .WillOnce(DeleteMessageData()); 174 EXPECT_CALL(handler2_, OnMessage( 175 MatchMessage(&handler2_, kTestMessage2, null_data))) 176 .WillOnce(DeleteMessageData()); 177 178 message_loop_.RunUntilIdle(); 179} 180 181TEST_F(ThreadWrapperTest, ClearDelayed) { 182 thread_->PostDelayed(kTestDelayMs1, &handler1_, kTestMessage1, NULL); 183 thread_->PostDelayed(kTestDelayMs2, &handler1_, kTestMessage2, NULL); 184 thread_->PostDelayed(kTestDelayMs3, &handler2_, kTestMessage1, NULL); 185 thread_->PostDelayed(kTestDelayMs4, &handler2_, kTestMessage1, NULL); 186 187 thread_->Clear(&handler1_, kTestMessage2); 188 189 InSequence in_seq; 190 191 talk_base::MessageData* null_data = NULL; 192 EXPECT_CALL(handler1_, OnMessage( 193 MatchMessage(&handler1_, kTestMessage1, null_data))) 194 .WillOnce(DeleteMessageData()); 195 EXPECT_CALL(handler2_, OnMessage( 196 MatchMessage(&handler2_, kTestMessage1, null_data))) 197 .WillOnce(DeleteMessageData()); 198 EXPECT_CALL(handler2_, OnMessage( 199 MatchMessage(&handler2_, kTestMessage1, null_data))) 200 .WillOnce(DeleteMessageData()); 201 202 message_loop_.PostDelayedTask( 203 FROM_HERE, 204 base::MessageLoop::QuitClosure(), 205 base::TimeDelta::FromMilliseconds(kMaxTestDelay)); 206 message_loop_.Run(); 207} 208 209// Verify that the queue is cleared when a handler is destroyed. 210TEST_F(ThreadWrapperTest, ClearDestoroyed) { 211 MockMessageHandler* handler_ptr; 212 { 213 MockMessageHandler handler; 214 handler_ptr = &handler; 215 thread_->Post(&handler, kTestMessage1, NULL); 216 } 217 talk_base::MessageList removed; 218 thread_->Clear(handler_ptr, talk_base::MQID_ANY, &removed); 219 DCHECK_EQ(0U, removed.size()); 220} 221 222// Verify that Send() calls handler synchronously when called on the 223// same thread. 224TEST_F(ThreadWrapperTest, SendSameThread) { 225 talk_base::MessageData* data = new talk_base::MessageData(); 226 227 EXPECT_CALL(handler1_, OnMessage( 228 MatchMessage(&handler1_, kTestMessage1, data))) 229 .WillOnce(DeleteMessageData()); 230 thread_->Send(&handler1_, kTestMessage1, data); 231} 232 233void InitializeWrapperForNewThread(talk_base::Thread** thread, 234 base::WaitableEvent* done_event) { 235 JingleThreadWrapper::EnsureForCurrentMessageLoop(); 236 JingleThreadWrapper::current()->set_send_allowed(true); 237 *thread = JingleThreadWrapper::current(); 238 done_event->Signal(); 239} 240 241// Verify that Send() calls handler synchronously when called for a 242// different thread. 243TEST_F(ThreadWrapperTest, SendToOtherThread) { 244 JingleThreadWrapper::current()->set_send_allowed(true); 245 246 base::Thread second_thread("JingleThreadWrapperTest"); 247 second_thread.Start(); 248 249 base::WaitableEvent initialized_event(true, false); 250 talk_base::Thread* target; 251 second_thread.message_loop()->PostTask( 252 FROM_HERE, base::Bind(&InitializeWrapperForNewThread, 253 &target, &initialized_event)); 254 initialized_event.Wait(); 255 256 ASSERT_TRUE(target != NULL); 257 258 talk_base::MessageData* data = new talk_base::MessageData(); 259 260 EXPECT_CALL(handler1_, OnMessage( 261 MatchMessage(&handler1_, kTestMessage1, data))) 262 .WillOnce(DeleteMessageData()); 263 target->Send(&handler1_, kTestMessage1, data); 264 265 Mock::VerifyAndClearExpectations(&handler1_); 266} 267 268// Verify that thread handles Send() while another Send() is 269// pending. The test creates second thread and Send()s kTestMessage1 270// to that thread. kTestMessage1 handler calls PingMainThread() which 271// tries to Send() kTestMessage2 to the main thread. 272TEST_F(ThreadWrapperTest, SendDuringSend) { 273 JingleThreadWrapper::current()->set_send_allowed(true); 274 275 base::Thread second_thread("JingleThreadWrapperTest"); 276 second_thread.Start(); 277 278 base::WaitableEvent initialized_event(true, false); 279 talk_base::Thread* target; 280 second_thread.message_loop()->PostTask( 281 FROM_HERE, base::Bind(&InitializeWrapperForNewThread, 282 &target, &initialized_event)); 283 initialized_event.Wait(); 284 285 ASSERT_TRUE(target != NULL); 286 287 talk_base::MessageData* data = new talk_base::MessageData(); 288 289 EXPECT_CALL(handler1_, OnMessage( 290 MatchMessage(&handler1_, kTestMessage1, data))) 291 .WillOnce(DoAll( 292 InvokeWithoutArgs( 293 this, &ThreadWrapperTest::PingMainThread), 294 DeleteMessageData())); 295 target->Send(&handler1_, kTestMessage1, data); 296 297 Mock::VerifyAndClearExpectations(&handler1_); 298} 299 300TEST_F(ThreadWrapperTest, Dispose) { 301 bool deleted_; 302 thread_->Dispose(new DeletableObject(&deleted_)); 303 EXPECT_FALSE(deleted_); 304 message_loop_.RunUntilIdle(); 305 EXPECT_TRUE(deleted_); 306} 307 308} // namespace jingle_glue 309