Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ d2aff862

History | View | Annotate | Download (30.5 kB)

1 162c1c1f Guido Trotter
#!/usr/bin/python
2 162c1c1f Guido Trotter
#
3 162c1c1f Guido Trotter
4 162c1c1f Guido Trotter
# Copyright (C) 2006, 2007 Google Inc.
5 162c1c1f Guido Trotter
#
6 162c1c1f Guido Trotter
# This program is free software; you can redistribute it and/or modify
7 162c1c1f Guido Trotter
# it under the terms of the GNU General Public License as published by
8 162c1c1f Guido Trotter
# the Free Software Foundation; either version 2 of the License, or
9 162c1c1f Guido Trotter
# (at your option) any later version.
10 162c1c1f Guido Trotter
#
11 162c1c1f Guido Trotter
# This program is distributed in the hope that it will be useful, but
12 162c1c1f Guido Trotter
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 162c1c1f Guido Trotter
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 162c1c1f Guido Trotter
# General Public License for more details.
15 162c1c1f Guido Trotter
#
16 162c1c1f Guido Trotter
# You should have received a copy of the GNU General Public License
17 162c1c1f Guido Trotter
# along with this program; if not, write to the Free Software
18 162c1c1f Guido Trotter
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 162c1c1f Guido Trotter
# 0.0510-1301, USA.
20 162c1c1f Guido Trotter
21 162c1c1f Guido Trotter
22 162c1c1f Guido Trotter
"""Script for unittesting the locking module"""
23 162c1c1f Guido Trotter
24 162c1c1f Guido Trotter
25 162c1c1f Guido Trotter
import os
26 162c1c1f Guido Trotter
import unittest
27 162c1c1f Guido Trotter
import time
28 162c1c1f Guido Trotter
import Queue
29 162c1c1f Guido Trotter
30 162c1c1f Guido Trotter
from ganeti import locking
31 a95fd5d7 Guido Trotter
from ganeti import errors
32 162c1c1f Guido Trotter
from threading import Thread
33 162c1c1f Guido Trotter
34 162c1c1f Guido Trotter
35 42a999d1 Guido Trotter
# This is used to test the ssynchronize decorator.
36 42a999d1 Guido Trotter
# Since it's passed as input to a decorator it must be declared as a global.
37 42a999d1 Guido Trotter
_decoratorlock = locking.SharedLock()
38 42a999d1 Guido Trotter
39 42a999d1 Guido Trotter
40 162c1c1f Guido Trotter
class TestSharedLock(unittest.TestCase):
41 d6646186 Guido Trotter
  """SharedLock tests"""
42 162c1c1f Guido Trotter
43 162c1c1f Guido Trotter
  def setUp(self):
44 162c1c1f Guido Trotter
    self.sl = locking.SharedLock()
45 162c1c1f Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
46 162c1c1f Guido Trotter
    self.done = Queue.Queue(0)
47 162c1c1f Guido Trotter
48 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
49 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
50 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
51 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
52 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
53 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
54 162c1c1f Guido Trotter
    self.sl.release()
55 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
56 162c1c1f Guido Trotter
    self.sl.acquire()
57 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
58 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=1))
59 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
60 162c1c1f Guido Trotter
    self.sl.release()
61 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
62 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
63 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
64 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
65 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
66 162c1c1f Guido Trotter
    self.sl.release()
67 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
68 162c1c1f Guido Trotter
69 162c1c1f Guido Trotter
  def testBooleanValue(self):
70 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
71 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
72 162c1c1f Guido Trotter
    self.sl.release()
73 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
74 162c1c1f Guido Trotter
    self.sl.release()
75 162c1c1f Guido Trotter
76 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
77 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
78 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
79 162c1c1f Guido Trotter
80 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
81 162c1c1f Guido Trotter
    self.sl.acquire()
82 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
83 162c1c1f Guido Trotter
84 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
85 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
86 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
87 162c1c1f Guido Trotter
88 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
89 162c1c1f Guido Trotter
    self.sl.acquire()
90 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
91 162c1c1f Guido Trotter
92 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
93 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
94 162c1c1f Guido Trotter
  def _doItSharer(self):
95 a95fd5d7 Guido Trotter
    try:
96 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
97 a95fd5d7 Guido Trotter
      self.done.put('SHR')
98 a95fd5d7 Guido Trotter
      self.sl.release()
99 a95fd5d7 Guido Trotter
    except errors.LockError:
100 a95fd5d7 Guido Trotter
      self.done.put('ERR')
101 162c1c1f Guido Trotter
102 162c1c1f Guido Trotter
  def _doItExclusive(self):
103 a95fd5d7 Guido Trotter
    try:
104 a95fd5d7 Guido Trotter
      self.sl.acquire()
105 a95fd5d7 Guido Trotter
      self.done.put('EXC')
106 a95fd5d7 Guido Trotter
      self.sl.release()
107 a95fd5d7 Guido Trotter
    except errors.LockError:
108 a95fd5d7 Guido Trotter
      self.done.put('ERR')
109 a95fd5d7 Guido Trotter
110 a95fd5d7 Guido Trotter
  def _doItDelete(self):
111 a95fd5d7 Guido Trotter
    try:
112 4354ab03 Guido Trotter
      self.sl.delete()
113 a95fd5d7 Guido Trotter
      self.done.put('DEL')
114 a95fd5d7 Guido Trotter
    except errors.LockError:
115 a95fd5d7 Guido Trotter
      self.done.put('ERR')
116 162c1c1f Guido Trotter
117 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
118 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
119 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
120 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
121 162c1c1f Guido Trotter
    self.sl.release()
122 162c1c1f Guido Trotter
123 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
124 162c1c1f Guido Trotter
    self.sl.acquire()
125 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
126 162c1c1f Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
127 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
128 162c1c1f Guido Trotter
    self.sl.release()
129 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
130 162c1c1f Guido Trotter
131 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
132 a95fd5d7 Guido Trotter
    self.sl.acquire()
133 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
134 a95fd5d7 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
135 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
136 a95fd5d7 Guido Trotter
    self.sl.release()
137 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
138 a95fd5d7 Guido Trotter
139 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
140 162c1c1f Guido Trotter
    self.sl.acquire()
141 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
142 162c1c1f Guido Trotter
    time.sleep(0.05)
143 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
144 162c1c1f Guido Trotter
    self.sl.release()
145 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
146 162c1c1f Guido Trotter
147 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
148 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
149 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
150 162c1c1f Guido Trotter
    time.sleep(0.05)
151 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
152 162c1c1f Guido Trotter
    self.sl.release()
153 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
154 162c1c1f Guido Trotter
155 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
156 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
157 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
158 a95fd5d7 Guido Trotter
    time.sleep(0.05)
159 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
160 a95fd5d7 Guido Trotter
    self.sl.release()
161 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
162 a95fd5d7 Guido Trotter
163 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
164 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
165 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
166 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
167 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
168 162c1c1f Guido Trotter
    time.sleep(0.05)
169 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
170 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
171 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
172 162c1c1f Guido Trotter
    self.sl.release()
173 162c1c1f Guido Trotter
    # The exclusive passed before
174 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
175 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
176 162c1c1f Guido Trotter
177 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
178 162c1c1f Guido Trotter
    self.sl.acquire()
179 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
180 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
181 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
182 162c1c1f Guido Trotter
    time.sleep(0.05)
183 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
184 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
185 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
186 162c1c1f Guido Trotter
    self.sl.release()
187 162c1c1f Guido Trotter
    # The sharer passed before
188 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
189 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
190 162c1c1f Guido Trotter
191 a95fd5d7 Guido Trotter
  def testNoNonBlocking(self):
192 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
193 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
194 a95fd5d7 Guido Trotter
    self.sl.acquire()
195 a95fd5d7 Guido Trotter
    self.sl.delete(blocking=0) # Fine, because the lock is already acquired
196 a95fd5d7 Guido Trotter
197 a95fd5d7 Guido Trotter
  def testDelete(self):
198 a95fd5d7 Guido Trotter
    self.sl.delete()
199 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
200 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
201 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
202 a95fd5d7 Guido Trotter
203 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
204 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
205 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
206 84152b96 Guido Trotter
207 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
208 a95fd5d7 Guido Trotter
    self.sl.acquire()
209 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
210 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
211 a95fd5d7 Guido Trotter
    time.sleep(0.05)
212 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
213 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
214 a95fd5d7 Guido Trotter
    time.sleep(0.05)
215 a95fd5d7 Guido Trotter
    self.sl.delete()
216 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
217 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
218 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
219 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
220 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
221 a95fd5d7 Guido Trotter
222 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
223 a95fd5d7 Guido Trotter
    self.sl.acquire()
224 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
225 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
226 a95fd5d7 Guido Trotter
    time.sleep(0.05)
227 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
228 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
229 a95fd5d7 Guido Trotter
    time.sleep(0.05)
230 a95fd5d7 Guido Trotter
    self.sl.delete()
231 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
232 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
233 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
234 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
235 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
236 a95fd5d7 Guido Trotter
237 162c1c1f Guido Trotter
238 42a999d1 Guido Trotter
class TestSSynchronizedDecorator(unittest.TestCase):
239 42a999d1 Guido Trotter
  """Shared Lock Synchronized decorator test"""
240 42a999d1 Guido Trotter
241 42a999d1 Guido Trotter
  def setUp(self):
242 42a999d1 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
243 42a999d1 Guido Trotter
    self.done = Queue.Queue(0)
244 42a999d1 Guido Trotter
245 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock)
246 42a999d1 Guido Trotter
  def _doItExclusive(self):
247 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned())
248 42a999d1 Guido Trotter
    self.done.put('EXC')
249 42a999d1 Guido Trotter
250 42a999d1 Guido Trotter
  @locking.ssynchronized(_decoratorlock, shared=1)
251 42a999d1 Guido Trotter
  def _doItSharer(self):
252 42a999d1 Guido Trotter
    self.assert_(_decoratorlock._is_owned(shared=1))
253 42a999d1 Guido Trotter
    self.done.put('SHR')
254 42a999d1 Guido Trotter
255 42a999d1 Guido Trotter
  def testDecoratedFunctions(self):
256 42a999d1 Guido Trotter
    self._doItExclusive()
257 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
258 42a999d1 Guido Trotter
    self._doItSharer()
259 42a999d1 Guido Trotter
    self.assert_(not _decoratorlock._is_owned())
260 42a999d1 Guido Trotter
261 42a999d1 Guido Trotter
  def testSharersCanCoexist(self):
262 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
263 42a999d1 Guido Trotter
    Thread(target=self._doItSharer).start()
264 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
265 42a999d1 Guido Trotter
    _decoratorlock.release()
266 42a999d1 Guido Trotter
267 42a999d1 Guido Trotter
  def testExclusiveBlocksExclusive(self):
268 42a999d1 Guido Trotter
    _decoratorlock.acquire()
269 42a999d1 Guido Trotter
    Thread(target=self._doItExclusive).start()
270 42a999d1 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
271 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
272 42a999d1 Guido Trotter
    _decoratorlock.release()
273 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
274 42a999d1 Guido Trotter
275 42a999d1 Guido Trotter
  def testExclusiveBlocksSharer(self):
276 42a999d1 Guido Trotter
    _decoratorlock.acquire()
277 42a999d1 Guido Trotter
    Thread(target=self._doItSharer).start()
278 42a999d1 Guido Trotter
    time.sleep(0.05)
279 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
280 42a999d1 Guido Trotter
    _decoratorlock.release()
281 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
282 42a999d1 Guido Trotter
283 42a999d1 Guido Trotter
  def testSharerBlocksExclusive(self):
284 42a999d1 Guido Trotter
    _decoratorlock.acquire(shared=1)
285 42a999d1 Guido Trotter
    Thread(target=self._doItExclusive).start()
286 42a999d1 Guido Trotter
    time.sleep(0.05)
287 42a999d1 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
288 42a999d1 Guido Trotter
    _decoratorlock.release()
289 42a999d1 Guido Trotter
    self.assert_(self.done.get(True, 1))
290 42a999d1 Guido Trotter
291 42a999d1 Guido Trotter
292 aaae9bc0 Guido Trotter
class TestLockSet(unittest.TestCase):
293 aaae9bc0 Guido Trotter
  """LockSet tests"""
294 aaae9bc0 Guido Trotter
295 aaae9bc0 Guido Trotter
  def setUp(self):
296 aaae9bc0 Guido Trotter
    self.resources = ['one', 'two', 'three']
297 cdb08f44 Michael Hanselmann
    self.ls = locking.LockSet(members=self.resources)
298 aaae9bc0 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
299 aaae9bc0 Guido Trotter
    self.done = Queue.Queue(0)
300 aaae9bc0 Guido Trotter
301 aaae9bc0 Guido Trotter
  def testResources(self):
302 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
303 aaae9bc0 Guido Trotter
    newls = locking.LockSet()
304 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
305 aaae9bc0 Guido Trotter
306 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
307 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
308 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
309 aaae9bc0 Guido Trotter
    self.ls.release()
310 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
311 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
312 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
313 aaae9bc0 Guido Trotter
    self.ls.release()
314 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
315 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
316 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
317 aaae9bc0 Guido Trotter
    self.ls.release('one')
318 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
319 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
320 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
321 aaae9bc0 Guido Trotter
    self.ls.release()
322 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
323 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
324 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
325 aaae9bc0 Guido Trotter
    self.ls.release()
326 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
327 aaae9bc0 Guido Trotter
328 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
329 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
330 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
331 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
332 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
333 aaae9bc0 Guido Trotter
    self.ls.release()
334 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
335 aaae9bc0 Guido Trotter
    self.ls.release('one')
336 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
337 aaae9bc0 Guido Trotter
    self.ls.release('three')
338 aaae9bc0 Guido Trotter
339 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
340 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
341 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
342 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
343 aaae9bc0 Guido Trotter
344 aaae9bc0 Guido Trotter
  def testAddRemove(self):
345 aaae9bc0 Guido Trotter
    self.ls.add('four')
346 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
347 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
348 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
349 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
350 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
351 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
352 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
353 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
354 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
355 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
356 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
357 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight', acquired=1)
358 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
359 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
360 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set([]))
361 d2aff862 Guido Trotter
    self.ls.acquire(None, shared=1)
362 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'eight')
363 d2aff862 Guido Trotter
    self.ls.release()
364 d2aff862 Guido Trotter
    self.ls.acquire(None)
365 d2aff862 Guido Trotter
    self.ls.add('eight', acquired=1)
366 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._names())
367 d2aff862 Guido Trotter
    self.assert_('eight' in self.ls._list_owned())
368 d2aff862 Guido Trotter
    self.ls.add('nine')
369 d2aff862 Guido Trotter
    self.assert_('nine' in self.ls._names())
370 d2aff862 Guido Trotter
    self.assert_('nine' not in self.ls._list_owned())
371 aaae9bc0 Guido Trotter
    self.ls.release()
372 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
373 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
374 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
375 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
376 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
377 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
378 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
379 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
380 aaae9bc0 Guido Trotter
381 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
382 aaae9bc0 Guido Trotter
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
383 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
384 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
385 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
386 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
387 3f404fc5 Guido Trotter
                      ['two', 'three'])
388 aaae9bc0 Guido Trotter
389 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
390 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
391 aaae9bc0 Guido Trotter
    self.ls.add('four')
392 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
393 aaae9bc0 Guido Trotter
394 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
395 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
396 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
397 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
398 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
399 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
400 aaae9bc0 Guido Trotter
401 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
402 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
403 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
404 d4803c24 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
405 d4803c24 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
406 d4803c24 Guido Trotter
    self.assertEquals(self.ls._names(), set(['one', 'two', 'three']))
407 3b7ed473 Guido Trotter
    # I can still add/remove elements...
408 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
409 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
410 3b7ed473 Guido Trotter
    self.ls.release()
411 3b7ed473 Guido Trotter
    # share the set-lock
412 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
413 3b7ed473 Guido Trotter
    # adding new elements is not possible
414 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
415 3b7ed473 Guido Trotter
    self.ls.release()
416 3b7ed473 Guido Trotter
417 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
418 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
419 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
420 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
421 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
422 d4f6a91c Guido Trotter
423 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
424 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
425 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
426 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
427 2e1d6d96 Guido Trotter
    # New locks can still be addded
428 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
429 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
430 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
431 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
432 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
433 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
434 2e1d6d96 Guido Trotter
435 aaae9bc0 Guido Trotter
  def _doLockSet(self, set, shared):
436 aaae9bc0 Guido Trotter
    try:
437 aaae9bc0 Guido Trotter
      self.ls.acquire(set, shared=shared)
438 aaae9bc0 Guido Trotter
      self.done.put('DONE')
439 aaae9bc0 Guido Trotter
      self.ls.release()
440 aaae9bc0 Guido Trotter
    except errors.LockError:
441 aaae9bc0 Guido Trotter
      self.done.put('ERR')
442 aaae9bc0 Guido Trotter
443 3b7ed473 Guido Trotter
  def _doAddSet(self, set):
444 3b7ed473 Guido Trotter
    try:
445 3b7ed473 Guido Trotter
      self.ls.add(set, acquired=1)
446 3b7ed473 Guido Trotter
      self.done.put('DONE')
447 3b7ed473 Guido Trotter
      self.ls.release()
448 3b7ed473 Guido Trotter
    except errors.LockError:
449 3b7ed473 Guido Trotter
      self.done.put('ERR')
450 3b7ed473 Guido Trotter
451 aaae9bc0 Guido Trotter
  def _doRemoveSet(self, set):
452 aaae9bc0 Guido Trotter
    self.done.put(self.ls.remove(set))
453 aaae9bc0 Guido Trotter
454 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
455 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
456 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
457 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
458 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
459 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
460 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
461 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
462 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
463 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
464 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
465 aaae9bc0 Guido Trotter
    self.ls.release()
466 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
467 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
468 aaae9bc0 Guido Trotter
469 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
470 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
471 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
472 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
473 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 0)).start()
474 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
475 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
476 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
477 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 0)).start()
478 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 1)).start()
479 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
480 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
481 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
482 aaae9bc0 Guido Trotter
    self.ls.release()
483 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
484 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
485 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
486 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
487 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
488 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
489 aaae9bc0 Guido Trotter
490 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
491 aaae9bc0 Guido Trotter
    self.ls.add('four')
492 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
493 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
494 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
495 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
496 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
497 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
498 aaae9bc0 Guido Trotter
    self.ls.remove('one')
499 aaae9bc0 Guido Trotter
    self.ls.release()
500 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
501 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
502 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
503 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
504 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
505 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
506 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
507 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
508 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
509 aaae9bc0 Guido Trotter
    self.ls.remove('five')
510 aaae9bc0 Guido Trotter
    self.ls.release()
511 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
512 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
513 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
514 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
515 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
516 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
517 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
518 aaae9bc0 Guido Trotter
    self.ls.remove('four')
519 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['six'])
520 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'])).start()
521 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
522 aaae9bc0 Guido Trotter
    self.ls.release()
523 aaae9bc0 Guido Trotter
524 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
525 3b7ed473 Guido Trotter
    # share the set-lock...
526 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
527 3b7ed473 Guido Trotter
    # ...another thread can share it too
528 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
529 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
530 3b7ed473 Guido Trotter
    # ...or just share some elements
531 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
532 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
533 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
534 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
535 3b7ed473 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'], )).start()
536 3b7ed473 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
537 3b7ed473 Guido Trotter
    # this just releases the set-lock
538 3b7ed473 Guido Trotter
    self.ls.release([])
539 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
540 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
541 3b7ed473 Guido Trotter
    self.ls.release()
542 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
543 3b7ed473 Guido Trotter
544 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
545 3b7ed473 Guido Trotter
    # acquire the set-lock...
546 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
547 3b7ed473 Guido Trotter
    # ...no one can do anything else
548 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
549 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
550 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['three'], 0)).start()
551 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['two'], 1)).start()
552 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
553 b5c0e9d9 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
554 3b7ed473 Guido Trotter
    self.ls.release()
555 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
556 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
557 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
558 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
559 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
560 3b7ed473 Guido Trotter
561 d2aff862 Guido Trotter
  def testConcurrentSetLockAdd(self):
562 d2aff862 Guido Trotter
    self.ls.acquire('one')
563 d2aff862 Guido Trotter
    # Another thread wants the whole SetLock
564 d2aff862 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
565 d2aff862 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
566 d2aff862 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
567 d2aff862 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'four')
568 d2aff862 Guido Trotter
    self.ls.release()
569 d2aff862 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
570 d2aff862 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
571 d2aff862 Guido Trotter
    self.ls.acquire(None)
572 d2aff862 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
573 d2aff862 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
574 d2aff862 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
575 d2aff862 Guido Trotter
    self.ls.add('four')
576 d2aff862 Guido Trotter
    self.ls.add('five', acquired=1)
577 d2aff862 Guido Trotter
    self.ls.add('six', acquired=1, shared=1)
578 d2aff862 Guido Trotter
    self.assertEquals(self.ls._list_owned(),
579 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'five', 'six']))
580 d2aff862 Guido Trotter
    self.assertEquals(self.ls._is_owned(), True)
581 d2aff862 Guido Trotter
    self.assertEquals(self.ls._names(),
582 d2aff862 Guido Trotter
      set(['one', 'two', 'three', 'four', 'five', 'six']))
583 d2aff862 Guido Trotter
    self.ls.release()
584 d2aff862 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
585 d2aff862 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
586 d2aff862 Guido Trotter
587 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
588 b2dabfd6 Guido Trotter
    # get the set-lock
589 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
590 b2dabfd6 Guido Trotter
    # now empty it...
591 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
592 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
593 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
594 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
595 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
596 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
597 b2dabfd6 Guido Trotter
    self.ls.release()
598 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
599 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
600 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
601 b2dabfd6 Guido Trotter
    # empty it again...
602 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
603 b2dabfd6 Guido Trotter
    # now share it...
604 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
605 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
606 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
607 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
608 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
609 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
610 b2dabfd6 Guido Trotter
    self.ls.release()
611 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
612 b2dabfd6 Guido Trotter
613 aaae9bc0 Guido Trotter
614 7ee7c0c7 Guido Trotter
class TestGanetiLockManager(unittest.TestCase):
615 7ee7c0c7 Guido Trotter
616 7ee7c0c7 Guido Trotter
  def setUp(self):
617 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
618 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
619 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
620 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
621 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
622 7ee7c0c7 Guido Trotter
623 7ee7c0c7 Guido Trotter
  def tearDown(self):
624 7ee7c0c7 Guido Trotter
    # Don't try this at home...
625 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
626 7ee7c0c7 Guido Trotter
627 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
628 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
629 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
630 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
631 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
632 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
633 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
634 7ee7c0c7 Guido Trotter
635 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
636 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
637 7ee7c0c7 Guido Trotter
638 7ee7c0c7 Guido Trotter
  def testLockNames(self):
639 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
640 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
641 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
642 cdb08f44 Michael Hanselmann
                     set(self.instances))
643 7ee7c0c7 Guido Trotter
644 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
645 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
646 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
647 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
648 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
649 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
650 7ee7c0c7 Guido Trotter
651 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
652 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
653 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
654 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
655 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
656 7ee7c0c7 Guido Trotter
657 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
658 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
659 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
660 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
661 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
662 cdb08f44 Michael Hanselmann
                     set(self.instances))
663 7ee7c0c7 Guido Trotter
664 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
665 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
666 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
667 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
668 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
669 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
670 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
671 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
672 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
673 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
674 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
675 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
676 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
677 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
678 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
679 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
680 7ee7c0c7 Guido Trotter
681 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
682 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
683 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
684 90c942d1 Guido Trotter
                      set(self.instances))
685 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
686 90c942d1 Guido Trotter
                      set(self.instances))
687 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
688 90c942d1 Guido Trotter
                      set(self.nodes))
689 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
690 90c942d1 Guido Trotter
                      set(self.nodes))
691 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
692 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
693 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
694 d4f6a91c Guido Trotter
695 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
696 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
697 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
698 d4f6a91c Guido Trotter
                      set(self.instances))
699 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
700 d4f6a91c Guido Trotter
                      set(self.instances))
701 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
702 d4f6a91c Guido Trotter
                      set(['n2']))
703 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
704 d4f6a91c Guido Trotter
                      set(['n2']))
705 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
706 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
707 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
708 90c942d1 Guido Trotter
709 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
710 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
711 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
712 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
713 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
714 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
715 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
716 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
717 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
718 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
719 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
720 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
721 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
722 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
723 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
724 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
725 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
726 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
727 7ee7c0c7 Guido Trotter
728 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
729 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
730 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
731 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
732 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
733 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
734 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
735 7ee7c0c7 Guido Trotter
736 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
737 7ee7c0c7 Guido Trotter
  # some locks at another level.
738 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
739 7ee7c0c7 Guido Trotter
    try:
740 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
741 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
742 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
743 7ee7c0c7 Guido Trotter
      self.GL.release(level)
744 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
745 7ee7c0c7 Guido Trotter
    except errors.LockError:
746 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
747 7ee7c0c7 Guido Trotter
748 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
749 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
750 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
751 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
752 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
753 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
754 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
755 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
756 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
757 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
758 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
759 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
760 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
761 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
762 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
763 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
764 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
765 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
766 7ee7c0c7 Guido Trotter
767 7ee7c0c7 Guido Trotter
768 162c1c1f Guido Trotter
if __name__ == '__main__':
769 162c1c1f Guido Trotter
  unittest.main()
770 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
771 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)