blob: c8f952ec591483dfa670271a724fccb0f8df38d8 [file] [log] [blame]
# -*- coding: utf-8 -*-
#
# test/test_pidlockfile.py
# Part of python-daemon, an implementation of PEP 3143.
#
# Copyright © 2008–2010 Ben Finney <ben+python@benfinney.id.au>
#
# This is free software: you may copy, modify, and/or distribute this work
# under the terms of the Python Software Foundation License, version 2 or
# later as published by the Python Software Foundation.
# No warranty expressed or implied. See the file LICENSE.PSF-2 for details.
""" Unit test for pidlockfile module.
"""
import __builtin__
import os
from StringIO import StringIO
import itertools
import tempfile
import errno
import lockfile
import scaffold
from daemon import pidlockfile
class FakeFileDescriptorStringIO(StringIO, object):
""" A StringIO class that fakes a file descriptor. """
_fileno_generator = itertools.count()
def __init__(self, *args, **kwargs):
self._fileno = self._fileno_generator.next()
super_instance = super(FakeFileDescriptorStringIO, self)
super_instance.__init__(*args, **kwargs)
def fileno(self):
return self._fileno
class Exception_TestCase(scaffold.Exception_TestCase):
""" Test cases for module exception classes. """
def __init__(self, *args, **kwargs):
""" Set up a new instance. """
super(Exception_TestCase, self).__init__(*args, **kwargs)
self.valid_exceptions = {
pidlockfile.PIDFileError: dict(
min_args = 1,
types = (Exception,),
),
pidlockfile.PIDFileParseError: dict(
min_args = 2,
types = (pidlockfile.PIDFileError, ValueError),
),
}
def make_pidlockfile_scenarios():
""" Make a collection of scenarios for testing PIDLockFile instances. """
mock_current_pid = 235
mock_other_pid = 8642
mock_pidfile_path = tempfile.mktemp()
mock_pidfile_empty = FakeFileDescriptorStringIO()
mock_pidfile_current_pid = FakeFileDescriptorStringIO(
"%(mock_current_pid)d\n" % vars())
mock_pidfile_other_pid = FakeFileDescriptorStringIO(
"%(mock_other_pid)d\n" % vars())
mock_pidfile_bogus = FakeFileDescriptorStringIO(
"b0gUs")
scenarios = {
'simple': {},
'not-exist': {
'open_func_name': 'mock_open_nonexist',
'os_open_func_name': 'mock_os_open_nonexist',
},
'not-exist-write-denied': {
'open_func_name': 'mock_open_nonexist',
'os_open_func_name': 'mock_os_open_nonexist',
},
'not-exist-write-busy': {
'open_func_name': 'mock_open_nonexist',
'os_open_func_name': 'mock_os_open_nonexist',
},
'exist-read-denied': {
'open_func_name': 'mock_open_read_denied',
'os_open_func_name': 'mock_os_open_read_denied',
},
'exist-locked-read-denied': {
'locking_pid': mock_other_pid,
'open_func_name': 'mock_open_read_denied',
'os_open_func_name': 'mock_os_open_read_denied',
},
'exist-empty': {},
'exist-invalid': {
'pidfile': mock_pidfile_bogus,
},
'exist-current-pid': {
'pidfile': mock_pidfile_current_pid,
'pidfile_pid': mock_current_pid,
},
'exist-current-pid-locked': {
'pidfile': mock_pidfile_current_pid,
'pidfile_pid': mock_current_pid,
'locking_pid': mock_current_pid,
},
'exist-other-pid': {
'pidfile': mock_pidfile_other_pid,
'pidfile_pid': mock_other_pid,
},
'exist-other-pid-locked': {
'pidfile': mock_pidfile_other_pid,
'pidfile_pid': mock_other_pid,
'locking_pid': mock_other_pid,
},
}
for scenario in scenarios.values():
scenario['pid'] = mock_current_pid
scenario['path'] = mock_pidfile_path
if 'pidfile' not in scenario:
scenario['pidfile'] = mock_pidfile_empty
if 'pidfile_pid' not in scenario:
scenario['pidfile_pid'] = None
if 'locking_pid' not in scenario:
scenario['locking_pid'] = None
if 'open_func_name' not in scenario:
scenario['open_func_name'] = 'mock_open_okay'
if 'os_open_func_name' not in scenario:
scenario['os_open_func_name'] = 'mock_os_open_okay'
return scenarios
def setup_pidfile_fixtures(testcase):
""" Set up common fixtures for PID file test cases. """
testcase.mock_tracker = scaffold.MockTracker()
scenarios = make_pidlockfile_scenarios()
testcase.pidlockfile_scenarios = scenarios
def get_scenario_option(testcase, key, default=None):
value = default
try:
value = testcase.scenario[key]
except (NameError, TypeError, AttributeError, KeyError):
pass
return value
scaffold.mock(
"os.getpid",
returns=scenarios['simple']['pid'],
tracker=testcase.mock_tracker)
def make_mock_open_funcs(testcase):
def mock_open_nonexist(filename, mode, buffering):
if 'r' in mode:
raise IOError(
errno.ENOENT, "No such file %(filename)r" % vars())
else:
result = testcase.scenario['pidfile']
return result
def mock_open_read_denied(filename, mode, buffering):
if 'r' in mode:
raise IOError(
errno.EPERM, "Read denied on %(filename)r" % vars())
else:
result = testcase.scenario['pidfile']
return result
def mock_open_okay(filename, mode, buffering):
result = testcase.scenario['pidfile']
return result
def mock_os_open_nonexist(filename, flags, mode):
if (flags & os.O_CREAT):
result = testcase.scenario['pidfile'].fileno()
else:
raise OSError(
errno.ENOENT, "No such file %(filename)r" % vars())
return result
def mock_os_open_read_denied(filename, flags, mode):
if (flags & os.O_CREAT):
result = testcase.scenario['pidfile'].fileno()
else:
raise OSError(
errno.EPERM, "Read denied on %(filename)r" % vars())
return result
def mock_os_open_okay(filename, flags, mode):
result = testcase.scenario['pidfile'].fileno()
return result
funcs = dict(
(name, obj) for (name, obj) in vars().items()
if hasattr(obj, '__call__'))
return funcs
testcase.mock_pidfile_open_funcs = make_mock_open_funcs(testcase)
def mock_open(filename, mode='r', buffering=None):
scenario_path = get_scenario_option(testcase, 'path')
if filename == scenario_path:
func_name = testcase.scenario['open_func_name']
mock_open_func = testcase.mock_pidfile_open_funcs[func_name]
result = mock_open_func(filename, mode, buffering)
else:
result = FakeFileDescriptorStringIO()
return result
scaffold.mock(
"__builtin__.open",
returns_func=mock_open,
tracker=testcase.mock_tracker)
def mock_os_open(filename, flags, mode=None):
scenario_path = get_scenario_option(testcase, 'path')
if filename == scenario_path:
func_name = testcase.scenario['os_open_func_name']
mock_os_open_func = testcase.mock_pidfile_open_funcs[func_name]
result = mock_os_open_func(filename, flags, mode)
else:
result = FakeFileDescriptorStringIO().fileno()
return result
scaffold.mock(
"os.open",
returns_func=mock_os_open,
tracker=testcase.mock_tracker)
def mock_os_fdopen(fd, mode='r', buffering=None):
scenario_pidfile = get_scenario_option(
testcase, 'pidfile', FakeFileDescriptorStringIO())
if fd == testcase.scenario['pidfile'].fileno():
result = testcase.scenario['pidfile']
else:
raise OSError(errno.EBADF, "Bad file descriptor")
return result
scaffold.mock(
"os.fdopen",
returns_func=mock_os_fdopen,
tracker=testcase.mock_tracker)
testcase.scenario = NotImplemented
def setup_lockfile_method_mocks(testcase, scenario, class_name):
""" Set up common mock methods for lockfile class. """
def mock_read_pid():
return scenario['pidfile_pid']
def mock_is_locked():
return (scenario['locking_pid'] is not None)
def mock_i_am_locking():
return (
scenario['locking_pid'] == scenario['pid'])
def mock_acquire(timeout=None):
if scenario['locking_pid'] is not None:
raise lockfile.AlreadyLocked()
scenario['locking_pid'] = scenario['pid']
def mock_release():
if scenario['locking_pid'] is None:
raise lockfile.NotLocked()
if scenario['locking_pid'] != scenario['pid']:
raise lockfile.NotMyLock()
scenario['locking_pid'] = None
def mock_break_lock():
scenario['locking_pid'] = None
for func_name in [
'read_pid',
'is_locked', 'i_am_locking',
'acquire', 'release', 'break_lock',
]:
mock_func = vars()["mock_%(func_name)s" % vars()]
lockfile_func_name = "%(class_name)s.%(func_name)s" % vars()
mock_lockfile_func = scaffold.Mock(
lockfile_func_name,
returns_func=mock_func,
tracker=testcase.mock_tracker)
try:
scaffold.mock(
lockfile_func_name,
mock_obj=mock_lockfile_func,
tracker=testcase.mock_tracker)
except NameError:
pass
def setup_pidlockfile_fixtures(testcase, scenario_name=None):
""" Set up common fixtures for PIDLockFile test cases. """
setup_pidfile_fixtures(testcase)
scaffold.mock(
"pidlockfile.write_pid_to_pidfile",
tracker=testcase.mock_tracker)
scaffold.mock(
"pidlockfile.remove_existing_pidfile",
tracker=testcase.mock_tracker)
if scenario_name is not None:
set_pidlockfile_scenario(testcase, scenario_name, clear_tracker=False)
def set_pidlockfile_scenario(testcase, scenario_name, clear_tracker=True):
""" Set up the test case to the specified scenario. """
testcase.scenario = testcase.pidlockfile_scenarios[scenario_name]
setup_lockfile_method_mocks(
testcase, testcase.scenario, "lockfile.LinkFileLock")
testcase.pidlockfile_args = dict(
path=testcase.scenario['path'],
)
testcase.test_instance = pidlockfile.PIDLockFile(
**testcase.pidlockfile_args)
if clear_tracker:
testcase.mock_tracker.clear()
class PIDLockFile_TestCase(scaffold.TestCase):
""" Test cases for PIDLockFile class. """
def setUp(self):
""" Set up test fixtures. """
setup_pidlockfile_fixtures(self, 'exist-other-pid')
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_instantiate(self):
""" New instance of PIDLockFile should be created. """
instance = self.test_instance
self.failUnlessIsInstance(instance, pidlockfile.PIDLockFile)
def test_inherits_from_linkfilelock(self):
""" Should inherit from LinkFileLock. """
instance = self.test_instance
self.failUnlessIsInstance(instance, lockfile.LinkFileLock)
def test_has_specified_path(self):
""" Should have specified path. """
instance = self.test_instance
expect_path = self.scenario['path']
self.failUnlessEqual(expect_path, instance.path)
class PIDLockFile_read_pid_TestCase(scaffold.TestCase):
""" Test cases for PIDLockFile.read_pid method. """
def setUp(self):
""" Set up test fixtures. """
setup_pidlockfile_fixtures(self, 'exist-other-pid')
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_gets_pid_via_read_pid_from_pidfile(self):
""" Should get PID via read_pid_from_pidfile. """
instance = self.test_instance
test_pid = self.scenario['pidfile_pid']
expect_pid = test_pid
result = instance.read_pid()
self.failUnlessEqual(expect_pid, result)
class PIDLockFile_acquire_TestCase(scaffold.TestCase):
""" Test cases for PIDLockFile.acquire function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidlockfile_fixtures(self)
set_pidlockfile_scenario(self, 'not-exist')
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_calls_linkfilelock_acquire(self):
""" Should first call LinkFileLock.acquire method. """
instance = self.test_instance
expect_mock_output = """\
Called lockfile.LinkFileLock.acquire()
...
"""
instance.acquire()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_calls_linkfilelock_acquire_with_timeout(self):
""" Should call LinkFileLock.acquire method with specified timeout. """
instance = self.test_instance
test_timeout = object()
expect_mock_output = """\
Called lockfile.LinkFileLock.acquire(timeout=%(test_timeout)r)
...
""" % vars()
instance.acquire(timeout=test_timeout)
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_writes_pid_to_specified_file(self):
""" Should request writing current PID to specified file. """
instance = self.test_instance
pidfile_path = self.scenario['path']
expect_mock_output = """\
...
Called pidlockfile.write_pid_to_pidfile(%(pidfile_path)r)
""" % vars()
instance.acquire()
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_raises_lock_failed_on_write_error(self):
""" Should raise LockFailed error if write fails. """
set_pidlockfile_scenario(self, 'not-exist-write-busy')
instance = self.test_instance
pidfile_path = self.scenario['path']
mock_error = OSError(errno.EBUSY, "Bad stuff", pidfile_path)
pidlockfile.write_pid_to_pidfile.mock_raises = mock_error
expect_error = pidlockfile.LockFailed
self.failUnlessRaises(
expect_error,
instance.acquire)
class PIDLockFile_release_TestCase(scaffold.TestCase):
""" Test cases for PIDLockFile.release function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidlockfile_fixtures(self)
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_does_not_remove_existing_pidfile_if_not_locking(self):
""" Should not request removal of PID file if not locking. """
set_pidlockfile_scenario(self, 'exist-empty')
instance = self.test_instance
expect_error = lockfile.NotLocked
unwanted_mock_output = (
"..."
"Called pidlockfile.remove_existing_pidfile"
"...")
self.failUnlessRaises(
expect_error,
instance.release)
self.failIfMockCheckerMatch(unwanted_mock_output)
def test_does_not_remove_existing_pidfile_if_not_my_lock(self):
""" Should not request removal of PID file if we are not locking. """
set_pidlockfile_scenario(self, 'exist-other-pid-locked')
instance = self.test_instance
expect_error = lockfile.NotMyLock
unwanted_mock_output = (
"..."
"Called pidlockfile.remove_existing_pidfile"
"...")
self.failUnlessRaises(
expect_error,
instance.release)
self.failIfMockCheckerMatch(unwanted_mock_output)
def test_removes_existing_pidfile_if_i_am_locking(self):
""" Should request removal of specified PID file if lock is ours. """
set_pidlockfile_scenario(self, 'exist-current-pid-locked')
instance = self.test_instance
pidfile_path = self.scenario['path']
expect_mock_output = """\
...
Called pidlockfile.remove_existing_pidfile(%(pidfile_path)r)
...
""" % vars()
instance.release()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_calls_linkfilelock_release(self):
""" Should finally call LinkFileLock.release method. """
set_pidlockfile_scenario(self, 'exist-current-pid-locked')
instance = self.test_instance
expect_mock_output = """\
...
Called lockfile.LinkFileLock.release()
"""
instance.release()
self.failUnlessMockCheckerMatch(expect_mock_output)
class PIDLockFile_break_lock_TestCase(scaffold.TestCase):
""" Test cases for PIDLockFile.break_lock function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidlockfile_fixtures(self)
set_pidlockfile_scenario(self, 'exist-other-pid-locked')
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_calls_linkfilelock_break_lock(self):
""" Should first call LinkFileLock.break_lock method. """
instance = self.test_instance
expect_mock_output = """\
Called lockfile.LinkFileLock.break_lock()
...
"""
instance.break_lock()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_removes_existing_pidfile(self):
""" Should request removal of specified PID file. """
instance = self.test_instance
pidfile_path = self.scenario['path']
expect_mock_output = """\
...
Called pidlockfile.remove_existing_pidfile(%(pidfile_path)r)
""" % vars()
instance.break_lock()
self.failUnlessMockCheckerMatch(expect_mock_output)
class read_pid_from_pidfile_TestCase(scaffold.TestCase):
""" Test cases for read_pid_from_pidfile function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidfile_fixtures(self)
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_opens_specified_filename(self):
""" Should attempt to open specified pidfile filename. """
set_pidlockfile_scenario(self, 'exist-other-pid')
pidfile_path = self.scenario['path']
expect_mock_output = """\
Called __builtin__.open(%(pidfile_path)r, 'r')
""" % vars()
dummy = pidlockfile.read_pid_from_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_reads_pid_from_file(self):
""" Should read the PID from the specified file. """
set_pidlockfile_scenario(self, 'exist-other-pid')
pidfile_path = self.scenario['path']
expect_pid = self.scenario['pidfile_pid']
pid = pidlockfile.read_pid_from_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessEqual(expect_pid, pid)
def test_returns_none_when_file_nonexist(self):
""" Should return None when the PID file does not exist. """
set_pidlockfile_scenario(self, 'not-exist')
pidfile_path = self.scenario['path']
pid = pidlockfile.read_pid_from_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessIs(None, pid)
def test_raises_error_when_file_read_fails(self):
""" Should raise error when the PID file read fails. """
set_pidlockfile_scenario(self, 'exist-read-denied')
pidfile_path = self.scenario['path']
expect_error = EnvironmentError
self.failUnlessRaises(
expect_error,
pidlockfile.read_pid_from_pidfile, pidfile_path)
def test_raises_error_when_file_empty(self):
""" Should raise error when the PID file is empty. """
set_pidlockfile_scenario(self, 'exist-empty')
pidfile_path = self.scenario['path']
expect_error = pidlockfile.PIDFileParseError
self.failUnlessRaises(
expect_error,
pidlockfile.read_pid_from_pidfile, pidfile_path)
def test_raises_error_when_file_contents_invalid(self):
""" Should raise error when the PID file contents are invalid. """
set_pidlockfile_scenario(self, 'exist-invalid')
pidfile_path = self.scenario['path']
expect_error = pidlockfile.PIDFileParseError
self.failUnlessRaises(
expect_error,
pidlockfile.read_pid_from_pidfile, pidfile_path)
class remove_existing_pidfile_TestCase(scaffold.TestCase):
""" Test cases for remove_existing_pidfile function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidfile_fixtures(self)
scaffold.mock(
"os.remove",
tracker=self.mock_tracker)
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_removes_specified_filename(self):
""" Should attempt to remove specified PID file filename. """
set_pidlockfile_scenario(self, 'exist-current-pid')
pidfile_path = self.scenario['path']
expect_mock_output = """\
Called os.remove(%(pidfile_path)r)
""" % vars()
pidlockfile.remove_existing_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_ignores_file_not_exist_error(self):
""" Should ignore error if file does not exist. """
set_pidlockfile_scenario(self, 'not-exist')
pidfile_path = self.scenario['path']
mock_error = OSError(errno.ENOENT, "Not there", pidfile_path)
os.remove.mock_raises = mock_error
expect_mock_output = """\
Called os.remove(%(pidfile_path)r)
""" % vars()
pidlockfile.remove_existing_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_propagates_arbitrary_oserror(self):
""" Should propagate any OSError other than ENOENT. """
set_pidlockfile_scenario(self, 'exist-current-pid')
pidfile_path = self.scenario['path']
mock_error = OSError(errno.EACCES, "Denied", pidfile_path)
os.remove.mock_raises = mock_error
self.failUnlessRaises(
type(mock_error),
pidlockfile.remove_existing_pidfile,
pidfile_path)
class write_pid_to_pidfile_TestCase(scaffold.TestCase):
""" Test cases for write_pid_to_pidfile function. """
def setUp(self):
""" Set up test fixtures. """
setup_pidfile_fixtures(self)
set_pidlockfile_scenario(self, 'not-exist')
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_opens_specified_filename(self):
""" Should attempt to open specified PID file filename. """
pidfile_path = self.scenario['path']
expect_flags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY)
expect_mode = 0644
expect_mock_output = """\
Called os.open(%(pidfile_path)r, %(expect_flags)r, %(expect_mode)r)
...
""" % vars()
pidlockfile.write_pid_to_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_writes_pid_to_file(self):
""" Should write the current PID to the specified file. """
pidfile_path = self.scenario['path']
self.scenario['pidfile'].close = scaffold.Mock(
"PIDLockFile.close",
tracker=self.mock_tracker)
expect_line = "%(pid)d\n" % self.scenario
pidlockfile.write_pid_to_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessEqual(expect_line, self.scenario['pidfile'].getvalue())
def test_closes_file_after_write(self):
""" Should close the specified file after writing. """
pidfile_path = self.scenario['path']
self.scenario['pidfile'].write = scaffold.Mock(
"PIDLockFile.write",
tracker=self.mock_tracker)
self.scenario['pidfile'].close = scaffold.Mock(
"PIDLockFile.close",
tracker=self.mock_tracker)
expect_mock_output = """\
...
Called PIDLockFile.write(...)
Called PIDLockFile.close()
""" % vars()
pidlockfile.write_pid_to_pidfile(pidfile_path)
scaffold.mock_restore()
self.failUnlessMockCheckerMatch(expect_mock_output)
class TimeoutPIDLockFile_TestCase(scaffold.TestCase):
""" Test cases for ‘TimeoutPIDLockFile’ class. """
def setUp(self):
""" Set up test fixtures. """
self.mock_tracker = scaffold.MockTracker()
pidlockfile_scenarios = make_pidlockfile_scenarios()
self.pidlockfile_scenario = pidlockfile_scenarios['simple']
pidfile_path = self.pidlockfile_scenario['path']
scaffold.mock(
"pidlockfile.PIDLockFile.__init__",
tracker=self.mock_tracker)
scaffold.mock(
"pidlockfile.PIDLockFile.acquire",
tracker=self.mock_tracker)
self.scenario = {
'pidfile_path': self.pidlockfile_scenario['path'],
'acquire_timeout': object(),
}
self.test_kwargs = dict(
path=self.scenario['pidfile_path'],
acquire_timeout=self.scenario['acquire_timeout'],
)
self.test_instance = pidlockfile.TimeoutPIDLockFile(**self.test_kwargs)
def tearDown(self):
""" Tear down test fixtures. """
scaffold.mock_restore()
def test_inherits_from_pidlockfile(self):
""" Should inherit from PIDLockFile. """
instance = self.test_instance
self.failUnlessIsInstance(instance, pidlockfile.PIDLockFile)
def test_init_has_expected_signature(self):
""" Should have expected signature for ‘__init__’. """
def test_func(self, path, acquire_timeout=None, *args, **kwargs): pass
test_func.__name__ = '__init__'
self.failUnlessFunctionSignatureMatch(
test_func,
pidlockfile.TimeoutPIDLockFile.__init__)
def test_has_specified_acquire_timeout(self):
""" Should have specified ‘acquire_timeout’ value. """
instance = self.test_instance
expect_timeout = self.test_kwargs['acquire_timeout']
self.failUnlessEqual(expect_timeout, instance.acquire_timeout)
def test_calls_superclass_init(self):
""" Should call the superclass ‘__init__’. """
expect_path = self.test_kwargs['path']
expect_mock_output = """\
Called pidlockfile.PIDLockFile.__init__(
%(expect_path)r)
""" % vars()
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_acquire_uses_specified_timeout(self):
""" Should call the superclass ‘acquire’ with specified timeout. """
instance = self.test_instance
test_timeout = object()
expect_timeout = test_timeout
self.mock_tracker.clear()
expect_mock_output = """\
Called pidlockfile.PIDLockFile.acquire(%(expect_timeout)r)
""" % vars()
instance.acquire(test_timeout)
self.failUnlessMockCheckerMatch(expect_mock_output)
def test_acquire_uses_stored_timeout_by_default(self):
""" Should call superclass ‘acquire’ with stored timeout by default. """
instance = self.test_instance
test_timeout = self.test_kwargs['acquire_timeout']
expect_timeout = test_timeout
self.mock_tracker.clear()
expect_mock_output = """\
Called pidlockfile.PIDLockFile.acquire(%(expect_timeout)r)
""" % vars()
instance.acquire()
self.failUnlessMockCheckerMatch(expect_mock_output)