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#include "webrtc/test/testsupport/gtest_disable.h" 15 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()); 37 EXPECT_FALSE(worker()->RunningForTest()); // not started yet 38 } 39 40 virtual void OnWorkStop() { 41 ++harness_->thread_stopped_; 42 EXPECT_EQ(harness_->main_thread_, Thread::Current()); 43 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet 44 } 45 46 virtual void OnWorkDone() { 47 ++harness_->thread_done_; 48 EXPECT_EQ(harness_->main_thread_, Thread::Current()); 49 EXPECT_TRUE(worker()->RunningForTest()); // not stopped yet 50 } 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_; 60 DISALLOW_EVIL_CONSTRUCTORS(SlowSignalThread); 61 }; 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_; 131 DISALLOW_EVIL_CONSTRUCTORS(OwnerThread); 132}; 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. 137TEST_F(SignalThreadTest, DISABLED_ON_MAC(OwnerThreadGoesAway)) { 138 { 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 160TEST_F(SignalThreadTest, DISABLED_ON_MAC(ThreadFinishes)) { 161 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 169TEST_F(SignalThreadTest, DISABLED_ON_MAC(ReleasedThreadFinishes)) { 170 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 181TEST_F(SignalThreadTest, DISABLED_ON_MAC(DestroyedThreadCleansUp)) { 182 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 190TEST_F(SignalThreadTest, DISABLED_ON_MAC(DeferredDestroyedThreadCleansUp)) { 191 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} 200