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