Statistics
| Branch: | Tag: | Revision:

root / test / ganeti.locking_unittest.py @ c9c4f19e

History | View | Annotate | Download (7.7 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 162c1c1f Guido Trotter
if __name__ == '__main__':
234 162c1c1f Guido Trotter
  unittest.main()
235 162c1c1f Guido Trotter
  #suite = unittest.TestLoader().loadTestsFromTestCase(TestSharedLock)
236 162c1c1f Guido Trotter
  #unittest.TextTestRunner(verbosity=2).run(suite)