- add third_party src.
[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 TEST_F(SharedExclusiveLockTest, TestSharedShared) {
152   int value0, value1;
153   bool done0, done1;
154   ReadTask reader0(shared_exclusive_lock_.get(), &value_, &done0);
155   ReadTask reader1(shared_exclusive_lock_.get(), &value_, &done1);
156
157   // Test shared locks can be shared without waiting.
158   {
159     SharedScope ss(shared_exclusive_lock_.get());
160     value_ = 1;
161     done0 = false;
162     done1 = false;
163     reader0.PostRead(&value0);
164     reader1.PostRead(&value1);
165     Thread::SleepMs(kProcessTimeInMs);
166   }
167
168   EXPECT_TRUE_WAIT(done0, kProcessTimeoutInMs);
169   EXPECT_EQ(1, value0);
170   EXPECT_LE(reader0.waiting_time_in_ms(), kNoWaitThresholdInMs);
171   EXPECT_TRUE_WAIT(done1, kProcessTimeoutInMs);
172   EXPECT_EQ(1, value1);
173   EXPECT_LE(reader1.waiting_time_in_ms(), kNoWaitThresholdInMs);
174 }
175
176 TEST_F(SharedExclusiveLockTest, TestSharedExclusive) {
177   bool done;
178   WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
179
180   // Test exclusive lock needs to wait for shared lock.
181   {
182     SharedScope ss(shared_exclusive_lock_.get());
183     value_ = 1;
184     done = false;
185     writer.PostWrite(2);
186     Thread::SleepMs(kProcessTimeInMs);
187     EXPECT_EQ(1, value_);
188   }
189
190   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
191   EXPECT_EQ(2, value_);
192   EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
193 }
194
195 TEST_F(SharedExclusiveLockTest, TestExclusiveShared) {
196   int value;
197   bool done;
198   ReadTask reader(shared_exclusive_lock_.get(), &value_, &done);
199
200   // Test shared lock needs to wait for exclusive lock.
201   {
202     ExclusiveScope es(shared_exclusive_lock_.get());
203     value_ = 1;
204     done = false;
205     reader.PostRead(&value);
206     Thread::SleepMs(kProcessTimeInMs);
207     value_ = 2;
208   }
209
210   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
211   EXPECT_EQ(2, value);
212   EXPECT_GE(reader.waiting_time_in_ms(), kWaitThresholdInMs);
213 }
214
215 TEST_F(SharedExclusiveLockTest, TestExclusiveExclusive) {
216   bool done;
217   WriteTask writer(shared_exclusive_lock_.get(), &value_, &done);
218
219   // Test exclusive lock needs to wait for exclusive lock.
220   {
221     ExclusiveScope es(shared_exclusive_lock_.get());
222     value_ = 1;
223     done = false;
224     writer.PostWrite(2);
225     Thread::SleepMs(kProcessTimeInMs);
226     EXPECT_EQ(1, value_);
227   }
228
229   EXPECT_TRUE_WAIT(done, kProcessTimeoutInMs);
230   EXPECT_EQ(2, value_);
231   EXPECT_GE(writer.waiting_time_in_ms(), kWaitThresholdInMs);
232 }
233
234 }  // namespace talk_base