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