blob: eeae030fbc5e1b45eaa7f266497d8ef197cba43b [file] [log] [blame]
deadbeef8290ddf2017-07-11 16:56:05 -07001/*
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 <memory>
12
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/constructormagic.h"
14#include "rtc_base/gunit.h"
15#include "rtc_base/signalthread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010016#include "rtc_base/socketserver.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/thread.h"
Yves Gerey3e707812018-11-28 16:47:49 +010018#include "test/gtest.h"
deadbeef8290ddf2017-07-11 16:56:05 -070019
Mirko Bonadeie10b1632018-12-11 18:43:40 +010020namespace rtc {
21namespace {
deadbeef8290ddf2017-07-11 16:56:05 -070022
23// 10 seconds.
24static const int kTimeout = 10000;
25
26class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
27 public:
28 class SlowSignalThread : public SignalThread {
29 public:
30 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {}
31
Steve Anton9de3aac2017-10-24 10:08:26 -070032 ~SlowSignalThread() override {
deadbeef8290ddf2017-07-11 16:56:05 -070033 EXPECT_EQ(harness_->main_thread_, Thread::Current());
34 ++harness_->thread_deleted_;
35 }
36
37 const SignalThreadTest* harness() { return harness_; }
38
39 protected:
Steve Anton9de3aac2017-10-24 10:08:26 -070040 void OnWorkStart() override {
deadbeef8290ddf2017-07-11 16:56:05 -070041 ASSERT_TRUE(harness_ != nullptr);
42 ++harness_->thread_started_;
43 EXPECT_EQ(harness_->main_thread_, Thread::Current());
44 EXPECT_FALSE(worker()->RunningForTest()); // not started yet
45 }
46
Steve Anton9de3aac2017-10-24 10:08:26 -070047 void OnWorkStop() override {
deadbeef8290ddf2017-07-11 16:56:05 -070048 ++harness_->thread_stopped_;
49 EXPECT_EQ(harness_->main_thread_, Thread::Current());
50 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
51 }
52
Steve Anton9de3aac2017-10-24 10:08:26 -070053 void OnWorkDone() override {
deadbeef8290ddf2017-07-11 16:56:05 -070054 ++harness_->thread_done_;
55 EXPECT_EQ(harness_->main_thread_, Thread::Current());
56 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
57 }
58
Steve Anton9de3aac2017-10-24 10:08:26 -070059 void DoWork() override {
deadbeef8290ddf2017-07-11 16:56:05 -070060 EXPECT_NE(harness_->main_thread_, Thread::Current());
61 EXPECT_EQ(worker(), Thread::Current());
62 Thread::Current()->socketserver()->Wait(250, false);
63 }
64
65 private:
66 SignalThreadTest* harness_;
67 RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
68 };
69
70 void OnWorkComplete(rtc::SignalThread* thread) {
71 SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
72 EXPECT_EQ(t->harness(), this);
73 EXPECT_EQ(main_thread_, Thread::Current());
74
75 ++thread_completed_;
76 if (!called_release_) {
77 thread->Release();
78 }
79 }
80
Steve Anton9de3aac2017-10-24 10:08:26 -070081 void SetUp() override {
deadbeef8290ddf2017-07-11 16:56:05 -070082 main_thread_ = Thread::Current();
83 thread_ = new SlowSignalThread(this);
84 thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
85 called_release_ = false;
86 thread_started_ = 0;
87 thread_done_ = 0;
88 thread_completed_ = 0;
89 thread_stopped_ = 0;
90 thread_deleted_ = 0;
91 }
92
deadbeef8290ddf2017-07-11 16:56:05 -070093 void ExpectState(int started,
94 int done,
95 int completed,
96 int stopped,
97 int deleted) {
98 EXPECT_EQ(started, thread_started_);
99 EXPECT_EQ(done, thread_done_);
100 EXPECT_EQ(completed, thread_completed_);
101 EXPECT_EQ(stopped, thread_stopped_);
102 EXPECT_EQ(deleted, thread_deleted_);
103 }
104
105 void ExpectStateWait(int started,
106 int done,
107 int completed,
108 int stopped,
109 int deleted,
110 int timeout) {
111 EXPECT_EQ_WAIT(started, thread_started_, timeout);
112 EXPECT_EQ_WAIT(done, thread_done_, timeout);
113 EXPECT_EQ_WAIT(completed, thread_completed_, timeout);
114 EXPECT_EQ_WAIT(stopped, thread_stopped_, timeout);
115 EXPECT_EQ_WAIT(deleted, thread_deleted_, timeout);
116 }
117
118 Thread* main_thread_;
119 SlowSignalThread* thread_;
120 bool called_release_;
121
122 int thread_started_;
123 int thread_done_;
124 int thread_completed_;
125 int thread_stopped_;
126 int thread_deleted_;
127};
128
129class OwnerThread : public Thread, public sigslot::has_slots<> {
130 public:
131 explicit OwnerThread(SignalThreadTest* harness)
132 : harness_(harness), has_run_(false) {}
133
Steve Anton9de3aac2017-10-24 10:08:26 -0700134 ~OwnerThread() override { Stop(); }
deadbeef8290ddf2017-07-11 16:56:05 -0700135
Steve Anton9de3aac2017-10-24 10:08:26 -0700136 void Run() override {
deadbeef8290ddf2017-07-11 16:56:05 -0700137 SignalThreadTest::SlowSignalThread* signal_thread =
138 new SignalThreadTest::SlowSignalThread(harness_);
139 signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
140 signal_thread->Start();
141 Thread::Current()->socketserver()->Wait(100, false);
142 signal_thread->Release();
143 // Delete |signal_thread|.
144 signal_thread->Destroy(true);
145 has_run_ = true;
146 }
147
148 bool has_run() { return has_run_; }
149 void OnWorkDone(SignalThread* signal_thread) {
150 FAIL() << " This shouldn't get called.";
151 }
152
153 private:
154 SignalThreadTest* harness_;
155 bool has_run_;
156 RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
157};
158
159// Test for when the main thread goes away while the
160// signal thread is still working. This may happen
161// when shutting down the process.
162TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
163 // We don't use |thread_| for this test, so destroy it.
164 thread_->Destroy(true);
165
166 {
167 std::unique_ptr<OwnerThread> owner(new OwnerThread(this));
168 main_thread_ = owner.get();
169 owner->Start();
170 while (!owner->has_run()) {
171 Thread::Current()->socketserver()->Wait(10, false);
172 }
173 }
174 // At this point the main thread has gone away.
175 // Give the SignalThread a little time to do its callback,
176 // which will crash if the signal thread doesn't handle
177 // this situation well.
178 Thread::Current()->socketserver()->Wait(500, false);
179}
180
181TEST_F(SignalThreadTest, ThreadFinishes) {
182 thread_->Start();
183 ExpectState(1, 0, 0, 0, 0);
184 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
185}
186
187TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
188 thread_->Start();
189 ExpectState(1, 0, 0, 0, 0);
190 thread_->Release();
191 called_release_ = true;
192 ExpectState(1, 0, 0, 0, 0);
193 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
194}
195
196TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
197 thread_->Start();
198 ExpectState(1, 0, 0, 0, 0);
199 thread_->Destroy(true);
200 ExpectState(1, 0, 0, 1, 1);
201 Thread::Current()->ProcessMessages(0);
202 ExpectState(1, 0, 0, 1, 1);
203}
204
205TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
206 thread_->Start();
207 ExpectState(1, 0, 0, 0, 0);
208 thread_->Destroy(false);
209 ExpectState(1, 0, 0, 1, 0);
210 ExpectStateWait(1, 1, 0, 1, 1, kTimeout);
211}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100212
213} // namespace
214} // namespace rtc