blob: 9375b5010ddcb30d635531be11533d5b32e54a28 [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
Niels Möller5a96a0e2019-04-30 11:45:58 +020015#include "absl/memory/memory.h"
Steve Anton10542f22019-01-11 09:11:00 -080016#include "rtc_base/constructor_magic.h"
Yves Gereyc2accf22019-09-06 01:26:09 +020017#include "rtc_base/critical_section.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "rtc_base/gunit.h"
Niels Möller5a96a0e2019-04-30 11:45:58 +020019#include "rtc_base/null_socket_server.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/thread.h"
Yves Gereyc2accf22019-09-06 01:26:09 +020021#include "rtc_base/thread_annotations.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "test/gtest.h"
deadbeef8290ddf2017-07-11 16:56:05 -070023
Mirko Bonadeie10b1632018-12-11 18:43:40 +010024namespace rtc {
25namespace {
deadbeef8290ddf2017-07-11 16:56:05 -070026
27// 10 seconds.
28static const int kTimeout = 10000;
29
Mirko Bonadei6a489f22019-04-09 15:11:12 +020030class SignalThreadTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef8290ddf2017-07-11 16:56:05 -070031 public:
32 class SlowSignalThread : public SignalThread {
33 public:
34 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {}
35
Steve Anton9de3aac2017-10-24 10:08:26 -070036 ~SlowSignalThread() override {
deadbeef8290ddf2017-07-11 16:56:05 -070037 EXPECT_EQ(harness_->main_thread_, Thread::Current());
38 ++harness_->thread_deleted_;
39 }
40
41 const SignalThreadTest* harness() { return harness_; }
42
43 protected:
Steve Anton9de3aac2017-10-24 10:08:26 -070044 void OnWorkStart() override {
deadbeef8290ddf2017-07-11 16:56:05 -070045 ASSERT_TRUE(harness_ != nullptr);
46 ++harness_->thread_started_;
47 EXPECT_EQ(harness_->main_thread_, Thread::Current());
48 EXPECT_FALSE(worker()->RunningForTest()); // not started yet
49 }
50
Steve Anton9de3aac2017-10-24 10:08:26 -070051 void OnWorkStop() override {
deadbeef8290ddf2017-07-11 16:56:05 -070052 ++harness_->thread_stopped_;
53 EXPECT_EQ(harness_->main_thread_, Thread::Current());
54 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
55 }
56
Steve Anton9de3aac2017-10-24 10:08:26 -070057 void OnWorkDone() override {
deadbeef8290ddf2017-07-11 16:56:05 -070058 ++harness_->thread_done_;
59 EXPECT_EQ(harness_->main_thread_, Thread::Current());
60 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
61 }
62
Steve Anton9de3aac2017-10-24 10:08:26 -070063 void DoWork() override {
deadbeef8290ddf2017-07-11 16:56:05 -070064 EXPECT_NE(harness_->main_thread_, Thread::Current());
65 EXPECT_EQ(worker(), Thread::Current());
66 Thread::Current()->socketserver()->Wait(250, false);
67 }
68
69 private:
70 SignalThreadTest* harness_;
71 RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
72 };
73
74 void OnWorkComplete(rtc::SignalThread* thread) {
75 SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
76 EXPECT_EQ(t->harness(), this);
77 EXPECT_EQ(main_thread_, Thread::Current());
78
79 ++thread_completed_;
80 if (!called_release_) {
81 thread->Release();
82 }
83 }
84
Steve Anton9de3aac2017-10-24 10:08:26 -070085 void SetUp() override {
deadbeef8290ddf2017-07-11 16:56:05 -070086 main_thread_ = Thread::Current();
87 thread_ = new SlowSignalThread(this);
88 thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
89 called_release_ = false;
90 thread_started_ = 0;
91 thread_done_ = 0;
92 thread_completed_ = 0;
93 thread_stopped_ = 0;
94 thread_deleted_ = 0;
95 }
96
deadbeef8290ddf2017-07-11 16:56:05 -070097 void ExpectState(int started,
98 int done,
99 int completed,
100 int stopped,
101 int deleted) {
102 EXPECT_EQ(started, thread_started_);
103 EXPECT_EQ(done, thread_done_);
104 EXPECT_EQ(completed, thread_completed_);
105 EXPECT_EQ(stopped, thread_stopped_);
106 EXPECT_EQ(deleted, thread_deleted_);
107 }
108
109 void ExpectStateWait(int started,
110 int done,
111 int completed,
112 int stopped,
113 int deleted,
114 int timeout) {
115 EXPECT_EQ_WAIT(started, thread_started_, timeout);
116 EXPECT_EQ_WAIT(done, thread_done_, timeout);
117 EXPECT_EQ_WAIT(completed, thread_completed_, timeout);
118 EXPECT_EQ_WAIT(stopped, thread_stopped_, timeout);
119 EXPECT_EQ_WAIT(deleted, thread_deleted_, timeout);
120 }
121
122 Thread* main_thread_;
123 SlowSignalThread* thread_;
124 bool called_release_;
125
126 int thread_started_;
127 int thread_done_;
128 int thread_completed_;
129 int thread_stopped_;
130 int thread_deleted_;
131};
132
133class OwnerThread : public Thread, public sigslot::has_slots<> {
134 public:
135 explicit OwnerThread(SignalThreadTest* harness)
Niels Möller5a96a0e2019-04-30 11:45:58 +0200136 : Thread(absl::make_unique<NullSocketServer>()),
137 harness_(harness),
138 has_run_(false) {}
deadbeef8290ddf2017-07-11 16:56:05 -0700139
Steve Anton9de3aac2017-10-24 10:08:26 -0700140 ~OwnerThread() override { Stop(); }
deadbeef8290ddf2017-07-11 16:56:05 -0700141
Steve Anton9de3aac2017-10-24 10:08:26 -0700142 void Run() override {
deadbeef8290ddf2017-07-11 16:56:05 -0700143 SignalThreadTest::SlowSignalThread* signal_thread =
144 new SignalThreadTest::SlowSignalThread(harness_);
145 signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
146 signal_thread->Start();
147 Thread::Current()->socketserver()->Wait(100, false);
148 signal_thread->Release();
149 // Delete |signal_thread|.
150 signal_thread->Destroy(true);
Yves Gereyc2accf22019-09-06 01:26:09 +0200151 {
152 rtc::CritScope cs(&crit_);
153 has_run_ = true;
154 }
deadbeef8290ddf2017-07-11 16:56:05 -0700155 }
156
Yves Gereyc2accf22019-09-06 01:26:09 +0200157 bool has_run() {
158 rtc::CritScope cs(&crit_);
159 return has_run_;
160 }
161 void OnWorkDone(SignalThread* /*signal_thread*/) {
deadbeef8290ddf2017-07-11 16:56:05 -0700162 FAIL() << " This shouldn't get called.";
163 }
164
165 private:
Yves Gereyc2accf22019-09-06 01:26:09 +0200166 rtc::CriticalSection crit_;
deadbeef8290ddf2017-07-11 16:56:05 -0700167 SignalThreadTest* harness_;
Yves Gereyc2accf22019-09-06 01:26:09 +0200168 bool has_run_ RTC_GUARDED_BY(crit_);
deadbeef8290ddf2017-07-11 16:56:05 -0700169 RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
170};
171
172// Test for when the main thread goes away while the
173// signal thread is still working. This may happen
174// when shutting down the process.
175TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
176 // We don't use |thread_| for this test, so destroy it.
177 thread_->Destroy(true);
178
179 {
180 std::unique_ptr<OwnerThread> owner(new OwnerThread(this));
181 main_thread_ = owner.get();
182 owner->Start();
183 while (!owner->has_run()) {
184 Thread::Current()->socketserver()->Wait(10, false);
185 }
186 }
187 // At this point the main thread has gone away.
188 // Give the SignalThread a little time to do its callback,
189 // which will crash if the signal thread doesn't handle
190 // this situation well.
191 Thread::Current()->socketserver()->Wait(500, false);
192}
193
194TEST_F(SignalThreadTest, ThreadFinishes) {
195 thread_->Start();
196 ExpectState(1, 0, 0, 0, 0);
197 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
198}
199
200TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
201 thread_->Start();
202 ExpectState(1, 0, 0, 0, 0);
203 thread_->Release();
204 called_release_ = true;
205 ExpectState(1, 0, 0, 0, 0);
206 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
207}
208
209TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
210 thread_->Start();
211 ExpectState(1, 0, 0, 0, 0);
212 thread_->Destroy(true);
213 ExpectState(1, 0, 0, 1, 1);
214 Thread::Current()->ProcessMessages(0);
215 ExpectState(1, 0, 0, 1, 1);
216}
217
218TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
219 thread_->Start();
220 ExpectState(1, 0, 0, 0, 0);
221 thread_->Destroy(false);
222 ExpectState(1, 0, 0, 1, 0);
223 ExpectStateWait(1, 1, 0, 1, 1, kTimeout);
224}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100225
226} // namespace
227} // namespace rtc