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