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/gunit.h"
     12 #include "webrtc/base/signalthread.h"
     13 #include "webrtc/base/thread.h"
     14 
     15 using namespace rtc;
     16 
     17 class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
     18  public:
     19   class SlowSignalThread : public SignalThread {
     20    public:
     21     SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {
     22     }
     23 
     24     virtual ~SlowSignalThread() {
     25       EXPECT_EQ(harness_->main_thread_, Thread::Current());
     26       ++harness_->thread_deleted_;
     27     }
     28 
     29     const SignalThreadTest* harness() { return harness_; }
     30 
     31    protected:
     32     virtual void OnWorkStart() {
     33       ASSERT_TRUE(harness_ != NULL);
     34       ++harness_->thread_started_;
     35       EXPECT_EQ(harness_->main_thread_, Thread::Current());
     36       EXPECT_FALSE(worker()->RunningForTest());  // not started yet
     37     }
     38 
     39     virtual void OnWorkStop() {
     40       ++harness_->thread_stopped_;
     41       EXPECT_EQ(harness_->main_thread_, Thread::Current());
     42       EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
     43     }
     44 
     45     virtual void OnWorkDone() {
     46       ++harness_->thread_done_;
     47       EXPECT_EQ(harness_->main_thread_, Thread::Current());
     48       EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
     49     }
     50 
     51     virtual void DoWork() {
     52       EXPECT_NE(harness_->main_thread_, Thread::Current());
     53       EXPECT_EQ(worker(), Thread::Current());
     54       Thread::Current()->socketserver()->Wait(250, false);
     55     }
     56 
     57    private:
     58     SignalThreadTest* harness_;
     59     RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
     60   };
     61 
     62   void OnWorkComplete(rtc::SignalThread* thread) {
     63     SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
     64     EXPECT_EQ(t->harness(), this);
     65     EXPECT_EQ(main_thread_, Thread::Current());
     66 
     67     ++thread_completed_;
     68     if (!called_release_) {
     69       thread->Release();
     70     }
     71   }
     72 
     73   virtual void SetUp() {
     74     main_thread_ = Thread::Current();
     75     thread_ = new SlowSignalThread(this);
     76     thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
     77     called_release_ = false;
     78     thread_started_ = 0;
     79     thread_done_ = 0;
     80     thread_completed_ = 0;
     81     thread_stopped_ = 0;
     82     thread_deleted_ = 0;
     83   }
     84 
     85   virtual void TearDown() {
     86   }
     87 
     88   Thread* main_thread_;
     89   SlowSignalThread* thread_;
     90   bool called_release_;
     91 
     92   int thread_started_;
     93   int thread_done_;
     94   int thread_completed_;
     95   int thread_stopped_;
     96   int thread_deleted_;
     97 };
     98 
     99 class OwnerThread : public Thread, public sigslot::has_slots<> {
    100  public:
    101   explicit OwnerThread(SignalThreadTest* harness)
    102       : harness_(harness),
    103         has_run_(false) {
    104   }
    105 
    106   virtual ~OwnerThread() {
    107     Stop();
    108   }
    109 
    110   virtual void Run() {
    111     SignalThreadTest::SlowSignalThread* signal_thread =
    112         new SignalThreadTest::SlowSignalThread(harness_);
    113     signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
    114     signal_thread->Start();
    115     Thread::Current()->socketserver()->Wait(100, false);
    116     signal_thread->Release();
    117     // Delete |signal_thread|.
    118     signal_thread->Destroy(true);
    119     has_run_ = true;
    120   }
    121 
    122   bool has_run() { return has_run_; }
    123   void OnWorkDone(SignalThread* signal_thread) {
    124     FAIL() << " This shouldn't get called.";
    125   }
    126 
    127  private:
    128   SignalThreadTest* harness_;
    129   bool has_run_;
    130   RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
    131 };
    132 
    133 // Test for when the main thread goes away while the
    134 // signal thread is still working.  This may happen
    135 // when shutting down the process.
    136 TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
    137   {
    138     scoped_ptr<OwnerThread> owner(new OwnerThread(this));
    139     main_thread_ = owner.get();
    140     owner->Start();
    141     while (!owner->has_run()) {
    142       Thread::Current()->socketserver()->Wait(10, false);
    143     }
    144   }
    145   // At this point the main thread has gone away.
    146   // Give the SignalThread a little time to do its callback,
    147   // which will crash if the signal thread doesn't handle
    148   // this situation well.
    149   Thread::Current()->socketserver()->Wait(500, false);
    150 }
    151 
    152 #define EXPECT_STATE(started, done, completed, stopped, deleted) \
    153   EXPECT_EQ(started, thread_started_); \
    154   EXPECT_EQ(done, thread_done_); \
    155   EXPECT_EQ(completed, thread_completed_); \
    156   EXPECT_EQ(stopped, thread_stopped_); \
    157   EXPECT_EQ(deleted, thread_deleted_);
    158 
    159 TEST_F(SignalThreadTest, ThreadFinishes) {
    160   thread_->Start();
    161   EXPECT_STATE(1, 0, 0, 0, 0);
    162   Thread::SleepMs(500);
    163   EXPECT_STATE(1, 0, 0, 0, 0);
    164   Thread::Current()->ProcessMessages(0);
    165   EXPECT_STATE(1, 1, 1, 0, 1);
    166 }
    167 
    168 TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
    169   thread_->Start();
    170   EXPECT_STATE(1, 0, 0, 0, 0);
    171   thread_->Release();
    172   called_release_ = true;
    173   EXPECT_STATE(1, 0, 0, 0, 0);
    174   Thread::SleepMs(500);
    175   EXPECT_STATE(1, 0, 0, 0, 0);
    176   Thread::Current()->ProcessMessages(0);
    177   EXPECT_STATE(1, 1, 1, 0, 1);
    178 }
    179 
    180 TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
    181   thread_->Start();
    182   EXPECT_STATE(1, 0, 0, 0, 0);
    183   thread_->Destroy(true);
    184   EXPECT_STATE(1, 0, 0, 1, 1);
    185   Thread::Current()->ProcessMessages(0);
    186   EXPECT_STATE(1, 0, 0, 1, 1);
    187 }
    188 
    189 TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
    190   thread_->Start();
    191   EXPECT_STATE(1, 0, 0, 0, 0);
    192   thread_->Destroy(false);
    193   EXPECT_STATE(1, 0, 0, 1, 0);
    194   Thread::SleepMs(500);
    195   EXPECT_STATE(1, 0, 0, 1, 0);
    196   Thread::Current()->ProcessMessages(0);
    197   EXPECT_STATE(1, 1, 0, 1, 1);
    198 }
    199