~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/__init__.py

  • Committer: Vincent Ladeuil
  • Date: 2011-08-12 09:49:24 UTC
  • mfrom: (6015.9.10 2.4)
  • mto: This revision was merged to the branch mainline in revision 6066.
  • Revision ID: v.ladeuil+lp@free.fr-20110812094924-knc5s0g7vs31a2f1
Merge 2.4 into trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
"""Testing framework extensions"""
18
18
 
19
 
# TODO: Perhaps there should be an API to find out if bzr running under the
20
 
# test suite -- some plugins might want to avoid making intrusive changes if
21
 
# this is the case.  However, we want behaviour under to test to diverge as
22
 
# little as possible, so this should be used rarely if it's added at all.
23
 
# (Suggestion from j-a-meinel, 2005-11-24)
24
 
 
25
19
# NOTE: Some classes in here use camelCaseNaming() rather than
26
20
# underscore_naming().  That's for consistency with unittest; it's not the
27
21
# general style of bzrlib.  Please continue that consistency when adding e.g.
94
88
    memory,
95
89
    pathfilter,
96
90
    )
 
91
from bzrlib.symbol_versioning import (
 
92
    deprecated_function,
 
93
    deprecated_in,
 
94
    )
97
95
from bzrlib.tests import (
98
96
    test_server,
99
97
    TestUtil,
1172
1170
 
1173
1171
    def permit_dir(self, name):
1174
1172
        """Permit a directory to be used by this test. See permit_url."""
1175
 
        name_transport = _mod_transport.get_transport(name)
 
1173
        name_transport = _mod_transport.get_transport_from_path(name)
1176
1174
        self.permit_url(name)
1177
1175
        self.permit_url(name_transport.base)
1178
1176
 
1257
1255
        self.addCleanup(transport_server.stop_server)
1258
1256
        # Obtain a real transport because if the server supplies a password, it
1259
1257
        # will be hidden from the base on the client side.
1260
 
        t = _mod_transport.get_transport(transport_server.get_url())
 
1258
        t = _mod_transport.get_transport_from_url(transport_server.get_url())
1261
1259
        # Some transport servers effectively chroot the backing transport;
1262
1260
        # others like SFTPServer don't - users of the transport can walk up the
1263
1261
        # transport to read the entire backing transport. This wouldn't matter
1804
1802
        self._preserved_lazy_hooks.clear()
1805
1803
 
1806
1804
    def knownFailure(self, reason):
1807
 
        """This test has failed for some known reason."""
1808
 
        raise KnownFailure(reason)
 
1805
        """Declare that this test fails for a known reason
 
1806
 
 
1807
        Tests that are known to fail should generally be using expectedFailure
 
1808
        with an appropriate reverse assertion if a change could cause the test
 
1809
        to start passing. Conversely if the test has no immediate prospect of
 
1810
        succeeding then using skip is more suitable.
 
1811
 
 
1812
        When this method is called while an exception is being handled, that
 
1813
        traceback will be used, otherwise a new exception will be thrown to
 
1814
        provide one but won't be reported.
 
1815
        """
 
1816
        self._add_reason(reason)
 
1817
        try:
 
1818
            exc_info = sys.exc_info()
 
1819
            if exc_info != (None, None, None):
 
1820
                self._report_traceback(exc_info)
 
1821
            else:
 
1822
                try:
 
1823
                    raise self.failureException(reason)
 
1824
                except self.failureException:
 
1825
                    exc_info = sys.exc_info()
 
1826
            # GZ 02-08-2011: Maybe cleanup this err.exc_info attribute too?
 
1827
            raise testtools.testcase._ExpectedFailure(exc_info)
 
1828
        finally:
 
1829
            del exc_info
1809
1830
 
1810
1831
    def _suppress_log(self):
1811
1832
        """Remove the log info from details."""
2398
2419
 
2399
2420
        :param relpath: a path relative to the base url.
2400
2421
        """
2401
 
        t = _mod_transport.get_transport(self.get_url(relpath))
 
2422
        t = _mod_transport.get_transport_from_url(self.get_url(relpath))
2402
2423
        self.assertFalse(t.is_readonly())
2403
2424
        return t
2404
2425
 
2629
2650
            backing_server = self.get_server()
2630
2651
        smart_server = test_server.SmartTCPServer_for_testing()
2631
2652
        self.start_server(smart_server, backing_server)
2632
 
        remote_transport = _mod_transport.get_transport(smart_server.get_url()
 
2653
        remote_transport = _mod_transport.get_transport_from_url(smart_server.get_url()
2633
2654
                                                   ).clone(path)
2634
2655
        return remote_transport
2635
2656
 
2652
2673
    def setUp(self):
2653
2674
        super(TestCaseWithMemoryTransport, self).setUp()
2654
2675
        # Ensure that ConnectedTransport doesn't leak sockets
2655
 
        def get_transport_with_cleanup(*args, **kwargs):
2656
 
            t = orig_get_transport(*args, **kwargs)
 
2676
        def get_transport_from_url_with_cleanup(*args, **kwargs):
 
2677
            t = orig_get_transport_from_url(*args, **kwargs)
2657
2678
            if isinstance(t, _mod_transport.ConnectedTransport):
2658
2679
                self.addCleanup(t.disconnect)
2659
2680
            return t
2660
2681
 
2661
 
        orig_get_transport = self.overrideAttr(_mod_transport, 'get_transport',
2662
 
                                               get_transport_with_cleanup)
 
2682
        orig_get_transport_from_url = self.overrideAttr(
 
2683
            _mod_transport, 'get_transport_from_url',
 
2684
            get_transport_from_url_with_cleanup)
2663
2685
        self._make_test_root()
2664
2686
        self.addCleanup(os.chdir, os.getcwdu())
2665
2687
        self.makeAndChdirToTestDir()
3924
3946
        'bzrlib.tests.test_export',
3925
3947
        'bzrlib.tests.test_export_pot',
3926
3948
        'bzrlib.tests.test_extract',
 
3949
        'bzrlib.tests.test_features',
3927
3950
        'bzrlib.tests.test_fetch',
3928
3951
        'bzrlib.tests.test_fixtures',
3929
3952
        'bzrlib.tests.test_fifo_cache',
3930
3953
        'bzrlib.tests.test_filters',
 
3954
        'bzrlib.tests.test_filter_tree',
3931
3955
        'bzrlib.tests.test_ftp_transport',
3932
3956
        'bzrlib.tests.test_foreign',
3933
3957
        'bzrlib.tests.test_generate_docs',
4324
4348
        the module is available.
4325
4349
    """
4326
4350
 
 
4351
    from bzrlib.tests.features import ModuleAvailableFeature
4327
4352
    py_module = pyutils.get_named_object(py_module_name)
4328
4353
    scenarios = [
4329
4354
        ('python', {'module': py_module}),
4370
4395
                         % (os.path.basename(dirname), printable_e))
4371
4396
 
4372
4397
 
4373
 
class Feature(object):
4374
 
    """An operating system Feature."""
4375
 
 
4376
 
    def __init__(self):
4377
 
        self._available = None
4378
 
 
4379
 
    def available(self):
4380
 
        """Is the feature available?
4381
 
 
4382
 
        :return: True if the feature is available.
4383
 
        """
4384
 
        if self._available is None:
4385
 
            self._available = self._probe()
4386
 
        return self._available
4387
 
 
4388
 
    def _probe(self):
4389
 
        """Implement this method in concrete features.
4390
 
 
4391
 
        :return: True if the feature is available.
4392
 
        """
4393
 
        raise NotImplementedError
4394
 
 
4395
 
    def __str__(self):
4396
 
        if getattr(self, 'feature_name', None):
4397
 
            return self.feature_name()
4398
 
        return self.__class__.__name__
4399
 
 
4400
 
 
4401
 
class _SymlinkFeature(Feature):
4402
 
 
4403
 
    def _probe(self):
4404
 
        return osutils.has_symlinks()
4405
 
 
4406
 
    def feature_name(self):
4407
 
        return 'symlinks'
4408
 
 
4409
 
SymlinkFeature = _SymlinkFeature()
4410
 
 
4411
 
 
4412
 
class _HardlinkFeature(Feature):
4413
 
 
4414
 
    def _probe(self):
4415
 
        return osutils.has_hardlinks()
4416
 
 
4417
 
    def feature_name(self):
4418
 
        return 'hardlinks'
4419
 
 
4420
 
HardlinkFeature = _HardlinkFeature()
4421
 
 
4422
 
 
4423
 
class _OsFifoFeature(Feature):
4424
 
 
4425
 
    def _probe(self):
4426
 
        return getattr(os, 'mkfifo', None)
4427
 
 
4428
 
    def feature_name(self):
4429
 
        return 'filesystem fifos'
4430
 
 
4431
 
OsFifoFeature = _OsFifoFeature()
4432
 
 
4433
 
 
4434
 
class _UnicodeFilenameFeature(Feature):
4435
 
    """Does the filesystem support Unicode filenames?"""
4436
 
 
4437
 
    def _probe(self):
4438
 
        try:
4439
 
            # Check for character combinations unlikely to be covered by any
4440
 
            # single non-unicode encoding. We use the characters
4441
 
            # - greek small letter alpha (U+03B1) and
4442
 
            # - braille pattern dots-123456 (U+283F).
4443
 
            os.stat(u'\u03b1\u283f')
4444
 
        except UnicodeEncodeError:
4445
 
            return False
4446
 
        except (IOError, OSError):
4447
 
            # The filesystem allows the Unicode filename but the file doesn't
4448
 
            # exist.
4449
 
            return True
4450
 
        else:
4451
 
            # The filesystem allows the Unicode filename and the file exists,
4452
 
            # for some reason.
4453
 
            return True
4454
 
 
4455
 
UnicodeFilenameFeature = _UnicodeFilenameFeature()
4456
 
 
4457
 
 
4458
 
class _CompatabilityThunkFeature(Feature):
4459
 
    """This feature is just a thunk to another feature.
4460
 
 
4461
 
    It issues a deprecation warning if it is accessed, to let you know that you
4462
 
    should really use a different feature.
4463
 
    """
4464
 
 
4465
 
    def __init__(self, dep_version, module, name,
4466
 
                 replacement_name, replacement_module=None):
4467
 
        super(_CompatabilityThunkFeature, self).__init__()
4468
 
        self._module = module
4469
 
        if replacement_module is None:
4470
 
            replacement_module = module
4471
 
        self._replacement_module = replacement_module
4472
 
        self._name = name
4473
 
        self._replacement_name = replacement_name
4474
 
        self._dep_version = dep_version
4475
 
        self._feature = None
4476
 
 
4477
 
    def _ensure(self):
4478
 
        if self._feature is None:
4479
 
            depr_msg = self._dep_version % ('%s.%s'
4480
 
                                            % (self._module, self._name))
4481
 
            use_msg = ' Use %s.%s instead.' % (self._replacement_module,
4482
 
                                               self._replacement_name)
4483
 
            symbol_versioning.warn(depr_msg + use_msg, DeprecationWarning)
4484
 
            # Import the new feature and use it as a replacement for the
4485
 
            # deprecated one.
4486
 
            self._feature = pyutils.get_named_object(
4487
 
                self._replacement_module, self._replacement_name)
4488
 
 
4489
 
    def _probe(self):
4490
 
        self._ensure()
4491
 
        return self._feature._probe()
4492
 
 
4493
 
 
4494
 
class ModuleAvailableFeature(Feature):
4495
 
    """This is a feature than describes a module we want to be available.
4496
 
 
4497
 
    Declare the name of the module in __init__(), and then after probing, the
4498
 
    module will be available as 'self.module'.
4499
 
 
4500
 
    :ivar module: The module if it is available, else None.
4501
 
    """
4502
 
 
4503
 
    def __init__(self, module_name):
4504
 
        super(ModuleAvailableFeature, self).__init__()
4505
 
        self.module_name = module_name
4506
 
 
4507
 
    def _probe(self):
4508
 
        try:
4509
 
            self._module = __import__(self.module_name, {}, {}, [''])
4510
 
            return True
4511
 
        except ImportError:
4512
 
            return False
4513
 
 
4514
 
    @property
4515
 
    def module(self):
4516
 
        if self.available(): # Make sure the probe has been done
4517
 
            return self._module
4518
 
        return None
4519
 
 
4520
 
    def feature_name(self):
4521
 
        return self.module_name
4522
 
 
4523
 
 
4524
4398
def probe_unicode_in_user_encoding():
4525
4399
    """Try to encode several unicode strings to use in unicode-aware tests.
4526
4400
    Return first successfull match.
4554
4428
    return None
4555
4429
 
4556
4430
 
4557
 
class _HTTPSServerFeature(Feature):
4558
 
    """Some tests want an https Server, check if one is available.
4559
 
 
4560
 
    Right now, the only way this is available is under python2.6 which provides
4561
 
    an ssl module.
4562
 
    """
4563
 
 
4564
 
    def _probe(self):
4565
 
        try:
4566
 
            import ssl
4567
 
            return True
4568
 
        except ImportError:
4569
 
            return False
4570
 
 
4571
 
    def feature_name(self):
4572
 
        return 'HTTPSServer'
4573
 
 
4574
 
 
4575
 
HTTPSServerFeature = _HTTPSServerFeature()
4576
 
 
4577
 
 
4578
 
class _UnicodeFilename(Feature):
4579
 
    """Does the filesystem support Unicode filenames?"""
4580
 
 
4581
 
    def _probe(self):
4582
 
        try:
4583
 
            os.stat(u'\u03b1')
4584
 
        except UnicodeEncodeError:
4585
 
            return False
4586
 
        except (IOError, OSError):
4587
 
            # The filesystem allows the Unicode filename but the file doesn't
4588
 
            # exist.
4589
 
            return True
4590
 
        else:
4591
 
            # The filesystem allows the Unicode filename and the file exists,
4592
 
            # for some reason.
4593
 
            return True
4594
 
 
4595
 
UnicodeFilename = _UnicodeFilename()
4596
 
 
4597
 
 
4598
 
class _ByteStringNamedFilesystem(Feature):
4599
 
    """Is the filesystem based on bytes?"""
4600
 
 
4601
 
    def _probe(self):
4602
 
        if os.name == "posix":
4603
 
            return True
4604
 
        return False
4605
 
 
4606
 
ByteStringNamedFilesystem = _ByteStringNamedFilesystem()
4607
 
 
4608
 
 
4609
 
class _UTF8Filesystem(Feature):
4610
 
    """Is the filesystem UTF-8?"""
4611
 
 
4612
 
    def _probe(self):
4613
 
        if osutils._fs_enc.upper() in ('UTF-8', 'UTF8'):
4614
 
            return True
4615
 
        return False
4616
 
 
4617
 
UTF8Filesystem = _UTF8Filesystem()
4618
 
 
4619
 
 
4620
 
class _BreakinFeature(Feature):
4621
 
    """Does this platform support the breakin feature?"""
4622
 
 
4623
 
    def _probe(self):
4624
 
        from bzrlib import breakin
4625
 
        if breakin.determine_signal() is None:
4626
 
            return False
4627
 
        if sys.platform == 'win32':
4628
 
            # Windows doesn't have os.kill, and we catch the SIGBREAK signal.
4629
 
            # We trigger SIGBREAK via a Console api so we need ctypes to
4630
 
            # access the function
4631
 
            try:
4632
 
                import ctypes
4633
 
            except OSError:
4634
 
                return False
4635
 
        return True
4636
 
 
4637
 
    def feature_name(self):
4638
 
        return "SIGQUIT or SIGBREAK w/ctypes on win32"
4639
 
 
4640
 
 
4641
 
BreakinFeature = _BreakinFeature()
4642
 
 
4643
 
 
4644
 
class _CaseInsCasePresFilenameFeature(Feature):
4645
 
    """Is the file-system case insensitive, but case-preserving?"""
4646
 
 
4647
 
    def _probe(self):
4648
 
        fileno, name = tempfile.mkstemp(prefix='MixedCase')
4649
 
        try:
4650
 
            # first check truly case-preserving for created files, then check
4651
 
            # case insensitive when opening existing files.
4652
 
            name = osutils.normpath(name)
4653
 
            base, rel = osutils.split(name)
4654
 
            found_rel = osutils.canonical_relpath(base, name)
4655
 
            return (found_rel == rel
4656
 
                    and os.path.isfile(name.upper())
4657
 
                    and os.path.isfile(name.lower()))
4658
 
        finally:
4659
 
            os.close(fileno)
4660
 
            os.remove(name)
4661
 
 
4662
 
    def feature_name(self):
4663
 
        return "case-insensitive case-preserving filesystem"
4664
 
 
4665
 
CaseInsCasePresFilenameFeature = _CaseInsCasePresFilenameFeature()
4666
 
 
4667
 
 
4668
 
class _CaseInsensitiveFilesystemFeature(Feature):
4669
 
    """Check if underlying filesystem is case-insensitive but *not* case
4670
 
    preserving.
4671
 
    """
4672
 
    # Note that on Windows, Cygwin, MacOS etc, the file-systems are far
4673
 
    # more likely to be case preserving, so this case is rare.
4674
 
 
4675
 
    def _probe(self):
4676
 
        if CaseInsCasePresFilenameFeature.available():
4677
 
            return False
4678
 
 
4679
 
        if TestCaseWithMemoryTransport.TEST_ROOT is None:
4680
 
            root = osutils.mkdtemp(prefix='testbzr-', suffix='.tmp')
4681
 
            TestCaseWithMemoryTransport.TEST_ROOT = root
4682
 
        else:
4683
 
            root = TestCaseWithMemoryTransport.TEST_ROOT
4684
 
        tdir = osutils.mkdtemp(prefix='case-sensitive-probe-', suffix='',
4685
 
            dir=root)
4686
 
        name_a = osutils.pathjoin(tdir, 'a')
4687
 
        name_A = osutils.pathjoin(tdir, 'A')
4688
 
        os.mkdir(name_a)
4689
 
        result = osutils.isdir(name_A)
4690
 
        _rmtree_temp_dir(tdir)
4691
 
        return result
4692
 
 
4693
 
    def feature_name(self):
4694
 
        return 'case-insensitive filesystem'
4695
 
 
4696
 
CaseInsensitiveFilesystemFeature = _CaseInsensitiveFilesystemFeature()
4697
 
 
4698
 
 
4699
 
class _CaseSensitiveFilesystemFeature(Feature):
4700
 
 
4701
 
    def _probe(self):
4702
 
        if CaseInsCasePresFilenameFeature.available():
4703
 
            return False
4704
 
        elif CaseInsensitiveFilesystemFeature.available():
4705
 
            return False
4706
 
        else:
4707
 
            return True
4708
 
 
4709
 
    def feature_name(self):
4710
 
        return 'case-sensitive filesystem'
4711
 
 
4712
 
# new coding style is for feature instances to be lowercase
4713
 
case_sensitive_filesystem_feature = _CaseSensitiveFilesystemFeature()
4714
 
 
4715
 
 
4716
4431
# Only define SubUnitBzrRunner if subunit is available.
4717
4432
try:
4718
4433
    from subunit import TestProtocolClient
4736
4451
except ImportError:
4737
4452
    pass
4738
4453
 
4739
 
class _PosixPermissionsFeature(Feature):
4740
 
 
4741
 
    def _probe(self):
4742
 
        def has_perms():
4743
 
            # create temporary file and check if specified perms are maintained.
4744
 
            import tempfile
4745
 
 
4746
 
            write_perms = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR
4747
 
            f = tempfile.mkstemp(prefix='bzr_perms_chk_')
4748
 
            fd, name = f
4749
 
            os.close(fd)
4750
 
            os.chmod(name, write_perms)
4751
 
 
4752
 
            read_perms = os.stat(name).st_mode & 0777
4753
 
            os.unlink(name)
4754
 
            return (write_perms == read_perms)
4755
 
 
4756
 
        return (os.name == 'posix') and has_perms()
4757
 
 
4758
 
    def feature_name(self):
4759
 
        return 'POSIX permissions support'
4760
 
 
4761
 
posix_permissions_feature = _PosixPermissionsFeature()
 
4454
 
 
4455
@deprecated_function(deprecated_in((2, 5, 0)))
 
4456
def ModuleAvailableFeature(name):
 
4457
    from bzrlib.tests import features
 
4458
    return features.ModuleAvailableFeature(name)
 
4459