Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ cdb08f44

History | View | Annotate | Download (24.8 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 162c1c1f Guido Trotter
class TestSharedLock(unittest.TestCase):
36 d6646186 Guido Trotter
  """SharedLock tests"""
37 162c1c1f Guido Trotter
38 162c1c1f Guido Trotter
  def setUp(self):
39 162c1c1f Guido Trotter
    self.sl = locking.SharedLock()
40 162c1c1f Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
41 162c1c1f Guido Trotter
    self.done = Queue.Queue(0)
42 162c1c1f Guido Trotter
43 162c1c1f Guido Trotter
  def testSequenceAndOwnership(self):
44 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
45 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
46 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
47 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
48 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
49 162c1c1f Guido Trotter
    self.sl.release()
50 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
51 162c1c1f Guido Trotter
    self.sl.acquire()
52 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
53 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=1))
54 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=0))
55 162c1c1f Guido Trotter
    self.sl.release()
56 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
57 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
58 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned())
59 162c1c1f Guido Trotter
    self.assert_(self.sl._is_owned(shared=1))
60 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned(shared=0))
61 162c1c1f Guido Trotter
    self.sl.release()
62 162c1c1f Guido Trotter
    self.assert_(not self.sl._is_owned())
63 162c1c1f Guido Trotter
64 162c1c1f Guido Trotter
  def testBooleanValue(self):
65 162c1c1f Guido Trotter
    # semaphores are supposed to return a true value on a successful acquire
66 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire(shared=1))
67 162c1c1f Guido Trotter
    self.sl.release()
68 162c1c1f Guido Trotter
    self.assert_(self.sl.acquire())
69 162c1c1f Guido Trotter
    self.sl.release()
70 162c1c1f Guido Trotter
71 162c1c1f Guido Trotter
  def testDoubleLockingStoE(self):
72 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
73 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
74 162c1c1f Guido Trotter
75 162c1c1f Guido Trotter
  def testDoubleLockingEtoS(self):
76 162c1c1f Guido Trotter
    self.sl.acquire()
77 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
78 162c1c1f Guido Trotter
79 162c1c1f Guido Trotter
  def testDoubleLockingStoS(self):
80 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
81 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire, shared=1)
82 162c1c1f Guido Trotter
83 162c1c1f Guido Trotter
  def testDoubleLockingEtoE(self):
84 162c1c1f Guido Trotter
    self.sl.acquire()
85 162c1c1f Guido Trotter
    self.assertRaises(AssertionError, self.sl.acquire)
86 162c1c1f Guido Trotter
87 162c1c1f Guido Trotter
  # helper functions: called in a separate thread they acquire the lock, send
88 162c1c1f Guido Trotter
  # their identifier on the done queue, then release it.
89 162c1c1f Guido Trotter
  def _doItSharer(self):
90 a95fd5d7 Guido Trotter
    try:
91 a95fd5d7 Guido Trotter
      self.sl.acquire(shared=1)
92 a95fd5d7 Guido Trotter
      self.done.put('SHR')
93 a95fd5d7 Guido Trotter
      self.sl.release()
94 a95fd5d7 Guido Trotter
    except errors.LockError:
95 a95fd5d7 Guido Trotter
      self.done.put('ERR')
96 162c1c1f Guido Trotter
97 162c1c1f Guido Trotter
  def _doItExclusive(self):
98 a95fd5d7 Guido Trotter
    try:
99 a95fd5d7 Guido Trotter
      self.sl.acquire()
100 a95fd5d7 Guido Trotter
      self.done.put('EXC')
101 a95fd5d7 Guido Trotter
      self.sl.release()
102 a95fd5d7 Guido Trotter
    except errors.LockError:
103 a95fd5d7 Guido Trotter
      self.done.put('ERR')
104 a95fd5d7 Guido Trotter
105 a95fd5d7 Guido Trotter
  def _doItDelete(self):
106 a95fd5d7 Guido Trotter
    try:
107 4354ab03 Guido Trotter
      self.sl.delete()
108 a95fd5d7 Guido Trotter
      self.done.put('DEL')
109 a95fd5d7 Guido Trotter
    except errors.LockError:
110 a95fd5d7 Guido Trotter
      self.done.put('ERR')
111 162c1c1f Guido Trotter
112 162c1c1f Guido Trotter
  def testSharersCanCoexist(self):
113 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
114 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
115 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
116 162c1c1f Guido Trotter
    self.sl.release()
117 162c1c1f Guido Trotter
118 162c1c1f Guido Trotter
  def testExclusiveBlocksExclusive(self):
119 162c1c1f Guido Trotter
    self.sl.acquire()
120 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
121 162c1c1f Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
122 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
123 162c1c1f Guido Trotter
    self.sl.release()
124 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
125 162c1c1f Guido Trotter
126 a95fd5d7 Guido Trotter
  def testExclusiveBlocksDelete(self):
127 a95fd5d7 Guido Trotter
    self.sl.acquire()
128 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
129 a95fd5d7 Guido Trotter
    # give it a bit of time to check that it's not actually doing anything
130 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
131 a95fd5d7 Guido Trotter
    self.sl.release()
132 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
133 a95fd5d7 Guido Trotter
134 162c1c1f Guido Trotter
  def testExclusiveBlocksSharer(self):
135 162c1c1f Guido Trotter
    self.sl.acquire()
136 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
137 162c1c1f Guido Trotter
    time.sleep(0.05)
138 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
139 162c1c1f Guido Trotter
    self.sl.release()
140 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
141 162c1c1f Guido Trotter
142 162c1c1f Guido Trotter
  def testSharerBlocksExclusive(self):
143 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
144 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
145 162c1c1f Guido Trotter
    time.sleep(0.05)
146 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
147 162c1c1f Guido Trotter
    self.sl.release()
148 162c1c1f Guido Trotter
    self.assert_(self.done.get(True, 1))
149 162c1c1f Guido Trotter
150 a95fd5d7 Guido Trotter
  def testSharerBlocksDelete(self):
151 a95fd5d7 Guido Trotter
    self.sl.acquire(shared=1)
152 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
153 a95fd5d7 Guido Trotter
    time.sleep(0.05)
154 a95fd5d7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
155 a95fd5d7 Guido Trotter
    self.sl.release()
156 a95fd5d7 Guido Trotter
    self.assert_(self.done.get(True, 1))
157 a95fd5d7 Guido Trotter
158 162c1c1f Guido Trotter
  def testWaitingExclusiveBlocksSharer(self):
159 162c1c1f Guido Trotter
    self.sl.acquire(shared=1)
160 162c1c1f Guido Trotter
    # the lock is acquired in shared mode...
161 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
162 162c1c1f Guido Trotter
    # ...but now an exclusive is waiting...
163 162c1c1f Guido Trotter
    time.sleep(0.05)
164 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
165 162c1c1f Guido Trotter
    # ...so the sharer should be blocked as well
166 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
167 162c1c1f Guido Trotter
    self.sl.release()
168 162c1c1f Guido Trotter
    # The exclusive passed before
169 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
170 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
171 162c1c1f Guido Trotter
172 162c1c1f Guido Trotter
  def testWaitingSharerBlocksExclusive(self):
173 162c1c1f Guido Trotter
    self.sl.acquire()
174 162c1c1f Guido Trotter
    # the lock is acquired in exclusive mode...
175 162c1c1f Guido Trotter
    Thread(target=self._doItSharer).start()
176 162c1c1f Guido Trotter
    # ...but now a sharer is waiting...
177 162c1c1f Guido Trotter
    time.sleep(0.05)
178 162c1c1f Guido Trotter
    Thread(target=self._doItExclusive).start()
179 162c1c1f Guido Trotter
    # ...the exclusive is waiting too...
180 162c1c1f Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
181 162c1c1f Guido Trotter
    self.sl.release()
182 162c1c1f Guido Trotter
    # The sharer passed before
183 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'SHR')
184 162c1c1f Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'EXC')
185 162c1c1f Guido Trotter
186 a95fd5d7 Guido Trotter
  def testNoNonBlocking(self):
187 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.acquire, blocking=0)
188 a95fd5d7 Guido Trotter
    self.assertRaises(NotImplementedError, self.sl.delete, blocking=0)
189 a95fd5d7 Guido Trotter
    self.sl.acquire()
190 a95fd5d7 Guido Trotter
    self.sl.delete(blocking=0) # Fine, because the lock is already acquired
191 a95fd5d7 Guido Trotter
192 a95fd5d7 Guido Trotter
  def testDelete(self):
193 a95fd5d7 Guido Trotter
    self.sl.delete()
194 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire)
195 84152b96 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.acquire, shared=1)
196 a95fd5d7 Guido Trotter
    self.assertRaises(errors.LockError, self.sl.delete)
197 a95fd5d7 Guido Trotter
198 84152b96 Guido Trotter
  def testNoDeleteIfSharer(self):
199 84152b96 Guido Trotter
    self.sl.acquire(shared=1)
200 84152b96 Guido Trotter
    self.assertRaises(AssertionError, self.sl.delete)
201 84152b96 Guido Trotter
202 a95fd5d7 Guido Trotter
  def testDeletePendingSharersExclusiveDelete(self):
203 a95fd5d7 Guido Trotter
    self.sl.acquire()
204 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
205 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
206 a95fd5d7 Guido Trotter
    time.sleep(0.05)
207 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
208 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
209 a95fd5d7 Guido Trotter
    time.sleep(0.05)
210 a95fd5d7 Guido Trotter
    self.sl.delete()
211 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
212 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
213 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
214 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
215 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
216 a95fd5d7 Guido Trotter
217 a95fd5d7 Guido Trotter
  def testDeletePendingDeleteExclusiveSharers(self):
218 a95fd5d7 Guido Trotter
    self.sl.acquire()
219 a95fd5d7 Guido Trotter
    Thread(target=self._doItDelete).start()
220 a95fd5d7 Guido Trotter
    Thread(target=self._doItExclusive).start()
221 a95fd5d7 Guido Trotter
    time.sleep(0.05)
222 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
223 a95fd5d7 Guido Trotter
    Thread(target=self._doItSharer).start()
224 a95fd5d7 Guido Trotter
    time.sleep(0.05)
225 a95fd5d7 Guido Trotter
    self.sl.delete()
226 a95fd5d7 Guido Trotter
    # The two threads who were pending return both ERR
227 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
228 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
229 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
230 a95fd5d7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
231 a95fd5d7 Guido Trotter
232 162c1c1f Guido Trotter
233 aaae9bc0 Guido Trotter
class TestLockSet(unittest.TestCase):
234 aaae9bc0 Guido Trotter
  """LockSet tests"""
235 aaae9bc0 Guido Trotter
236 aaae9bc0 Guido Trotter
  def setUp(self):
237 aaae9bc0 Guido Trotter
    self.resources = ['one', 'two', 'three']
238 cdb08f44 Michael Hanselmann
    self.ls = locking.LockSet(members=self.resources)
239 aaae9bc0 Guido Trotter
    # helper threads use the 'done' queue to tell the master they finished.
240 aaae9bc0 Guido Trotter
    self.done = Queue.Queue(0)
241 aaae9bc0 Guido Trotter
242 aaae9bc0 Guido Trotter
  def testResources(self):
243 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._names(), set(self.resources))
244 aaae9bc0 Guido Trotter
    newls = locking.LockSet()
245 aaae9bc0 Guido Trotter
    self.assertEquals(newls._names(), set())
246 aaae9bc0 Guido Trotter
247 aaae9bc0 Guido Trotter
  def testAcquireRelease(self):
248 0cc00929 Guido Trotter
    self.assert_(self.ls.acquire('one'))
249 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
250 aaae9bc0 Guido Trotter
    self.ls.release()
251 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
252 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one']), set(['one']))
253 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one']))
254 aaae9bc0 Guido Trotter
    self.ls.release()
255 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
256 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'three'])
257 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'two', 'three']))
258 aaae9bc0 Guido Trotter
    self.ls.release('one')
259 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two', 'three']))
260 aaae9bc0 Guido Trotter
    self.ls.release(['three'])
261 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['two']))
262 aaae9bc0 Guido Trotter
    self.ls.release()
263 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
264 0cc00929 Guido Trotter
    self.assertEquals(self.ls.acquire(['one', 'three']), set(['one', 'three']))
265 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['one', 'three']))
266 aaae9bc0 Guido Trotter
    self.ls.release()
267 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
268 aaae9bc0 Guido Trotter
269 aaae9bc0 Guido Trotter
  def testNoDoubleAcquire(self):
270 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
271 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, 'one')
272 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
273 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two', 'three'])
274 aaae9bc0 Guido Trotter
    self.ls.release()
275 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'])
276 aaae9bc0 Guido Trotter
    self.ls.release('one')
277 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.acquire, ['two'])
278 aaae9bc0 Guido Trotter
    self.ls.release('three')
279 aaae9bc0 Guido Trotter
280 aaae9bc0 Guido Trotter
  def testNoWrongRelease(self):
281 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release)
282 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
283 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.release, 'two')
284 aaae9bc0 Guido Trotter
285 aaae9bc0 Guido Trotter
  def testAddRemove(self):
286 aaae9bc0 Guido Trotter
    self.ls.add('four')
287 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set())
288 aaae9bc0 Guido Trotter
    self.assert_('four' in self.ls._names())
289 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six', 'seven'], acquired=1)
290 aaae9bc0 Guido Trotter
    self.assert_('five' in self.ls._names())
291 aaae9bc0 Guido Trotter
    self.assert_('six' in self.ls._names())
292 aaae9bc0 Guido Trotter
    self.assert_('seven' in self.ls._names())
293 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['five', 'six', 'seven']))
294 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['five', 'six']), ['five', 'six'])
295 aaae9bc0 Guido Trotter
    self.assert_('five' not in self.ls._names())
296 aaae9bc0 Guido Trotter
    self.assert_('six' not in self.ls._names())
297 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven']))
298 aaae9bc0 Guido Trotter
    self.ls.add('eight', acquired=1, shared=1)
299 aaae9bc0 Guido Trotter
    self.assert_('eight' in self.ls._names())
300 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['seven', 'eight']))
301 aaae9bc0 Guido Trotter
    self.ls.remove('seven')
302 aaae9bc0 Guido Trotter
    self.assert_('seven' not in self.ls._names())
303 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls._list_owned(), set(['eight']))
304 aaae9bc0 Guido Trotter
    self.ls.release()
305 aaae9bc0 Guido Trotter
    self.ls.remove(['two'])
306 aaae9bc0 Guido Trotter
    self.assert_('two' not in self.ls._names())
307 aaae9bc0 Guido Trotter
    self.ls.acquire('three')
308 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['three']), ['three'])
309 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
310 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('three'), [])
311 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['one'])
312 aaae9bc0 Guido Trotter
    self.assert_('one' not in self.ls._names())
313 aaae9bc0 Guido Trotter
314 aaae9bc0 Guido Trotter
  def testRemoveNonBlocking(self):
315 aaae9bc0 Guido Trotter
    self.assertRaises(NotImplementedError, self.ls.remove, 'one', blocking=0)
316 aaae9bc0 Guido Trotter
    self.ls.acquire('one')
317 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), ['one'])
318 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
319 3f404fc5 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0),
320 3f404fc5 Guido Trotter
                      ['two', 'three'])
321 aaae9bc0 Guido Trotter
322 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
323 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
324 aaae9bc0 Guido Trotter
    self.ls.add('four')
325 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
326 aaae9bc0 Guido Trotter
327 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
328 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
329 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
330 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
331 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
332 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
333 aaae9bc0 Guido Trotter
334 3b7ed473 Guido Trotter
  def testAcquireSetLock(self):
335 3b7ed473 Guido Trotter
    # acquire the set-lock exclusively
336 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None), set(['one', 'two', 'three']))
337 3b7ed473 Guido Trotter
    # I can still add/remove elements...
338 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three']), ['two', 'three'])
339 3b7ed473 Guido Trotter
    self.assert_(self.ls.add('six'))
340 3b7ed473 Guido Trotter
    self.ls.release()
341 3b7ed473 Guido Trotter
    # share the set-lock
342 3b7ed473 Guido Trotter
    self.assertEquals(self.ls.acquire(None, shared=1), set(['one', 'six']))
343 3b7ed473 Guido Trotter
    # adding new elements is not possible
344 3b7ed473 Guido Trotter
    self.assertRaises(AssertionError, self.ls.add, 'five')
345 3b7ed473 Guido Trotter
    self.ls.release()
346 3b7ed473 Guido Trotter
347 aaae9bc0 Guido Trotter
  def _doLockSet(self, set, shared):
348 aaae9bc0 Guido Trotter
    try:
349 aaae9bc0 Guido Trotter
      self.ls.acquire(set, shared=shared)
350 aaae9bc0 Guido Trotter
      self.done.put('DONE')
351 aaae9bc0 Guido Trotter
      self.ls.release()
352 aaae9bc0 Guido Trotter
    except errors.LockError:
353 aaae9bc0 Guido Trotter
      self.done.put('ERR')
354 aaae9bc0 Guido Trotter
355 3b7ed473 Guido Trotter
  def _doAddSet(self, set):
356 3b7ed473 Guido Trotter
    try:
357 3b7ed473 Guido Trotter
      self.ls.add(set, acquired=1)
358 3b7ed473 Guido Trotter
      self.done.put('DONE')
359 3b7ed473 Guido Trotter
      self.ls.release()
360 3b7ed473 Guido Trotter
    except errors.LockError:
361 3b7ed473 Guido Trotter
      self.done.put('ERR')
362 3b7ed473 Guido Trotter
363 aaae9bc0 Guido Trotter
  def _doRemoveSet(self, set):
364 aaae9bc0 Guido Trotter
    self.done.put(self.ls.remove(set))
365 aaae9bc0 Guido Trotter
366 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
367 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
368 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
369 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
370 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
371 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
372 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
373 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
374 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
375 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
376 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
377 aaae9bc0 Guido Trotter
    self.ls.release()
378 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
379 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
380 aaae9bc0 Guido Trotter
381 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
382 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
383 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
384 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
385 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 0)).start()
386 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
387 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
388 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
389 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 0)).start()
390 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 1)).start()
391 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
392 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
393 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
394 aaae9bc0 Guido Trotter
    self.ls.release()
395 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
396 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
397 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
398 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
399 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
400 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
401 aaae9bc0 Guido Trotter
402 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
403 aaae9bc0 Guido Trotter
    self.ls.add('four')
404 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
405 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
406 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
407 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
408 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
409 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
410 aaae9bc0 Guido Trotter
    self.ls.remove('one')
411 aaae9bc0 Guido Trotter
    self.ls.release()
412 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
413 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
414 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
415 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
416 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
417 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
418 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
419 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
420 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
421 aaae9bc0 Guido Trotter
    self.ls.remove('five')
422 aaae9bc0 Guido Trotter
    self.ls.release()
423 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
424 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
425 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
426 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
427 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
428 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
429 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
430 aaae9bc0 Guido Trotter
    self.ls.remove('four')
431 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['six'])
432 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'])).start()
433 3f404fc5 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
434 aaae9bc0 Guido Trotter
    self.ls.release()
435 aaae9bc0 Guido Trotter
436 3b7ed473 Guido Trotter
  def testConcurrentSharedSetLock(self):
437 3b7ed473 Guido Trotter
    # share the set-lock...
438 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=1)
439 3b7ed473 Guido Trotter
    # ...another thread can share it too
440 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
441 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
442 3b7ed473 Guido Trotter
    # ...or just share some elements
443 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'three'], 1)).start()
444 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
445 3b7ed473 Guido Trotter
    # ...but not add new ones or remove any
446 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
447 3b7ed473 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'], )).start()
448 3b7ed473 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
449 3b7ed473 Guido Trotter
    # this just releases the set-lock
450 3b7ed473 Guido Trotter
    self.ls.release([])
451 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
452 3b7ed473 Guido Trotter
    # release the lock on the actual elements so remove() can proceed too
453 3b7ed473 Guido Trotter
    self.ls.release()
454 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['two'])
455 3b7ed473 Guido Trotter
456 3b7ed473 Guido Trotter
  def testConcurrentExclusiveSetLock(self):
457 3b7ed473 Guido Trotter
    # acquire the set-lock...
458 3b7ed473 Guido Trotter
    self.ls.acquire(None, shared=0)
459 3b7ed473 Guido Trotter
    # ...no one can do anything else
460 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 1)).start()
461 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(None, 0)).start()
462 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['three'], 0)).start()
463 3b7ed473 Guido Trotter
    Thread(target=self._doLockSet, args=(['two'], 1)).start()
464 3b7ed473 Guido Trotter
    Thread(target=self._doAddSet, args=(['nine'])).start()
465 3b7ed473 Guido Trotter
    self.ls.release()
466 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
467 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
468 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
469 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
470 3b7ed473 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
471 3b7ed473 Guido Trotter
472 aaae9bc0 Guido Trotter
473 7ee7c0c7 Guido Trotter
class TestGanetiLockManager(unittest.TestCase):
474 7ee7c0c7 Guido Trotter
475 7ee7c0c7 Guido Trotter
  def setUp(self):
476 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
477 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
478 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
479 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
480 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
481 7ee7c0c7 Guido Trotter
482 7ee7c0c7 Guido Trotter
  def tearDown(self):
483 7ee7c0c7 Guido Trotter
    # Don't try this at home...
484 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
485 7ee7c0c7 Guido Trotter
486 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
487 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
488 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
489 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
490 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
491 7ee7c0c7 Guido Trotter
492 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
493 7ee7c0c7 Guido Trotter
    # We are not passing test=True, so instantiating a new one should fail
494 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
495 7ee7c0c7 Guido Trotter
496 7ee7c0c7 Guido Trotter
  def testLockNames(self):
497 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
498 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
499 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
500 cdb08f44 Michael Hanselmann
                     set(self.instances))
501 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
502 7ee7c0c7 Guido Trotter
503 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
504 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
505 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
506 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
507 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
508 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
509 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
510 7ee7c0c7 Guido Trotter
511 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
512 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
513 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
514 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
515 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
516 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
517 7ee7c0c7 Guido Trotter
518 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
519 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
520 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
521 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
522 cdb08f44 Michael Hanselmann
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE),
523 cdb08f44 Michael Hanselmann
                     set(self.instances))
524 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
525 7ee7c0c7 Guido Trotter
526 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
527 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
528 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
529 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
530 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
531 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
532 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
533 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
534 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
535 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
536 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
537 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
538 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
539 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_CONFIG)
540 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
541 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
542 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
543 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
544 7ee7c0c7 Guido Trotter
545 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
546 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
547 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
548 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
549 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
550 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
551 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
552 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
553 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
554 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
555 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
556 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
557 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
558 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
559 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
560 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
561 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
562 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
563 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
564 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
565 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
566 7ee7c0c7 Guido Trotter
567 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
568 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
569 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
570 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
571 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
572 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
573 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
574 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
575 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
576 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CONFIG, ['config'])
577 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
578 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
579 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
580 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
581 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
582 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
583 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CONFIG, ['config'])
584 7ee7c0c7 Guido Trotter
585 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
586 7ee7c0c7 Guido Trotter
  # some locks at another level.
587 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
588 7ee7c0c7 Guido Trotter
    try:
589 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
590 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
591 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
592 7ee7c0c7 Guido Trotter
      self.GL.release(level)
593 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
594 7ee7c0c7 Guido Trotter
    except errors.LockError:
595 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
596 7ee7c0c7 Guido Trotter
597 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
598 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
599 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
600 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
601 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
602 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
603 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
604 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
605 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
606 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
607 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
608 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_CONFIG)
609 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
610 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
611 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
612 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
613 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
614 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
615 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
616 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
617 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
618 7ee7c0c7 Guido Trotter
619 7ee7c0c7 Guido Trotter
620 162c1c1f Guido Trotter
if __name__ == '__main__':
621 162c1c1f Guido Trotter
  unittest.main()
622 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
623 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)