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