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:
IsLocked_Worker()24 bool IsLocked_Worker() {
25 if (!crit_.TryEnter()) {
26 return true;
27 }
28 crit_.Leave();
29 return false;
30 }
IsLocked()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 {
DeletedLockCheckerDeletedLockChecker42 DeletedLockChecker(MessageQueueTest* test, bool* was_locked, bool* deleted)
43 : test(test), was_locked(was_locked), deleted(deleted) { }
~DeletedLockCheckerDeletedLockChecker44 ~DeletedLockChecker() {
45 *deleted = true;
46 *was_locked = test->IsLocked();
47 }
48 MessageQueueTest* test;
49 bool* was_locked;
50 bool* deleted;
51 };
52
DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder(MessageQueue * q)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
TEST_F(MessageQueueTest,DelayedPostsWithIdenticalTimesAreProcessedInFifoOrder)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
TEST_F(MessageQueueTest,DisposeNotLocked)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:
DeletedMessageHandler(bool * deleted)95 explicit DeletedMessageHandler(bool* deleted) : deleted_(deleted) { }
~DeletedMessageHandler()96 ~DeletedMessageHandler() {
97 *deleted_ = true;
98 }
OnMessage(Message * msg)99 void OnMessage(Message* msg) { }
100 private:
101 bool* deleted_;
102 };
103
TEST_F(MessageQueueTest,DiposeHandlerWithPostedMessagePending)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 {
UnwrapMainThreadScopeUnwrapMainThreadScope117 UnwrapMainThreadScope() : rewrap_(Thread::Current() != NULL) {
118 if (rewrap_) ThreadManager::Instance()->UnwrapCurrentThread();
119 }
~UnwrapMainThreadScopeUnwrapMainThreadScope120 ~UnwrapMainThreadScope() {
121 if (rewrap_) ThreadManager::Instance()->WrapCurrentThread();
122 }
123 private:
124 bool rewrap_;
125 };
126
TEST(MessageQueueManager,Clear)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