~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Jelmer Vernooij
  • Date: 2011-12-19 10:58:39 UTC
  • mfrom: (6383 +trunk)
  • mto: This revision was merged to the branch mainline in revision 6386.
  • Revision ID: jelmer@canonical.com-20111219105839-uji05ck4rkm1mj4j
Merge bzr.dev.

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 TestGetuserUnicode(tests.TestCase):
 
2099
 
 
2100
    def test_ascii_user(self):
 
2101
        self.overrideEnv('LOGNAME', 'jrandom')
 
2102
        self.assertEqual(u'jrandom', osutils.getuser_unicode())
 
2103
 
 
2104
    def test_unicode_user(self):
 
2105
        ue = osutils.get_user_encoding()
 
2106
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
 
2107
        if uni_val is None:
 
2108
            raise tests.TestSkipped(
 
2109
                'Cannot find a unicode character that works in encoding %s'
 
2110
                % (osutils.get_user_encoding(),))
 
2111
        uni_username = u'jrandom' + uni_val
 
2112
        encoded_username = uni_username.encode(ue)
 
2113
        self.overrideEnv('LOGNAME', encoded_username)
 
2114
        self.assertEqual(uni_username, osutils.getuser_unicode())
 
2115
        self.overrideEnv('LOGNAME', u'jrandom\xb6'.encode(ue))
 
2116
        self.assertEqual(u'jrandom\xb6', osutils.getuser_unicode())
 
2117
 
 
2118
 
 
2119
class TestBackupNames(tests.TestCase):
 
2120
 
 
2121
    def setUp(self):
 
2122
        super(TestBackupNames, self).setUp()
 
2123
        self.backups = []
 
2124
 
 
2125
    def backup_exists(self, name):
 
2126
        return name in self.backups
 
2127
 
 
2128
    def available_backup_name(self, name):
 
2129
        backup_name = osutils.available_backup_name(name, self.backup_exists)
 
2130
        self.backups.append(backup_name)
 
2131
        return backup_name
 
2132
 
 
2133
    def assertBackupName(self, expected, name):
 
2134
        self.assertEqual(expected, self.available_backup_name(name))
 
2135
 
 
2136
    def test_empty(self):
 
2137
        self.assertBackupName('file.~1~', 'file')
 
2138
 
 
2139
    def test_existing(self):
 
2140
        self.available_backup_name('file')
 
2141
        self.available_backup_name('file')
 
2142
        self.assertBackupName('file.~3~', 'file')
 
2143
        # Empty slots are found, this is not a strict requirement and may be
 
2144
        # revisited if we test against all implementations.
 
2145
        self.backups.remove('file.~2~')
 
2146
        self.assertBackupName('file.~2~', 'file')
 
2147
 
 
2148
 
 
2149
class TestFindExecutableInPath(tests.TestCase):
 
2150
 
 
2151
    def test_windows(self):
 
2152
        if sys.platform != 'win32':
 
2153
            raise tests.TestSkipped('test requires win32')
 
2154
        self.assertTrue(osutils.find_executable_on_path('explorer') is not None)
 
2155
        self.assertTrue(
 
2156
            osutils.find_executable_on_path('explorer.exe') is not None)
 
2157
        self.assertTrue(
 
2158
            osutils.find_executable_on_path('EXPLORER.EXE') is not None)
 
2159
        self.assertTrue(
 
2160
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2161
        self.assertTrue(osutils.find_executable_on_path('file.txt') is None)
 
2162
 
 
2163
    def test_other(self):
 
2164
        if sys.platform == 'win32':
 
2165
            raise tests.TestSkipped('test requires non-win32')
 
2166
        self.assertTrue(osutils.find_executable_on_path('sh') is not None)
 
2167
        self.assertTrue(
 
2168
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2169
 
 
2170
 
 
2171
class TestEnvironmentErrors(tests.TestCase):
 
2172
    """Test handling of environmental errors"""
 
2173
 
 
2174
    def test_is_oserror(self):
 
2175
        self.assertTrue(osutils.is_environment_error(
 
2176
            OSError(errno.EINVAL, "Invalid parameter")))
 
2177
 
 
2178
    def test_is_ioerror(self):
 
2179
        self.assertTrue(osutils.is_environment_error(
 
2180
            IOError(errno.EINVAL, "Invalid parameter")))
 
2181
 
 
2182
    def test_is_socket_error(self):
 
2183
        self.assertTrue(osutils.is_environment_error(
 
2184
            socket.error(errno.EINVAL, "Invalid parameter")))
 
2185
 
 
2186
    def test_is_select_error(self):
 
2187
        self.assertTrue(osutils.is_environment_error(
 
2188
            select.error(errno.EINVAL, "Invalid parameter")))
 
2189
 
 
2190
    def test_is_pywintypes_error(self):
 
2191
        self.requireFeature(features.pywintypes)
 
2192
        import pywintypes
 
2193
        self.assertTrue(osutils.is_environment_error(
 
2194
            pywintypes.error(errno.EINVAL, "Invalid parameter", "Caller")))