Upstream version 8.37.180.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / signalthread_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2004--2011, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "talk/base/gunit.h"
29 #include "talk/base/signalthread.h"
30 #include "talk/base/thread.h"
31
32 using namespace talk_base;
33
34 class SignalThreadTest : public testing::Test, public sigslot::has_slots<> {
35  public:
36   class SlowSignalThread : public SignalThread {
37    public:
38     SlowSignalThread(SignalThreadTest* harness) : harness_(harness) {
39     }
40
41     virtual ~SlowSignalThread() {
42       EXPECT_EQ(harness_->main_thread_, Thread::Current());
43       ++harness_->thread_deleted_;
44     }
45
46     const SignalThreadTest* harness() { return harness_; }
47
48    protected:
49     virtual void OnWorkStart() {
50       ASSERT_TRUE(harness_ != NULL);
51       ++harness_->thread_started_;
52       EXPECT_EQ(harness_->main_thread_, Thread::Current());
53       EXPECT_FALSE(worker()->RunningForTest());  // not started yet
54     }
55
56     virtual void OnWorkStop() {
57       ++harness_->thread_stopped_;
58       EXPECT_EQ(harness_->main_thread_, Thread::Current());
59       EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
60     }
61
62     virtual void OnWorkDone() {
63       ++harness_->thread_done_;
64       EXPECT_EQ(harness_->main_thread_, Thread::Current());
65       EXPECT_TRUE(worker()->RunningForTest());  // not stopped yet
66     }
67
68     virtual void DoWork() {
69       EXPECT_NE(harness_->main_thread_, Thread::Current());
70       EXPECT_EQ(worker(), Thread::Current());
71       Thread::Current()->socketserver()->Wait(250, false);
72     }
73
74    private:
75     SignalThreadTest* harness_;
76     DISALLOW_EVIL_CONSTRUCTORS(SlowSignalThread);
77   };
78
79   void OnWorkComplete(talk_base::SignalThread* thread) {
80     SlowSignalThread* t = static_cast<SlowSignalThread*>(thread);
81     EXPECT_EQ(t->harness(), this);
82     EXPECT_EQ(main_thread_, Thread::Current());
83
84     ++thread_completed_;
85     if (!called_release_) {
86       thread->Release();
87     }
88   }
89
90   virtual void SetUp() {
91     main_thread_ = Thread::Current();
92     thread_ = new SlowSignalThread(this);
93     thread_->SignalWorkDone.connect(this, &SignalThreadTest::OnWorkComplete);
94     called_release_ = false;
95     thread_started_ = 0;
96     thread_done_ = 0;
97     thread_completed_ = 0;
98     thread_stopped_ = 0;
99     thread_deleted_ = 0;
100   }
101
102   virtual void TearDown() {
103   }
104
105   Thread* main_thread_;
106   SlowSignalThread* thread_;
107   bool called_release_;
108
109   int thread_started_;
110   int thread_done_;
111   int thread_completed_;
112   int thread_stopped_;
113   int thread_deleted_;
114 };
115
116 class OwnerThread : public Thread, public sigslot::has_slots<> {
117  public:
118   explicit OwnerThread(SignalThreadTest* harness)
119       : harness_(harness),
120         has_run_(false) {
121   }
122
123   virtual ~OwnerThread() {
124     Stop();
125   }
126
127   virtual void Run() {
128     SignalThreadTest::SlowSignalThread* signal_thread =
129         new SignalThreadTest::SlowSignalThread(harness_);
130     signal_thread->SignalWorkDone.connect(this, &OwnerThread::OnWorkDone);
131     signal_thread->Start();
132     Thread::Current()->socketserver()->Wait(100, false);
133     signal_thread->Release();
134     // Delete |signal_thread|.
135     signal_thread->Destroy(true);
136     has_run_ = true;
137   }
138
139   bool has_run() { return has_run_; }
140   void OnWorkDone(SignalThread* signal_thread) {
141     FAIL() << " This shouldn't get called.";
142   }
143
144  private:
145   SignalThreadTest* harness_;
146   bool has_run_;
147   DISALLOW_EVIL_CONSTRUCTORS(OwnerThread);
148 };
149
150 // Test for when the main thread goes away while the
151 // signal thread is still working.  This may happen
152 // when shutting down the process.
153 TEST_F(SignalThreadTest, OwnerThreadGoesAway) {
154   {
155     scoped_ptr<OwnerThread> owner(new OwnerThread(this));
156     main_thread_ = owner.get();
157     owner->Start();
158     while (!owner->has_run()) {
159       Thread::Current()->socketserver()->Wait(10, false);
160     }
161   }
162   // At this point the main thread has gone away.
163   // Give the SignalThread a little time to do its callback,
164   // which will crash if the signal thread doesn't handle
165   // this situation well.
166   Thread::Current()->socketserver()->Wait(500, false);
167 }
168
169 #define EXPECT_STATE(started, done, completed, stopped, deleted) \
170   EXPECT_EQ(started, thread_started_); \
171   EXPECT_EQ(done, thread_done_); \
172   EXPECT_EQ(completed, thread_completed_); \
173   EXPECT_EQ(stopped, thread_stopped_); \
174   EXPECT_EQ(deleted, thread_deleted_);
175
176 TEST_F(SignalThreadTest, ThreadFinishes) {
177   thread_->Start();
178   EXPECT_STATE(1, 0, 0, 0, 0);
179   Thread::SleepMs(500);
180   EXPECT_STATE(1, 0, 0, 0, 0);
181   Thread::Current()->ProcessMessages(0);
182   EXPECT_STATE(1, 1, 1, 0, 1);
183 }
184
185 TEST_F(SignalThreadTest, ReleasedThreadFinishes) {
186   thread_->Start();
187   EXPECT_STATE(1, 0, 0, 0, 0);
188   thread_->Release();
189   called_release_ = true;
190   EXPECT_STATE(1, 0, 0, 0, 0);
191   Thread::SleepMs(500);
192   EXPECT_STATE(1, 0, 0, 0, 0);
193   Thread::Current()->ProcessMessages(0);
194   EXPECT_STATE(1, 1, 1, 0, 1);
195 }
196
197 TEST_F(SignalThreadTest, DestroyedThreadCleansUp) {
198   thread_->Start();
199   EXPECT_STATE(1, 0, 0, 0, 0);
200   thread_->Destroy(true);
201   EXPECT_STATE(1, 0, 0, 1, 1);
202   Thread::Current()->ProcessMessages(0);
203   EXPECT_STATE(1, 0, 0, 1, 1);
204 }
205
206 TEST_F(SignalThreadTest, DeferredDestroyedThreadCleansUp) {
207   thread_->Start();
208   EXPECT_STATE(1, 0, 0, 0, 0);
209   thread_->Destroy(false);
210   EXPECT_STATE(1, 0, 0, 1, 0);
211   Thread::SleepMs(500);
212   EXPECT_STATE(1, 0, 0, 1, 0);
213   Thread::Current()->ProcessMessages(0);
214   EXPECT_STATE(1, 1, 0, 1, 1);
215 }