blob: 95b4ac1d6e600de0e28228b72bba36d6ee417aa7 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
jbauch555604a2016-04-26 03:13:22 -070011#include <memory>
12
kwiberg4485ffb2016-04-26 08:14:39 -070013#include "webrtc/base/constructormagic.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000014#include "webrtc/base/gunit.h"
15#include "webrtc/base/signalthread.h"
16#include "webrtc/base/thread.h"
17
18using namespace rtc;
19
20class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
21 public:
22 class SlowSignalThread : public SignalThread {
23 public:
24 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {
25 }
26
27 virtual ~SlowSignalThread() {
28 EXPECT_EQ(harness_->main_thread_, Thread::Current());
29 ++harness_->thread_deleted_;
30 }
31
32 const SignalThreadTest* harness() { return harness_; }
33
34 protected:
35 virtual void OnWorkStart() {
36 ASSERT_TRUE(harness_ != NULL);
37 ++harness_->thread_started_;
38 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000039 EXPECT_FALSE(worker()->RunningForTest()); // not started yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000040 }
41
42 virtual void OnWorkStop() {
43 ++harness_->thread_stopped_;
44 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000045 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000046 }
47
48 virtual void OnWorkDone() {
49 ++harness_->thread_done_;
50 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000051 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000052 }
53
54 virtual void DoWork() {
55 EXPECT_NE(harness_->main_thread_, Thread::Current());
56 EXPECT_EQ(worker(), Thread::Current());
57 Thread::Current()->socketserver()->Wait(250, false);
58 }
59
60 private:
61 SignalThreadTest* harness_;
henrikg3c089d72015-09-16 05:37:44 -070062 RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000063 };
64
65 void OnWorkComplete(rtc::SignalThread* thread) {
66 SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
67 EXPECT_EQ(t->harness(), this);
68 EXPECT_EQ(main_thread_, Thread::Current());
69
70 ++thread_completed_;
71 if (!called_release_) {
72 thread->Release();
73 }
74 }
75
76 virtual void SetUp() {
77 main_thread_ = Thread::Current();
78 thread_ = new SlowSignalThread(this);
79 thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
80 called_release_ = false;
81 thread_started_ = 0;
82 thread_done_ = 0;
83 thread_completed_ = 0;
84 thread_stopped_ = 0;
85 thread_deleted_ = 0;
86 }
87
88 virtual void TearDown() {
89 }
90
91 Thread* main_thread_;
92 SlowSignalThread* thread_;
93 bool called_release_;
94
95 int thread_started_;
96 int thread_done_;
97 int thread_completed_;
98 int thread_stopped_;
99 int thread_deleted_;
100};
101
102class OwnerThread : public Thread, public sigslot::has_slots<> {
103 public:
104 explicit OwnerThread(SignalThreadTest* harness)
105 : harness_(harness),
106 has_run_(false) {
107 }
108
109 virtual ~OwnerThread() {
110 Stop();
111 }
112
113 virtual void Run() {
114 SignalThreadTest::SlowSignalThread* signal_thread =
115 new SignalThreadTest::SlowSignalThread(harness_);
116 signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
117 signal_thread->Start();
118 Thread::Current()->socketserver()->Wait(100, false);
119 signal_thread->Release();
120 // Delete |signal_thread|.
121 signal_thread->Destroy(true);
122 has_run_ = true;
123 }
124
125 bool has_run() { return has_run_; }
126 void OnWorkDone(SignalThread* signal_thread) {
127 FAIL() << " This shouldn't get called.";
128 }
129
130 private:
131 SignalThreadTest* harness_;
132 bool has_run_;
henrikg3c089d72015-09-16 05:37:44 -0700133 RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000134};
135
136// Test for when the main thread goes away while the
137// signal thread is still working. This may happen
138// when shutting down the process.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000139TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000140 {
jbauch555604a2016-04-26 03:13:22 -0700141 std::unique_ptr<OwnerThread> owner(new OwnerThread(this));
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000142 main_thread_ = owner.get();
143 owner->Start();
144 while (!owner->has_run()) {
145 Thread::Current()->socketserver()->Wait(10, false);
146 }
147 }
148 // At this point the main thread has gone away.
149 // Give the SignalThread a little time to do its callback,
150 // which will crash if the signal thread doesn't handle
151 // this situation well.
152 Thread::Current()->socketserver()->Wait(500, false);
153}
154
155#define EXPECT_STATE(started, done, completed, stopped, deleted) \
156 EXPECT_EQ(started, thread_started_); \
157 EXPECT_EQ(done, thread_done_); \
158 EXPECT_EQ(completed, thread_completed_); \
159 EXPECT_EQ(stopped, thread_stopped_); \
160 EXPECT_EQ(deleted, thread_deleted_);
161
ossua8aa9072016-06-02 08:47:07 -0700162#if defined(WEBRTC_LINUX)
163#define MAYBE_ThreadFinishes DISABLED_ThreadFinishes
164#else
165#define MAYBE_ThreadFinishes ThreadFinishes
166#endif
167TEST_F(SignalThreadTest, MAYBE_ThreadFinishes) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000168 thread_->Start();
169 EXPECT_STATE(1, 0, 0, 0, 0);
170 Thread::SleepMs(500);
171 EXPECT_STATE(1, 0, 0, 0, 0);
172 Thread::Current()->ProcessMessages(0);
173 EXPECT_STATE(1, 1, 1, 0, 1);
174}
175
ossua8aa9072016-06-02 08:47:07 -0700176#if defined(WEBRTC_LINUX)
177#define MAYBE_ReleasedThreadFinishes DISABLED_ReleasedThreadFinishes
178#else
179#define MAYBE_ReleasedThreadFinishes ReleasedThreadFinishes
180#endif
181TEST_F(SignalThreadTest, MAYBE_ReleasedThreadFinishes) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000182 thread_->Start();
183 EXPECT_STATE(1, 0, 0, 0, 0);
184 thread_->Release();
185 called_release_ = true;
186 EXPECT_STATE(1, 0, 0, 0, 0);
187 Thread::SleepMs(500);
188 EXPECT_STATE(1, 0, 0, 0, 0);
189 Thread::Current()->ProcessMessages(0);
190 EXPECT_STATE(1, 1, 1, 0, 1);
191}
192
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000193TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000194 thread_->Start();
195 EXPECT_STATE(1, 0, 0, 0, 0);
196 thread_->Destroy(true);
197 EXPECT_STATE(1, 0, 0, 1, 1);
198 Thread::Current()->ProcessMessages(0);
199 EXPECT_STATE(1, 0, 0, 1, 1);
200}
201
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000202TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000203 thread_->Start();
204 EXPECT_STATE(1, 0, 0, 0, 0);
205 thread_->Destroy(false);
206 EXPECT_STATE(1, 0, 0, 1, 0);
207 Thread::SleepMs(500);
208 EXPECT_STATE(1, 0, 0, 1, 0);
209 Thread::Current()->ProcessMessages(0);
210 EXPECT_STATE(1, 1, 0, 1, 1);
211}