##// END OF EJS Templates
test-lock.py: fix testing for forks...
test-lock.py: fix testing for forks The earlier test worked only because the held count went up to 2, so the first release brought it down to 1. Making a copy of the lock fixes that issue.

File last commit:

r26386:146cccdb default
r26386:146cccdb default
Show More
test-lock.py
155 lines | 4.7 KiB | text/x-python | PythonLexer
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 from __future__ import absolute_import
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 import copy
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 import os
import silenttestrunner
import tempfile
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 import types
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 import unittest
from mercurial import (
lock,
scmutil,
)
testlockname = 'testlock'
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 # work around http://bugs.python.org/issue1515
if types.MethodType not in copy._deepcopy_dispatch:
def _deepcopy_method(x, memo):
return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class)
copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
Siddharth Agarwal
test-lock.py: add a lock wrapper that allows faking the PID...
r26384 class lockwrapper(lock.lock):
def __init__(self, pidoffset, *args, **kwargs):
# lock.lock.__init__() calls lock(), so the pidoffset assignment needs
# to be earlier
self._pidoffset = pidoffset
super(lockwrapper, self).__init__(*args, **kwargs)
def _getpid(self):
return os.getpid() + self._pidoffset
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 class teststate(object):
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 def __init__(self, testcase, dir, pidoffset=0):
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 self._testcase = testcase
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 self._acquirecalled = False
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 self._releasecalled = False
self._postreleasecalled = False
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 self.vfs = scmutil.vfs(dir, audit=False)
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 self._pidoffset = pidoffset
Siddharth Agarwal
tests: add unit tests for locking code...
r26289
def makelock(self, *args, **kwargs):
Siddharth Agarwal
test-lock.py: allow PID to be changed in test state...
r26385 l = lockwrapper(self._pidoffset, self.vfs, testlockname,
releasefn=self.releasefn, acquirefn=self.acquirefn,
*args, **kwargs)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 l.postrelease.append(self.postreleasefn)
return l
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 def acquirefn(self):
self._acquirecalled = True
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 def releasefn(self):
self._releasecalled = True
def postreleasefn(self):
self._postreleasecalled = True
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 def assertacquirecalled(self, called):
self._testcase.assertEqual(
self._acquirecalled, called,
'expected acquire to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._acquirecalled),
))
def resetacquirefn(self):
self._acquirecalled = False
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 def assertreleasecalled(self, called):
self._testcase.assertEqual(
self._releasecalled, called,
'expected release to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._releasecalled),
))
def assertpostreleasecalled(self, called):
self._testcase.assertEqual(
self._postreleasecalled, called,
'expected postrelease to be %s but was actually %s' % (
self._tocalled(called),
self._tocalled(self._postreleasecalled),
))
def assertlockexists(self, exists):
actual = self.vfs.lexists(testlockname)
self._testcase.assertEqual(
actual, exists,
'expected lock to %s but actually did %s' % (
self._toexists(exists),
self._toexists(actual),
))
def _tocalled(self, called):
if called:
return 'called'
else:
return 'not called'
def _toexists(self, exists):
if exists:
Siddharth Agarwal
test-lock.py: copy-edit assertions about file existing...
r26381 return 'exist'
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 else:
Siddharth Agarwal
test-lock.py: copy-edit assertions about file existing...
r26381 return 'not exist'
Siddharth Agarwal
tests: add unit tests for locking code...
r26289
class testlock(unittest.TestCase):
def testlock(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.release()
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
def testrecursivelock(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
state.resetacquirefn()
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.lock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 # recursive lock should not call acquirefn again
state.assertacquirecalled(False)
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock.release() # brings lock refcount down from 2 to 1
state.assertreleasecalled(False)
state.assertpostreleasecalled(False)
state.assertlockexists(True)
lock.release() # releases the lock
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
def testlockfork(self):
Siddharth Agarwal
test-lock.py: move temp dir generation to testcase...
r26382 state = teststate(self, tempfile.mkdtemp(dir=os.getcwd()))
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 lock = state.makelock()
Siddharth Agarwal
lock: move acquirefn call to inside the lock...
r26321 state.assertacquirecalled(True)
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 # fake a fork
Siddharth Agarwal
test-lock.py: fix testing for forks...
r26386 forklock = copy.deepcopy(lock)
forklock._pidoffset = 1
forklock.release()
Siddharth Agarwal
tests: add unit tests for locking code...
r26289 state.assertreleasecalled(False)
state.assertpostreleasecalled(False)
state.assertlockexists(True)
# release the actual lock
lock.release()
state.assertreleasecalled(True)
state.assertpostreleasecalled(True)
state.assertlockexists(False)
if __name__ == '__main__':
silenttestrunner.main(__name__)