blob: 14761865b8a78f35db799e2239f5e90bc906ec37 [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "rtc_base/signal_thread.h"
12
deadbeef8290ddf2017-07-11 16:56:05 -070013#include <memory>
14
Steve Anton10542f22019-01-11 09:11:00 -080015#include "rtc_base/constructor_magic.h"
Yves Gereyc2accf22019-09-06 01:26:09 +020016#include "rtc_base/critical_section.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/gunit.h"
Niels Möller5a96a0e2019-04-30 11:45:58 +020018#include "rtc_base/null_socket_server.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "rtc_base/thread.h"
Yves Gereyc2accf22019-09-06 01:26:09 +020020#include "rtc_base/thread_annotations.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "test/gtest.h"
deadbeef8290ddf2017-07-11 16:56:05 -070022
Mirko Bonadeie10b1632018-12-11 18:43:40 +010023namespace rtc {
24namespace {
deadbeef8290ddf2017-07-11 16:56:05 -070025
26// 10 seconds.
27static const int kTimeout = 10000;
28
Mirko Bonadei6a489f22019-04-09 15:11:12 +020029class SignalThreadTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef8290ddf2017-07-11 16:56:05 -070030 public:
31 class SlowSignalThread : public SignalThread {
32 public:
33 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {}
34
Steve Anton9de3aac2017-10-24 10:08:26 -070035 ~SlowSignalThread() override {
deadbeef8290ddf2017-07-11 16:56:05 -070036 EXPECT_EQ(harness_->main_thread_, Thread::Current());
37 ++harness_->thread_deleted_;
38 }
39
40 const SignalThreadTest* harness() { return harness_; }
41
42 protected:
Steve Anton9de3aac2017-10-24 10:08:26 -070043 void OnWorkStart() override {
deadbeef8290ddf2017-07-11 16:56:05 -070044 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
Steve Anton9de3aac2017-10-24 10:08:26 -070050 void OnWorkStop() override {
deadbeef8290ddf2017-07-11 16:56:05 -070051 ++harness_->thread_stopped_;
52 EXPECT_EQ(harness_->main_thread_, Thread::Current());
53 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
54 }
55
Steve Anton9de3aac2017-10-24 10:08:26 -070056 void OnWorkDone() override {
deadbeef8290ddf2017-07-11 16:56:05 -070057 ++harness_->thread_done_;
58 EXPECT_EQ(harness_->main_thread_, Thread::Current());
59 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
60 }
61
Steve Anton9de3aac2017-10-24 10:08:26 -070062 void DoWork() override {
deadbeef8290ddf2017-07-11 16:56:05 -070063 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
73 void OnWorkComplete(rtc::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
Steve Anton9de3aac2017-10-24 10:08:26 -070084 void SetUp() override {
deadbeef8290ddf2017-07-11 16:56:05 -070085 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
deadbeef8290ddf2017-07-11 16:56:05 -070096 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
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
132class OwnerThread : public Thread, public sigslot::has_slots<> {
133 public:
134 explicit OwnerThread(SignalThreadTest* harness)
Mirko Bonadei317a1f02019-09-17 17:06:18 +0200135 : Thread(std::make_unique<NullSocketServer>()),
Niels Möller5a96a0e2019-04-30 11:45:58 +0200136 harness_(harness),
137 has_run_(false) {}
deadbeef8290ddf2017-07-11 16:56:05 -0700138
Steve Anton9de3aac2017-10-24 10:08:26 -0700139 ~OwnerThread() override { Stop(); }
deadbeef8290ddf2017-07-11 16:56:05 -0700140
Steve Anton9de3aac2017-10-24 10:08:26 -0700141 void Run() override {
deadbeef8290ddf2017-07-11 16:56:05 -0700142 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);
Yves Gereyc2accf22019-09-06 01:26:09 +0200150 {
151 rtc::CritScope cs(&crit_);
152 has_run_ = true;
153 }
deadbeef8290ddf2017-07-11 16:56:05 -0700154 }
155
Yves Gereyc2accf22019-09-06 01:26:09 +0200156 bool has_run() {
157 rtc::CritScope cs(&crit_);
158 return has_run_;
159 }
160 void OnWorkDone(SignalThread* /*signal_thread*/) {
deadbeef8290ddf2017-07-11 16:56:05 -0700161 FAIL() << " This shouldn't get called.";
162 }
163
164 private:
Yves Gereyc2accf22019-09-06 01:26:09 +0200165 rtc::CriticalSection crit_;
deadbeef8290ddf2017-07-11 16:56:05 -0700166 SignalThreadTest* harness_;
Yves Gereyc2accf22019-09-06 01:26:09 +0200167 bool has_run_ RTC_GUARDED_BY(crit_);
deadbeef8290ddf2017-07-11 16:56:05 -0700168 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.
174TEST_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
193TEST_F(SignalThreadTest, ThreadFinishes) {
194 thread_->Start();
195 ExpectState(1, 0, 0, 0, 0);
196 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
197}
198
199TEST_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
208TEST_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
217TEST_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}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100224
225} // namespace
226} // namespace rtc