Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / sharedexclusivelock_unittest.cc
1 /*
2  * libjingle
3  * Copyright 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/common.h"
29 #include "talk/base/gunit.h"
30 #include "talk/base/messagehandler.h"
31 #include "talk/base/messagequeue.h"
32 #include "talk/base/scoped_ptr.h"
33 #include "talk/base/sharedexclusivelock.h"
34 #include "talk/base/thread.h"
35 #include "talk/base/timeutils.h"
36
37 namespace talk_base {
38
39 static const uint32 kMsgRead = 0;
40 static const uint32 kMsgWrite = 0;
41 static const int kNoWaitThresholdInMs = 10;
42 static const int kWaitThresholdInMs = 80;
43 static const int kProcessTimeInMs = 100;
44 static const int kProcessTimeoutInMs = 5000;
45
46 class SharedExclusiveTask : public MessageHandler {
47  public:
48   SharedExclusiveTask(SharedExclusiveLock* shared_exclusive_lock,
49                       int* value,
50                       bool* done)
51       : shared_exclusive_lock_(shared_exclusive_lock),
52         waiting_time_in_ms_(0),
53         value_(value),
54         done_(done) {
55     worker_thread_.reset(new Thread());
56     worker_thread_->Start();
57   }
58
59   int waiting_time_in_ms() const { return waiting_time_in_ms_; }
60
61  protected:
62   scoped_ptr<Thread> worker_thread_;
63   SharedExclusiveLock* shared_exclusive_lock_;
64   int waiting_time_in_ms_;
65   int* value_;
66   bool* done_;
67 };
68
69 class ReadTask : public SharedExclusiveTask {
70  public:
71   ReadTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
72       : SharedExclusiveTask(shared_exclusive_lock, value, done) {
73   }
74
75   void PostRead(int* value) {
76     worker_thread_->Post(this, kMsgRead, new TypedMessageData<int*>(value));
77   }
78
79  private:
80   virtual void OnMessage(Message* message) {
81     ASSERT(talk_base::Thread::Current() == worker_thread_.get());
82     ASSERT(message != NULL);
83     ASSERT(message->message_id == kMsgRead);
84
85     TypedMessageData<int*>* message_data =
86         static_cast<TypedMessageData<int*>*>(message->pdata);
87
88     uint32 start_time = Time();
89     {
90       SharedScope ss(shared_exclusive_lock_);
91       waiting_time_in_ms_ = TimeDiff(Time(), start_time);
92
93       Thread::SleepMs(kProcessTimeInMs);
94       *message_data->data() = *value_;
95       *done_ = true;
96     }
97     delete message->pdata;
98     message->pdata = NULL;
99   }
100 };
101
102 class WriteTask : public SharedExclusiveTask {
103  public:
104   WriteTask(SharedExclusiveLock* shared_exclusive_lock, int* value, bool* done)
105       : SharedExclusiveTask(shared_exclusive_lock, value, done) {
106   }
107
108   void PostWrite(int value) {
109     worker_thread_->Post(this, kMsgWrite, new TypedMessageData<int>(value));
110   }
111
112  private:
113   virtual void OnMessage(Message* message) {
114     ASSERT(talk_base::Thread::Current() == worker_thread_.get());
115     ASSERT(message != NULL);
116     ASSERT(message->message_id == kMsgWrite);
117
118     TypedMessageData<int>* message_data =
119         static_cast<TypedMessageData<int>*>(message->pdata);
120
121     uint32 start_time = Time();
122     {
123       ExclusiveScope es(shared_exclusive_lock_);
124       waiting_time_in_ms_ = TimeDiff(Time(), start_time);
125
126       Thread::SleepMs(kProcessTimeInMs);
127       *value_ = message_data->data();
128       *done_ = true;
129     }
130     delete message->pdata;
131     message->pdata = NULL;
132   }
133 };
134
135 // Unit test for SharedExclusiveLock.
136 class SharedExclusiveLockTest
137     : public testing::Test {
138  public:
139   SharedExclusiveLockTest() : value_(0) {
140   }
141
142   virtual void SetUp() {
143     shared_exclusive_lock_.reset(new SharedExclusiveLock());
144   }
145
146  protected:
147   scoped_ptr<SharedExclusiveLock> shared_exclusive_lock_;
148   int value_;
149 };
150
151 // Flaky: https://code.google.com/p/webrtc/issues/detail?id=3318
152 TEST_F(SharedExclusiveLockTest, DISABLED_TestSharedShared) {
153   int value0, value1;
154   bool done0, done1;
155   ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
156   ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
157
158   // Test shared locks can be shared without waiting.
159   {
160     SharedScope ss(shared_exclusive_lock_.get());
161     value_ = 1;
162     done0 = false;
163     done1 = false;
164     reader0.PostRead(&value0);
165     reader1.PostRead(&value1);
166     Thread::SleepMs(kProcessTimeInMs);
167   }
168
169   EXPECT_TRUE_WAIT(done0, kProcessTimeoutInMs);
170   EXPECT_EQ(1, value0);
171   EXPECT_LE(reader0.waiting_time_in_ms(), kNoWaitThresholdInMs);
172   EXPECT_TRUE_WAIT(done1, kProcessTimeoutInMs);
173   EXPECT_EQ(1, value1);
174   EXPECT_LE(reader1.waiting_time_in_ms(), kNoWaitThresholdInMs);
175 }
176
177 TEST_F(SharedExclusiveLockTest, TestSharedExclusive) {
178   bool done;
179   WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
180
181   // Test exclusive lock needs to wait for shared lock.
182   {
183     SharedScope ss(shared_exclusive_lock_.get());
184     value_ = 1;
185     done = false;
186     writer.PostWrite(2);
187     Thread::SleepMs(kProcessTimeInMs);
188     EXPECT_EQ(1, value_);
189   }
190
191   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
192   EXPECT_EQ(2, value_);
193   EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
194 }
195
196 TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
197   int value;
198   bool done;
199   ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
200
201   // Test shared lock needs to wait for exclusive lock.
202   {
203     ExclusiveScope es(shared_exclusive_lock_.get());
204     value_ = 1;
205     done = false;
206     reader.PostRead(&value);
207     Thread::SleepMs(kProcessTimeInMs);
208     value_ = 2;
209   }
210
211   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
212   EXPECT_EQ(2, value);
213   EXPECT_GE(reader.waiting_time_in_ms(), kWaitThresholdInMs);
214 }
215
216 TEST_F(SharedExclusiveLockTest, TestExclusiveExclusive) {
217   bool done;
218   WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
219
220   // Test exclusive lock needs to wait for exclusive lock.
221   {
222     ExclusiveScope es(shared_exclusive_lock_.get());
223     value_ = 1;
224     done = false;
225     writer.PostWrite(2);
226     Thread::SleepMs(kProcessTimeInMs);
227     EXPECT_EQ(1, value_);
228   }
229
230   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
231   EXPECT_EQ(2, value_);
232   EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
233 }
234
235 }  // namespace talk_base