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