Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ d65e5776

History | View | Annotate | Download (28.9 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 aaae9bc0 Guido Trotter
    self.ls.add('eight', acquired=1, shared=1)
358 aaae9bc0 Guido Trotter
    self.assert_('eight' in self.ls._names())
359 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
360 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
361 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
362 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['eight']))
363 aaae9bc0 Guido Trotter
    self.ls.release()
364 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
365 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
366 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
367 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
368 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
369 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
370 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
371 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
372 aaae9bc0 Guido Trotter
373 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
374 aaae9bc0 Guido Trotter
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
375 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
376 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
377 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
378 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
379 3f404fc5 Guido Trotter
                      ['two', 'three'])
380 aaae9bc0 Guido Trotter
381 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
382 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
383 aaae9bc0 Guido Trotter
    self.ls.add('four')
384 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
385 aaae9bc0 Guido Trotter
386 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
387 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
388 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
389 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
390 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
391 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
392 aaae9bc0 Guido Trotter
393 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
394 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
395 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
396 3b7ed473 Guido Trotter
    # I can still add/remove elements...
397 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
398 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
399 3b7ed473 Guido Trotter
    self.ls.release()
400 3b7ed473 Guido Trotter
    # share the set-lock
401 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
402 3b7ed473 Guido Trotter
    # adding new elements is not possible
403 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
404 3b7ed473 Guido Trotter
    self.ls.release()
405 3b7ed473 Guido Trotter
406 d4f6a91c Guido Trotter
  def testAcquireWithRepetitions(self):
407 d4f6a91c Guido Trotter
    self.assertEquals(self.ls.acquire(['two', 'two', 'three'], shared=1),
408 d4f6a91c Guido Trotter
                      set(['two', 'two', 'three']))
409 d4f6a91c Guido Trotter
    self.ls.release(['two', 'two'])
410 d4f6a91c Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['three']))
411 d4f6a91c Guido Trotter
412 2e1d6d96 Guido Trotter
  def testEmptyAcquire(self):
413 2e1d6d96 Guido Trotter
    # Acquire an empty list of locks...
414 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([]), set())
415 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
416 2e1d6d96 Guido Trotter
    # New locks can still be addded
417 2e1d6d96 Guido Trotter
    self.assert_(self.ls.add('six'))
418 2e1d6d96 Guido Trotter
    # "re-acquiring" is not an issue, since we had really acquired nothing
419 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls.acquire([], shared=1), set())
420 2e1d6d96 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
421 2e1d6d96 Guido Trotter
    # We haven't really acquired anything, so we cannot release
422 2e1d6d96 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
423 2e1d6d96 Guido Trotter
424 aaae9bc0 Guido Trotter
  def _doLockSet(self, set, shared):
425 aaae9bc0 Guido Trotter
    try:
426 aaae9bc0 Guido Trotter
      self.ls.acquire(set, shared=shared)
427 aaae9bc0 Guido Trotter
      self.done.put('DONE')
428 aaae9bc0 Guido Trotter
      self.ls.release()
429 aaae9bc0 Guido Trotter
    except errors.LockError:
430 aaae9bc0 Guido Trotter
      self.done.put('ERR')
431 aaae9bc0 Guido Trotter
432 3b7ed473 Guido Trotter
  def _doAddSet(self, set):
433 3b7ed473 Guido Trotter
    try:
434 3b7ed473 Guido Trotter
      self.ls.add(set, acquired=1)
435 3b7ed473 Guido Trotter
      self.done.put('DONE')
436 3b7ed473 Guido Trotter
      self.ls.release()
437 3b7ed473 Guido Trotter
    except errors.LockError:
438 3b7ed473 Guido Trotter
      self.done.put('ERR')
439 3b7ed473 Guido Trotter
440 aaae9bc0 Guido Trotter
  def _doRemoveSet(self, set):
441 aaae9bc0 Guido Trotter
    self.done.put(self.ls.remove(set))
442 aaae9bc0 Guido Trotter
443 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
444 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
445 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
446 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
447 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
448 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
449 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
450 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
451 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
452 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
453 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
454 aaae9bc0 Guido Trotter
    self.ls.release()
455 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
456 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
457 aaae9bc0 Guido Trotter
458 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
459 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
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=('three', 0)).start()
463 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
464 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
465 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
466 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 0)).start()
467 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 1)).start()
468 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
469 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
470 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
471 aaae9bc0 Guido Trotter
    self.ls.release()
472 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
473 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
474 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
475 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
476 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
477 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
478 aaae9bc0 Guido Trotter
479 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
480 aaae9bc0 Guido Trotter
    self.ls.add('four')
481 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
482 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
483 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
484 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
485 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
486 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
487 aaae9bc0 Guido Trotter
    self.ls.remove('one')
488 aaae9bc0 Guido Trotter
    self.ls.release()
489 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
490 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
491 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
492 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
493 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
494 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
495 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
496 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
497 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
498 aaae9bc0 Guido Trotter
    self.ls.remove('five')
499 aaae9bc0 Guido Trotter
    self.ls.release()
500 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
501 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
502 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
503 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
504 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
505 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
506 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
507 aaae9bc0 Guido Trotter
    self.ls.remove('four')
508 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['six'])
509 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'])).start()
510 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
511 aaae9bc0 Guido Trotter
    self.ls.release()
512 aaae9bc0 Guido Trotter
513 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
514 3b7ed473 Guido Trotter
    # share the set-lock...
515 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
516 3b7ed473 Guido Trotter
    # ...another thread can share it too
517 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
518 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
519 3b7ed473 Guido Trotter
    # ...or just share some elements
520 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
521 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
522 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
523 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
524 3b7ed473 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'], )).start()
525 3b7ed473 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
526 3b7ed473 Guido Trotter
    # this just releases the set-lock
527 3b7ed473 Guido Trotter
    self.ls.release([])
528 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
529 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
530 3b7ed473 Guido Trotter
    self.ls.release()
531 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
532 3b7ed473 Guido Trotter
533 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
534 3b7ed473 Guido Trotter
    # acquire the set-lock...
535 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
536 3b7ed473 Guido Trotter
    # ...no one can do anything else
537 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
538 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
539 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['three'], 0)).start()
540 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['two'], 1)).start()
541 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
542 b5c0e9d9 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
543 3b7ed473 Guido Trotter
    self.ls.release()
544 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
545 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
546 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
547 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
548 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
549 3b7ed473 Guido Trotter
550 b2dabfd6 Guido Trotter
  def testEmptyLockSet(self):
551 b2dabfd6 Guido Trotter
    # get the set-lock
552 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None), set(['one', 'two', 'three']))
553 b2dabfd6 Guido Trotter
    # now empty it...
554 b2dabfd6 Guido Trotter
    self.ls.remove(['one', 'two', 'three'])
555 b2dabfd6 Guido Trotter
    # and adds/locks by another thread still wait
556 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
557 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
558 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
559 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
560 b2dabfd6 Guido Trotter
    self.ls.release()
561 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
562 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
563 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
564 b2dabfd6 Guido Trotter
    # empty it again...
565 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.remove(['nine']), ['nine'])
566 b2dabfd6 Guido Trotter
    # now share it...
567 b2dabfd6 Guido Trotter
    self.assertEqual(self.ls.acquire(None, shared=1), set())
568 b2dabfd6 Guido Trotter
    # other sharers can go, adds still wait
569 b2dabfd6 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
570 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
571 b2dabfd6 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
572 b2dabfd6 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
573 b2dabfd6 Guido Trotter
    self.ls.release()
574 b2dabfd6 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
575 b2dabfd6 Guido Trotter
576 aaae9bc0 Guido Trotter
577 7ee7c0c7 Guido Trotter
class TestGanetiLockManager(unittest.TestCase):
578 7ee7c0c7 Guido Trotter
579 7ee7c0c7 Guido Trotter
  def setUp(self):
580 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
581 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
582 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
583 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
584 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
585 7ee7c0c7 Guido Trotter
586 7ee7c0c7 Guido Trotter
  def tearDown(self):
587 7ee7c0c7 Guido Trotter
    # Don't try this at home...
588 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
589 7ee7c0c7 Guido Trotter
590 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
591 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
592 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
593 b10b9d74 Guido Trotter
    # This relationship is also used in the Processor to recursively acquire
594 b10b9d74 Guido Trotter
    # the right locks. Again, please don't break it.
595 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
596 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
597 7ee7c0c7 Guido Trotter
598 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
599 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
600 7ee7c0c7 Guido Trotter
601 7ee7c0c7 Guido Trotter
  def testLockNames(self):
602 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
603 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
604 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
605 cdb08f44 Michael Hanselmann
                     set(self.instances))
606 7ee7c0c7 Guido Trotter
607 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
608 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
609 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
610 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
611 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
612 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
613 7ee7c0c7 Guido Trotter
614 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
615 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
616 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
617 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
618 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
619 7ee7c0c7 Guido Trotter
620 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
621 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
622 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
623 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
624 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
625 cdb08f44 Michael Hanselmann
                     set(self.instances))
626 7ee7c0c7 Guido Trotter
627 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
628 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
629 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
630 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1'])
631 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
632 04e1bfaf Guido Trotter
    self.GL.release(locking.LEVEL_NODE, ['n2'])
633 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
634 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
635 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
636 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set())
637 04e1bfaf Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
638 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
639 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
640 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
641 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
642 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
643 7ee7c0c7 Guido Trotter
644 90c942d1 Guido Trotter
  def testAcquireWholeSets(self):
645 90c942d1 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
646 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
647 90c942d1 Guido Trotter
                      set(self.instances))
648 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
649 90c942d1 Guido Trotter
                      set(self.instances))
650 90c942d1 Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, None, shared=1),
651 90c942d1 Guido Trotter
                      set(self.nodes))
652 90c942d1 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
653 90c942d1 Guido Trotter
                      set(self.nodes))
654 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
655 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
656 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
657 d4f6a91c Guido Trotter
658 d4f6a91c Guido Trotter
  def testAcquireWholeAndPartial(self):
659 d4f6a91c Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
660 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_INSTANCE, None),
661 d4f6a91c Guido Trotter
                      set(self.instances))
662 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE),
663 d4f6a91c Guido Trotter
                      set(self.instances))
664 d4f6a91c Guido Trotter
    self.assertEquals(self.GL.acquire(locking.LEVEL_NODE, ['n2'], shared=1),
665 d4f6a91c Guido Trotter
                      set(['n2']))
666 d4f6a91c Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE),
667 d4f6a91c Guido Trotter
                      set(['n2']))
668 d4f6a91c Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
669 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
670 90c942d1 Guido Trotter
    self.GL.release(locking.LEVEL_CLUSTER)
671 90c942d1 Guido Trotter
672 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
673 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
674 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
675 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
676 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
677 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
678 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
679 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
680 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
681 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
682 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
683 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
684 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
685 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
686 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
687 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
688 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
689 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
690 7ee7c0c7 Guido Trotter
691 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
692 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
693 04e1bfaf Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n2'])
694 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
695 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
696 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
697 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
698 7ee7c0c7 Guido Trotter
699 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
700 7ee7c0c7 Guido Trotter
  # some locks at another level.
701 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
702 7ee7c0c7 Guido Trotter
    try:
703 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
704 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
705 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
706 7ee7c0c7 Guido Trotter
      self.GL.release(level)
707 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
708 7ee7c0c7 Guido Trotter
    except errors.LockError:
709 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
710 7ee7c0c7 Guido Trotter
711 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
712 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
713 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
714 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
715 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
716 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
717 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
718 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
719 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
720 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
721 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
722 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
723 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
724 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
725 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
726 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
727 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
728 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
729 7ee7c0c7 Guido Trotter
730 7ee7c0c7 Guido Trotter
731 162c1c1f Guido Trotter
if __name__ == '__main__':
732 162c1c1f Guido Trotter
  unittest.main()
733 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
734 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)