Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/talk/base/sharedexclusivelock_unittest.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 7.0 KB
Line 
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
37namespace talk_base {
38
39static const uint32 kMsgRead = 0;
40static const uint32 kMsgWrite = 0;
41static const int kNoWaitThresholdInMs = 10;
42static const int kWaitThresholdInMs = 80;
43static const int kProcessTimeInMs = 100;
44static const int kProcessTimeoutInMs = 5000;
45
46class 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
69class 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
102class 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.
136class 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
151TEST_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
176TEST_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
195TEST_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
215TEST_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
Note: See TracBrowser for help on using the repository browser.