blob: fe6c6023a65841eeb6205935df238d724ed1bb21 [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
11#include "webrtc/base/gunit.h"
12#include "webrtc/base/signalthread.h"
13#include "webrtc/base/thread.h"
henrike@webrtc.orgfded02c2014-09-19 13:10:10 +000014#include "webrtc/test/testsupport/gtest_disable.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000015
16using namespace rtc;
17
18class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
19 public:
20 class SlowSignalThread : public SignalThread {
21 public:
22 SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {
23 }
24
25 virtual ~SlowSignalThread() {
26 EXPECT_EQ(harness_->main_thread_, Thread::Current());
27 ++harness_->thread_deleted_;
28 }
29
30 const SignalThreadTest* harness() { return harness_; }
31
32 protected:
33 virtual void OnWorkStart() {
34 ASSERT_TRUE(harness_ != NULL);
35 ++harness_->thread_started_;
36 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000037 EXPECT_FALSE(worker()->RunningForTest()); // not started yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000038 }
39
40 virtual void OnWorkStop() {
41 ++harness_->thread_stopped_;
42 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000043 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000044 }
45
46 virtual void OnWorkDone() {
47 ++harness_->thread_done_;
48 EXPECT_EQ(harness_->main_thread_, Thread::Current());
fischman@webrtc.orge5063b12014-05-23 17:28:50 +000049 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000050 }
51
52 virtual void DoWork() {
53 EXPECT_NE(harness_->main_thread_, Thread::Current());
54 EXPECT_EQ(worker(), Thread::Current());
55 Thread::Current()->socketserver()->Wait(250, false);
56 }
57
58 private:
59 SignalThreadTest* harness_;
henrikg3c089d72015-09-16 05:37:44 -070060 RTC_DISALLOW_COPY_AND_ASSIGN(SlowSignalThread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000061 };
62
63 void OnWorkComplete(rtc::SignalThread* thread) {
64 SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
65 EXPECT_EQ(t->harness(), this);
66 EXPECT_EQ(main_thread_, Thread::Current());
67
68 ++thread_completed_;
69 if (!called_release_) {
70 thread->Release();
71 }
72 }
73
74 virtual void SetUp() {
75 main_thread_ = Thread::Current();
76 thread_ = new SlowSignalThread(this);
77 thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
78 called_release_ = false;
79 thread_started_ = 0;
80 thread_done_ = 0;
81 thread_completed_ = 0;
82 thread_stopped_ = 0;
83 thread_deleted_ = 0;
84 }
85
86 virtual void TearDown() {
87 }
88
89 Thread* main_thread_;
90 SlowSignalThread* thread_;
91 bool called_release_;
92
93 int thread_started_;
94 int thread_done_;
95 int thread_completed_;
96 int thread_stopped_;
97 int thread_deleted_;
98};
99
100class OwnerThread : public Thread, public sigslot::has_slots<> {
101 public:
102 explicit OwnerThread(SignalThreadTest* harness)
103 : harness_(harness),
104 has_run_(false) {
105 }
106
107 virtual ~OwnerThread() {
108 Stop();
109 }
110
111 virtual void Run() {
112 SignalThreadTest::SlowSignalThread* signal_thread =
113 new SignalThreadTest::SlowSignalThread(harness_);
114 signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
115 signal_thread->Start();
116 Thread::Current()->socketserver()->Wait(100, false);
117 signal_thread->Release();
118 // Delete |signal_thread|.
119 signal_thread->Destroy(true);
120 has_run_ = true;
121 }
122
123 bool has_run() { return has_run_; }
124 void OnWorkDone(SignalThread* signal_thread) {
125 FAIL() << " This shouldn't get called.";
126 }
127
128 private:
129 SignalThreadTest* harness_;
130 bool has_run_;
henrikg3c089d72015-09-16 05:37:44 -0700131 RTC_DISALLOW_COPY_AND_ASSIGN(OwnerThread);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000132};
133
134// Test for when the main thread goes away while the
135// signal thread is still working. This may happen
136// when shutting down the process.
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000137TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000138 {
139 scoped_ptr<OwnerThread> owner(new OwnerThread(this));
140 main_thread_ = owner.get();
141 owner->Start();
142 while (!owner->has_run()) {
143 Thread::Current()->socketserver()->Wait(10, false);
144 }
145 }
146 // At this point the main thread has gone away.
147 // Give the SignalThread a little time to do its callback,
148 // which will crash if the signal thread doesn't handle
149 // this situation well.
150 Thread::Current()->socketserver()->Wait(500, false);
151}
152
153#define EXPECT_STATE(started, done, completed, stopped, deleted) \
154 EXPECT_EQ(started, thread_started_); \
155 EXPECT_EQ(done, thread_done_); \
156 EXPECT_EQ(completed, thread_completed_); \
157 EXPECT_EQ(stopped, thread_stopped_); \
158 EXPECT_EQ(deleted, thread_deleted_);
159
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000160TEST_F(SignalThreadTest, ThreadFinishes) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000161 thread_->Start();
162 EXPECT_STATE(1, 0, 0, 0, 0);
163 Thread::SleepMs(500);
164 EXPECT_STATE(1, 0, 0, 0, 0);
165 Thread::Current()->ProcessMessages(0);
166 EXPECT_STATE(1, 1, 1, 0, 1);
167}
168
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000169TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000170 thread_->Start();
171 EXPECT_STATE(1, 0, 0, 0, 0);
172 thread_->Release();
173 called_release_ = true;
174 EXPECT_STATE(1, 0, 0, 0, 0);
175 Thread::SleepMs(500);
176 EXPECT_STATE(1, 0, 0, 0, 0);
177 Thread::Current()->ProcessMessages(0);
178 EXPECT_STATE(1, 1, 1, 0, 1);
179}
180
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000181TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000182 thread_->Start();
183 EXPECT_STATE(1, 0, 0, 0, 0);
184 thread_->Destroy(true);
185 EXPECT_STATE(1, 0, 0, 1, 1);
186 Thread::Current()->ProcessMessages(0);
187 EXPECT_STATE(1, 0, 0, 1, 1);
188}
189
henrike@webrtc.orgc732a3e2014-10-09 22:08:15 +0000190TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000191 thread_->Start();
192 EXPECT_STATE(1, 0, 0, 0, 0);
193 thread_->Destroy(false);
194 EXPECT_STATE(1, 0, 0, 1, 0);
195 Thread::SleepMs(500);
196 EXPECT_STATE(1, 0, 0, 1, 0);
197 Thread::Current()->ProcessMessages(0);
198 EXPECT_STATE(1, 1, 0, 1, 1);
199}