Revision 19b9ba9a test/ganeti.locking_unittest.py
b/test/ganeti.locking_unittest.py | ||
---|---|---|
27 | 27 |
import time |
28 | 28 |
import Queue |
29 | 29 |
import threading |
30 |
import random |
|
30 | 31 |
|
31 | 32 |
from ganeti import locking |
32 | 33 |
from ganeti import errors |
34 |
from ganeti import utils |
|
33 | 35 |
|
34 | 36 |
import testutils |
35 | 37 |
|
... | ... | |
1422 | 1424 |
self.GL.release(locking.LEVEL_CLUSTER, ['BGL']) |
1423 | 1425 |
|
1424 | 1426 |
|
1427 |
class TestLockMonitor(_ThreadedTestCase): |
|
1428 |
def setUp(self): |
|
1429 |
_ThreadedTestCase.setUp(self) |
|
1430 |
self.lm = locking.LockMonitor() |
|
1431 |
|
|
1432 |
def testSingleThread(self): |
|
1433 |
locks = [] |
|
1434 |
|
|
1435 |
for i in range(100): |
|
1436 |
name = "TestLock%s" % i |
|
1437 |
locks.append(locking.SharedLock(name, monitor=self.lm)) |
|
1438 |
|
|
1439 |
self.assertEqual(len(self.lm._locks), len(locks)) |
|
1440 |
|
|
1441 |
# Delete all locks |
|
1442 |
del locks[:] |
|
1443 |
|
|
1444 |
# The garbage collector might needs some time |
|
1445 |
def _CheckLocks(): |
|
1446 |
if self.lm._locks: |
|
1447 |
raise utils.RetryAgain() |
|
1448 |
|
|
1449 |
utils.Retry(_CheckLocks, 0.1, 30.0) |
|
1450 |
|
|
1451 |
self.assertFalse(self.lm._locks) |
|
1452 |
|
|
1453 |
def testMultiThread(self): |
|
1454 |
locks = [] |
|
1455 |
|
|
1456 |
def _CreateLock(prev, next, name): |
|
1457 |
prev.wait() |
|
1458 |
locks.append(locking.SharedLock(name, monitor=self.lm)) |
|
1459 |
if next: |
|
1460 |
next.set() |
|
1461 |
|
|
1462 |
expnames = [] |
|
1463 |
|
|
1464 |
first = threading.Event() |
|
1465 |
prev = first |
|
1466 |
|
|
1467 |
# Use a deterministic random generator |
|
1468 |
for i in random.Random(4263).sample(range(100), 33): |
|
1469 |
name = "MtTestLock%s" % i |
|
1470 |
expnames.append(name) |
|
1471 |
|
|
1472 |
ev = threading.Event() |
|
1473 |
self._addThread(target=_CreateLock, args=(prev, ev, name)) |
|
1474 |
prev = ev |
|
1475 |
|
|
1476 |
# Add locks |
|
1477 |
first.set() |
|
1478 |
self._waitThreads() |
|
1479 |
|
|
1480 |
# Check order in which locks were added |
|
1481 |
self.assertEqual([i.name for i in locks], expnames) |
|
1482 |
|
|
1483 |
# Sync queries are not supported |
|
1484 |
self.assertRaises(NotImplementedError, self.lm.QueryLocks, ["name"], True) |
|
1485 |
|
|
1486 |
# Check query result |
|
1487 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1488 |
[[name, None, None] for name in utils.NiceSort(expnames)]) |
|
1489 |
|
|
1490 |
# Test exclusive acquire |
|
1491 |
for tlock in locks[::4]: |
|
1492 |
tlock.acquire(shared=0) |
|
1493 |
try: |
|
1494 |
def _GetExpResult(name): |
|
1495 |
if tlock.name == name: |
|
1496 |
return [name, "exclusive", [threading.currentThread().getName()]] |
|
1497 |
return [name, None, None] |
|
1498 |
|
|
1499 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1500 |
[_GetExpResult(name) |
|
1501 |
for name in utils.NiceSort(expnames)]) |
|
1502 |
finally: |
|
1503 |
tlock.release() |
|
1504 |
|
|
1505 |
# Test shared acquire |
|
1506 |
def _Acquire(lock, shared, ev): |
|
1507 |
lock.acquire(shared=shared) |
|
1508 |
try: |
|
1509 |
ev.wait() |
|
1510 |
finally: |
|
1511 |
lock.release() |
|
1512 |
|
|
1513 |
for tlock1 in locks[::11]: |
|
1514 |
for tlock2 in locks[::-15]: |
|
1515 |
if tlock2 == tlock1: |
|
1516 |
continue |
|
1517 |
|
|
1518 |
for tlock3 in locks[::10]: |
|
1519 |
if tlock3 == tlock2: |
|
1520 |
continue |
|
1521 |
|
|
1522 |
ev = threading.Event() |
|
1523 |
|
|
1524 |
# Acquire locks |
|
1525 |
tthreads1 = [] |
|
1526 |
for i in range(3): |
|
1527 |
tthreads1.append(self._addThread(target=_Acquire, |
|
1528 |
args=(tlock1, 1, ev))) |
|
1529 |
tthread2 = self._addThread(target=_Acquire, args=(tlock2, 1, ev)) |
|
1530 |
tthread3 = self._addThread(target=_Acquire, args=(tlock3, 0, ev)) |
|
1531 |
|
|
1532 |
# Check query result |
|
1533 |
for (name, mode, owner) in self.lm.QueryLocks(["name", "mode", |
|
1534 |
"owner"], False): |
|
1535 |
if name == tlock1.name: |
|
1536 |
self.assertEqual(mode, "shared") |
|
1537 |
self.assertEqual(set(owner), set(i.getName() for i in tthreads1)) |
|
1538 |
continue |
|
1539 |
|
|
1540 |
if name == tlock2.name: |
|
1541 |
self.assertEqual(mode, "shared") |
|
1542 |
self.assertEqual(owner, [tthread2.getName()]) |
|
1543 |
continue |
|
1544 |
|
|
1545 |
if name == tlock3.name: |
|
1546 |
self.assertEqual(mode, "exclusive") |
|
1547 |
self.assertEqual(owner, [tthread3.getName()]) |
|
1548 |
continue |
|
1549 |
|
|
1550 |
self.assert_(name in expnames) |
|
1551 |
self.assert_(mode is None) |
|
1552 |
self.assert_(owner is None) |
|
1553 |
|
|
1554 |
# Release locks again |
|
1555 |
ev.set() |
|
1556 |
|
|
1557 |
self._waitThreads() |
|
1558 |
|
|
1559 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1560 |
[[name, None, None] |
|
1561 |
for name in utils.NiceSort(expnames)]) |
|
1562 |
|
|
1563 |
def testDelete(self): |
|
1564 |
lock = locking.SharedLock("TestLock", monitor=self.lm) |
|
1565 |
|
|
1566 |
self.assertEqual(len(self.lm._locks), 1) |
|
1567 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1568 |
[[lock.name, None, None]]) |
|
1569 |
|
|
1570 |
lock.delete() |
|
1571 |
|
|
1572 |
self.assertEqual(self.lm.QueryLocks(["name", "mode", "owner"], False), |
|
1573 |
[[lock.name, "deleted", None]]) |
|
1574 |
self.assertEqual(len(self.lm._locks), 1) |
|
1575 |
|
|
1576 |
|
|
1425 | 1577 |
if __name__ == '__main__': |
1426 | 1578 |
testutils.GanetiTestProgram() |
Also available in: Unified diff