1761
1760
self.addCleanup(osutils.set_or_unset_env, name, value)
1764
def recordCalls(self, obj, attr_name):
1765
"""Monkeypatch in a wrapper that will record calls.
1767
The monkeypatch is automatically removed when the test concludes.
1769
:param obj: The namespace holding the reference to be replaced;
1770
typically a module, class, or object.
1771
:param attr_name: A string for the name of the attribute to
1773
:returns: A list that will be extended with one item every time the
1774
function is called, with a tuple of (args, kwargs).
1778
def decorator(*args, **kwargs):
1779
calls.append((args, kwargs))
1780
return orig(*args, **kwargs)
1781
orig = self.overrideAttr(obj, attr_name, decorator)
1784
1763
def _cleanEnvironment(self):
1785
1764
for name, value in isolated_environ.iteritems():
1786
1765
self.overrideEnv(name, value)
1793
1772
self._preserved_lazy_hooks.clear()
1795
1774
def knownFailure(self, reason):
1796
"""Declare that this test fails for a known reason
1798
Tests that are known to fail should generally be using expectedFailure
1799
with an appropriate reverse assertion if a change could cause the test
1800
to start passing. Conversely if the test has no immediate prospect of
1801
succeeding then using skip is more suitable.
1803
When this method is called while an exception is being handled, that
1804
traceback will be used, otherwise a new exception will be thrown to
1805
provide one but won't be reported.
1807
self._add_reason(reason)
1809
exc_info = sys.exc_info()
1810
if exc_info != (None, None, None):
1811
self._report_traceback(exc_info)
1814
raise self.failureException(reason)
1815
except self.failureException:
1816
exc_info = sys.exc_info()
1817
# GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
1818
raise testtools.testcase._ExpectedFailure(exc_info)
1775
"""This test has failed for some known reason."""
1776
raise KnownFailure(reason)
1822
1778
def _suppress_log(self):
1823
1779
"""Remove the log info from details."""
2664
2616
def setUp(self):
2665
2617
super(TestCaseWithMemoryTransport, self).setUp()
2666
2618
# Ensure that ConnectedTransport doesn't leak sockets
2667
def get_transport_from_url_with_cleanup(*args, **kwargs):
2668
t = orig_get_transport_from_url(*args, **kwargs)
2619
def get_transport_with_cleanup(*args, **kwargs):
2620
t = orig_get_transport(*args, **kwargs)
2669
2621
if isinstance(t, _mod_transport.ConnectedTransport):
2670
2622
self.addCleanup(t.disconnect)
2673
orig_get_transport_from_url = self.overrideAttr(
2674
_mod_transport, 'get_transport_from_url',
2675
get_transport_from_url_with_cleanup)
2625
orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2626
get_transport_with_cleanup)
2676
2627
self._make_test_root()
2677
2628
self.addCleanup(os.chdir, os.getcwdu())
2678
2629
self.makeAndChdirToTestDir()
3937
3888
'bzrlib.tests.test_export',
3938
3889
'bzrlib.tests.test_export_pot',
3939
3890
'bzrlib.tests.test_extract',
3940
'bzrlib.tests.test_features',
3941
3891
'bzrlib.tests.test_fetch',
3942
3892
'bzrlib.tests.test_fixtures',
3943
3893
'bzrlib.tests.test_fifo_cache',
3944
3894
'bzrlib.tests.test_filters',
3945
'bzrlib.tests.test_filter_tree',
3946
3895
'bzrlib.tests.test_ftp_transport',
3947
3896
'bzrlib.tests.test_foreign',
3948
3897
'bzrlib.tests.test_generate_docs',
4386
4334
% (os.path.basename(dirname), printable_e))
4337
class Feature(object):
4338
"""An operating system Feature."""
4341
self._available = None
4343
def available(self):
4344
"""Is the feature available?
4346
:return: True if the feature is available.
4348
if self._available is None:
4349
self._available = self._probe()
4350
return self._available
4353
"""Implement this method in concrete features.
4355
:return: True if the feature is available.
4357
raise NotImplementedError
4360
if getattr(self, 'feature_name', None):
4361
return self.feature_name()
4362
return self.__class__.__name__
4365
class _SymlinkFeature(Feature):
4368
return osutils.has_symlinks()
4370
def feature_name(self):
4373
SymlinkFeature = _SymlinkFeature()
4376
class _HardlinkFeature(Feature):
4379
return osutils.has_hardlinks()
4381
def feature_name(self):
4384
HardlinkFeature = _HardlinkFeature()
4387
class _OsFifoFeature(Feature):
4390
return getattr(os, 'mkfifo', None)
4392
def feature_name(self):
4393
return 'filesystem fifos'
4395
OsFifoFeature = _OsFifoFeature()
4398
class _UnicodeFilenameFeature(Feature):
4399
"""Does the filesystem support Unicode filenames?"""
4403
# Check for character combinations unlikely to be covered by any
4404
# single non-unicode encoding. We use the characters
4405
# - greek small letter alpha (U+03B1) and
4406
# - braille pattern dots-123456 (U+283F).
4407
os.stat(u'\u03b1\u283f')
4408
except UnicodeEncodeError:
4410
except (IOError, OSError):
4411
# The filesystem allows the Unicode filename but the file doesn't
4415
# The filesystem allows the Unicode filename and the file exists,
4419
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4422
class _CompatabilityThunkFeature(Feature):
4423
"""This feature is just a thunk to another feature.
4425
It issues a deprecation warning if it is accessed, to let you know that you
4426
should really use a different feature.
4429
def __init__(self, dep_version, module, name,
4430
replacement_name, replacement_module=None):
4431
super(_CompatabilityThunkFeature, self).__init__()
4432
self._module = module
4433
if replacement_module is None:
4434
replacement_module = module
4435
self._replacement_module = replacement_module
4437
self._replacement_name = replacement_name
4438
self._dep_version = dep_version
4439
self._feature = None
4442
if self._feature is None:
4443
depr_msg = self._dep_version % ('%s.%s'
4444
% (self._module, self._name))
4445
use_msg = ' Use %s.%s instead.' % (self._replacement_module,
4446
self._replacement_name)
4447
symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4448
# Import the new feature and use it as a replacement for the
4450
self._feature = pyutils.get_named_object(
4451
self._replacement_module, self._replacement_name)
4455
return self._feature._probe()
4458
class ModuleAvailableFeature(Feature):
4459
"""This is a feature than describes a module we want to be available.
4461
Declare the name of the module in __init__(), and then after probing, the
4462
module will be available as 'self.module'.
4464
:ivar module: The module if it is available, else None.
4467
def __init__(self, module_name):
4468
super(ModuleAvailableFeature, self).__init__()
4469
self.module_name = module_name
4473
self._module = __import__(self.module_name, {}, {}, [''])
4480
if self.available(): # Make sure the probe has been done
4484
def feature_name(self):
4485
return self.module_name
4389
4488
def probe_unicode_in_user_encoding():
4390
4489
"""Try to encode several unicode strings to use in unicode-aware tests.
4391
4490
Return first successfull match.
4521
class _HTTPSServerFeature(Feature):
4522
"""Some tests want an https Server, check if one is available.
4524
Right now, the only way this is available is under python2.6 which provides
4535
def feature_name(self):
4536
return 'HTTPSServer'
4539
HTTPSServerFeature = _HTTPSServerFeature()
4542
class _UnicodeFilename(Feature):
4543
"""Does the filesystem support Unicode filenames?"""
4548
except UnicodeEncodeError:
4550
except (IOError, OSError):
4551
# The filesystem allows the Unicode filename but the file doesn't
4555
# The filesystem allows the Unicode filename and the file exists,
4559
UnicodeFilename = _UnicodeFilename()
4562
class _ByteStringNamedFilesystem(Feature):
4563
"""Is the filesystem based on bytes?"""
4566
if os.name == "posix":
4570
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4573
class _UTF8Filesystem(Feature):
4574
"""Is the filesystem UTF-8?"""
4577
if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
4581
UTF8Filesystem = _UTF8Filesystem()
4584
class _BreakinFeature(Feature):
4585
"""Does this platform support the breakin feature?"""
4588
from bzrlib import breakin
4589
if breakin.determine_signal() is None:
4591
if sys.platform == 'win32':
4592
# Windows doesn't have os.kill, and we catch the SIGBREAK signal.
4593
# We trigger SIGBREAK via a Console api so we need ctypes to
4594
# access the function
4601
def feature_name(self):
4602
return "SIGQUIT or SIGBREAK w/ctypes on win32"
4605
BreakinFeature = _BreakinFeature()
4608
class _CaseInsCasePresFilenameFeature(Feature):
4609
"""Is the file-system case insensitive, but case-preserving?"""
4612
fileno, name = tempfile.mkstemp(prefix='MixedCase')
4614
# first check truly case-preserving for created files, then check
4615
# case insensitive when opening existing files.
4616
name = osutils.normpath(name)
4617
base, rel = osutils.split(name)
4618
found_rel = osutils.canonical_relpath(base, name)
4619
return (found_rel == rel
4620
and os.path.isfile(name.upper())
4621
and os.path.isfile(name.lower()))
4626
def feature_name(self):
4627
return "case-insensitive case-preserving filesystem"
4629
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
4632
class _CaseInsensitiveFilesystemFeature(Feature):
4633
"""Check if underlying filesystem is case-insensitive but *not* case
4636
# Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4637
# more likely to be case preserving, so this case is rare.
4640
if CaseInsCasePresFilenameFeature.available():
4643
if TestCaseWithMemoryTransport.TEST_ROOT is None:
4644
root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4645
TestCaseWithMemoryTransport.TEST_ROOT = root
4647
root = TestCaseWithMemoryTransport.TEST_ROOT
4648
tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
4650
name_a = osutils.pathjoin(tdir, 'a')
4651
name_A = osutils.pathjoin(tdir, 'A')
4653
result = osutils.isdir(name_A)
4654
_rmtree_temp_dir(tdir)
4657
def feature_name(self):
4658
return 'case-insensitive filesystem'
4660
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4663
class _CaseSensitiveFilesystemFeature(Feature):
4666
if CaseInsCasePresFilenameFeature.available():
4668
elif CaseInsensitiveFilesystemFeature.available():
4673
def feature_name(self):
4674
return 'case-sensitive filesystem'
4676
# new coding style is for feature instances to be lowercase
4677
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4422
4680
# Only define SubUnitBzrRunner if subunit is available.
4424
4682
from subunit import TestProtocolClient
4442
4700
except ImportError:
4446
@deprecated_function(deprecated_in((2, 5, 0)))
4447
def ModuleAvailableFeature(name):
4448
from bzrlib.tests import features
4449
return features.ModuleAvailableFeature(name)
4703
class _PosixPermissionsFeature(Feature):
4707
# create temporary file and check if specified perms are maintained.
4710
write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
4711
f = tempfile.mkstemp(prefix='bzr_perms_chk_')
4714
os.chmod(name, write_perms)
4716
read_perms = os.stat(name).st_mode & 0777
4718
return (write_perms == read_perms)
4720
return (os.name == 'posix') and has_perms()
4722
def feature_name(self):
4723
return 'POSIX permissions support'
4725
posix_permissions_feature = _PosixPermissionsFeature()