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