blob: ac9affece59c13514edc34f1844071db652baba6 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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"
henrike@webrtc.orgfded02c2014-09-19 13:10:10 +000019#include "webrtc/test/testsupport/gtest_disable.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000020
21using namespace rtc;
22
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000023class MessageQueueForTest : public MessageQueue {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000024 public:
25 bool IsLocked_Worker() {
26 if (!crit_.TryEnter()) {
27 return true;
28 }
29 crit_.Leave();
30 return false;
31 }
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000032
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033 bool IsLocked() {
34 // We have to do this on a worker thread, or else the TryEnter will
35 // succeed, since our critical sections are reentrant.
36 Thread worker;
37 worker.Start();
38 return worker.Invoke<bool>(
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000039 rtc::Bind(&MessageQueueForTest::IsLocked_Worker, this));
40 }
41
42 size_t GetDmsgqSize() {
43 return dmsgq_.size();
44 }
45
46 const DelayedMessage& GetDmsgqTop() {
47 return dmsgq_.top();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000048 }
49};
50
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000051class MessageQueueTest : public testing::Test {
52 protected:
53 MessageQueueForTest q_;
54};
55
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000056struct DeletedLockChecker {
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000057 DeletedLockChecker(MessageQueueForTest* q, bool* was_locked, bool* deleted)
58 : q_(q), was_locked(was_locked), deleted(deleted) { }
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000059 ~DeletedLockChecker() {
60 *deleted = true;
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000061 *was_locked = q_->IsLocked();
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000062 }
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000063 MessageQueueForTest* q_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000064 bool* was_locked;
65 bool* deleted;
66};
67
68static void DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(
69 MessageQueue* q) {
70 EXPECT_TRUE(q != NULL);
71 TimeStamp now = Time();
72 q->PostAt(now, NULL, 3);
73 q->PostAt(now - 2, NULL, 0);
74 q->PostAt(now - 1, NULL, 1);
75 q->PostAt(now, NULL, 4);
76 q->PostAt(now - 1, NULL, 2);
77
78 Message msg;
79 for (size_t i=0; i<5; ++i) {
80 memset(&msg, 0, sizeof(msg));
81 EXPECT_TRUE(q->Get(&msg, 0));
82 EXPECT_EQ(i, msg.message_id);
83 }
84
85 EXPECT_FALSE(q->Get(&msg, 0)); // No more messages
86}
87
88TEST_F(MessageQueueTest,
89 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder) {
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000090 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q_);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000091 NullSocketServer nullss;
92 MessageQueue q_nullss(&nullss);
93 DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(&q_nullss);
94}
95
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +000096TEST_F(MessageQueueTest, DisposeNotLocked) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000097 bool was_locked = true;
98 bool deleted = false;
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +000099 DeletedLockChecker* d = new DeletedLockChecker(&q_, &was_locked, &deleted);
100 q_.Dispose(d);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000101 Message msg;
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000102 EXPECT_FALSE(q_.Get(&msg, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000103 EXPECT_TRUE(deleted);
104 EXPECT_FALSE(was_locked);
105}
106
107class DeletedMessageHandler : public MessageHandler {
108 public:
109 explicit DeletedMessageHandler(bool* deleted) : deleted_(deleted) { }
110 ~DeletedMessageHandler() {
111 *deleted_ = true;
112 }
113 void OnMessage(Message* msg) { }
114 private:
115 bool* deleted_;
116};
117
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000118// TODO(decurtis): Test that ordering of elements is done properly.
119// TODO(decurtis): Test that timestamps are being properly set.
120
121TEST_F(MessageQueueTest, DisposeHandlerWithPostedMessagePending) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000122 bool deleted = false;
123 DeletedMessageHandler *handler = new DeletedMessageHandler(&deleted);
124 // First, post a dispose.
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000125 q_.Dispose(handler);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000126 // Now, post a message, which should *not* be returned by Get().
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000127 q_.Post(handler, 1);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000128 Message msg;
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000129 EXPECT_FALSE(q_.Get(&msg, 0));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000130 EXPECT_TRUE(deleted);
131}
132
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000133// Test Clear for removing messages that have been posted for times in
134// the past.
135TEST_F(MessageQueueTest, ClearPast) {
136 TimeStamp now = Time();
137 Message msg;
138
139 // Test removing the only element.
140 q_.PostAt(now - 4, NULL, 1);
141 q_.Clear(NULL, 1, NULL);
142
143 // Make sure the queue is empty now.
144 EXPECT_FALSE(q_.Get(&msg, 0));
145
146 // Test removing the one element with a two element list.
147 q_.PostAt(now - 4, NULL, 1);
148 q_.PostAt(now - 2, NULL, 3);
149
150 q_.Clear(NULL, 1, NULL);
151
152 EXPECT_TRUE(q_.Get(&msg, 0));
153 EXPECT_EQ(3U, msg.message_id);
154
155 // Make sure the queue is empty now.
156 EXPECT_FALSE(q_.Get(&msg, 0));
157
158
159 // Test removing the three element with a two element list.
160 q_.PostAt(now - 4, NULL, 1);
161 q_.PostAt(now - 2, NULL, 3);
162
163 q_.Clear(NULL, 3, NULL);
164
165 EXPECT_TRUE(q_.Get(&msg, 0));
166 EXPECT_EQ(1U, msg.message_id);
167
168 // Make sure the queue is empty now.
169 EXPECT_FALSE(q_.Get(&msg, 0));
170
171
172 // Test removing the two element in a three element list.
173 q_.PostAt(now - 4, NULL, 1);
174 q_.PostAt(now - 3, NULL, 2);
175 q_.PostAt(now - 2, NULL, 3);
176
177 q_.Clear(NULL, 2, NULL);
178
179 EXPECT_TRUE(q_.Get(&msg, 0));
180 EXPECT_EQ(1U, msg.message_id);
181
182 EXPECT_TRUE(q_.Get(&msg, 0));
183 EXPECT_EQ(3U, msg.message_id);
184
185 // Make sure the queue is empty now.
186 EXPECT_FALSE(q_.Get(&msg, 0));
187
188
189 // Test not clearing any messages.
190 q_.PostAt(now - 4, NULL, 1);
191 q_.PostAt(now - 3, NULL, 2);
192 q_.PostAt(now - 2, NULL, 3);
193
194 // Remove nothing.
195 q_.Clear(NULL, 0, NULL);
196 q_.Clear(NULL, 4, NULL);
197
198 EXPECT_TRUE(q_.Get(&msg, 0));
199 EXPECT_EQ(1U, msg.message_id);
200
201 EXPECT_TRUE(q_.Get(&msg, 0));
202 EXPECT_EQ(2U, msg.message_id);
203
204 EXPECT_TRUE(q_.Get(&msg, 0));
205 EXPECT_EQ(3U, msg.message_id);
206
207 // Make sure the queue is empty now.
208 EXPECT_FALSE(q_.Get(&msg, 0));
209}
210
211// Test clearing messages that have been posted for the future.
212TEST_F(MessageQueueTest, ClearFuture) {
213 EXPECT_EQ(0U, q_.GetDmsgqSize());
214 q_.PostDelayed(10, NULL, 4);
215 EXPECT_EQ(1U, q_.GetDmsgqSize());
216 q_.PostDelayed(13, NULL, 4);
217 EXPECT_EQ(2U, q_.GetDmsgqSize());
218 q_.PostDelayed(9, NULL, 2);
219 EXPECT_EQ(3U, q_.GetDmsgqSize());
220 q_.PostDelayed(11, NULL, 10);
221 EXPECT_EQ(4U, q_.GetDmsgqSize());
222
223 EXPECT_EQ(9, q_.GetDmsgqTop().cmsDelay_);
224
225 MessageList removed;
226 q_.Clear(NULL, 10, &removed);
227 EXPECT_EQ(1U, removed.size());
228 EXPECT_EQ(3U, q_.GetDmsgqSize());
229
230 removed.clear();
231 q_.Clear(NULL, 4, &removed);
232 EXPECT_EQ(2U, removed.size());
233 EXPECT_EQ(1U, q_.GetDmsgqSize());
234
235 removed.clear();
236 q_.Clear(NULL, 4, &removed);
237 EXPECT_EQ(0U, removed.size());
238 EXPECT_EQ(1U, q_.GetDmsgqSize());
239
240 removed.clear();
241 q_.Clear(NULL, 2, &removed);
242 EXPECT_EQ(1U, removed.size());
243 EXPECT_EQ(0U, q_.GetDmsgqSize());
244
245 Message msg;
246 EXPECT_FALSE(q_.Get(&msg, 0));
247}
248
249
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000250struct UnwrapMainThreadScope {
251 UnwrapMainThreadScope() : rewrap_(Thread::Current() != NULL) {
252 if (rewrap_) ThreadManager::Instance()->UnwrapCurrentThread();
253 }
254 ~UnwrapMainThreadScope() {
255 if (rewrap_) ThreadManager::Instance()->WrapCurrentThread();
256 }
257 private:
258 bool rewrap_;
259};
260
decurtis@webrtc.org2bffc3c2015-02-21 01:45:04 +0000261TEST(MessageQueueManager, DeletedHandler) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000262 UnwrapMainThreadScope s;
263 if (MessageQueueManager::IsInitialized()) {
264 LOG(LS_INFO) << "Unable to run MessageQueueManager::Clear test, since the "
265 << "MessageQueueManager was already initialized by some "
266 << "other test in this run.";
267 return;
268 }
269 bool deleted = false;
270 DeletedMessageHandler* handler = new DeletedMessageHandler(&deleted);
271 delete handler;
272 EXPECT_TRUE(deleted);
273 EXPECT_FALSE(MessageQueueManager::IsInitialized());
274}