• 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/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:
SlowSignalThread(SignalThreadTest * harness)21     SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {
22     }
23 
~SlowSignalThread()24     virtual ~SlowSignalThread() {
25       EXPECT_EQ(harness_->main_thread_, Thread::Current());
26       ++harness_->thread_deleted_;
27     }
28 
harness()29     const SignalThreadTest* harness() { return harness_; }
30 
31    protected:
OnWorkStart()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 
OnWorkStop()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 
OnWorkDone()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 
DoWork()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 
OnWorkComplete(rtc::SignalThread * thread)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 
SetUp()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 
TearDown()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:
OwnerThread(SignalThreadTest * harness)101   explicit OwnerThread(SignalThreadTest* harness)
102       : harness_(harness),
103         has_run_(false) {
104   }
105 
~OwnerThread()106   virtual ~OwnerThread() {
107     Stop();
108   }
109 
Run()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 
has_run()122   bool has_run() { return has_run_; }
OnWorkDone(SignalThread * signal_thread)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.
TEST_F(SignalThreadTest,OwnerThreadGoesAway)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 
TEST_F(SignalThreadTest,ThreadFinishes)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 
TEST_F(SignalThreadTest,ReleasedThreadFinishes)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 
TEST_F(SignalThreadTest,DestroyedThreadCleansUp)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 
TEST_F(SignalThreadTest,DeferredDestroyedThreadCleansUp)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