blob: d9304d494d1cc1cb82c391018a350fe0f8235e9e [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"
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 Gerey3e707812018-11-28 16:47:49 +010020#include "test/gtest.h"
deadbeef8290ddf2017-07-11 16:56:05 -070021
Mirko Bonadeie10b1632018-12-11 18:43:40 +010022namespace rtc {
23namespace {
deadbeef8290ddf2017-07-11 16:56:05 -070024
25// 10 seconds.
26static const int kTimeout = 10000;
27
Mirko Bonadei6a489f22019-04-09 15:11:12 +020028class SignalThreadTest : public ::testing::Test, public sigslot::has_slots<> {
deadbeef8290ddf2017-07-11 16:56:05 -070029 public:
30 class SlowSignalThread : public SignalThread {
31 public:
32 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {}
33
Steve Anton9de3aac2017-10-24 10:08:26 -070034 ~SlowSignalThread() override {
deadbeef8290ddf2017-07-11 16:56:05 -070035 EXPECT_EQ(harness_->main_thread_, Thread::Current());
36 ++harness_->thread_deleted_;
37 }
38
39 const SignalThreadTest* harness() { return harness_; }
40
41 protected:
Steve Anton9de3aac2017-10-24 10:08:26 -070042 void OnWorkStart() override {
deadbeef8290ddf2017-07-11 16:56:05 -070043 ASSERT_TRUE(harness_ != nullptr);
44 ++harness_->thread_started_;
45 EXPECT_EQ(harness_->main_thread_, Thread::Current());
46 EXPECT_FALSE(worker()->RunningForTest()); // not started yet
47 }
48
Steve Anton9de3aac2017-10-24 10:08:26 -070049 void OnWorkStop() override {
deadbeef8290ddf2017-07-11 16:56:05 -070050 ++harness_->thread_stopped_;
51 EXPECT_EQ(harness_->main_thread_, Thread::Current());
52 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
53 }
54
Steve Anton9de3aac2017-10-24 10:08:26 -070055 void OnWorkDone() override {
deadbeef8290ddf2017-07-11 16:56:05 -070056 ++harness_->thread_done_;
57 EXPECT_EQ(harness_->main_thread_, Thread::Current());
58 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
59 }
60
Steve Anton9de3aac2017-10-24 10:08:26 -070061 void DoWork() override {
deadbeef8290ddf2017-07-11 16:56:05 -070062 EXPECT_NE(harness_->main_thread_, Thread::Current());
63 EXPECT_EQ(worker(), Thread::Current());
64 Thread::Current()->socketserver()->Wait(250, false);
65 }
66
67 private:
68 SignalThreadTest* harness_;
69 RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
70 };
71
72 void OnWorkComplete(rtc::SignalThread* thread) {
73 SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
74 EXPECT_EQ(t->harness(), this);
75 EXPECT_EQ(main_thread_, Thread::Current());
76
77 ++thread_completed_;
78 if (!called_release_) {
79 thread->Release();
80 }
81 }
82
Steve Anton9de3aac2017-10-24 10:08:26 -070083 void SetUp() override {
deadbeef8290ddf2017-07-11 16:56:05 -070084 main_thread_ = Thread::Current();
85 thread_ = new SlowSignalThread(this);
86 thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
87 called_release_ = false;
88 thread_started_ = 0;
89 thread_done_ = 0;
90 thread_completed_ = 0;
91 thread_stopped_ = 0;
92 thread_deleted_ = 0;
93 }
94
deadbeef8290ddf2017-07-11 16:56:05 -070095 void ExpectState(int started,
96 int done,
97 int completed,
98 int stopped,
99 int deleted) {
100 EXPECT_EQ(started, thread_started_);
101 EXPECT_EQ(done, thread_done_);
102 EXPECT_EQ(completed, thread_completed_);
103 EXPECT_EQ(stopped, thread_stopped_);
104 EXPECT_EQ(deleted, thread_deleted_);
105 }
106
107 void ExpectStateWait(int started,
108 int done,
109 int completed,
110 int stopped,
111 int deleted,
112 int timeout) {
113 EXPECT_EQ_WAIT(started, thread_started_, timeout);
114 EXPECT_EQ_WAIT(done, thread_done_, timeout);
115 EXPECT_EQ_WAIT(completed, thread_completed_, timeout);
116 EXPECT_EQ_WAIT(stopped, thread_stopped_, timeout);
117 EXPECT_EQ_WAIT(deleted, thread_deleted_, timeout);
118 }
119
120 Thread* main_thread_;
121 SlowSignalThread* thread_;
122 bool called_release_;
123
124 int thread_started_;
125 int thread_done_;
126 int thread_completed_;
127 int thread_stopped_;
128 int thread_deleted_;
129};
130
131class OwnerThread : public Thread, public sigslot::has_slots<> {
132 public:
133 explicit OwnerThread(SignalThreadTest* harness)
Niels Möller5a96a0e2019-04-30 11:45:58 +0200134 : Thread(absl::make_unique<NullSocketServer>()),
135 harness_(harness),
136 has_run_(false) {}
deadbeef8290ddf2017-07-11 16:56:05 -0700137
Steve Anton9de3aac2017-10-24 10:08:26 -0700138 ~OwnerThread() override { Stop(); }
deadbeef8290ddf2017-07-11 16:56:05 -0700139
Steve Anton9de3aac2017-10-24 10:08:26 -0700140 void Run() override {
deadbeef8290ddf2017-07-11 16:56:05 -0700141 SignalThreadTest::SlowSignalThread* signal_thread =
142 new SignalThreadTest::SlowSignalThread(harness_);
143 signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
144 signal_thread->Start();
145 Thread::Current()->socketserver()->Wait(100, false);
146 signal_thread->Release();
147 // Delete |signal_thread|.
148 signal_thread->Destroy(true);
149 has_run_ = true;
150 }
151
152 bool has_run() { return has_run_; }
153 void OnWorkDone(SignalThread* signal_thread) {
154 FAIL() << " This shouldn't get called.";
155 }
156
157 private:
158 SignalThreadTest* harness_;
159 bool has_run_;
160 RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
161};
162
163// Test for when the main thread goes away while the
164// signal thread is still working. This may happen
165// when shutting down the process.
166TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
167 // We don't use |thread_| for this test, so destroy it.
168 thread_->Destroy(true);
169
170 {
171 std::unique_ptr<OwnerThread> owner(new OwnerThread(this));
172 main_thread_ = owner.get();
173 owner->Start();
174 while (!owner->has_run()) {
175 Thread::Current()->socketserver()->Wait(10, false);
176 }
177 }
178 // At this point the main thread has gone away.
179 // Give the SignalThread a little time to do its callback,
180 // which will crash if the signal thread doesn't handle
181 // this situation well.
182 Thread::Current()->socketserver()->Wait(500, false);
183}
184
185TEST_F(SignalThreadTest, ThreadFinishes) {
186 thread_->Start();
187 ExpectState(1, 0, 0, 0, 0);
188 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
189}
190
191TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
192 thread_->Start();
193 ExpectState(1, 0, 0, 0, 0);
194 thread_->Release();
195 called_release_ = true;
196 ExpectState(1, 0, 0, 0, 0);
197 ExpectStateWait(1, 1, 1, 0, 1, kTimeout);
198}
199
200TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
201 thread_->Start();
202 ExpectState(1, 0, 0, 0, 0);
203 thread_->Destroy(true);
204 ExpectState(1, 0, 0, 1, 1);
205 Thread::Current()->ProcessMessages(0);
206 ExpectState(1, 0, 0, 1, 1);
207}
208
209TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
210 thread_->Start();
211 ExpectState(1, 0, 0, 0, 0);
212 thread_->Destroy(false);
213 ExpectState(1, 0, 0, 1, 0);
214 ExpectStateWait(1, 1, 0, 1, 1, kTimeout);
215}
Mirko Bonadeie10b1632018-12-11 18:43:40 +0100216
217} // namespace
218} // namespace rtc