def test_rmlinkError(self): """ An exception raised by L{rmlink} other than C{ENOENT} is passed up to the caller of L{FilesystemLock.lock}. """ def fakeRmlink(name): raise OSError(errno.ENOSYS, None) self.patch(lockfile, 'rmlink', fakeRmlink) def fakeKill(pid, signal): if signal != 0: raise OSError(errno.EPERM, None) if pid == 43125: raise OSError(errno.ESRCH, None) self.patch(lockfile, 'kill', fakeKill) lockf = self.mktemp() # Make it appear locked so it has to use readlink lockfile.symlink(str(43125), lockf) lock = lockfile.FilesystemLock(lockf) exc = self.assertRaises(OSError, lock.lock) self.assertEqual(exc.errno, errno.ENOSYS) self.assertFalse(lock.locked)
def test_lockReleasedBeforeCheck(self): """ If the lock is initially held but then released before it can be examined to determine if the process which held it still exists, it is acquired and the C{clean} and C{locked} attributes are set to C{True}. """ def fakeReadlink(name): # Pretend to be another process releasing the lock. lockfile.rmlink(lockf) # Fall back to the real implementation of readlink. readlinkPatch.restore() return lockfile.readlink(name) readlinkPatch = self.patch(lockfile, 'readlink', fakeReadlink) def fakeKill(pid, signal): if signal != 0: raise OSError(errno.EPERM, None) if pid == 43125: raise OSError(errno.ESRCH, None) self.patch(lockfile, 'kill', fakeKill) lockf = self.mktemp() lock = lockfile.FilesystemLock(lockf) lockfile.symlink(str(43125), lockf) self.assertTrue(lock.lock()) self.assertTrue(lock.clean) self.assertTrue(lock.locked)
def test_lockCleanedUpConcurrently(self): """ If a second process cleans up the lock after a first one checks the lock and finds that no process is holding it, the first process does not fail when it tries to clean up the lock. """ def fakeRmlink(name): rmlinkPatch.restore() # Pretend to be another process cleaning up the lock. lockfile.rmlink(lockf) # Fall back to the real implementation of rmlink. return lockfile.rmlink(name) rmlinkPatch = self.patch(lockfile, 'rmlink', fakeRmlink) def fakeKill(pid, signal): if signal != 0: raise OSError(errno.EPERM, None) if pid == 43125: raise OSError(errno.ESRCH, None) self.patch(lockfile, 'kill', fakeKill) lockf = self.mktemp() lock = lockfile.FilesystemLock(lockf) lockfile.symlink(str(43125), lockf) self.assertTrue(lock.lock()) self.assertTrue(lock.clean) self.assertTrue(lock.locked)
def test_symlinkEEXIST(self): """ L{lockfile.symlink} raises L{OSError} with C{errno} set to L{EEXIST} when an attempt is made to create a symlink which already exists. """ name = self.mktemp() lockfile.symlink('foo', name) exc = self.assertRaises(OSError, lockfile.symlink, 'foo', name) self.assertEqual(exc.errno, errno.EEXIST)
def test_unlockOther(self): """ L{FilesystemLock.unlock} raises L{ValueError} if called for a lock which is held by a different process. """ lockf = self.mktemp() lockfile.symlink(str(os.getpid() + 1), lockf) lock = lockfile.FilesystemLock(lockf) self.assertRaises(ValueError, lock.unlock)
def _readlinkErrorTest(self, exceptionType, errno): def fakeReadlink(name): raise exceptionType(errno, None) self.patch(lockfile, 'readlink', fakeReadlink) lockf = self.mktemp() # Make it appear locked so it has to use readlink lockfile.symlink(str(43125), lockf) lock = lockfile.FilesystemLock(lockf) exc = self.assertRaises(exceptionType, lock.lock) self.assertEqual(exc.errno, errno) self.assertFalse(lock.locked)
def test_lockReleasedDuringAcquireReadlink(self): """ If the lock is initially held but is released while an attempt is made to acquire it, the lock attempt fails and L{FilesystemLock.lock} returns C{False}. """ def fakeReadlink(name): # While another process is doing os.rmdir which the # Windows implementation of rmlink does, a readlink call # will fail with EACCES. raise IOError(errno.EACCES, None) readlinkPatch = self.patch(lockfile, 'readlink', fakeReadlink) lockf = self.mktemp() lock = lockfile.FilesystemLock(lockf) lockfile.symlink(str(43125), lockf) self.assertFalse(lock.lock()) self.assertFalse(lock.locked)
def test_killError(self): """ If L{kill} raises an exception other than L{OSError} with errno set to C{ESRCH}, the exception is passed up to the caller of L{FilesystemLock.lock}. """ def fakeKill(pid, signal): raise OSError(errno.EPERM, None) self.patch(lockfile, 'kill', fakeKill) lockf = self.mktemp() # Make it appear locked so it has to use readlink lockfile.symlink(str(43125), lockf) lock = lockfile.FilesystemLock(lockf) exc = self.assertRaises(OSError, lock.lock) self.assertEqual(exc.errno, errno.EPERM) self.assertFalse(lock.locked)
def test_uncleanlyAcquire(self): """ If a lock was held by a process which no longer exists, it can be acquired, the C{clean} attribute is set to C{False}, and the C{locked} attribute is set to C{True}. """ owner = 12345 def fakeKill(pid, signal): if signal != 0: raise OSError(errno.EPERM, None) if pid == owner: raise OSError(errno.ESRCH, None) lockf = self.mktemp() self.patch(lockfile, 'kill', fakeKill) lockfile.symlink(str(owner), lockf) lock = lockfile.FilesystemLock(lockf) self.assertTrue(lock.lock()) self.assertFalse(lock.clean) self.assertTrue(lock.locked) self.assertEqual(lockfile.readlink(lockf), str(os.getpid()))