~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Ross Lagerwall
  • Date: 2012-08-07 06:32:51 UTC
  • mto: (6437.63.5 2.5)
  • mto: This revision was merged to the branch mainline in revision 6558.
  • Revision ID: rosslagerwall@gmail.com-20120807063251-x9p03ghg2ws8oqjc
Add bzrlib/locale to .bzrignore

bzrlib/locale is generated with ./setup.py build_mo which is in turn called
by ./setup.py build

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005-2010 Canonical Ltd
 
1
# Copyright (C) 2005-2011 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
20
20
import errno
21
21
import os
22
22
import re
 
23
import select
23
24
import socket
24
 
import stat
25
25
import sys
26
26
import time
27
27
 
28
28
from bzrlib import (
29
29
    errors,
 
30
    lazy_regex,
30
31
    osutils,
 
32
    symbol_versioning,
31
33
    tests,
32
34
    trace,
33
35
    win32utils,
37
39
    file_utils,
38
40
    test__walkdirs_win32,
39
41
    )
40
 
 
41
 
 
42
 
class _UTF8DirReaderFeature(tests.Feature):
 
42
from bzrlib.tests.scenarios import load_tests_apply_scenarios
 
43
 
 
44
 
 
45
class _UTF8DirReaderFeature(features.Feature):
43
46
 
44
47
    def _probe(self):
45
48
        try:
52
55
    def feature_name(self):
53
56
        return 'bzrlib._readdir_pyx'
54
57
 
55
 
UTF8DirReaderFeature = _UTF8DirReaderFeature()
 
58
UTF8DirReaderFeature = features.ModuleAvailableFeature('bzrlib._readdir_pyx')
56
59
 
57
 
term_ios_feature = tests.ModuleAvailableFeature('termios')
 
60
term_ios_feature = features.ModuleAvailableFeature('termios')
58
61
 
59
62
 
60
63
def _already_unicode(s):
95
98
    return scenarios
96
99
 
97
100
 
98
 
def load_tests(basic_tests, module, loader):
99
 
    suite = loader.suiteClass()
100
 
    dir_reader_tests, remaining_tests = tests.split_suite_by_condition(
101
 
        basic_tests, tests.condition_isinstance(TestDirReader))
102
 
    tests.multiply_tests(dir_reader_tests, dir_reader_scenarios(), suite)
103
 
    suite.addTest(remaining_tests)
104
 
    return suite
 
101
load_tests = load_tests_apply_scenarios
105
102
 
106
103
 
107
104
class TestContainsWhitespace(tests.TestCase):
108
105
 
109
106
    def test_contains_whitespace(self):
110
 
        self.failUnless(osutils.contains_whitespace(u' '))
111
 
        self.failUnless(osutils.contains_whitespace(u'hello there'))
112
 
        self.failUnless(osutils.contains_whitespace(u'hellothere\n'))
113
 
        self.failUnless(osutils.contains_whitespace(u'hello\nthere'))
114
 
        self.failUnless(osutils.contains_whitespace(u'hello\rthere'))
115
 
        self.failUnless(osutils.contains_whitespace(u'hello\tthere'))
 
107
        self.assertTrue(osutils.contains_whitespace(u' '))
 
108
        self.assertTrue(osutils.contains_whitespace(u'hello there'))
 
109
        self.assertTrue(osutils.contains_whitespace(u'hellothere\n'))
 
110
        self.assertTrue(osutils.contains_whitespace(u'hello\nthere'))
 
111
        self.assertTrue(osutils.contains_whitespace(u'hello\rthere'))
 
112
        self.assertTrue(osutils.contains_whitespace(u'hello\tthere'))
116
113
 
117
114
        # \xa0 is "Non-breaking-space" which on some python locales thinks it
118
115
        # is whitespace, but we do not.
119
 
        self.failIf(osutils.contains_whitespace(u''))
120
 
        self.failIf(osutils.contains_whitespace(u'hellothere'))
121
 
        self.failIf(osutils.contains_whitespace(u'hello\xa0there'))
 
116
        self.assertFalse(osutils.contains_whitespace(u''))
 
117
        self.assertFalse(osutils.contains_whitespace(u'hellothere'))
 
118
        self.assertFalse(osutils.contains_whitespace(u'hello\xa0there'))
122
119
 
123
120
 
124
121
class TestRename(tests.TestCaseInTempDir):
138
135
        # This should work everywhere
139
136
        self.create_file('a', 'something in a\n')
140
137
        self._fancy_rename('a', 'b')
141
 
        self.failIfExists('a')
142
 
        self.failUnlessExists('b')
 
138
        self.assertPathDoesNotExist('a')
 
139
        self.assertPathExists('b')
143
140
        self.check_file_contents('b', 'something in a\n')
144
141
 
145
142
        self.create_file('a', 'new something in a\n')
152
149
        self.create_file('target', 'data in target\n')
153
150
        self.assertRaises((IOError, OSError), self._fancy_rename,
154
151
                          'missingsource', 'target')
155
 
        self.failUnlessExists('target')
 
152
        self.assertPathExists('target')
156
153
        self.check_file_contents('target', 'data in target\n')
157
154
 
158
155
    def test_fancy_rename_fails_if_source_and_target_missing(self):
163
160
        # Rename should be semi-atomic on all platforms
164
161
        self.create_file('a', 'something in a\n')
165
162
        osutils.rename('a', 'b')
166
 
        self.failIfExists('a')
167
 
        self.failUnlessExists('b')
 
163
        self.assertPathDoesNotExist('a')
 
164
        self.assertPathExists('b')
168
165
        self.check_file_contents('b', 'something in a\n')
169
166
 
170
167
        self.create_file('a', 'new something in a\n')
184
181
        shape = sorted(os.listdir('.'))
185
182
        self.assertEquals(['A', 'B'], shape)
186
183
 
187
 
    def test_rename_error(self):
188
 
        # We wrap os.rename to make it give an error including the filenames
189
 
        # https://bugs.launchpad.net/bzr/+bug/491763
190
 
        err = self.assertRaises(OSError, osutils.rename,
191
 
            'nonexistent', 'target')
192
 
        self.assertContainsString(str(err), 'nonexistent')
193
 
 
194
184
 
195
185
class TestRandChars(tests.TestCase):
196
186
 
242
232
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
243
233
 
244
234
 
 
235
class TestLstat(tests.TestCaseInTempDir):
 
236
 
 
237
    def test_lstat_matches_fstat(self):
 
238
        # On Windows, lstat and fstat don't always agree, primarily in the
 
239
        # 'st_ino' and 'st_dev' fields. So we force them to be '0' in our
 
240
        # custom implementation.
 
241
        if sys.platform == 'win32':
 
242
            # We only have special lstat/fstat if we have the extension.
 
243
            # Without it, we may end up re-reading content when we don't have
 
244
            # to, but otherwise it doesn't effect correctness.
 
245
            self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
 
246
        f = open('test-file.txt', 'wb')
 
247
        self.addCleanup(f.close)
 
248
        f.write('some content\n')
 
249
        f.flush()
 
250
        self.assertEqualStat(osutils.fstat(f.fileno()),
 
251
                             osutils.lstat('test-file.txt'))
 
252
 
 
253
 
245
254
class TestRmTree(tests.TestCaseInTempDir):
246
255
 
247
256
    def test_rmtree(self):
259
268
 
260
269
        osutils.rmtree('dir')
261
270
 
262
 
        self.failIfExists('dir/file')
263
 
        self.failIfExists('dir')
 
271
        self.assertPathDoesNotExist('dir/file')
 
272
        self.assertPathDoesNotExist('dir')
264
273
 
265
274
 
266
275
class TestDeleteAny(tests.TestCaseInTempDir):
421
430
class TestLinks(tests.TestCaseInTempDir):
422
431
 
423
432
    def test_dereference_path(self):
424
 
        self.requireFeature(tests.SymlinkFeature)
 
433
        self.requireFeature(features.SymlinkFeature)
425
434
        cwd = osutils.realpath('.')
426
435
        os.mkdir('bar')
427
436
        bar_path = osutils.pathjoin(cwd, 'bar')
474
483
 
475
484
class TestCanonicalRelPath(tests.TestCaseInTempDir):
476
485
 
477
 
    _test_needs_features = [tests.CaseInsCasePresFilenameFeature]
 
486
    _test_needs_features = [features.CaseInsCasePresFilenameFeature]
478
487
 
479
488
    def test_canonical_relpath_simple(self):
480
489
        f = file('MixedCaseName', 'w')
481
490
        f.close()
482
491
        actual = osutils.canonical_relpath(self.test_base_dir, 'mixedcasename')
483
 
        self.failUnlessEqual('work/MixedCaseName', actual)
 
492
        self.assertEqual('work/MixedCaseName', actual)
484
493
 
485
494
    def test_canonical_relpath_missing_tail(self):
486
495
        os.mkdir('MixedCaseParent')
487
496
        actual = osutils.canonical_relpath(self.test_base_dir,
488
497
                                           'mixedcaseparent/nochild')
489
 
        self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
498
        self.assertEqual('work/MixedCaseParent/nochild', actual)
490
499
 
491
500
 
492
501
class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
810
819
        self.assertEqual(None, osutils.safe_file_id(None))
811
820
 
812
821
 
 
822
class TestPosixFuncs(tests.TestCase):
 
823
    """Test that the posix version of normpath returns an appropriate path
 
824
       when used with 2 leading slashes."""
 
825
 
 
826
    def test_normpath(self):
 
827
        self.assertEqual('/etc/shadow', osutils._posix_normpath('/etc/shadow'))
 
828
        self.assertEqual('/etc/shadow', osutils._posix_normpath('//etc/shadow'))
 
829
        self.assertEqual('/etc/shadow', osutils._posix_normpath('///etc/shadow'))
 
830
 
 
831
 
813
832
class TestWin32Funcs(tests.TestCase):
814
833
    """Test that _win32 versions of os utilities return appropriate paths."""
815
834
 
868
887
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
869
888
        # relative path
870
889
        cwd = osutils.getcwd().rstrip('/')
871
 
        drive = osutils._nt_splitdrive(cwd)[0]
 
890
        drive = osutils.ntpath.splitdrive(cwd)[0]
872
891
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
873
892
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
874
893
        # unicode path
880
899
    """Test win32 functions that create files."""
881
900
 
882
901
    def test_getcwd(self):
883
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
902
        self.requireFeature(features.UnicodeFilenameFeature)
884
903
        os.mkdir(u'mu-\xb5')
885
904
        os.chdir(u'mu-\xb5')
886
905
        # TODO: jam 20060427 This will probably fail on Mac OSX because
916
935
        b.close()
917
936
 
918
937
        osutils._win32_rename('b', 'a')
919
 
        self.failUnlessExists('a')
920
 
        self.failIfExists('b')
 
938
        self.assertPathExists('a')
 
939
        self.assertPathDoesNotExist('b')
921
940
        self.assertFileEqual('baz\n', 'a')
922
941
 
923
942
    def test_rename_missing_file(self):
976
995
    """Test mac special functions that require directories."""
977
996
 
978
997
    def test_getcwd(self):
979
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
998
        self.requireFeature(features.UnicodeFilenameFeature)
980
999
        os.mkdir(u'B\xe5gfors')
981
1000
        os.chdir(u'B\xe5gfors')
982
1001
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
983
1002
 
984
1003
    def test_getcwd_nonnorm(self):
985
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1004
        self.requireFeature(features.UnicodeFilenameFeature)
986
1005
        # Test that _mac_getcwd() will normalize this path
987
1006
        os.mkdir(u'Ba\u030agfors')
988
1007
        os.chdir(u'Ba\u030agfors')
1071
1090
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
1072
1091
 
1073
1092
    def test_walkdirs_os_error(self):
1074
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
 
1093
        # <https://bugs.launchpad.net/bzr/+bug/338653>
1075
1094
        # Pyrex readdir didn't raise useful messages if it had an error
1076
1095
        # reading the directory
1077
1096
        if sys.platform == 'win32':
1078
1097
            raise tests.TestNotApplicable(
1079
1098
                "readdir IOError not tested on win32")
 
1099
        self.requireFeature(features.not_running_as_root)
1080
1100
        os.mkdir("test-unreadable")
1081
1101
        os.chmod("test-unreadable", 0000)
1082
1102
        # must chmod it back so that it can be removed
1090
1110
        # Ensure the message contains the file name
1091
1111
        self.assertContainsRe(str(e), "\./test-unreadable")
1092
1112
 
 
1113
 
 
1114
    def test_walkdirs_encoding_error(self):
 
1115
        # <https://bugs.launchpad.net/bzr/+bug/488519>
 
1116
        # walkdirs didn't raise a useful message when the filenames
 
1117
        # are not using the filesystem's encoding
 
1118
 
 
1119
        # require a bytestring based filesystem
 
1120
        self.requireFeature(features.ByteStringNamedFilesystem)
 
1121
 
 
1122
        tree = [
 
1123
            '.bzr',
 
1124
            '0file',
 
1125
            '1dir/',
 
1126
            '1dir/0file',
 
1127
            '1dir/1dir/',
 
1128
            '1file'
 
1129
            ]
 
1130
 
 
1131
        self.build_tree(tree)
 
1132
 
 
1133
        # rename the 1file to a latin-1 filename
 
1134
        os.rename("./1file", "\xe8file")
 
1135
        if "\xe8file" not in os.listdir("."):
 
1136
            self.skip("Lack filesystem that preserves arbitrary bytes")
 
1137
 
 
1138
        self._save_platform_info()
 
1139
        win32utils.winver = None # Avoid the win32 detection code
 
1140
        osutils._fs_enc = 'UTF-8'
 
1141
 
 
1142
        # this should raise on error
 
1143
        def attempt():
 
1144
            for dirdetail, dirblock in osutils.walkdirs('.'):
 
1145
                pass
 
1146
 
 
1147
        self.assertRaises(errors.BadFilenameEncoding, attempt)
 
1148
 
1093
1149
    def test__walkdirs_utf8(self):
1094
1150
        tree = [
1095
1151
            '.bzr',
1161
1217
        self.requireFeature(UTF8DirReaderFeature)
1162
1218
        self._save_platform_info()
1163
1219
        win32utils.winver = None # Avoid the win32 detection code
1164
 
        osutils._fs_enc = 'UTF-8'
1165
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
 
1220
        osutils._fs_enc = 'utf-8'
 
1221
        self.assertDirReaderIs(
 
1222
            UTF8DirReaderFeature.module.UTF8DirReader)
1166
1223
 
1167
1224
    def test_force_walkdirs_utf8_fs_ascii(self):
1168
1225
        self.requireFeature(UTF8DirReaderFeature)
1169
1226
        self._save_platform_info()
1170
1227
        win32utils.winver = None # Avoid the win32 detection code
1171
 
        osutils._fs_enc = 'US-ASCII'
1172
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
1173
 
 
1174
 
    def test_force_walkdirs_utf8_fs_ANSI(self):
1175
 
        self.requireFeature(UTF8DirReaderFeature)
1176
 
        self._save_platform_info()
1177
 
        win32utils.winver = None # Avoid the win32 detection code
1178
 
        osutils._fs_enc = 'ANSI_X3.4-1968'
1179
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
 
1228
        osutils._fs_enc = 'ascii'
 
1229
        self.assertDirReaderIs(
 
1230
            UTF8DirReaderFeature.module.UTF8DirReader)
1180
1231
 
1181
1232
    def test_force_walkdirs_utf8_fs_latin1(self):
1182
1233
        self._save_platform_info()
1183
1234
        win32utils.winver = None # Avoid the win32 detection code
1184
 
        osutils._fs_enc = 'latin1'
 
1235
        osutils._fs_enc = 'iso-8859-1'
1185
1236
        self.assertDirReaderIs(osutils.UnicodeDirReader)
1186
1237
 
1187
1238
    def test_force_walkdirs_utf8_nt(self):
1200
1251
 
1201
1252
    def test_unicode_walkdirs(self):
1202
1253
        """Walkdirs should always return unicode paths."""
1203
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1254
        self.requireFeature(features.UnicodeFilenameFeature)
1204
1255
        name0 = u'0file-\xb6'
1205
1256
        name1 = u'1dir-\u062c\u0648'
1206
1257
        name2 = u'2file-\u0633'
1243
1294
 
1244
1295
        The abspath portion might be in unicode or utf-8
1245
1296
        """
1246
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1297
        self.requireFeature(features.UnicodeFilenameFeature)
1247
1298
        name0 = u'0file-\xb6'
1248
1299
        name1 = u'1dir-\u062c\u0648'
1249
1300
        name2 = u'2file-\u0633'
1304
1355
 
1305
1356
        The abspath portion should be in unicode
1306
1357
        """
1307
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1358
        self.requireFeature(features.UnicodeFilenameFeature)
1308
1359
        # Use the unicode reader. TODO: split into driver-and-driven unit
1309
1360
        # tests.
1310
1361
        self._save_platform_info()
1351
1402
 
1352
1403
    def test__walkdirs_utf8_win32readdir(self):
1353
1404
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1354
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1405
        self.requireFeature(features.UnicodeFilenameFeature)
1355
1406
        from bzrlib._walkdirs_win32 import Win32ReadDir
1356
1407
        self._save_platform_info()
1357
1408
        osutils._selected_dir_reader = Win32ReadDir()
1408
1459
    def test__walkdirs_utf_win32_find_file_stat_file(self):
1409
1460
        """make sure our Stat values are valid"""
1410
1461
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1411
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1462
        self.requireFeature(features.UnicodeFilenameFeature)
1412
1463
        from bzrlib._walkdirs_win32 import Win32ReadDir
1413
1464
        name0u = u'0file-\xb6'
1414
1465
        name0 = name0u.encode('utf8')
1432
1483
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
1433
1484
        """make sure our Stat values are valid"""
1434
1485
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1435
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1486
        self.requireFeature(features.UnicodeFilenameFeature)
1436
1487
        from bzrlib._walkdirs_win32 import Win32ReadDir
1437
1488
        name0u = u'0dir-\u062c\u0648'
1438
1489
        name0 = name0u.encode('utf8')
1538
1589
        self.assertEqual(['c'], os.listdir('target/b'))
1539
1590
 
1540
1591
    def test_copy_tree_symlinks(self):
1541
 
        self.requireFeature(tests.SymlinkFeature)
 
1592
        self.requireFeature(features.SymlinkFeature)
1542
1593
        self.build_tree(['source/'])
1543
1594
        os.symlink('a/generic/path', 'source/lnk')
1544
1595
        osutils.copy_tree('source', 'target')
1569
1620
                          ('d', 'source/b', 'target/b'),
1570
1621
                          ('f', 'source/b/c', 'target/b/c'),
1571
1622
                         ], processed_files)
1572
 
        self.failIfExists('target')
 
1623
        self.assertPathDoesNotExist('target')
1573
1624
        if osutils.has_symlinks():
1574
1625
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
1575
1626
 
1621
1672
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
1622
1673
        self.assertEqual('foo', old)
1623
1674
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
1624
 
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
 
1675
        self.assertFalse('BZR_TEST_ENV_VAR' in os.environ)
1625
1676
 
1626
1677
 
1627
1678
class TestSizeShaFile(tests.TestCaseInTempDir):
1678
1729
 
1679
1730
class TestReCompile(tests.TestCase):
1680
1731
 
 
1732
    def _deprecated_re_compile_checked(self, *args, **kwargs):
 
1733
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
1734
            osutils.re_compile_checked, *args, **kwargs)
 
1735
 
1681
1736
    def test_re_compile_checked(self):
1682
 
        r = osutils.re_compile_checked(r'A*', re.IGNORECASE)
 
1737
        r = self._deprecated_re_compile_checked(r'A*', re.IGNORECASE)
1683
1738
        self.assertTrue(r.match('aaaa'))
1684
1739
        self.assertTrue(r.match('aAaA'))
1685
1740
 
1686
1741
    def test_re_compile_checked_error(self):
1687
1742
        # like https://bugs.launchpad.net/bzr/+bug/251352
 
1743
 
 
1744
        # Due to possible test isolation error, re.compile is not lazy at
 
1745
        # this point. We re-install lazy compile.
 
1746
        lazy_regex.install_lazy_compile()
1688
1747
        err = self.assertRaises(
1689
1748
            errors.BzrCommandError,
1690
 
            osutils.re_compile_checked, '*', re.IGNORECASE, 'test case')
 
1749
            self._deprecated_re_compile_checked, '*', re.IGNORECASE, 'test case')
1691
1750
        self.assertEqual(
1692
 
            "Invalid regular expression in test case: '*': "
1693
 
            "nothing to repeat",
 
1751
            'Invalid regular expression in test case: '
 
1752
            '"*" nothing to repeat',
1694
1753
            str(err))
1695
1754
 
1696
1755
 
1697
1756
class TestDirReader(tests.TestCaseInTempDir):
1698
1757
 
 
1758
    scenarios = dir_reader_scenarios()
 
1759
 
1699
1760
    # Set by load_tests
1700
1761
    _dir_reader_class = None
1701
1762
    _native_to_unicode = None
1801
1862
        return filtered_dirblocks
1802
1863
 
1803
1864
    def test_walk_unicode_tree(self):
1804
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1865
        self.requireFeature(features.UnicodeFilenameFeature)
1805
1866
        tree, expected_dirblocks = self._get_unicode_tree()
1806
1867
        self.build_tree(tree)
1807
1868
        result = list(osutils._walkdirs_utf8('.'))
1808
1869
        self.assertEqual(expected_dirblocks, self._filter_out(result))
1809
1870
 
1810
1871
    def test_symlink(self):
1811
 
        self.requireFeature(tests.SymlinkFeature)
1812
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1872
        self.requireFeature(features.SymlinkFeature)
 
1873
        self.requireFeature(features.UnicodeFilenameFeature)
1813
1874
        target = u'target\N{Euro Sign}'
1814
1875
        link_name = u'l\N{Euro Sign}nk'
1815
1876
        os.symlink(target, link_name)
1833
1894
    But prior python versions failed to properly encode the passed unicode
1834
1895
    string.
1835
1896
    """
1836
 
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
 
1897
    _test_needs_features = [features.SymlinkFeature, features.UnicodeFilenameFeature]
1837
1898
 
1838
1899
    def setUp(self):
1839
1900
        super(tests.TestCaseInTempDir, self).setUp()
1842
1903
        os.symlink(self.target, self.link)
1843
1904
 
1844
1905
    def test_os_readlink_link_encoding(self):
1845
 
        if sys.version_info < (2, 6):
1846
 
            self.assertRaises(UnicodeEncodeError, os.readlink, self.link)
1847
 
        else:
1848
 
            self.assertEquals(self.target,  os.readlink(self.link))
 
1906
        self.assertEquals(self.target,  os.readlink(self.link))
1849
1907
 
1850
1908
    def test_os_readlink_link_decoding(self):
1851
1909
        self.assertEquals(self.target.encode(osutils._fs_enc),
1863
1921
        self.assertIsInstance(concurrency, int)
1864
1922
 
1865
1923
    def test_local_concurrency_environment_variable(self):
1866
 
        os.environ['BZR_CONCURRENCY'] = '2'
 
1924
        self.overrideEnv('BZR_CONCURRENCY', '2')
1867
1925
        self.assertEqual(2, osutils.local_concurrency(use_cache=False))
1868
 
        os.environ['BZR_CONCURRENCY'] = '3'
 
1926
        self.overrideEnv('BZR_CONCURRENCY', '3')
1869
1927
        self.assertEqual(3, osutils.local_concurrency(use_cache=False))
1870
 
        os.environ['BZR_CONCURRENCY'] = 'foo'
 
1928
        self.overrideEnv('BZR_CONCURRENCY', 'foo')
1871
1929
        self.assertEqual(1, osutils.local_concurrency(use_cache=False))
1872
1930
 
1873
1931
    def test_option_concurrency(self):
1874
 
        os.environ['BZR_CONCURRENCY'] = '1'
 
1932
        self.overrideEnv('BZR_CONCURRENCY', '1')
1875
1933
        self.run_bzr('rocks --concurrency 42')
1876
 
        # Command line overrides envrionment variable
 
1934
        # Command line overrides environment variable
1877
1935
        self.assertEquals('42', os.environ['BZR_CONCURRENCY'])
1878
1936
        self.assertEquals(42, osutils.local_concurrency(use_cache=False))
1879
1937
 
1917
1975
 
1918
1976
class TestTerminalWidth(tests.TestCase):
1919
1977
 
 
1978
    def setUp(self):
 
1979
        tests.TestCase.setUp(self)
 
1980
        self._orig_terminal_size_state = osutils._terminal_size_state
 
1981
        self._orig_first_terminal_size = osutils._first_terminal_size
 
1982
        self.addCleanup(self.restore_osutils_globals)
 
1983
        osutils._terminal_size_state = 'no_data'
 
1984
        osutils._first_terminal_size = None
 
1985
 
 
1986
    def restore_osutils_globals(self):
 
1987
        osutils._terminal_size_state = self._orig_terminal_size_state
 
1988
        osutils._first_terminal_size = self._orig_first_terminal_size
 
1989
 
1920
1990
    def replace_stdout(self, new):
1921
1991
        self.overrideAttr(sys, 'stdout', new)
1922
1992
 
1937
2007
    def test_defaults_to_BZR_COLUMNS(self):
1938
2008
        # BZR_COLUMNS is set by the test framework
1939
2009
        self.assertNotEqual('12', os.environ['BZR_COLUMNS'])
1940
 
        os.environ['BZR_COLUMNS'] = '12'
 
2010
        self.overrideEnv('BZR_COLUMNS', '12')
1941
2011
        self.assertEqual(12, osutils.terminal_width())
1942
2012
 
 
2013
    def test_BZR_COLUMNS_0_no_limit(self):
 
2014
        self.overrideEnv('BZR_COLUMNS', '0')
 
2015
        self.assertEqual(None, osutils.terminal_width())
 
2016
 
1943
2017
    def test_falls_back_to_COLUMNS(self):
1944
 
        del os.environ['BZR_COLUMNS']
 
2018
        self.overrideEnv('BZR_COLUMNS', None)
1945
2019
        self.assertNotEqual('42', os.environ['COLUMNS'])
1946
2020
        self.set_fake_tty()
1947
 
        os.environ['COLUMNS'] = '42'
 
2021
        self.overrideEnv('COLUMNS', '42')
1948
2022
        self.assertEqual(42, osutils.terminal_width())
1949
2023
 
1950
2024
    def test_tty_default_without_columns(self):
1951
 
        del os.environ['BZR_COLUMNS']
1952
 
        del os.environ['COLUMNS']
 
2025
        self.overrideEnv('BZR_COLUMNS', None)
 
2026
        self.overrideEnv('COLUMNS', None)
1953
2027
 
1954
2028
        def terminal_size(w, h):
1955
2029
            return 42, 42
1962
2036
        self.assertEqual(42, osutils.terminal_width())
1963
2037
 
1964
2038
    def test_non_tty_default_without_columns(self):
1965
 
        del os.environ['BZR_COLUMNS']
1966
 
        del os.environ['COLUMNS']
 
2039
        self.overrideEnv('BZR_COLUMNS', None)
 
2040
        self.overrideEnv('COLUMNS', None)
1967
2041
        self.replace_stdout(None)
1968
2042
        self.assertEqual(None, osutils.terminal_width())
1969
2043
 
1979
2053
        else:
1980
2054
            self.overrideAttr(termios, 'TIOCGWINSZ')
1981
2055
            del termios.TIOCGWINSZ
1982
 
        del os.environ['BZR_COLUMNS']
1983
 
        del os.environ['COLUMNS']
 
2056
        self.overrideEnv('BZR_COLUMNS', None)
 
2057
        self.overrideEnv('COLUMNS', None)
1984
2058
        # Whatever the result is, if we don't raise an exception, it's ok.
1985
2059
        osutils.terminal_width()
1986
2060
 
 
2061
 
1987
2062
class TestCreationOps(tests.TestCaseInTempDir):
1988
2063
    _test_needs_features = [features.chown_feature]
1989
2064
 
2018
2093
        self.assertEquals(self.path, 'test_file')
2019
2094
        self.assertEquals(self.uid, s.st_uid)
2020
2095
        self.assertEquals(self.gid, s.st_gid)
 
2096
 
 
2097
 
 
2098
class TestPathFromEnviron(tests.TestCase):
 
2099
 
 
2100
    def test_is_unicode(self):
 
2101
        self.overrideEnv('BZR_TEST_PATH', './anywhere at all/')
 
2102
        path = osutils.path_from_environ('BZR_TEST_PATH')
 
2103
        self.assertIsInstance(path, unicode)
 
2104
        self.assertEqual(u'./anywhere at all/', path)
 
2105
 
 
2106
    def test_posix_path_env_ascii(self):
 
2107
        self.overrideEnv('BZR_TEST_PATH', '/tmp')
 
2108
        home = osutils._posix_path_from_environ('BZR_TEST_PATH')
 
2109
        self.assertIsInstance(home, unicode)
 
2110
        self.assertEqual(u'/tmp', home)
 
2111
 
 
2112
    def test_posix_path_env_unicode(self):
 
2113
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2114
        self.overrideEnv('BZR_TEST_PATH', '/home/\xa7test')
 
2115
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2116
        self.assertEqual(u'/home/\xa7test',
 
2117
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2118
        osutils._fs_enc = "iso8859-5"
 
2119
        self.assertEqual(u'/home/\u0407test',
 
2120
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2121
        osutils._fs_enc = "utf-8"
 
2122
        self.assertRaises(errors.BadFilenameEncoding,
 
2123
            osutils._posix_path_from_environ, 'BZR_TEST_PATH')
 
2124
 
 
2125
 
 
2126
class TestGetHomeDir(tests.TestCase):
 
2127
 
 
2128
    def test_is_unicode(self):
 
2129
        home = osutils._get_home_dir()
 
2130
        self.assertIsInstance(home, unicode)
 
2131
 
 
2132
    def test_posix_homeless(self):
 
2133
        self.overrideEnv('HOME', None)
 
2134
        home = osutils._get_home_dir()
 
2135
        self.assertIsInstance(home, unicode)
 
2136
 
 
2137
    def test_posix_home_ascii(self):
 
2138
        self.overrideEnv('HOME', '/home/test')
 
2139
        home = osutils._posix_get_home_dir()
 
2140
        self.assertIsInstance(home, unicode)
 
2141
        self.assertEqual(u'/home/test', home)
 
2142
 
 
2143
    def test_posix_home_unicode(self):
 
2144
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2145
        self.overrideEnv('HOME', '/home/\xa7test')
 
2146
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2147
        self.assertEqual(u'/home/\xa7test', osutils._posix_get_home_dir())
 
2148
        osutils._fs_enc = "iso8859-5"
 
2149
        self.assertEqual(u'/home/\u0407test', osutils._posix_get_home_dir())
 
2150
        osutils._fs_enc = "utf-8"
 
2151
        self.assertRaises(errors.BadFilenameEncoding,
 
2152
            osutils._posix_get_home_dir)
 
2153
 
 
2154
 
 
2155
class TestGetuserUnicode(tests.TestCase):
 
2156
 
 
2157
    def test_is_unicode(self):
 
2158
        user = osutils.getuser_unicode()
 
2159
        self.assertIsInstance(user, unicode)
 
2160
 
 
2161
    def envvar_to_override(self):
 
2162
        if sys.platform == "win32":
 
2163
            # Disable use of platform calls on windows so envvar is used
 
2164
            self.overrideAttr(win32utils, 'has_ctypes', False)
 
2165
            return 'USERNAME' # only variable used on windows
 
2166
        return 'LOGNAME' # first variable checked by getpass.getuser()
 
2167
 
 
2168
    def test_ascii_user(self):
 
2169
        self.overrideEnv(self.envvar_to_override(), 'jrandom')
 
2170
        self.assertEqual(u'jrandom', osutils.getuser_unicode())
 
2171
 
 
2172
    def test_unicode_user(self):
 
2173
        ue = osutils.get_user_encoding()
 
2174
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
 
2175
        if uni_val is None:
 
2176
            raise tests.TestSkipped(
 
2177
                'Cannot find a unicode character that works in encoding %s'
 
2178
                % (osutils.get_user_encoding(),))
 
2179
        uni_username = u'jrandom' + uni_val
 
2180
        encoded_username = uni_username.encode(ue)
 
2181
        self.overrideEnv(self.envvar_to_override(), encoded_username)
 
2182
        self.assertEqual(uni_username, osutils.getuser_unicode())
 
2183
 
 
2184
 
 
2185
class TestBackupNames(tests.TestCase):
 
2186
 
 
2187
    def setUp(self):
 
2188
        super(TestBackupNames, self).setUp()
 
2189
        self.backups = []
 
2190
 
 
2191
    def backup_exists(self, name):
 
2192
        return name in self.backups
 
2193
 
 
2194
    def available_backup_name(self, name):
 
2195
        backup_name = osutils.available_backup_name(name, self.backup_exists)
 
2196
        self.backups.append(backup_name)
 
2197
        return backup_name
 
2198
 
 
2199
    def assertBackupName(self, expected, name):
 
2200
        self.assertEqual(expected, self.available_backup_name(name))
 
2201
 
 
2202
    def test_empty(self):
 
2203
        self.assertBackupName('file.~1~', 'file')
 
2204
 
 
2205
    def test_existing(self):
 
2206
        self.available_backup_name('file')
 
2207
        self.available_backup_name('file')
 
2208
        self.assertBackupName('file.~3~', 'file')
 
2209
        # Empty slots are found, this is not a strict requirement and may be
 
2210
        # revisited if we test against all implementations.
 
2211
        self.backups.remove('file.~2~')
 
2212
        self.assertBackupName('file.~2~', 'file')
 
2213
 
 
2214
 
 
2215
class TestFindExecutableInPath(tests.TestCase):
 
2216
 
 
2217
    def test_windows(self):
 
2218
        if sys.platform != 'win32':
 
2219
            raise tests.TestSkipped('test requires win32')
 
2220
        self.assertTrue(osutils.find_executable_on_path('explorer') is not None)
 
2221
        self.assertTrue(
 
2222
            osutils.find_executable_on_path('explorer.exe') is not None)
 
2223
        self.assertTrue(
 
2224
            osutils.find_executable_on_path('EXPLORER.EXE') is not None)
 
2225
        self.assertTrue(
 
2226
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2227
        self.assertTrue(osutils.find_executable_on_path('file.txt') is None)
 
2228
        
 
2229
    def test_windows_app_path(self):
 
2230
        if sys.platform != 'win32':
 
2231
            raise tests.TestSkipped('test requires win32')
 
2232
        # Override PATH env var so that exe can only be found on App Path
 
2233
        self.overrideEnv('PATH', '')
 
2234
        # Internt Explorer is always registered in the App Path
 
2235
        self.assertTrue(osutils.find_executable_on_path('iexplore') is not None)
 
2236
 
 
2237
    def test_other(self):
 
2238
        if sys.platform == 'win32':
 
2239
            raise tests.TestSkipped('test requires non-win32')
 
2240
        self.assertTrue(osutils.find_executable_on_path('sh') is not None)
 
2241
        self.assertTrue(
 
2242
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2243
 
 
2244
 
 
2245
class TestEnvironmentErrors(tests.TestCase):
 
2246
    """Test handling of environmental errors"""
 
2247
 
 
2248
    def test_is_oserror(self):
 
2249
        self.assertTrue(osutils.is_environment_error(
 
2250
            OSError(errno.EINVAL, "Invalid parameter")))
 
2251
 
 
2252
    def test_is_ioerror(self):
 
2253
        self.assertTrue(osutils.is_environment_error(
 
2254
            IOError(errno.EINVAL, "Invalid parameter")))
 
2255
 
 
2256
    def test_is_socket_error(self):
 
2257
        self.assertTrue(osutils.is_environment_error(
 
2258
            socket.error(errno.EINVAL, "Invalid parameter")))
 
2259
 
 
2260
    def test_is_select_error(self):
 
2261
        self.assertTrue(osutils.is_environment_error(
 
2262
            select.error(errno.EINVAL, "Invalid parameter")))
 
2263
 
 
2264
    def test_is_pywintypes_error(self):
 
2265
        self.requireFeature(features.pywintypes)
 
2266
        import pywintypes
 
2267
        self.assertTrue(osutils.is_environment_error(
 
2268
            pywintypes.error(errno.EINVAL, "Invalid parameter", "Caller")))