~bialix/bzr/2.0-bug-523069

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Johan Walles
  • Date: 2009-05-06 05:36:28 UTC
  • mfrom: (4332 +trunk)
  • mto: This revision was merged to the branch mainline in revision 4343.
  • Revision ID: johan.walles@gmail.com-20090506053628-tbf1wz4a0m9t684g
MergeĀ fromĀ upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
53
53
UTF8DirReaderFeature = _UTF8DirReaderFeature()
54
54
 
55
55
 
56
 
class TestOSUtils(tests.TestCaseInTempDir):
 
56
def _already_unicode(s):
 
57
    return s
 
58
 
 
59
 
 
60
def _fs_enc_to_unicode(s):
 
61
    return s.decode(osutils._fs_enc)
 
62
 
 
63
 
 
64
def _utf8_to_unicode(s):
 
65
    return s.decode('UTF-8')
 
66
 
 
67
 
 
68
def dir_reader_scenarios():
 
69
    # For each dir reader we define:
 
70
 
 
71
    # - native_to_unicode: a function converting the native_abspath as returned
 
72
    #   by DirReader.read_dir to its unicode representation
 
73
 
 
74
    # UnicodeDirReader is the fallback, it should be tested on all platforms.
 
75
    scenarios = [('unicode',
 
76
                  dict(_dir_reader_class=osutils.UnicodeDirReader,
 
77
                       _native_to_unicode=_already_unicode))]
 
78
    # Some DirReaders are platform specific and even there they may not be
 
79
    # available.
 
80
    if UTF8DirReaderFeature.available():
 
81
        from bzrlib import _readdir_pyx
 
82
        scenarios.append(('utf8',
 
83
                          dict(_dir_reader_class=_readdir_pyx.UTF8DirReader,
 
84
                               _native_to_unicode=_utf8_to_unicode)))
 
85
 
 
86
    if test__walkdirs_win32.Win32ReadDirFeature.available():
 
87
        try:
 
88
            from bzrlib import _walkdirs_win32
 
89
            # TODO: check on windows, it may be that we need to use/add
 
90
            # safe_unicode instead of _fs_enc_to_unicode
 
91
            scenarios.append(
 
92
                ('win32',
 
93
                 dict(_dir_reader_class=_walkdirs_win32.Win32ReadDir,
 
94
                      _native_to_unicode=_fs_enc_to_unicode)))
 
95
        except ImportError:
 
96
            pass
 
97
    return scenarios
 
98
 
 
99
 
 
100
def load_tests(basic_tests, module, loader):
 
101
    suite = loader.suiteClass()
 
102
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
 
103
        basic_tests, tests.condition_isinstance(TestDirReader))
 
104
    tests.multiply_tests(dir_reader_tests, dir_reader_scenarios(), suite)
 
105
    suite.addTest(remaining_tests)
 
106
    return suite
 
107
 
 
108
 
 
109
class TestContainsWhitespace(tests.TestCase):
57
110
 
58
111
    def test_contains_whitespace(self):
59
112
        self.failUnless(osutils.contains_whitespace(u' '))
69
122
        self.failIf(osutils.contains_whitespace(u'hellothere'))
70
123
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
71
124
 
 
125
 
 
126
class TestRename(tests.TestCaseInTempDir):
 
127
 
72
128
    def test_fancy_rename(self):
73
129
        # This should work everywhere
74
130
        def rename(a, b):
112
168
        shape = sorted(os.listdir('.'))
113
169
        self.assertEquals(['A', 'B'], shape)
114
170
 
 
171
 
 
172
class TestRandChars(tests.TestCase):
 
173
 
115
174
    def test_01_rand_chars_empty(self):
116
175
        result = osutils.rand_chars(0)
117
176
        self.assertEqual(result, '')
122
181
        self.assertEqual(type(result), str)
123
182
        self.assertContainsRe(result, r'^[a-z0-9]{100}$')
124
183
 
 
184
 
 
185
class TestIsInside(tests.TestCase):
 
186
 
125
187
    def test_is_inside(self):
126
188
        is_inside = osutils.is_inside
127
189
        self.assertTrue(is_inside('src', 'src/foo.c'))
156
218
                         (['src'], 'srccontrol/foo')]:
157
219
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
158
220
 
 
221
 
 
222
class TestRmTree(tests.TestCaseInTempDir):
 
223
 
159
224
    def test_rmtree(self):
160
225
        # Check to remove tree with read-only files/dirs
161
226
        os.mkdir('dir')
174
239
        self.failIfExists('dir/file')
175
240
        self.failIfExists('dir')
176
241
 
 
242
 
 
243
class TestKind(tests.TestCaseInTempDir):
 
244
 
177
245
    def test_file_kind(self):
178
246
        self.build_tree(['file', 'dir/'])
179
247
        self.assertEquals('file', osutils.file_kind('file'))
209
277
                os.remove('socket')
210
278
 
211
279
    def test_kind_marker(self):
212
 
        self.assertEqual(osutils.kind_marker('file'), '')
213
 
        self.assertEqual(osutils.kind_marker('directory'), '/')
214
 
        self.assertEqual(osutils.kind_marker('symlink'), '@')
215
 
        self.assertEqual(osutils.kind_marker('tree-reference'), '+')
 
280
        self.assertEqual("", osutils.kind_marker("file"))
 
281
        self.assertEqual("/", osutils.kind_marker('directory'))
 
282
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
 
283
        self.assertEqual("@", osutils.kind_marker("symlink"))
 
284
        self.assertEqual("+", osutils.kind_marker("tree-reference"))
 
285
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
 
286
 
 
287
 
 
288
class TestUmask(tests.TestCaseInTempDir):
216
289
 
217
290
    def test_get_umask(self):
218
291
        if sys.platform == 'win32':
231
304
        os.umask(0027)
232
305
        self.assertEqual(0027, osutils.get_umask())
233
306
 
 
307
 
 
308
class TestDateTime(tests.TestCase):
 
309
 
234
310
    def assertFormatedDelta(self, expected, seconds):
235
311
        """Assert osutils.format_delta formats as expected"""
236
312
        actual = osutils.format_delta(seconds)
277
353
        # Instead blackbox.test_locale should check for localized
278
354
        # dates once they do occur in output strings.
279
355
 
 
356
    def test_local_time_offset(self):
 
357
        """Test that local_time_offset() returns a sane value."""
 
358
        offset = osutils.local_time_offset()
 
359
        self.assertTrue(isinstance(offset, int))
 
360
        # Test that the offset is no more than a eighteen hours in
 
361
        # either direction.
 
362
        # Time zone handling is system specific, so it is difficult to
 
363
        # do more specific tests, but a value outside of this range is
 
364
        # probably wrong.
 
365
        eighteen_hours = 18 * 3600
 
366
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
367
 
 
368
    def test_local_time_offset_with_timestamp(self):
 
369
        """Test that local_time_offset() works with a timestamp."""
 
370
        offset = osutils.local_time_offset(1000000000.1234567)
 
371
        self.assertTrue(isinstance(offset, int))
 
372
        eighteen_hours = 18 * 3600
 
373
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
 
374
 
 
375
 
 
376
class TestLinks(tests.TestCaseInTempDir):
 
377
 
280
378
    def test_dereference_path(self):
281
379
        self.requireFeature(tests.SymlinkFeature)
282
380
        cwd = osutils.realpath('.')
325
423
            osutils.make_readonly('dangling')
326
424
            osutils.make_writable('dangling')
327
425
 
328
 
    def test_kind_marker(self):
329
 
        self.assertEqual("", osutils.kind_marker("file"))
330
 
        self.assertEqual("/", osutils.kind_marker(osutils._directory_kind))
331
 
        self.assertEqual("@", osutils.kind_marker("symlink"))
332
 
        self.assertRaises(errors.BzrError, osutils.kind_marker, "unknown")
333
 
 
334
426
    def test_host_os_dereferences_symlinks(self):
335
427
        osutils.host_os_dereferences_symlinks()
336
428
 
815
907
 
816
908
class TestWalkDirs(tests.TestCaseInTempDir):
817
909
 
 
910
    def assertExpectedBlocks(self, expected, result):
 
911
        self.assertEqual(expected,
 
912
                         [(dirinfo, [line[0:3] for line in block])
 
913
                          for dirinfo, block in result])
 
914
 
818
915
    def test_walkdirs(self):
819
916
        tree = [
820
917
            '.bzr',
852
949
            result.append((dirdetail, dirblock))
853
950
 
854
951
        self.assertTrue(found_bzrdir)
855
 
        self.assertEqual(expected_dirblocks,
856
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
952
        self.assertExpectedBlocks(expected_dirblocks, result)
857
953
        # you can search a subdir only, with a supplied prefix.
858
954
        result = []
859
955
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
860
956
            result.append(dirblock)
861
 
        self.assertEqual(expected_dirblocks[1:],
862
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
957
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
863
958
 
864
959
    def test_walkdirs_os_error(self):
865
960
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
871
966
        os.mkdir("test-unreadable")
872
967
        os.chmod("test-unreadable", 0000)
873
968
        # must chmod it back so that it can be removed
874
 
        self.addCleanup(lambda: os.chmod("test-unreadable", 0700))
 
969
        self.addCleanup(os.chmod, "test-unreadable", 0700)
875
970
        # The error is not raised until the generator is actually evaluated.
876
971
        # (It would be ok if it happened earlier but at the moment it
877
972
        # doesn't.)
918
1013
            result.append((dirdetail, dirblock))
919
1014
 
920
1015
        self.assertTrue(found_bzrdir)
921
 
        self.assertEqual(expected_dirblocks,
922
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
1016
        self.assertExpectedBlocks(expected_dirblocks, result)
 
1017
 
923
1018
        # you can search a subdir only, with a supplied prefix.
924
1019
        result = []
925
1020
        for dirblock in osutils.walkdirs('./1dir', '1dir'):
926
1021
            result.append(dirblock)
927
 
        self.assertEqual(expected_dirblocks[1:],
928
 
            [(dirinfo, [line[0:3] for line in block]) for dirinfo, block in result])
 
1022
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
929
1023
 
930
1024
    def _filter_out_stat(self, result):
931
1025
        """Filter out the stat value from the walkdirs result"""
946
1040
            osutils._selected_dir_reader = cur_dir_reader
947
1041
        self.addCleanup(restore)
948
1042
 
949
 
    def assertReadFSDirIs(self, expected):
 
1043
    def assertDirReaderIs(self, expected):
950
1044
        """Assert the right implementation for _walkdirs_utf8 is chosen."""
951
1045
        # Force it to redetect
952
1046
        osutils._selected_dir_reader = None
959
1053
        self._save_platform_info()
960
1054
        win32utils.winver = None # Avoid the win32 detection code
961
1055
        osutils._fs_enc = 'UTF-8'
962
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1056
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
963
1057
 
964
1058
    def test_force_walkdirs_utf8_fs_ascii(self):
965
1059
        self.requireFeature(UTF8DirReaderFeature)
966
1060
        self._save_platform_info()
967
1061
        win32utils.winver = None # Avoid the win32 detection code
968
1062
        osutils._fs_enc = 'US-ASCII'
969
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1063
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
970
1064
 
971
1065
    def test_force_walkdirs_utf8_fs_ANSI(self):
972
1066
        self.requireFeature(UTF8DirReaderFeature)
973
1067
        self._save_platform_info()
974
1068
        win32utils.winver = None # Avoid the win32 detection code
975
1069
        osutils._fs_enc = 'ANSI_X3.4-1968'
976
 
        self.assertReadFSDirIs(UTF8DirReaderFeature.reader)
 
1070
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
977
1071
 
978
1072
    def test_force_walkdirs_utf8_fs_latin1(self):
979
1073
        self._save_platform_info()
980
1074
        win32utils.winver = None # Avoid the win32 detection code
981
1075
        osutils._fs_enc = 'latin1'
982
 
        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
1076
        self.assertDirReaderIs(osutils.UnicodeDirReader)
983
1077
 
984
1078
    def test_force_walkdirs_utf8_nt(self):
985
1079
        # Disabled because the thunk of the whole walkdirs api is disabled.
987
1081
        self._save_platform_info()
988
1082
        win32utils.winver = 'Windows NT'
989
1083
        from bzrlib._walkdirs_win32 import Win32ReadDir
990
 
        self.assertReadFSDirIs(Win32ReadDir)
 
1084
        self.assertDirReaderIs(Win32ReadDir)
991
1085
 
992
1086
    def test_force_walkdirs_utf8_98(self):
993
1087
        self.requireFeature(test__walkdirs_win32.Win32ReadDirFeature)
994
1088
        self._save_platform_info()
995
1089
        win32utils.winver = 'Windows 98'
996
 
        self.assertReadFSDirIs(osutils.UnicodeDirReader)
 
1090
        self.assertDirReaderIs(osutils.UnicodeDirReader)
997
1091
 
998
1092
    def test_unicode_walkdirs(self):
999
1093
        """Walkdirs should always return unicode paths."""
1422
1516
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
1423
1517
 
1424
1518
 
1425
 
class TestLocalTimeOffset(tests.TestCase):
1426
 
 
1427
 
    def test_local_time_offset(self):
1428
 
        """Test that local_time_offset() returns a sane value."""
1429
 
        offset = osutils.local_time_offset()
1430
 
        self.assertTrue(isinstance(offset, int))
1431
 
        # Test that the offset is no more than a eighteen hours in
1432
 
        # either direction.
1433
 
        # Time zone handling is system specific, so it is difficult to
1434
 
        # do more specific tests, but a value outside of this range is
1435
 
        # probably wrong.
1436
 
        eighteen_hours = 18 * 3600
1437
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
1438
 
 
1439
 
    def test_local_time_offset_with_timestamp(self):
1440
 
        """Test that local_time_offset() works with a timestamp."""
1441
 
        offset = osutils.local_time_offset(1000000000.1234567)
1442
 
        self.assertTrue(isinstance(offset, int))
1443
 
        eighteen_hours = 18 * 3600
1444
 
        self.assertTrue(-eighteen_hours < offset < eighteen_hours)
1445
 
 
1446
 
 
1447
1519
class TestSizeShaFile(tests.TestCaseInTempDir):
1448
1520
 
1449
1521
    def test_sha_empty(self):
1512
1584
            "Invalid regular expression in test case: '*': "
1513
1585
            "nothing to repeat",
1514
1586
            str(err))
 
1587
 
 
1588
 
 
1589
class TestDirReader(tests.TestCaseInTempDir):
 
1590
 
 
1591
    # Set by load_tests
 
1592
    _dir_reader_class = None
 
1593
    _native_to_unicode = None
 
1594
 
 
1595
    def setUp(self):
 
1596
        tests.TestCaseInTempDir.setUp(self)
 
1597
 
 
1598
        # Save platform specific info and reset it
 
1599
        cur_dir_reader = osutils._selected_dir_reader
 
1600
 
 
1601
        def restore():
 
1602
            osutils._selected_dir_reader = cur_dir_reader
 
1603
        self.addCleanup(restore)
 
1604
 
 
1605
        osutils._selected_dir_reader = self._dir_reader_class()
 
1606
 
 
1607
    def _get_ascii_tree(self):
 
1608
        tree = [
 
1609
            '0file',
 
1610
            '1dir/',
 
1611
            '1dir/0file',
 
1612
            '1dir/1dir/',
 
1613
            '2file'
 
1614
            ]
 
1615
        expected_dirblocks = [
 
1616
                (('', '.'),
 
1617
                 [('0file', '0file', 'file'),
 
1618
                  ('1dir', '1dir', 'directory'),
 
1619
                  ('2file', '2file', 'file'),
 
1620
                 ]
 
1621
                ),
 
1622
                (('1dir', './1dir'),
 
1623
                 [('1dir/0file', '0file', 'file'),
 
1624
                  ('1dir/1dir', '1dir', 'directory'),
 
1625
                 ]
 
1626
                ),
 
1627
                (('1dir/1dir', './1dir/1dir'),
 
1628
                 [
 
1629
                 ]
 
1630
                ),
 
1631
            ]
 
1632
        return tree, expected_dirblocks
 
1633
 
 
1634
    def test_walk_cur_dir(self):
 
1635
        tree, expected_dirblocks = self._get_ascii_tree()
 
1636
        self.build_tree(tree)
 
1637
        result = list(osutils._walkdirs_utf8('.'))
 
1638
        # Filter out stat and abspath
 
1639
        self.assertEqual(expected_dirblocks,
 
1640
                         [(dirinfo, [line[0:3] for line in block])
 
1641
                          for dirinfo, block in result])
 
1642
 
 
1643
    def test_walk_sub_dir(self):
 
1644
        tree, expected_dirblocks = self._get_ascii_tree()
 
1645
        self.build_tree(tree)
 
1646
        # you can search a subdir only, with a supplied prefix.
 
1647
        result = list(osutils._walkdirs_utf8('./1dir', '1dir'))
 
1648
        # Filter out stat and abspath
 
1649
        self.assertEqual(expected_dirblocks[1:],
 
1650
                         [(dirinfo, [line[0:3] for line in block])
 
1651
                          for dirinfo, block in result])
 
1652
 
 
1653
    def _get_unicode_tree(self):
 
1654
        name0u = u'0file-\xb6'
 
1655
        name1u = u'1dir-\u062c\u0648'
 
1656
        name2u = u'2file-\u0633'
 
1657
        tree = [
 
1658
            name0u,
 
1659
            name1u + '/',
 
1660
            name1u + '/' + name0u,
 
1661
            name1u + '/' + name1u + '/',
 
1662
            name2u,
 
1663
            ]
 
1664
        name0 = name0u.encode('UTF-8')
 
1665
        name1 = name1u.encode('UTF-8')
 
1666
        name2 = name2u.encode('UTF-8')
 
1667
        expected_dirblocks = [
 
1668
                (('', '.'),
 
1669
                 [(name0, name0, 'file', './' + name0u),
 
1670
                  (name1, name1, 'directory', './' + name1u),
 
1671
                  (name2, name2, 'file', './' + name2u),
 
1672
                 ]
 
1673
                ),
 
1674
                ((name1, './' + name1u),
 
1675
                 [(name1 + '/' + name0, name0, 'file', './' + name1u
 
1676
                                                        + '/' + name0u),
 
1677
                  (name1 + '/' + name1, name1, 'directory', './' + name1u
 
1678
                                                            + '/' + name1u),
 
1679
                 ]
 
1680
                ),
 
1681
                ((name1 + '/' + name1, './' + name1u + '/' + name1u),
 
1682
                 [
 
1683
                 ]
 
1684
                ),
 
1685
            ]
 
1686
        return tree, expected_dirblocks
 
1687
 
 
1688
    def _filter_out(self, raw_dirblocks):
 
1689
        """Filter out a walkdirs_utf8 result.
 
1690
 
 
1691
        stat field is removed, all native paths are converted to unicode
 
1692
        """
 
1693
        filtered_dirblocks = []
 
1694
        for dirinfo, block in raw_dirblocks:
 
1695
            dirinfo = (dirinfo[0], self._native_to_unicode(dirinfo[1]))
 
1696
            details = []
 
1697
            for line in block:
 
1698
                details.append(line[0:3] + (self._native_to_unicode(line[4]), ))
 
1699
            filtered_dirblocks.append((dirinfo, details))
 
1700
        return filtered_dirblocks
 
1701
 
 
1702
    def test_walk_unicode_tree(self):
 
1703
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1704
        tree, expected_dirblocks = self._get_unicode_tree()
 
1705
        self.build_tree(tree)
 
1706
        result = list(osutils._walkdirs_utf8('.'))
 
1707
        self.assertEqual(expected_dirblocks, self._filter_out(result))
 
1708
 
 
1709
    def test_symlink(self):
 
1710
        self.requireFeature(tests.SymlinkFeature)
 
1711
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1712
        target = u'target\N{Euro Sign}'
 
1713
        link_name = u'l\N{Euro Sign}nk'
 
1714
        os.symlink(target, link_name)
 
1715
        target_utf8 = target.encode('UTF-8')
 
1716
        link_name_utf8 = link_name.encode('UTF-8')
 
1717
        expected_dirblocks = [
 
1718
                (('', '.'),
 
1719
                 [(link_name_utf8, link_name_utf8,
 
1720
                   'symlink', './' + link_name),],
 
1721
                 )]
 
1722
        result = list(osutils._walkdirs_utf8('.'))
 
1723
        self.assertEqual(expected_dirblocks, self._filter_out(result))
 
1724
 
 
1725
 
 
1726
class TestReadLink(tests.TestCaseInTempDir):
 
1727
    """Exposes os.readlink() problems and the osutils solution.
 
1728
 
 
1729
    The only guarantee offered by os.readlink(), starting with 2.6, is that a
 
1730
    unicode string will be returned if a unicode string is passed.
 
1731
 
 
1732
    But prior python versions failed to properly encode the passed unicode
 
1733
    string.
 
1734
    """
 
1735
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
 
1736
 
 
1737
    def setUp(self):
 
1738
        super(tests.TestCaseInTempDir, self).setUp()
 
1739
        self.link = u'l\N{Euro Sign}ink'
 
1740
        self.target = u'targe\N{Euro Sign}t'
 
1741
        os.symlink(self.target, self.link)
 
1742
 
 
1743
    def test_os_readlink_link_encoding(self):
 
1744
        if sys.version_info < (2, 6):
 
1745
            self.assertRaises(UnicodeEncodeError, os.readlink, self.link)
 
1746
        else:
 
1747
            self.assertEquals(self.target,  os.readlink(self.link))
 
1748
 
 
1749
    def test_os_readlink_link_decoding(self):
 
1750
        self.assertEquals(self.target.encode(osutils._fs_enc),
 
1751
                          os.readlink(self.link.encode(osutils._fs_enc)))