• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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