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 #include "webrtc/test/testsupport/gtest_disable.h"
20
21 using namespace rtc;
22
23 class MessageQueueTest: public testing::Test, public MessageQueue {
24 public:
IsLocked_Worker()25 bool IsLocked_Worker() {
26 if (!crit_.TryEnter()) {
27 return true;
28 }
29 crit_.Leave();
30 return false;
31 }
IsLocked()32 bool IsLocked() {
33 // We have to do this on a worker thread, or else the TryEnter will
34 // succeed, since our critical sections are reentrant.
35 Thread worker;
36 worker.Start();
37 return worker.Invoke<bool>(
38 rtc::Bind(&MessageQueueTest::IsLocked_Worker, this));
39 }
40 };
41
42 struct DeletedLockChecker {
DeletedLockCheckerDeletedLockChecker43 DeletedLockChecker(MessageQueueTest* test, bool* was_locked, bool* deleted)
44 : test(test), was_locked(was_locked), deleted(deleted) { }
~DeletedLockCheckerDeletedLockChecker45 ~DeletedLockChecker() {
46 *deleted = true;
47 *was_locked = test->IsLocked();
48 }
49 MessageQueueTest* test;
50 bool* was_locked;
51 bool* deleted;
52 };
53
DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(MessageQueue * q)54 static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
55 MessageQueue* q) {
56 EXPECT_TRUE(q != NULL);
57 TimeStamp now = Time();
58 q->PostAt(now, NULL, 3);
59 q->PostAt(now - 2, NULL, 0);
60 q->PostAt(now - 1, NULL, 1);
61 q->PostAt(now, NULL, 4);
62 q->PostAt(now - 1, NULL, 2);
63
64 Message msg;
65 for (size_t i=0; i<5; ++i) {
66 memset(&msg, 0, sizeof(msg));
67 EXPECT_TRUE(q->Get(&msg, 0));
68 EXPECT_EQ(i, msg.message_id);
69 }
70
71 EXPECT_FALSE(q->Get(&msg, 0)); // No more messages
72 }
73
TEST_F(MessageQueueTest,DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder)74 TEST_F(MessageQueueTest,
75 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
76 MessageQueue q;
77 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q);
78 NullSocketServer nullss;
79 MessageQueue q_nullss(&nullss);
80 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q_nullss);
81 }
82
TEST_F(MessageQueueTest,DISABLED_ON_MAC (DisposeNotLocked))83 TEST_F(MessageQueueTest, DISABLED_ON_MAC(DisposeNotLocked)) {
84 bool was_locked = true;
85 bool deleted = false;
86 DeletedLockChecker* d = new DeletedLockChecker(this, &was_locked, &deleted);
87 Dispose(d);
88 Message msg;
89 EXPECT_FALSE(Get(&msg, 0));
90 EXPECT_TRUE(deleted);
91 EXPECT_FALSE(was_locked);
92 }
93
94 class DeletedMessageHandler : public MessageHandler {
95 public:
DeletedMessageHandler(bool * deleted)96 explicit DeletedMessageHandler(bool* deleted) : deleted_(deleted) { }
~DeletedMessageHandler()97 ~DeletedMessageHandler() {
98 *deleted_ = true;
99 }
OnMessage(Message * msg)100 void OnMessage(Message* msg) { }
101 private:
102 bool* deleted_;
103 };
104
TEST_F(MessageQueueTest,DiposeHandlerWithPostedMessagePending)105 TEST_F(MessageQueueTest, DiposeHandlerWithPostedMessagePending) {
106 bool deleted = false;
107 DeletedMessageHandler *handler = new DeletedMessageHandler(&deleted);
108 // First, post a dispose.
109 Dispose(handler);
110 // Now, post a message, which should *not* be returned by Get().
111 Post(handler, 1);
112 Message msg;
113 EXPECT_FALSE(Get(&msg, 0));
114 EXPECT_TRUE(deleted);
115 }
116
117 struct UnwrapMainThreadScope {
UnwrapMainThreadScopeUnwrapMainThreadScope118 UnwrapMainThreadScope() : rewrap_(Thread::Current() != NULL) {
119 if (rewrap_) ThreadManager::Instance()->UnwrapCurrentThread();
120 }
~UnwrapMainThreadScopeUnwrapMainThreadScope121 ~UnwrapMainThreadScope() {
122 if (rewrap_) ThreadManager::Instance()->WrapCurrentThread();
123 }
124 private:
125 bool rewrap_;
126 };
127
TEST(MessageQueueManager,Clear)128 TEST(MessageQueueManager, Clear) {
129 UnwrapMainThreadScope s;
130 if (MessageQueueManager::IsInitialized()) {
131 LOG(LS_INFO) << "Unable to run MessageQueueManager::Clear test, since the "
132 << "MessageQueueManager was already initialized by some "
133 << "other test in this run.";
134 return;
135 }
136 bool deleted = false;
137 DeletedMessageHandler* handler = new DeletedMessageHandler(&deleted);
138 delete handler;
139 EXPECT_TRUE(deleted);
140 EXPECT_FALSE(MessageQueueManager::IsInitialized());
141 }
142