1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/base/messagequeue.h" 12 13 #include "webrtc/base/bind.h" 14 #include "webrtc/base/gunit.h" 15 #include "webrtc/base/logging.h" 16 #include "webrtc/base/thread.h" 17 #include "webrtc/base/timeutils.h" 18 #include "webrtc/base/nullsocketserver.h" 19 20 using namespace rtc; 21 22 class MessageQueueTest: public testing::Test, public MessageQueue { 23 public: 24 bool IsLocked_Worker() { 25 if (!crit_.TryEnter()) { 26 return true; 27 } 28 crit_.Leave(); 29 return false; 30 } 31 bool IsLocked() { 32 // We have to do this on a worker thread, or else the TryEnter will 33 // succeed, since our critical sections are reentrant. 34 Thread worker; 35 worker.Start(); 36 return worker.Invoke<bool>( 37 rtc::Bind(&MessageQueueTest::IsLocked_Worker, this)); 38 } 39 }; 40 41 struct DeletedLockChecker { 42 DeletedLockChecker(MessageQueueTest* test, bool* was_locked, bool* deleted) 43 : test(test), was_locked(was_locked), deleted(deleted) { } 44 ~DeletedLockChecker() { 45 *deleted = true; 46 *was_locked = test->IsLocked(); 47 } 48 MessageQueueTest* test; 49 bool* was_locked; 50 bool* deleted; 51 }; 52 53 static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder( 54 MessageQueue* q) { 55 EXPECT_TRUE(q != NULL); 56 TimeStamp now = Time(); 57 q->PostAt(now, NULL, 3); 58 q->PostAt(now - 2, NULL, 0); 59 q->PostAt(now - 1, NULL, 1); 60 q->PostAt(now, NULL, 4); 61 q->PostAt(now - 1, NULL, 2); 62 63 Message msg; 64 for (size_t i=0; i<5; ++i) { 65 memset(&msg, 0, sizeof(msg)); 66 EXPECT_TRUE(q->Get(&msg, 0)); 67 EXPECT_EQ(i, msg.message_id); 68 } 69 70 EXPECT_FALSE(q->Get(&msg, 0)); // No more messages 71 } 72 73 TEST_F(MessageQueueTest, 74 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) { 75 MessageQueue q; 76 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q); 77 NullSocketServer nullss; 78 MessageQueue q_nullss(&nullss); 79 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q_nullss); 80 } 81 82 TEST_F(MessageQueueTest, DisposeNotLocked) { 83 bool was_locked = true; 84 bool deleted = false; 85 DeletedLockChecker* d = new DeletedLockChecker(this, &was_locked, &deleted); 86 Dispose(d); 87 Message msg; 88 EXPECT_FALSE(Get(&msg, 0)); 89 EXPECT_TRUE(deleted); 90 EXPECT_FALSE(was_locked); 91 } 92 93 class DeletedMessageHandler : public MessageHandler { 94 public: 95 explicit DeletedMessageHandler(bool* deleted) : deleted_(deleted) { } 96 ~DeletedMessageHandler() { 97 *deleted_ = true; 98 } 99 void OnMessage(Message* msg) { } 100 private: 101 bool* deleted_; 102 }; 103 104 TEST_F(MessageQueueTest, DiposeHandlerWithPostedMessagePending) { 105 bool deleted = false; 106 DeletedMessageHandler *handler = new DeletedMessageHandler(&deleted); 107 // First, post a dispose. 108 Dispose(handler); 109 // Now, post a message, which should *not* be returned by Get(). 110 Post(handler, 1); 111 Message msg; 112 EXPECT_FALSE(Get(&msg, 0)); 113 EXPECT_TRUE(deleted); 114 } 115 116 struct UnwrapMainThreadScope { 117 UnwrapMainThreadScope() : rewrap_(Thread::Current() != NULL) { 118 if (rewrap_) ThreadManager::Instance()->UnwrapCurrentThread(); 119 } 120 ~UnwrapMainThreadScope() { 121 if (rewrap_) ThreadManager::Instance()->WrapCurrentThread(); 122 } 123 private: 124 bool rewrap_; 125 }; 126 127 TEST(MessageQueueManager, Clear) { 128 UnwrapMainThreadScope s; 129 if (MessageQueueManager::IsInitialized()) { 130 LOG(LS_INFO) << "Unable to run MessageQueueManager::Clear test, since the " 131 << "MessageQueueManager was already initialized by some " 132 << "other test in this run."; 133 return; 134 } 135 bool deleted = false; 136 DeletedMessageHandler* handler = new DeletedMessageHandler(&deleted); 137 delete handler; 138 EXPECT_TRUE(deleted); 139 EXPECT_FALSE(MessageQueueManager::IsInitialized()); 140 } 141