Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 90c942d1

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