~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/tests/test_osutils.py

  • Committer: Jelmer Vernooij
  • Date: 2012-03-29 14:54:16 UTC
  • mto: This revision was merged to the branch mainline in revision 6517.
  • Revision ID: jelmer@samba.org-20120329145416-fj8qchygrc4d9uwr
Fix tests.

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')
 
184
    def test_rename_exception(self):
 
185
        try:
 
186
            osutils.rename('nonexistent_path', 'different_nonexistent_path')
 
187
        except OSError, e:
 
188
            self.assertEqual(e.old_filename, 'nonexistent_path')
 
189
            self.assertEqual(e.new_filename, 'different_nonexistent_path')
 
190
            self.assertTrue('nonexistent_path' in e.strerror)
 
191
            self.assertTrue('different_nonexistent_path' in e.strerror)
193
192
 
194
193
 
195
194
class TestRandChars(tests.TestCase):
242
241
            self.assertFalse(osutils.is_inside_or_parent_of_any(dirs, fn))
243
242
 
244
243
 
 
244
class TestLstat(tests.TestCaseInTempDir):
 
245
 
 
246
    def test_lstat_matches_fstat(self):
 
247
        # On Windows, lstat and fstat don't always agree, primarily in the
 
248
        # 'st_ino' and 'st_dev' fields. So we force them to be '0' in our
 
249
        # custom implementation.
 
250
        if sys.platform == 'win32':
 
251
            # We only have special lstat/fstat if we have the extension.
 
252
            # Without it, we may end up re-reading content when we don't have
 
253
            # to, but otherwise it doesn't effect correctness.
 
254
            self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
 
255
        f = open('test-file.txt', 'wb')
 
256
        self.addCleanup(f.close)
 
257
        f.write('some content\n')
 
258
        f.flush()
 
259
        self.assertEqualStat(osutils.fstat(f.fileno()),
 
260
                             osutils.lstat('test-file.txt'))
 
261
 
 
262
 
245
263
class TestRmTree(tests.TestCaseInTempDir):
246
264
 
247
265
    def test_rmtree(self):
259
277
 
260
278
        osutils.rmtree('dir')
261
279
 
262
 
        self.failIfExists('dir/file')
263
 
        self.failIfExists('dir')
 
280
        self.assertPathDoesNotExist('dir/file')
 
281
        self.assertPathDoesNotExist('dir')
264
282
 
265
283
 
266
284
class TestDeleteAny(tests.TestCaseInTempDir):
421
439
class TestLinks(tests.TestCaseInTempDir):
422
440
 
423
441
    def test_dereference_path(self):
424
 
        self.requireFeature(tests.SymlinkFeature)
 
442
        self.requireFeature(features.SymlinkFeature)
425
443
        cwd = osutils.realpath('.')
426
444
        os.mkdir('bar')
427
445
        bar_path = osutils.pathjoin(cwd, 'bar')
474
492
 
475
493
class TestCanonicalRelPath(tests.TestCaseInTempDir):
476
494
 
477
 
    _test_needs_features = [tests.CaseInsCasePresFilenameFeature]
 
495
    _test_needs_features = [features.CaseInsCasePresFilenameFeature]
478
496
 
479
497
    def test_canonical_relpath_simple(self):
480
498
        f = file('MixedCaseName', 'w')
481
499
        f.close()
482
500
        actual = osutils.canonical_relpath(self.test_base_dir, 'mixedcasename')
483
 
        self.failUnlessEqual('work/MixedCaseName', actual)
 
501
        self.assertEqual('work/MixedCaseName', actual)
484
502
 
485
503
    def test_canonical_relpath_missing_tail(self):
486
504
        os.mkdir('MixedCaseParent')
487
505
        actual = osutils.canonical_relpath(self.test_base_dir,
488
506
                                           'mixedcaseparent/nochild')
489
 
        self.failUnlessEqual('work/MixedCaseParent/nochild', actual)
 
507
        self.assertEqual('work/MixedCaseParent/nochild', actual)
490
508
 
491
509
 
492
510
class Test_CICPCanonicalRelpath(tests.TestCaseWithTransport):
810
828
        self.assertEqual(None, osutils.safe_file_id(None))
811
829
 
812
830
 
 
831
class TestPosixFuncs(tests.TestCase):
 
832
    """Test that the posix version of normpath returns an appropriate path
 
833
       when used with 2 leading slashes."""
 
834
 
 
835
    def test_normpath(self):
 
836
        self.assertEqual('/etc/shadow', osutils._posix_normpath('/etc/shadow'))
 
837
        self.assertEqual('/etc/shadow', osutils._posix_normpath('//etc/shadow'))
 
838
        self.assertEqual('/etc/shadow', osutils._posix_normpath('///etc/shadow'))
 
839
 
 
840
 
813
841
class TestWin32Funcs(tests.TestCase):
814
842
    """Test that _win32 versions of os utilities return appropriate paths."""
815
843
 
868
896
        self.assertEqual('//HOST/path', osutils._win98_abspath('//HOST/path'))
869
897
        # relative path
870
898
        cwd = osutils.getcwd().rstrip('/')
871
 
        drive = osutils._nt_splitdrive(cwd)[0]
 
899
        drive = osutils.ntpath.splitdrive(cwd)[0]
872
900
        self.assertEqual(cwd+'/path', osutils._win98_abspath('path'))
873
901
        self.assertEqual(drive+'/path', osutils._win98_abspath('/path'))
874
902
        # unicode path
880
908
    """Test win32 functions that create files."""
881
909
 
882
910
    def test_getcwd(self):
883
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
911
        self.requireFeature(features.UnicodeFilenameFeature)
884
912
        os.mkdir(u'mu-\xb5')
885
913
        os.chdir(u'mu-\xb5')
886
914
        # TODO: jam 20060427 This will probably fail on Mac OSX because
916
944
        b.close()
917
945
 
918
946
        osutils._win32_rename('b', 'a')
919
 
        self.failUnlessExists('a')
920
 
        self.failIfExists('b')
 
947
        self.assertPathExists('a')
 
948
        self.assertPathDoesNotExist('b')
921
949
        self.assertFileEqual('baz\n', 'a')
922
950
 
923
951
    def test_rename_missing_file(self):
976
1004
    """Test mac special functions that require directories."""
977
1005
 
978
1006
    def test_getcwd(self):
979
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1007
        self.requireFeature(features.UnicodeFilenameFeature)
980
1008
        os.mkdir(u'B\xe5gfors')
981
1009
        os.chdir(u'B\xe5gfors')
982
1010
        self.assertEndsWith(osutils._mac_getcwd(), u'B\xe5gfors')
983
1011
 
984
1012
    def test_getcwd_nonnorm(self):
985
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1013
        self.requireFeature(features.UnicodeFilenameFeature)
986
1014
        # Test that _mac_getcwd() will normalize this path
987
1015
        os.mkdir(u'Ba\u030agfors')
988
1016
        os.chdir(u'Ba\u030agfors')
1071
1099
        self.assertExpectedBlocks(expected_dirblocks[1:], result)
1072
1100
 
1073
1101
    def test_walkdirs_os_error(self):
1074
 
        # <https://bugs.edge.launchpad.net/bzr/+bug/338653>
 
1102
        # <https://bugs.launchpad.net/bzr/+bug/338653>
1075
1103
        # Pyrex readdir didn't raise useful messages if it had an error
1076
1104
        # reading the directory
1077
1105
        if sys.platform == 'win32':
1078
1106
            raise tests.TestNotApplicable(
1079
1107
                "readdir IOError not tested on win32")
 
1108
        self.requireFeature(features.not_running_as_root)
1080
1109
        os.mkdir("test-unreadable")
1081
1110
        os.chmod("test-unreadable", 0000)
1082
1111
        # must chmod it back so that it can be removed
1090
1119
        # Ensure the message contains the file name
1091
1120
        self.assertContainsRe(str(e), "\./test-unreadable")
1092
1121
 
 
1122
 
 
1123
    def test_walkdirs_encoding_error(self):
 
1124
        # <https://bugs.launchpad.net/bzr/+bug/488519>
 
1125
        # walkdirs didn't raise a useful message when the filenames
 
1126
        # are not using the filesystem's encoding
 
1127
 
 
1128
        # require a bytestring based filesystem
 
1129
        self.requireFeature(features.ByteStringNamedFilesystem)
 
1130
 
 
1131
        tree = [
 
1132
            '.bzr',
 
1133
            '0file',
 
1134
            '1dir/',
 
1135
            '1dir/0file',
 
1136
            '1dir/1dir/',
 
1137
            '1file'
 
1138
            ]
 
1139
 
 
1140
        self.build_tree(tree)
 
1141
 
 
1142
        # rename the 1file to a latin-1 filename
 
1143
        os.rename("./1file", "\xe8file")
 
1144
        if "\xe8file" not in os.listdir("."):
 
1145
            self.skip("Lack filesystem that preserves arbitrary bytes")
 
1146
 
 
1147
        self._save_platform_info()
 
1148
        win32utils.winver = None # Avoid the win32 detection code
 
1149
        osutils._fs_enc = 'UTF-8'
 
1150
 
 
1151
        # this should raise on error
 
1152
        def attempt():
 
1153
            for dirdetail, dirblock in osutils.walkdirs('.'):
 
1154
                pass
 
1155
 
 
1156
        self.assertRaises(errors.BadFilenameEncoding, attempt)
 
1157
 
1093
1158
    def test__walkdirs_utf8(self):
1094
1159
        tree = [
1095
1160
            '.bzr',
1161
1226
        self.requireFeature(UTF8DirReaderFeature)
1162
1227
        self._save_platform_info()
1163
1228
        win32utils.winver = None # Avoid the win32 detection code
1164
 
        osutils._fs_enc = 'UTF-8'
1165
 
        self.assertDirReaderIs(UTF8DirReaderFeature.reader)
 
1229
        osutils._fs_enc = 'utf-8'
 
1230
        self.assertDirReaderIs(
 
1231
            UTF8DirReaderFeature.module.UTF8DirReader)
1166
1232
 
1167
1233
    def test_force_walkdirs_utf8_fs_ascii(self):
1168
1234
        self.requireFeature(UTF8DirReaderFeature)
1169
1235
        self._save_platform_info()
1170
1236
        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)
 
1237
        osutils._fs_enc = 'ascii'
 
1238
        self.assertDirReaderIs(
 
1239
            UTF8DirReaderFeature.module.UTF8DirReader)
1180
1240
 
1181
1241
    def test_force_walkdirs_utf8_fs_latin1(self):
1182
1242
        self._save_platform_info()
1183
1243
        win32utils.winver = None # Avoid the win32 detection code
1184
 
        osutils._fs_enc = 'latin1'
 
1244
        osutils._fs_enc = 'iso-8859-1'
1185
1245
        self.assertDirReaderIs(osutils.UnicodeDirReader)
1186
1246
 
1187
1247
    def test_force_walkdirs_utf8_nt(self):
1200
1260
 
1201
1261
    def test_unicode_walkdirs(self):
1202
1262
        """Walkdirs should always return unicode paths."""
1203
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1263
        self.requireFeature(features.UnicodeFilenameFeature)
1204
1264
        name0 = u'0file-\xb6'
1205
1265
        name1 = u'1dir-\u062c\u0648'
1206
1266
        name2 = u'2file-\u0633'
1243
1303
 
1244
1304
        The abspath portion might be in unicode or utf-8
1245
1305
        """
1246
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1306
        self.requireFeature(features.UnicodeFilenameFeature)
1247
1307
        name0 = u'0file-\xb6'
1248
1308
        name1 = u'1dir-\u062c\u0648'
1249
1309
        name2 = u'2file-\u0633'
1304
1364
 
1305
1365
        The abspath portion should be in unicode
1306
1366
        """
1307
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1367
        self.requireFeature(features.UnicodeFilenameFeature)
1308
1368
        # Use the unicode reader. TODO: split into driver-and-driven unit
1309
1369
        # tests.
1310
1370
        self._save_platform_info()
1351
1411
 
1352
1412
    def test__walkdirs_utf8_win32readdir(self):
1353
1413
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1354
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1414
        self.requireFeature(features.UnicodeFilenameFeature)
1355
1415
        from bzrlib._walkdirs_win32 import Win32ReadDir
1356
1416
        self._save_platform_info()
1357
1417
        osutils._selected_dir_reader = Win32ReadDir()
1408
1468
    def test__walkdirs_utf_win32_find_file_stat_file(self):
1409
1469
        """make sure our Stat values are valid"""
1410
1470
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1411
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1471
        self.requireFeature(features.UnicodeFilenameFeature)
1412
1472
        from bzrlib._walkdirs_win32 import Win32ReadDir
1413
1473
        name0u = u'0file-\xb6'
1414
1474
        name0 = name0u.encode('utf8')
1432
1492
    def test__walkdirs_utf_win32_find_file_stat_directory(self):
1433
1493
        """make sure our Stat values are valid"""
1434
1494
        self.requireFeature(test__walkdirs_win32.win32_readdir_feature)
1435
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1495
        self.requireFeature(features.UnicodeFilenameFeature)
1436
1496
        from bzrlib._walkdirs_win32 import Win32ReadDir
1437
1497
        name0u = u'0dir-\u062c\u0648'
1438
1498
        name0 = name0u.encode('utf8')
1538
1598
        self.assertEqual(['c'], os.listdir('target/b'))
1539
1599
 
1540
1600
    def test_copy_tree_symlinks(self):
1541
 
        self.requireFeature(tests.SymlinkFeature)
 
1601
        self.requireFeature(features.SymlinkFeature)
1542
1602
        self.build_tree(['source/'])
1543
1603
        os.symlink('a/generic/path', 'source/lnk')
1544
1604
        osutils.copy_tree('source', 'target')
1569
1629
                          ('d', 'source/b', 'target/b'),
1570
1630
                          ('f', 'source/b/c', 'target/b/c'),
1571
1631
                         ], processed_files)
1572
 
        self.failIfExists('target')
 
1632
        self.assertPathDoesNotExist('target')
1573
1633
        if osutils.has_symlinks():
1574
1634
            self.assertEqual([('source/lnk', 'target/lnk')], processed_links)
1575
1635
 
1621
1681
        old = osutils.set_or_unset_env('BZR_TEST_ENV_VAR', None)
1622
1682
        self.assertEqual('foo', old)
1623
1683
        self.assertEqual(None, os.environ.get('BZR_TEST_ENV_VAR'))
1624
 
        self.failIf('BZR_TEST_ENV_VAR' in os.environ)
 
1684
        self.assertFalse('BZR_TEST_ENV_VAR' in os.environ)
1625
1685
 
1626
1686
 
1627
1687
class TestSizeShaFile(tests.TestCaseInTempDir):
1678
1738
 
1679
1739
class TestReCompile(tests.TestCase):
1680
1740
 
 
1741
    def _deprecated_re_compile_checked(self, *args, **kwargs):
 
1742
        return self.applyDeprecated(symbol_versioning.deprecated_in((2, 2, 0)),
 
1743
            osutils.re_compile_checked, *args, **kwargs)
 
1744
 
1681
1745
    def test_re_compile_checked(self):
1682
 
        r = osutils.re_compile_checked(r'A*', re.IGNORECASE)
 
1746
        r = self._deprecated_re_compile_checked(r'A*', re.IGNORECASE)
1683
1747
        self.assertTrue(r.match('aaaa'))
1684
1748
        self.assertTrue(r.match('aAaA'))
1685
1749
 
1686
1750
    def test_re_compile_checked_error(self):
1687
1751
        # like https://bugs.launchpad.net/bzr/+bug/251352
 
1752
 
 
1753
        # Due to possible test isolation error, re.compile is not lazy at
 
1754
        # this point. We re-install lazy compile.
 
1755
        lazy_regex.install_lazy_compile()
1688
1756
        err = self.assertRaises(
1689
1757
            errors.BzrCommandError,
1690
 
            osutils.re_compile_checked, '*', re.IGNORECASE, 'test case')
 
1758
            self._deprecated_re_compile_checked, '*', re.IGNORECASE, 'test case')
1691
1759
        self.assertEqual(
1692
 
            "Invalid regular expression in test case: '*': "
1693
 
            "nothing to repeat",
 
1760
            'Invalid regular expression in test case: '
 
1761
            '"*" nothing to repeat',
1694
1762
            str(err))
1695
1763
 
1696
1764
 
1697
1765
class TestDirReader(tests.TestCaseInTempDir):
1698
1766
 
 
1767
    scenarios = dir_reader_scenarios()
 
1768
 
1699
1769
    # Set by load_tests
1700
1770
    _dir_reader_class = None
1701
1771
    _native_to_unicode = None
1801
1871
        return filtered_dirblocks
1802
1872
 
1803
1873
    def test_walk_unicode_tree(self):
1804
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1874
        self.requireFeature(features.UnicodeFilenameFeature)
1805
1875
        tree, expected_dirblocks = self._get_unicode_tree()
1806
1876
        self.build_tree(tree)
1807
1877
        result = list(osutils._walkdirs_utf8('.'))
1808
1878
        self.assertEqual(expected_dirblocks, self._filter_out(result))
1809
1879
 
1810
1880
    def test_symlink(self):
1811
 
        self.requireFeature(tests.SymlinkFeature)
1812
 
        self.requireFeature(tests.UnicodeFilenameFeature)
 
1881
        self.requireFeature(features.SymlinkFeature)
 
1882
        self.requireFeature(features.UnicodeFilenameFeature)
1813
1883
        target = u'target\N{Euro Sign}'
1814
1884
        link_name = u'l\N{Euro Sign}nk'
1815
1885
        os.symlink(target, link_name)
1833
1903
    But prior python versions failed to properly encode the passed unicode
1834
1904
    string.
1835
1905
    """
1836
 
    _test_needs_features = [tests.SymlinkFeature, tests.UnicodeFilenameFeature]
 
1906
    _test_needs_features = [features.SymlinkFeature, features.UnicodeFilenameFeature]
1837
1907
 
1838
1908
    def setUp(self):
1839
1909
        super(tests.TestCaseInTempDir, self).setUp()
1842
1912
        os.symlink(self.target, self.link)
1843
1913
 
1844
1914
    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))
 
1915
        self.assertEquals(self.target,  os.readlink(self.link))
1849
1916
 
1850
1917
    def test_os_readlink_link_decoding(self):
1851
1918
        self.assertEquals(self.target.encode(osutils._fs_enc),
1863
1930
        self.assertIsInstance(concurrency, int)
1864
1931
 
1865
1932
    def test_local_concurrency_environment_variable(self):
1866
 
        os.environ['BZR_CONCURRENCY'] = '2'
 
1933
        self.overrideEnv('BZR_CONCURRENCY', '2')
1867
1934
        self.assertEqual(2, osutils.local_concurrency(use_cache=False))
1868
 
        os.environ['BZR_CONCURRENCY'] = '3'
 
1935
        self.overrideEnv('BZR_CONCURRENCY', '3')
1869
1936
        self.assertEqual(3, osutils.local_concurrency(use_cache=False))
1870
 
        os.environ['BZR_CONCURRENCY'] = 'foo'
 
1937
        self.overrideEnv('BZR_CONCURRENCY', 'foo')
1871
1938
        self.assertEqual(1, osutils.local_concurrency(use_cache=False))
1872
1939
 
1873
1940
    def test_option_concurrency(self):
1874
 
        os.environ['BZR_CONCURRENCY'] = '1'
 
1941
        self.overrideEnv('BZR_CONCURRENCY', '1')
1875
1942
        self.run_bzr('rocks --concurrency 42')
1876
 
        # Command line overrides envrionment variable
 
1943
        # Command line overrides environment variable
1877
1944
        self.assertEquals('42', os.environ['BZR_CONCURRENCY'])
1878
1945
        self.assertEquals(42, osutils.local_concurrency(use_cache=False))
1879
1946
 
1917
1984
 
1918
1985
class TestTerminalWidth(tests.TestCase):
1919
1986
 
 
1987
    def setUp(self):
 
1988
        tests.TestCase.setUp(self)
 
1989
        self._orig_terminal_size_state = osutils._terminal_size_state
 
1990
        self._orig_first_terminal_size = osutils._first_terminal_size
 
1991
        self.addCleanup(self.restore_osutils_globals)
 
1992
        osutils._terminal_size_state = 'no_data'
 
1993
        osutils._first_terminal_size = None
 
1994
 
 
1995
    def restore_osutils_globals(self):
 
1996
        osutils._terminal_size_state = self._orig_terminal_size_state
 
1997
        osutils._first_terminal_size = self._orig_first_terminal_size
 
1998
 
1920
1999
    def replace_stdout(self, new):
1921
2000
        self.overrideAttr(sys, 'stdout', new)
1922
2001
 
1937
2016
    def test_defaults_to_BZR_COLUMNS(self):
1938
2017
        # BZR_COLUMNS is set by the test framework
1939
2018
        self.assertNotEqual('12', os.environ['BZR_COLUMNS'])
1940
 
        os.environ['BZR_COLUMNS'] = '12'
 
2019
        self.overrideEnv('BZR_COLUMNS', '12')
1941
2020
        self.assertEqual(12, osutils.terminal_width())
1942
2021
 
 
2022
    def test_BZR_COLUMNS_0_no_limit(self):
 
2023
        self.overrideEnv('BZR_COLUMNS', '0')
 
2024
        self.assertEqual(None, osutils.terminal_width())
 
2025
 
1943
2026
    def test_falls_back_to_COLUMNS(self):
1944
 
        del os.environ['BZR_COLUMNS']
 
2027
        self.overrideEnv('BZR_COLUMNS', None)
1945
2028
        self.assertNotEqual('42', os.environ['COLUMNS'])
1946
2029
        self.set_fake_tty()
1947
 
        os.environ['COLUMNS'] = '42'
 
2030
        self.overrideEnv('COLUMNS', '42')
1948
2031
        self.assertEqual(42, osutils.terminal_width())
1949
2032
 
1950
2033
    def test_tty_default_without_columns(self):
1951
 
        del os.environ['BZR_COLUMNS']
1952
 
        del os.environ['COLUMNS']
 
2034
        self.overrideEnv('BZR_COLUMNS', None)
 
2035
        self.overrideEnv('COLUMNS', None)
1953
2036
 
1954
2037
        def terminal_size(w, h):
1955
2038
            return 42, 42
1962
2045
        self.assertEqual(42, osutils.terminal_width())
1963
2046
 
1964
2047
    def test_non_tty_default_without_columns(self):
1965
 
        del os.environ['BZR_COLUMNS']
1966
 
        del os.environ['COLUMNS']
 
2048
        self.overrideEnv('BZR_COLUMNS', None)
 
2049
        self.overrideEnv('COLUMNS', None)
1967
2050
        self.replace_stdout(None)
1968
2051
        self.assertEqual(None, osutils.terminal_width())
1969
2052
 
1979
2062
        else:
1980
2063
            self.overrideAttr(termios, 'TIOCGWINSZ')
1981
2064
            del termios.TIOCGWINSZ
1982
 
        del os.environ['BZR_COLUMNS']
1983
 
        del os.environ['COLUMNS']
 
2065
        self.overrideEnv('BZR_COLUMNS', None)
 
2066
        self.overrideEnv('COLUMNS', None)
1984
2067
        # Whatever the result is, if we don't raise an exception, it's ok.
1985
2068
        osutils.terminal_width()
1986
2069
 
 
2070
 
1987
2071
class TestCreationOps(tests.TestCaseInTempDir):
1988
2072
    _test_needs_features = [features.chown_feature]
1989
2073
 
2018
2102
        self.assertEquals(self.path, 'test_file')
2019
2103
        self.assertEquals(self.uid, s.st_uid)
2020
2104
        self.assertEquals(self.gid, s.st_gid)
 
2105
 
 
2106
 
 
2107
class TestPathFromEnviron(tests.TestCase):
 
2108
 
 
2109
    def test_is_unicode(self):
 
2110
        self.overrideEnv('BZR_TEST_PATH', './anywhere at all/')
 
2111
        path = osutils.path_from_environ('BZR_TEST_PATH')
 
2112
        self.assertIsInstance(path, unicode)
 
2113
        self.assertEqual(u'./anywhere at all/', path)
 
2114
 
 
2115
    def test_posix_path_env_ascii(self):
 
2116
        self.overrideEnv('BZR_TEST_PATH', '/tmp')
 
2117
        home = osutils._posix_path_from_environ('BZR_TEST_PATH')
 
2118
        self.assertIsInstance(home, unicode)
 
2119
        self.assertEqual(u'/tmp', home)
 
2120
 
 
2121
    def test_posix_path_env_unicode(self):
 
2122
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2123
        self.overrideEnv('BZR_TEST_PATH', '/home/\xa7test')
 
2124
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2125
        self.assertEqual(u'/home/\xa7test',
 
2126
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2127
        osutils._fs_enc = "iso8859-5"
 
2128
        self.assertEqual(u'/home/\u0407test',
 
2129
            osutils._posix_path_from_environ('BZR_TEST_PATH'))
 
2130
        osutils._fs_enc = "utf-8"
 
2131
        self.assertRaises(errors.BadFilenameEncoding,
 
2132
            osutils._posix_path_from_environ, 'BZR_TEST_PATH')
 
2133
 
 
2134
 
 
2135
class TestGetHomeDir(tests.TestCase):
 
2136
 
 
2137
    def test_is_unicode(self):
 
2138
        home = osutils._get_home_dir()
 
2139
        self.assertIsInstance(home, unicode)
 
2140
 
 
2141
    def test_posix_homeless(self):
 
2142
        self.overrideEnv('HOME', None)
 
2143
        home = osutils._get_home_dir()
 
2144
        self.assertIsInstance(home, unicode)
 
2145
 
 
2146
    def test_posix_home_ascii(self):
 
2147
        self.overrideEnv('HOME', '/home/test')
 
2148
        home = osutils._posix_get_home_dir()
 
2149
        self.assertIsInstance(home, unicode)
 
2150
        self.assertEqual(u'/home/test', home)
 
2151
 
 
2152
    def test_posix_home_unicode(self):
 
2153
        self.requireFeature(features.ByteStringNamedFilesystem)
 
2154
        self.overrideEnv('HOME', '/home/\xa7test')
 
2155
        self.overrideAttr(osutils, "_fs_enc", "iso8859-1")
 
2156
        self.assertEqual(u'/home/\xa7test', osutils._posix_get_home_dir())
 
2157
        osutils._fs_enc = "iso8859-5"
 
2158
        self.assertEqual(u'/home/\u0407test', osutils._posix_get_home_dir())
 
2159
        osutils._fs_enc = "utf-8"
 
2160
        self.assertRaises(errors.BadFilenameEncoding,
 
2161
            osutils._posix_get_home_dir)
 
2162
 
 
2163
 
 
2164
class TestGetuserUnicode(tests.TestCase):
 
2165
 
 
2166
    def test_is_unicode(self):
 
2167
        user = osutils.getuser_unicode()
 
2168
        self.assertIsInstance(user, unicode)
 
2169
 
 
2170
    def envvar_to_override(self):
 
2171
        if sys.platform == "win32":
 
2172
            # Disable use of platform calls on windows so envvar is used
 
2173
            self.overrideAttr(win32utils, 'has_ctypes', False)
 
2174
            return 'USERNAME' # only variable used on windows
 
2175
        return 'LOGNAME' # first variable checked by getpass.getuser()
 
2176
 
 
2177
    def test_ascii_user(self):
 
2178
        self.overrideEnv(self.envvar_to_override(), 'jrandom')
 
2179
        self.assertEqual(u'jrandom', osutils.getuser_unicode())
 
2180
 
 
2181
    def test_unicode_user(self):
 
2182
        ue = osutils.get_user_encoding()
 
2183
        uni_val, env_val = tests.probe_unicode_in_user_encoding()
 
2184
        if uni_val is None:
 
2185
            raise tests.TestSkipped(
 
2186
                'Cannot find a unicode character that works in encoding %s'
 
2187
                % (osutils.get_user_encoding(),))
 
2188
        uni_username = u'jrandom' + uni_val
 
2189
        encoded_username = uni_username.encode(ue)
 
2190
        self.overrideEnv(self.envvar_to_override(), encoded_username)
 
2191
        self.assertEqual(uni_username, osutils.getuser_unicode())
 
2192
 
 
2193
 
 
2194
class TestBackupNames(tests.TestCase):
 
2195
 
 
2196
    def setUp(self):
 
2197
        super(TestBackupNames, self).setUp()
 
2198
        self.backups = []
 
2199
 
 
2200
    def backup_exists(self, name):
 
2201
        return name in self.backups
 
2202
 
 
2203
    def available_backup_name(self, name):
 
2204
        backup_name = osutils.available_backup_name(name, self.backup_exists)
 
2205
        self.backups.append(backup_name)
 
2206
        return backup_name
 
2207
 
 
2208
    def assertBackupName(self, expected, name):
 
2209
        self.assertEqual(expected, self.available_backup_name(name))
 
2210
 
 
2211
    def test_empty(self):
 
2212
        self.assertBackupName('file.~1~', 'file')
 
2213
 
 
2214
    def test_existing(self):
 
2215
        self.available_backup_name('file')
 
2216
        self.available_backup_name('file')
 
2217
        self.assertBackupName('file.~3~', 'file')
 
2218
        # Empty slots are found, this is not a strict requirement and may be
 
2219
        # revisited if we test against all implementations.
 
2220
        self.backups.remove('file.~2~')
 
2221
        self.assertBackupName('file.~2~', 'file')
 
2222
 
 
2223
 
 
2224
class TestFindExecutableInPath(tests.TestCase):
 
2225
 
 
2226
    def test_windows(self):
 
2227
        if sys.platform != 'win32':
 
2228
            raise tests.TestSkipped('test requires win32')
 
2229
        self.assertTrue(osutils.find_executable_on_path('explorer') is not None)
 
2230
        self.assertTrue(
 
2231
            osutils.find_executable_on_path('explorer.exe') is not None)
 
2232
        self.assertTrue(
 
2233
            osutils.find_executable_on_path('EXPLORER.EXE') is not None)
 
2234
        self.assertTrue(
 
2235
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2236
        self.assertTrue(osutils.find_executable_on_path('file.txt') is None)
 
2237
        
 
2238
    def test_windows_app_path(self):
 
2239
        if sys.platform != 'win32':
 
2240
            raise tests.TestSkipped('test requires win32')
 
2241
        # Override PATH env var so that exe can only be found on App Path
 
2242
        self.overrideEnv('PATH', '')
 
2243
        # Internt Explorer is always registered in the App Path
 
2244
        self.assertTrue(osutils.find_executable_on_path('iexplore') is not None)
 
2245
 
 
2246
    def test_other(self):
 
2247
        if sys.platform == 'win32':
 
2248
            raise tests.TestSkipped('test requires non-win32')
 
2249
        self.assertTrue(osutils.find_executable_on_path('sh') is not None)
 
2250
        self.assertTrue(
 
2251
            osutils.find_executable_on_path('THIS SHOULD NOT EXIST') is None)
 
2252
 
 
2253
 
 
2254
class TestEnvironmentErrors(tests.TestCase):
 
2255
    """Test handling of environmental errors"""
 
2256
 
 
2257
    def test_is_oserror(self):
 
2258
        self.assertTrue(osutils.is_environment_error(
 
2259
            OSError(errno.EINVAL, "Invalid parameter")))
 
2260
 
 
2261
    def test_is_ioerror(self):
 
2262
        self.assertTrue(osutils.is_environment_error(
 
2263
            IOError(errno.EINVAL, "Invalid parameter")))
 
2264
 
 
2265
    def test_is_socket_error(self):
 
2266
        self.assertTrue(osutils.is_environment_error(
 
2267
            socket.error(errno.EINVAL, "Invalid parameter")))
 
2268
 
 
2269
    def test_is_select_error(self):
 
2270
        self.assertTrue(osutils.is_environment_error(
 
2271
            select.error(errno.EINVAL, "Invalid parameter")))
 
2272
 
 
2273
    def test_is_pywintypes_error(self):
 
2274
        self.requireFeature(features.pywintypes)
 
2275
        import pywintypes
 
2276
        self.assertTrue(osutils.is_environment_error(
 
2277
            pywintypes.error(errno.EINVAL, "Invalid parameter", "Caller")))