Home | History | Annotate | Download | only in base
      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