Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ 7ee7c0c7

History | View | Annotate | Download (22.3 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 aaae9bc0 Guido Trotter
    self.ls = locking.LockSet(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 aaae9bc0 Guido Trotter
    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 aaae9bc0 Guido Trotter
    self.ls.acquire(['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 aaae9bc0 Guido Trotter
    self.ls.acquire(['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 aaae9bc0 Guido Trotter
    self.ls.remove(['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 aaae9bc0 Guido Trotter
    self.ls.remove(['three'])
309 aaae9bc0 Guido Trotter
    self.assert_('three' not in self.ls._names())
310 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls.remove('three'), ['three'])
311 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls.remove(['one', 'three', 'six']), ['three', 'six'])
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 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls.remove('one', blocking=0), [])
318 aaae9bc0 Guido Trotter
    self.ls.acquire(['two', 'three'])
319 aaae9bc0 Guido Trotter
    self.assertEquals(self.ls.remove(['two', 'three'], blocking=0), [])
320 aaae9bc0 Guido Trotter
321 aaae9bc0 Guido Trotter
  def testNoDoubleAdd(self):
322 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'two')
323 aaae9bc0 Guido Trotter
    self.ls.add('four')
324 aaae9bc0 Guido Trotter
    self.assertRaises(errors.LockError, self.ls.add, 'four')
325 aaae9bc0 Guido Trotter
326 aaae9bc0 Guido Trotter
  def testNoWrongRemoves(self):
327 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'three'], shared=1)
328 aaae9bc0 Guido Trotter
    # Cannot remove 'two' while holding something which is not a superset
329 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'two')
330 aaae9bc0 Guido Trotter
    # Cannot remove 'three' as we are sharing it
331 aaae9bc0 Guido Trotter
    self.assertRaises(AssertionError, self.ls.remove, 'three')
332 aaae9bc0 Guido Trotter
333 aaae9bc0 Guido Trotter
  def _doLockSet(self, set, shared):
334 aaae9bc0 Guido Trotter
    try:
335 aaae9bc0 Guido Trotter
      self.ls.acquire(set, shared=shared)
336 aaae9bc0 Guido Trotter
      self.done.put('DONE')
337 aaae9bc0 Guido Trotter
      self.ls.release()
338 aaae9bc0 Guido Trotter
    except errors.LockError:
339 aaae9bc0 Guido Trotter
      self.done.put('ERR')
340 aaae9bc0 Guido Trotter
341 aaae9bc0 Guido Trotter
  def _doRemoveSet(self, set):
342 aaae9bc0 Guido Trotter
    self.done.put(self.ls.remove(set))
343 aaae9bc0 Guido Trotter
344 aaae9bc0 Guido Trotter
  def testConcurrentSharedAcquire(self):
345 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'], shared=1)
346 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
347 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
348 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two', 'three'], 1)).start()
349 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
350 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
351 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
352 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
353 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
354 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
355 aaae9bc0 Guido Trotter
    self.ls.release()
356 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
357 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
358 aaae9bc0 Guido Trotter
359 aaae9bc0 Guido Trotter
  def testConcurrentExclusiveAcquire(self):
360 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two'])
361 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 1)).start()
362 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
363 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('three', 0)).start()
364 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
365 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
366 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
367 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 0)).start()
368 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=('one', 1)).start()
369 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 0)).start()
370 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['two', 'three'], 1)).start()
371 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
372 aaae9bc0 Guido Trotter
    self.ls.release()
373 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
374 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
375 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
376 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
377 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
378 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
379 aaae9bc0 Guido Trotter
380 aaae9bc0 Guido Trotter
  def testConcurrentRemove(self):
381 aaae9bc0 Guido Trotter
    self.ls.add('four')
382 aaae9bc0 Guido Trotter
    self.ls.acquire(['one', 'two', 'four'])
383 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 0)).start()
384 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'four'], 1)).start()
385 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 0)).start()
386 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['one', 'two'], 1)).start()
387 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
388 aaae9bc0 Guido Trotter
    self.ls.remove('one')
389 aaae9bc0 Guido Trotter
    self.ls.release()
390 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
391 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
392 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
393 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'ERR')
394 aaae9bc0 Guido Trotter
    self.ls.add(['five', 'six'], acquired=1)
395 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 1)).start()
396 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['three', 'six'], 0)).start()
397 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 1)).start()
398 aaae9bc0 Guido Trotter
    Thread(target=self._doLockSet, args=(['four', 'six'], 0)).start()
399 aaae9bc0 Guido Trotter
    self.ls.remove('five')
400 aaae9bc0 Guido Trotter
    self.ls.release()
401 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
402 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
403 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
404 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
405 aaae9bc0 Guido Trotter
    self.ls.acquire(['three', 'four'])
406 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['four', 'six'], )).start()
407 aaae9bc0 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
408 aaae9bc0 Guido Trotter
    self.ls.remove('four')
409 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), ['four'])
410 aaae9bc0 Guido Trotter
    Thread(target=self._doRemoveSet, args=(['two'])).start()
411 aaae9bc0 Guido Trotter
    self.assertEqual(self.done.get(True, 1), [])
412 aaae9bc0 Guido Trotter
    self.ls.release()
413 aaae9bc0 Guido Trotter
414 aaae9bc0 Guido Trotter
415 7ee7c0c7 Guido Trotter
class TestGanetiLockManager(unittest.TestCase):
416 7ee7c0c7 Guido Trotter
417 7ee7c0c7 Guido Trotter
  def setUp(self):
418 7ee7c0c7 Guido Trotter
    self.nodes=['n1', 'n2']
419 7ee7c0c7 Guido Trotter
    self.instances=['i1', 'i2', 'i3']
420 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes,
421 7ee7c0c7 Guido Trotter
                                        instances=self.instances)
422 7ee7c0c7 Guido Trotter
    self.done = Queue.Queue(0)
423 7ee7c0c7 Guido Trotter
424 7ee7c0c7 Guido Trotter
  def tearDown(self):
425 7ee7c0c7 Guido Trotter
    # Don't try this at home...
426 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
427 7ee7c0c7 Guido Trotter
428 7ee7c0c7 Guido Trotter
  def testLockingConstants(self):
429 7ee7c0c7 Guido Trotter
    # The locking library internally cheats by assuming its constants have some
430 7ee7c0c7 Guido Trotter
    # relationships with each other. Check those hold true.
431 7ee7c0c7 Guido Trotter
    for i in range(len(locking.LEVELS)):
432 7ee7c0c7 Guido Trotter
      self.assertEqual(i, locking.LEVELS[i])
433 7ee7c0c7 Guido Trotter
434 7ee7c0c7 Guido Trotter
  def testDoubleGLFails(self):
435 7ee7c0c7 Guido Trotter
    # We are not passing test=True, so instantiating a new one should fail
436 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, locking.GanetiLockManager)
437 7ee7c0c7 Guido Trotter
438 7ee7c0c7 Guido Trotter
  def testLockNames(self):
439 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
440 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
441 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(self.instances))
442 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
443 7ee7c0c7 Guido Trotter
444 7ee7c0c7 Guido Trotter
  def testInitAndResources(self):
445 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
446 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager()
447 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
448 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
449 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
450 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
451 7ee7c0c7 Guido Trotter
452 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
453 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(nodes=self.nodes)
454 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
455 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set(self.nodes))
456 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set())
457 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
458 7ee7c0c7 Guido Trotter
459 7ee7c0c7 Guido Trotter
    locking.GanetiLockManager._instance = None
460 7ee7c0c7 Guido Trotter
    self.GL = locking.GanetiLockManager(instances=self.instances)
461 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CLUSTER), set(['BGL']))
462 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_NODE), set())
463 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_INSTANCE), set(self.instances))
464 7ee7c0c7 Guido Trotter
    self.assertEqual(self.GL._names(locking.LEVEL_CONFIG), set(['config']))
465 7ee7c0c7 Guido Trotter
466 7ee7c0c7 Guido Trotter
  def testAcquireRelease(self):
467 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
468 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_CLUSTER), set(['BGL']))
469 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1', 'n2'], shared=1)
470 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
471 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
472 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_NODE), set(['n1']))
473 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
474 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
475 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE, ['i2'])
476 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i1']))
477 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
478 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
479 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_CONFIG)
480 7ee7c0c7 Guido Trotter
    self.assertRaises(errors.LockError, self.GL.acquire,
481 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i5'])
482 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'], shared=1)
483 7ee7c0c7 Guido Trotter
    self.assertEquals(self.GL._list_owned(locking.LEVEL_INSTANCE), set(['i3']))
484 7ee7c0c7 Guido Trotter
485 7ee7c0c7 Guido Trotter
  def testBGLDependency(self):
486 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
487 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1', 'n2'])
488 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
489 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i3'])
490 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
491 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
492 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
493 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
494 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
495 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
496 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_NODE)
497 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i1', 'i2'])
498 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
499 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER, ['BGL'])
500 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
501 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
502 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
503 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
504 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.release,
505 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CLUSTER)
506 7ee7c0c7 Guido Trotter
507 7ee7c0c7 Guido Trotter
  def testWrongOrder(self):
508 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
509 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
510 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
511 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
512 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
513 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
514 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
515 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
516 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CONFIG, ['config'])
517 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
518 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
519 7ee7c0c7 Guido Trotter
                      locking.LEVEL_NODE, ['n1'])
520 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
521 7ee7c0c7 Guido Trotter
                      locking.LEVEL_INSTANCE, ['i2'])
522 7ee7c0c7 Guido Trotter
    self.assertRaises(AssertionError, self.GL.acquire,
523 7ee7c0c7 Guido Trotter
                      locking.LEVEL_CONFIG, ['config'])
524 7ee7c0c7 Guido Trotter
525 7ee7c0c7 Guido Trotter
  # Helper function to run as a thread that shared the BGL and then acquires
526 7ee7c0c7 Guido Trotter
  # some locks at another level.
527 7ee7c0c7 Guido Trotter
  def _doLock(self, level, names, shared):
528 7ee7c0c7 Guido Trotter
    try:
529 7ee7c0c7 Guido Trotter
      self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
530 7ee7c0c7 Guido Trotter
      self.GL.acquire(level, names, shared=shared)
531 7ee7c0c7 Guido Trotter
      self.done.put('DONE')
532 7ee7c0c7 Guido Trotter
      self.GL.release(level)
533 7ee7c0c7 Guido Trotter
      self.GL.release(locking.LEVEL_CLUSTER)
534 7ee7c0c7 Guido Trotter
    except errors.LockError:
535 7ee7c0c7 Guido Trotter
      self.done.put('ERR')
536 7ee7c0c7 Guido Trotter
537 7ee7c0c7 Guido Trotter
  def testConcurrency(self):
538 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CLUSTER, ['BGL'], shared=1)
539 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
540 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
541 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_NODE, ['n1'])
542 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i3'])
543 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_CONFIG, ['config'])
544 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i1', 1)).start()
545 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
546 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i3', 1)).start()
547 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
548 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_CONFIG)
549 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
550 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
551 7ee7c0c7 Guido Trotter
    self.GL.acquire(locking.LEVEL_INSTANCE, ['i2'], shared=1)
552 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 1)).start()
553 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
554 7ee7c0c7 Guido Trotter
    Thread(target=self._doLock, args=(locking.LEVEL_INSTANCE, 'i2', 0)).start()
555 7ee7c0c7 Guido Trotter
    self.assertRaises(Queue.Empty, self.done.get, True, 0.2)
556 7ee7c0c7 Guido Trotter
    self.GL.release(locking.LEVEL_INSTANCE)
557 7ee7c0c7 Guido Trotter
    self.assertEqual(self.done.get(True, 1), 'DONE')
558 7ee7c0c7 Guido Trotter
559 7ee7c0c7 Guido Trotter
560 162c1c1f Guido Trotter
if __name__ == '__main__':
561 162c1c1f Guido Trotter
  unittest.main()
562 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
563 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)