~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to protocols/jabber/googletalk/libjingle/talk/base/sharedexclusivelock_unittest.cc

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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