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